ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-customize-nav-menu-setting.php (18930B)


      1 <?php
      2 /**
      3  * Customize API: WP_Customize_Nav_Menu_Setting class
      4  *
      5  * @package WordPress
      6  * @subpackage Customize
      7  * @since 4.4.0
      8  */
      9 
     10 /**
     11  * Customize Setting to represent a nav_menu.
     12  *
     13  * Subclass of WP_Customize_Setting to represent a nav_menu taxonomy term, and
     14  * the IDs for the nav_menu_items associated with the nav menu.
     15  *
     16  * @since 4.3.0
     17  *
     18  * @see wp_get_nav_menu_object()
     19  * @see WP_Customize_Setting
     20  */
     21 class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting {
     22 
     23 	const ID_PATTERN = '/^nav_menu\[(?P<id>-?\d+)\]$/';
     24 
     25 	const TAXONOMY = 'nav_menu';
     26 
     27 	const TYPE = 'nav_menu';
     28 
     29 	/**
     30 	 * Setting type.
     31 	 *
     32 	 * @since 4.3.0
     33 	 * @var string
     34 	 */
     35 	public $type = self::TYPE;
     36 
     37 	/**
     38 	 * Default setting value.
     39 	 *
     40 	 * @since 4.3.0
     41 	 * @var array
     42 	 *
     43 	 * @see wp_get_nav_menu_object()
     44 	 */
     45 	public $default = array(
     46 		'name'        => '',
     47 		'description' => '',
     48 		'parent'      => 0,
     49 		'auto_add'    => false,
     50 	);
     51 
     52 	/**
     53 	 * Default transport.
     54 	 *
     55 	 * @since 4.3.0
     56 	 * @var string
     57 	 */
     58 	public $transport = 'postMessage';
     59 
     60 	/**
     61 	 * The term ID represented by this setting instance.
     62 	 *
     63 	 * A negative value represents a placeholder ID for a new menu not yet saved.
     64 	 *
     65 	 * @since 4.3.0
     66 	 * @var int
     67 	 */
     68 	public $term_id;
     69 
     70 	/**
     71 	 * Previous (placeholder) term ID used before creating a new menu.
     72 	 *
     73 	 * This value will be exported to JS via the {@see 'customize_save_response'} filter
     74 	 * so that JavaScript can update the settings to refer to the newly-assigned
     75 	 * term ID. This value is always negative to indicate it does not refer to
     76 	 * a real term.
     77 	 *
     78 	 * @since 4.3.0
     79 	 * @var int
     80 	 *
     81 	 * @see WP_Customize_Nav_Menu_Setting::update()
     82 	 * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response()
     83 	 */
     84 	public $previous_term_id;
     85 
     86 	/**
     87 	 * Whether or not update() was called.
     88 	 *
     89 	 * @since 4.3.0
     90 	 * @var bool
     91 	 */
     92 	protected $is_updated = false;
     93 
     94 	/**
     95 	 * Status for calling the update method, used in customize_save_response filter.
     96 	 *
     97 	 * See {@see 'customize_save_response'}.
     98 	 *
     99 	 * When status is inserted, the placeholder term ID is stored in `$previous_term_id`.
    100 	 * When status is error, the error is stored in `$update_error`.
    101 	 *
    102 	 * @since 4.3.0
    103 	 * @var string updated|inserted|deleted|error
    104 	 *
    105 	 * @see WP_Customize_Nav_Menu_Setting::update()
    106 	 * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response()
    107 	 */
    108 	public $update_status;
    109 
    110 	/**
    111 	 * Any error object returned by wp_update_nav_menu_object() when setting is updated.
    112 	 *
    113 	 * @since 4.3.0
    114 	 * @var WP_Error
    115 	 *
    116 	 * @see WP_Customize_Nav_Menu_Setting::update()
    117 	 * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response()
    118 	 */
    119 	public $update_error;
    120 
    121 	/**
    122 	 * Constructor.
    123 	 *
    124 	 * Any supplied $args override class property defaults.
    125 	 *
    126 	 * @since 4.3.0
    127 	 *
    128 	 * @throws Exception If $id is not valid for this setting type.
    129 	 *
    130 	 * @param WP_Customize_Manager $manager Customizer bootstrap instance.
    131 	 * @param string               $id      A specific ID of the setting.
    132 	 *                                      Can be a theme mod or option name.
    133 	 * @param array                $args    Optional. Setting arguments.
    134 	 */
    135 	public function __construct( WP_Customize_Manager $manager, $id, array $args = array() ) {
    136 		if ( empty( $manager->nav_menus ) ) {
    137 			throw new Exception( 'Expected WP_Customize_Manager::$nav_menus to be set.' );
    138 		}
    139 
    140 		if ( ! preg_match( self::ID_PATTERN, $id, $matches ) ) {
    141 			throw new Exception( "Illegal widget setting ID: $id" );
    142 		}
    143 
    144 		$this->term_id = (int) $matches['id'];
    145 
    146 		parent::__construct( $manager, $id, $args );
    147 	}
    148 
    149 	/**
    150 	 * Get the instance data for a given widget setting.
    151 	 *
    152 	 * @since 4.3.0
    153 	 *
    154 	 * @see wp_get_nav_menu_object()
    155 	 *
    156 	 * @return array Instance data.
    157 	 */
    158 	public function value() {
    159 		if ( $this->is_previewed && get_current_blog_id() === $this->_previewed_blog_id ) {
    160 			$undefined  = new stdClass(); // Symbol.
    161 			$post_value = $this->post_value( $undefined );
    162 
    163 			if ( $undefined === $post_value ) {
    164 				$value = $this->_original_value;
    165 			} else {
    166 				$value = $post_value;
    167 			}
    168 		} else {
    169 			$value = false;
    170 
    171 			// Note that a term_id of less than one indicates a nav_menu not yet inserted.
    172 			if ( $this->term_id > 0 ) {
    173 				$term = wp_get_nav_menu_object( $this->term_id );
    174 
    175 				if ( $term ) {
    176 					$value = wp_array_slice_assoc( (array) $term, array_keys( $this->default ) );
    177 
    178 					$nav_menu_options  = (array) get_option( 'nav_menu_options', array() );
    179 					$value['auto_add'] = false;
    180 
    181 					if ( isset( $nav_menu_options['auto_add'] ) && is_array( $nav_menu_options['auto_add'] ) ) {
    182 						$value['auto_add'] = in_array( $term->term_id, $nav_menu_options['auto_add'], true );
    183 					}
    184 				}
    185 			}
    186 
    187 			if ( ! is_array( $value ) ) {
    188 				$value = $this->default;
    189 			}
    190 		}
    191 
    192 		return $value;
    193 	}
    194 
    195 	/**
    196 	 * Handle previewing the setting.
    197 	 *
    198 	 * @since 4.3.0
    199 	 * @since 4.4.0 Added boolean return value
    200 	 *
    201 	 * @see WP_Customize_Manager::post_value()
    202 	 *
    203 	 * @return bool False if method short-circuited due to no-op.
    204 	 */
    205 	public function preview() {
    206 		if ( $this->is_previewed ) {
    207 			return false;
    208 		}
    209 
    210 		$undefined      = new stdClass();
    211 		$is_placeholder = ( $this->term_id < 0 );
    212 		$is_dirty       = ( $undefined !== $this->post_value( $undefined ) );
    213 		if ( ! $is_placeholder && ! $is_dirty ) {
    214 			return false;
    215 		}
    216 
    217 		$this->is_previewed       = true;
    218 		$this->_original_value    = $this->value();
    219 		$this->_previewed_blog_id = get_current_blog_id();
    220 
    221 		add_filter( 'wp_get_nav_menus', array( $this, 'filter_wp_get_nav_menus' ), 10, 2 );
    222 		add_filter( 'wp_get_nav_menu_object', array( $this, 'filter_wp_get_nav_menu_object' ), 10, 2 );
    223 		add_filter( 'default_option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) );
    224 		add_filter( 'option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) );
    225 
    226 		return true;
    227 	}
    228 
    229 	/**
    230 	 * Filters the wp_get_nav_menus() result to ensure the inserted menu object is included, and the deleted one is removed.
    231 	 *
    232 	 * @since 4.3.0
    233 	 *
    234 	 * @see wp_get_nav_menus()
    235 	 *
    236 	 * @param WP_Term[] $menus An array of menu objects.
    237 	 * @param array     $args  An array of arguments used to retrieve menu objects.
    238 	 * @return WP_Term[] Array of menu objects.
    239 	 */
    240 	public function filter_wp_get_nav_menus( $menus, $args ) {
    241 		if ( get_current_blog_id() !== $this->_previewed_blog_id ) {
    242 			return $menus;
    243 		}
    244 
    245 		$setting_value = $this->value();
    246 		$is_delete     = ( false === $setting_value );
    247 		$index         = -1;
    248 
    249 		// Find the existing menu item's position in the list.
    250 		foreach ( $menus as $i => $menu ) {
    251 			if ( (int) $this->term_id === (int) $menu->term_id || (int) $this->previous_term_id === (int) $menu->term_id ) {
    252 				$index = $i;
    253 				break;
    254 			}
    255 		}
    256 
    257 		if ( $is_delete ) {
    258 			// Handle deleted menu by removing it from the list.
    259 			if ( -1 !== $index ) {
    260 				array_splice( $menus, $index, 1 );
    261 			}
    262 		} else {
    263 			// Handle menus being updated or inserted.
    264 			$menu_obj = (object) array_merge(
    265 				array(
    266 					'term_id'          => $this->term_id,
    267 					'term_taxonomy_id' => $this->term_id,
    268 					'slug'             => sanitize_title( $setting_value['name'] ),
    269 					'count'            => 0,
    270 					'term_group'       => 0,
    271 					'taxonomy'         => self::TAXONOMY,
    272 					'filter'           => 'raw',
    273 				),
    274 				$setting_value
    275 			);
    276 
    277 			array_splice( $menus, $index, ( -1 === $index ? 0 : 1 ), array( $menu_obj ) );
    278 		}
    279 
    280 		// Make sure the menu objects get re-sorted after an update/insert.
    281 		if ( ! $is_delete && ! empty( $args['orderby'] ) ) {
    282 			$menus = wp_list_sort(
    283 				$menus,
    284 				array(
    285 					$args['orderby'] => 'ASC',
    286 				)
    287 			);
    288 		}
    289 		// @todo Add support for $args['hide_empty'] === true.
    290 
    291 		return $menus;
    292 	}
    293 
    294 	/**
    295 	 * Temporary non-closure passing of orderby value to function.
    296 	 *
    297 	 * @since 4.3.0
    298 	 * @var string
    299 	 *
    300 	 * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus()
    301 	 * @see WP_Customize_Nav_Menu_Setting::_sort_menus_by_orderby()
    302 	 */
    303 	protected $_current_menus_sort_orderby;
    304 
    305 	/**
    306 	 * Sort menu objects by the class-supplied orderby property.
    307 	 *
    308 	 * This is a workaround for a lack of closures.
    309 	 *
    310 	 * @since 4.3.0
    311 	 * @deprecated 4.7.0 Use wp_list_sort()
    312 	 *
    313 	 * @param object $menu1
    314 	 * @param object $menu2
    315 	 * @return int
    316 	 *
    317 	 * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus()
    318 	 */
    319 	protected function _sort_menus_by_orderby( $menu1, $menu2 ) {
    320 		_deprecated_function( __METHOD__, '4.7.0', 'wp_list_sort' );
    321 
    322 		$key = $this->_current_menus_sort_orderby;
    323 		return strcmp( $menu1->$key, $menu2->$key );
    324 	}
    325 
    326 	/**
    327 	 * Filters the wp_get_nav_menu_object() result to supply the previewed menu object.
    328 	 *
    329 	 * Requesting a nav_menu object by anything but ID is not supported.
    330 	 *
    331 	 * @since 4.3.0
    332 	 *
    333 	 * @see wp_get_nav_menu_object()
    334 	 *
    335 	 * @param object|null $menu_obj Object returned by wp_get_nav_menu_object().
    336 	 * @param string      $menu_id  ID of the nav_menu term. Requests by slug or name will be ignored.
    337 	 * @return object|null
    338 	 */
    339 	public function filter_wp_get_nav_menu_object( $menu_obj, $menu_id ) {
    340 		$ok = (
    341 			get_current_blog_id() === $this->_previewed_blog_id
    342 			&&
    343 			is_int( $menu_id )
    344 			&&
    345 			$menu_id === $this->term_id
    346 		);
    347 		if ( ! $ok ) {
    348 			return $menu_obj;
    349 		}
    350 
    351 		$setting_value = $this->value();
    352 
    353 		// Handle deleted menus.
    354 		if ( false === $setting_value ) {
    355 			return false;
    356 		}
    357 
    358 		// Handle sanitization failure by preventing short-circuiting.
    359 		if ( null === $setting_value ) {
    360 			return $menu_obj;
    361 		}
    362 
    363 		$menu_obj = (object) array_merge(
    364 			array(
    365 				'term_id'          => $this->term_id,
    366 				'term_taxonomy_id' => $this->term_id,
    367 				'slug'             => sanitize_title( $setting_value['name'] ),
    368 				'count'            => 0,
    369 				'term_group'       => 0,
    370 				'taxonomy'         => self::TAXONOMY,
    371 				'filter'           => 'raw',
    372 			),
    373 			$setting_value
    374 		);
    375 
    376 		return $menu_obj;
    377 	}
    378 
    379 	/**
    380 	 * Filters the nav_menu_options option to include this menu's auto_add preference.
    381 	 *
    382 	 * @since 4.3.0
    383 	 *
    384 	 * @param array $nav_menu_options Nav menu options including auto_add.
    385 	 * @return array (Maybe) modified nav menu options.
    386 	 */
    387 	public function filter_nav_menu_options( $nav_menu_options ) {
    388 		if ( get_current_blog_id() !== $this->_previewed_blog_id ) {
    389 			return $nav_menu_options;
    390 		}
    391 
    392 		$menu             = $this->value();
    393 		$nav_menu_options = $this->filter_nav_menu_options_value(
    394 			$nav_menu_options,
    395 			$this->term_id,
    396 			false === $menu ? false : $menu['auto_add']
    397 		);
    398 
    399 		return $nav_menu_options;
    400 	}
    401 
    402 	/**
    403 	 * Sanitize an input.
    404 	 *
    405 	 * Note that parent::sanitize() erroneously does wp_unslash() on $value, but
    406 	 * we remove that in this override.
    407 	 *
    408 	 * @since 4.3.0
    409 	 *
    410 	 * @param array $value The value to sanitize.
    411 	 * @return array|false|null Null if an input isn't valid. False if it is marked for deletion.
    412 	 *                          Otherwise the sanitized value.
    413 	 */
    414 	public function sanitize( $value ) {
    415 		// Menu is marked for deletion.
    416 		if ( false === $value ) {
    417 			return $value;
    418 		}
    419 
    420 		// Invalid.
    421 		if ( ! is_array( $value ) ) {
    422 			return null;
    423 		}
    424 
    425 		$default = array(
    426 			'name'        => '',
    427 			'description' => '',
    428 			'parent'      => 0,
    429 			'auto_add'    => false,
    430 		);
    431 		$value   = array_merge( $default, $value );
    432 		$value   = wp_array_slice_assoc( $value, array_keys( $default ) );
    433 
    434 		$value['name']        = trim( esc_html( $value['name'] ) ); // This sanitization code is used in wp-admin/nav-menus.php.
    435 		$value['description'] = sanitize_text_field( $value['description'] );
    436 		$value['parent']      = max( 0, (int) $value['parent'] );
    437 		$value['auto_add']    = ! empty( $value['auto_add'] );
    438 
    439 		if ( '' === $value['name'] ) {
    440 			$value['name'] = _x( '(unnamed)', 'Missing menu name.' );
    441 		}
    442 
    443 		/** This filter is documented in wp-includes/class-wp-customize-setting.php */
    444 		return apply_filters( "customize_sanitize_{$this->id}", $value, $this );
    445 	}
    446 
    447 	/**
    448 	 * Storage for data to be sent back to client in customize_save_response filter.
    449 	 *
    450 	 * See {@see 'customize_save_response'}.
    451 	 *
    452 	 * @since 4.3.0
    453 	 * @var array
    454 	 *
    455 	 * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response()
    456 	 */
    457 	protected $_widget_nav_menu_updates = array();
    458 
    459 	/**
    460 	 * Create/update the nav_menu term for this setting.
    461 	 *
    462 	 * Any created menus will have their assigned term IDs exported to the client
    463 	 * via the {@see 'customize_save_response'} filter. Likewise, any errors will be exported
    464 	 * to the client via the customize_save_response() filter.
    465 	 *
    466 	 * To delete a menu, the client can send false as the value.
    467 	 *
    468 	 * @since 4.3.0
    469 	 *
    470 	 * @see wp_update_nav_menu_object()
    471 	 *
    472 	 * @param array|false $value {
    473 	 *     The value to update. Note that slug cannot be updated via wp_update_nav_menu_object().
    474 	 *     If false, then the menu will be deleted entirely.
    475 	 *
    476 	 *     @type string $name        The name of the menu to save.
    477 	 *     @type string $description The term description. Default empty string.
    478 	 *     @type int    $parent      The id of the parent term. Default 0.
    479 	 *     @type bool   $auto_add    Whether pages will auto_add to this menu. Default false.
    480 	 * }
    481 	 * @return null|void
    482 	 */
    483 	protected function update( $value ) {
    484 		if ( $this->is_updated ) {
    485 			return;
    486 		}
    487 
    488 		$this->is_updated = true;
    489 		$is_placeholder   = ( $this->term_id < 0 );
    490 		$is_delete        = ( false === $value );
    491 
    492 		add_filter( 'customize_save_response', array( $this, 'amend_customize_save_response' ) );
    493 
    494 		$auto_add = null;
    495 		if ( $is_delete ) {
    496 			// If the current setting term is a placeholder, a delete request is a no-op.
    497 			if ( $is_placeholder ) {
    498 				$this->update_status = 'deleted';
    499 			} else {
    500 				$r = wp_delete_nav_menu( $this->term_id );
    501 
    502 				if ( is_wp_error( $r ) ) {
    503 					$this->update_status = 'error';
    504 					$this->update_error  = $r;
    505 				} else {
    506 					$this->update_status = 'deleted';
    507 					$auto_add            = false;
    508 				}
    509 			}
    510 		} else {
    511 			// Insert or update menu.
    512 			$menu_data              = wp_array_slice_assoc( $value, array( 'description', 'parent' ) );
    513 			$menu_data['menu-name'] = $value['name'];
    514 
    515 			$menu_id              = $is_placeholder ? 0 : $this->term_id;
    516 			$r                    = wp_update_nav_menu_object( $menu_id, wp_slash( $menu_data ) );
    517 			$original_name        = $menu_data['menu-name'];
    518 			$name_conflict_suffix = 1;
    519 			while ( is_wp_error( $r ) && 'menu_exists' === $r->get_error_code() ) {
    520 				$name_conflict_suffix += 1;
    521 				/* translators: 1: Original menu name, 2: Duplicate count. */
    522 				$menu_data['menu-name'] = sprintf( __( '%1$s (%2$d)' ), $original_name, $name_conflict_suffix );
    523 				$r                      = wp_update_nav_menu_object( $menu_id, wp_slash( $menu_data ) );
    524 			}
    525 
    526 			if ( is_wp_error( $r ) ) {
    527 				$this->update_status = 'error';
    528 				$this->update_error  = $r;
    529 			} else {
    530 				if ( $is_placeholder ) {
    531 					$this->previous_term_id = $this->term_id;
    532 					$this->term_id          = $r;
    533 					$this->update_status    = 'inserted';
    534 				} else {
    535 					$this->update_status = 'updated';
    536 				}
    537 
    538 				$auto_add = $value['auto_add'];
    539 			}
    540 		}
    541 
    542 		if ( null !== $auto_add ) {
    543 			$nav_menu_options = $this->filter_nav_menu_options_value(
    544 				(array) get_option( 'nav_menu_options', array() ),
    545 				$this->term_id,
    546 				$auto_add
    547 			);
    548 			update_option( 'nav_menu_options', $nav_menu_options );
    549 		}
    550 
    551 		if ( 'inserted' === $this->update_status ) {
    552 			// Make sure that new menus assigned to nav menu locations use their new IDs.
    553 			foreach ( $this->manager->settings() as $setting ) {
    554 				if ( ! preg_match( '/^nav_menu_locations\[/', $setting->id ) ) {
    555 					continue;
    556 				}
    557 
    558 				$post_value = $setting->post_value( null );
    559 				if ( ! is_null( $post_value ) && (int) $post_value === $this->previous_term_id ) {
    560 					$this->manager->set_post_value( $setting->id, $this->term_id );
    561 					$setting->save();
    562 				}
    563 			}
    564 
    565 			// Make sure that any nav_menu widgets referencing the placeholder nav menu get updated and sent back to client.
    566 			foreach ( array_keys( $this->manager->unsanitized_post_values() ) as $setting_id ) {
    567 				$nav_menu_widget_setting = $this->manager->get_setting( $setting_id );
    568 				if ( ! $nav_menu_widget_setting || ! preg_match( '/^widget_nav_menu\[/', $nav_menu_widget_setting->id ) ) {
    569 					continue;
    570 				}
    571 
    572 				$widget_instance = $nav_menu_widget_setting->post_value(); // Note that this calls WP_Customize_Widgets::sanitize_widget_instance().
    573 				if ( empty( $widget_instance['nav_menu'] ) || (int) $widget_instance['nav_menu'] !== $this->previous_term_id ) {
    574 					continue;
    575 				}
    576 
    577 				$widget_instance['nav_menu'] = $this->term_id;
    578 				$updated_widget_instance     = $this->manager->widgets->sanitize_widget_js_instance( $widget_instance );
    579 				$this->manager->set_post_value( $nav_menu_widget_setting->id, $updated_widget_instance );
    580 				$nav_menu_widget_setting->save();
    581 
    582 				$this->_widget_nav_menu_updates[ $nav_menu_widget_setting->id ] = $updated_widget_instance;
    583 			}
    584 		}
    585 	}
    586 
    587 	/**
    588 	 * Updates a nav_menu_options array.
    589 	 *
    590 	 * @since 4.3.0
    591 	 *
    592 	 * @see WP_Customize_Nav_Menu_Setting::filter_nav_menu_options()
    593 	 * @see WP_Customize_Nav_Menu_Setting::update()
    594 	 *
    595 	 * @param array $nav_menu_options Array as returned by get_option( 'nav_menu_options' ).
    596 	 * @param int   $menu_id          The term ID for the given menu.
    597 	 * @param bool  $auto_add         Whether to auto-add or not.
    598 	 * @return array (Maybe) modified nav_menu_otions array.
    599 	 */
    600 	protected function filter_nav_menu_options_value( $nav_menu_options, $menu_id, $auto_add ) {
    601 		$nav_menu_options = (array) $nav_menu_options;
    602 		if ( ! isset( $nav_menu_options['auto_add'] ) ) {
    603 			$nav_menu_options['auto_add'] = array();
    604 		}
    605 
    606 		$i = array_search( $menu_id, $nav_menu_options['auto_add'], true );
    607 
    608 		if ( $auto_add && false === $i ) {
    609 			array_push( $nav_menu_options['auto_add'], $this->term_id );
    610 		} elseif ( ! $auto_add && false !== $i ) {
    611 			array_splice( $nav_menu_options['auto_add'], $i, 1 );
    612 		}
    613 
    614 		return $nav_menu_options;
    615 	}
    616 
    617 	/**
    618 	 * Export data for the JS client.
    619 	 *
    620 	 * @since 4.3.0
    621 	 *
    622 	 * @see WP_Customize_Nav_Menu_Setting::update()
    623 	 *
    624 	 * @param array $data Additional information passed back to the 'saved' event on `wp.customize`.
    625 	 * @return array Export data.
    626 	 */
    627 	public function amend_customize_save_response( $data ) {
    628 		if ( ! isset( $data['nav_menu_updates'] ) ) {
    629 			$data['nav_menu_updates'] = array();
    630 		}
    631 		if ( ! isset( $data['widget_nav_menu_updates'] ) ) {
    632 			$data['widget_nav_menu_updates'] = array();
    633 		}
    634 
    635 		$data['nav_menu_updates'][] = array(
    636 			'term_id'          => $this->term_id,
    637 			'previous_term_id' => $this->previous_term_id,
    638 			'error'            => $this->update_error ? $this->update_error->get_error_code() : null,
    639 			'status'           => $this->update_status,
    640 			'saved_value'      => 'deleted' === $this->update_status ? null : $this->value(),
    641 		);
    642 
    643 		$data['widget_nav_menu_updates'] = array_merge(
    644 			$data['widget_nav_menu_updates'],
    645 			$this->_widget_nav_menu_updates
    646 		);
    647 		$this->_widget_nav_menu_updates  = array();
    648 
    649 		return $data;
    650 	}
    651 }