Customizer: Improve performance of menus by caching results of `wp_setup_nav_menu_item()` calls.
Also fixes property list in phpdoc for `wp_setup_nav_menu_item()`. Fixes #32769. Built from https://develop.svn.wordpress.org/trunk@33256 git-svn-id: http://core.svn.wordpress.org/trunk@33228 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
0ae5642b42
commit
c5bd85552e
|
@ -496,7 +496,12 @@ final class WP_Customize_Nav_Menus {
|
|||
|
||||
// Create a setting for each menu item (which doesn't actually manage data, currently).
|
||||
$menu_item_setting_id = 'nav_menu_item[' . $item->ID . ']';
|
||||
$this->manager->add_setting( new WP_Customize_Nav_Menu_Item_Setting( $this->manager, $menu_item_setting_id ) );
|
||||
|
||||
$value = (array) $item;
|
||||
$value['nav_menu_term_id'] = $menu_id;
|
||||
$this->manager->add_setting( new WP_Customize_Nav_Menu_Item_Setting( $this->manager, $menu_item_setting_id, array(
|
||||
'value' => $value,
|
||||
) ) );
|
||||
|
||||
// Create a control for each menu item.
|
||||
$this->manager->add_control( new WP_Customize_Nav_Menu_Item_Control( $this->manager, $menu_item_setting_id, array(
|
||||
|
|
|
@ -701,14 +701,21 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
*
|
||||
* A negative value represents a placeholder ID for a new menu not yet saved.
|
||||
*
|
||||
* @todo Should this be $db_id, and also use this for WP_Customize_Nav_Menu_Setting::$term_id
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $post_id;
|
||||
|
||||
/**
|
||||
* Storage of pre-setup menu item to prevent wasted calls to wp_setup_nav_menu_item().
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Previous (placeholder) post ID used before creating a new menu item.
|
||||
*
|
||||
|
@ -806,11 +813,34 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
}
|
||||
|
||||
$this->post_id = intval( $matches['id'] );
|
||||
|
||||
$menu = $this->value();
|
||||
$this->original_nav_menu_term_id = $menu['nav_menu_term_id'];
|
||||
add_action( 'wp_update_nav_menu_item', array( $this, 'flush_cached_value' ), 10, 2 );
|
||||
|
||||
parent::__construct( $manager, $id, $args );
|
||||
|
||||
// Ensure that an initially-supplied value is valid.
|
||||
if ( isset( $this->value ) ) {
|
||||
$this->populate_value();
|
||||
foreach ( array_diff( array_keys( $this->default ), array_keys( $this->value ) ) as $missing ) {
|
||||
throw new Exception( "Supplied nav_menu_item value missing property: $missing" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached value when this nav menu item is updated.
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param int $menu_id The term ID for the menu.
|
||||
* @param int $menu_item_id The post ID for the menu item.
|
||||
*/
|
||||
public function flush_cached_value( $menu_id, $menu_item_id ) {
|
||||
unset( $menu_id );
|
||||
if ( $menu_item_id === $this->post_id ) {
|
||||
$this->value = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -821,7 +851,7 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
*
|
||||
* @see wp_setup_nav_menu_item()
|
||||
*
|
||||
* @return array Instance data.
|
||||
* @return array|false Instance data array, or false if the item is marked for deletion.
|
||||
*/
|
||||
public function value() {
|
||||
if ( $this->is_previewed && $this->_previewed_blog_id === get_current_blog_id() ) {
|
||||
|
@ -833,6 +863,8 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
} else {
|
||||
$value = $post_value;
|
||||
}
|
||||
} else if ( isset( $this->value ) ) {
|
||||
$value = $this->value;
|
||||
} else {
|
||||
$value = false;
|
||||
|
||||
|
@ -840,54 +872,109 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
if ( $this->post_id > 0 ) {
|
||||
$post = get_post( $this->post_id );
|
||||
if ( $post && self::POST_TYPE === $post->post_type ) {
|
||||
$item = wp_setup_nav_menu_item( $post );
|
||||
$value = wp_array_slice_assoc(
|
||||
(array) $item,
|
||||
array_keys( $this->default )
|
||||
);
|
||||
$value['position'] = $item->menu_order;
|
||||
$value['status'] = $item->post_status;
|
||||
$value['original_title'] = '';
|
||||
|
||||
$menus = wp_get_post_terms( $post->ID, WP_Customize_Nav_Menu_Setting::TAXONOMY, array(
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
if ( ! empty( $menus ) ) {
|
||||
$value['nav_menu_term_id'] = array_shift( $menus );
|
||||
} else {
|
||||
$value['nav_menu_term_id'] = 0;
|
||||
}
|
||||
|
||||
if ( 'post_type' === $value['type'] ) {
|
||||
$original_title = get_the_title( $value['object_id'] );
|
||||
} elseif ( 'taxonomy' === $value['type'] ) {
|
||||
$original_title = get_term_field( 'name', $value['object_id'], $value['object'], 'raw' );
|
||||
if ( is_wp_error( $original_title ) ) {
|
||||
$original_title = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $original_title ) ) {
|
||||
$value['original_title'] = html_entity_decode( $original_title, ENT_QUOTES, get_bloginfo( 'charset' ) );
|
||||
}
|
||||
$value = (array) wp_setup_nav_menu_item( $post );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! is_array( $value ) ) {
|
||||
$value = $this->default;
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
foreach ( array( 'object_id', 'menu_item_parent', 'nav_menu_term_id' ) as $key ) {
|
||||
$value[ $key ] = intval( $value[ $key ] );
|
||||
}
|
||||
// Cache the value for future calls to avoid having to re-call wp_setup_nav_menu_item().
|
||||
$this->value = $value;
|
||||
$this->populate_value();
|
||||
$value = $this->value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the value is fully populated with the necessary properties.
|
||||
*
|
||||
* Translates some properties added by wp_setup_nav_menu_item() and removes others.
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @see WP_Customize_Nav_Menu_Item_Setting::value()
|
||||
*/
|
||||
protected function populate_value() {
|
||||
if ( ! is_array( $this->value ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $this->value['menu_order'] ) ) {
|
||||
$this->value['position'] = $this->value['menu_order'];
|
||||
unset( $this->value['menu_order'] );
|
||||
}
|
||||
if ( isset( $this->value['post_status'] ) ) {
|
||||
$this->value['status'] = $this->value['post_status'];
|
||||
unset( $this->value['post_status'] );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->value['original_title'] ) ) {
|
||||
$original_title = '';
|
||||
if ( 'post_type' === $this->value['type'] ) {
|
||||
$original_title = get_the_title( $this->value['object_id'] );
|
||||
} elseif ( 'taxonomy' === $this->value['type'] ) {
|
||||
$original_title = get_term_field( 'name', $this->value['object_id'], $this->value['object'], 'raw' );
|
||||
if ( is_wp_error( $original_title ) ) {
|
||||
$original_title = '';
|
||||
}
|
||||
}
|
||||
$this->value['original_title'] = html_entity_decode( $original_title, ENT_QUOTES, get_bloginfo( 'charset' ) );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->value['nav_menu_term_id'] ) && $this->post_id > 0 ) {
|
||||
$menus = wp_get_post_terms( $this->post_id, WP_Customize_Nav_Menu_Setting::TAXONOMY, array(
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
if ( ! empty( $menus ) ) {
|
||||
$this->value['nav_menu_term_id'] = array_shift( $menus );
|
||||
} else {
|
||||
$this->value['nav_menu_term_id'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( array( 'object_id', 'menu_item_parent', 'nav_menu_term_id' ) as $key ) {
|
||||
if ( ! is_int( $this->value[ $key ] ) ) {
|
||||
$this->value[ $key ] = intval( $this->value[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
// Remove remaining properties available on a setup nav_menu_item post object which aren't relevant to the setting value.
|
||||
$irrelevant_properties = array(
|
||||
'ID',
|
||||
'comment_count',
|
||||
'comment_status',
|
||||
'db_id',
|
||||
'filter',
|
||||
'guid',
|
||||
'ping_status',
|
||||
'pinged',
|
||||
'post_author',
|
||||
'post_content',
|
||||
'post_content_filtered',
|
||||
'post_date',
|
||||
'post_date_gmt',
|
||||
'post_excerpt',
|
||||
'post_mime_type',
|
||||
'post_modified',
|
||||
'post_modified_gmt',
|
||||
'post_name',
|
||||
'post_parent',
|
||||
'post_password',
|
||||
'post_title',
|
||||
'post_type',
|
||||
'to_ping',
|
||||
'type_label',
|
||||
);
|
||||
foreach ( $irrelevant_properties as $property ) {
|
||||
unset( $this->value[ $property ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle previewing the setting.
|
||||
*
|
||||
|
@ -1043,16 +1130,21 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
$item->menu_order = $item->position;
|
||||
unset( $item->position );
|
||||
|
||||
$item->post_author = get_current_user_id();
|
||||
|
||||
if ( $item->title ) {
|
||||
$item->post_title = $item->title;
|
||||
}
|
||||
|
||||
$item->ID = $this->post_id;
|
||||
$item->db_id = $this->post_id;
|
||||
$post = new WP_Post( (object) $item );
|
||||
$post = wp_setup_nav_menu_item( $post );
|
||||
|
||||
if ( empty( $post->post_author ) ) {
|
||||
$post->post_author = get_current_user_id();
|
||||
}
|
||||
|
||||
if ( ! isset( $post->type_label ) ) {
|
||||
$post->type_label = null;
|
||||
}
|
||||
return $post;
|
||||
}
|
||||
|
||||
|
@ -1160,6 +1252,9 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
|||
$is_placeholder = ( $this->post_id < 0 );
|
||||
$is_delete = ( false === $value );
|
||||
|
||||
// Update the cached value.
|
||||
$this->value = $value;
|
||||
|
||||
add_filter( 'customize_save_response', array( $this, 'amend_customize_save_response' ) );
|
||||
|
||||
if ( $is_delete ) {
|
||||
|
|
|
@ -658,20 +658,23 @@ function wp_get_nav_menu_items( $menu, $args = array() ) {
|
|||
* Decorates a menu item object with the shared navigation menu item properties.
|
||||
*
|
||||
* Properties:
|
||||
* - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist).
|
||||
* - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.
|
||||
* - type: The family of objects originally represented, such as "post_type" or "taxonomy."
|
||||
* - object: The type of object originally represented, such as "category," "post", or "attachment."
|
||||
* - type_label: The singular label used to describe this type of menu item.
|
||||
* - post_parent: The DB ID of the original object's parent object, if any (0 otherwise).
|
||||
* - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise.
|
||||
* - url: The URL to which this menu item points.
|
||||
* - title: The title of this menu item.
|
||||
* - target: The target attribute of the link element for this menu item.
|
||||
* - attr_title: The title attribute of the link element for this menu item.
|
||||
* - classes: The array of class attribute values for the link element of this menu item.
|
||||
* - xfn: The XFN relationship expressed in the link of this menu item.
|
||||
* - description: The description of this menu item.
|
||||
* - ID: The term_id if the menu item represents a taxonomy term.
|
||||
* - attr_title: The title attribute of the link element for this menu item.
|
||||
* - classes: The array of class attribute values for the link element of this menu item.
|
||||
* - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist).
|
||||
* - description: The description of this menu item.
|
||||
* - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise.
|
||||
* - object: The type of object originally represented, such as "category," "post", or "attachment."
|
||||
* - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.
|
||||
* - post_parent: The DB ID of the original object's parent object, if any (0 otherwise).
|
||||
* - post_title: A "no title" label if menu item represents a post that lacks a title.
|
||||
* - target: The target attribute of the link element for this menu item.
|
||||
* - title: The title of this menu item.
|
||||
* - type: The family of objects originally represented, such as "post_type" or "taxonomy."
|
||||
* - type_label: The singular label used to describe this type of menu item.
|
||||
* - url: The URL to which this menu item points.
|
||||
* - xfn: The XFN relationship expressed in the link of this menu item.
|
||||
* - _invalid: Whether the menu item represents an object that no longer exists.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '4.3-beta2-33255';
|
||||
$wp_version = '4.3-beta2-33256';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue