Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit d5e0bbc

Browse files
authored
Merge pull request #56 from xwp/bugfix/saving-menus-issue_3
Re-use methods in WP_Customize_Nav_Menus in favor of duplication
2 parents 310b365 + adca567 commit d5e0bbc

File tree

5 files changed

+73
-467
lines changed

5 files changed

+73
-467
lines changed

php/class-customize-snapshot-manager.php

Lines changed: 67 additions & 237 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,6 @@ public function __construct( Plugin $plugin ) {
124124
add_action( 'admin_bar_menu', array( $this, 'customize_menu' ), 41 );
125125
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_templates' ) );
126126

127-
add_filter( 'theme_mod_nav_menu_locations', array( $this, 'filter_theme_mod_nav_menu_locations' ) );
128-
add_filter( 'wp_get_nav_menus', array( $this, 'filter_wp_get_nav_menus' ) );
129-
add_filter( 'wp_get_nav_menu_items', array( $this, 'filter_wp_get_nav_menu_items' ), 10, 3 );
130-
add_filter( 'wp_get_nav_menu_object', array( $this, 'filter_wp_get_nav_menu_object' ), 10, 2 );
131-
132-
// Needs priority 12 since it has to happen after the default nav menus are registered.
133-
add_action( 'customize_register', array( $this, 'customize_register_nav_menus' ), 12 );
134-
135127
/*
136128
* Add WP_Customize_Widget component hooks which were short-circuited in 4.5 (r36611 for #35895).
137129
* See https://core.trac.wordpress.org/ticket/35895
@@ -163,8 +155,46 @@ public function __construct( Plugin $plugin ) {
163155
}
164156
}
165157

158+
/*
159+
* Add WP_Customize_Nav_Menu component hooks which were short-circuited in 4.5 (r36611 for #35895).
160+
* See https://core.trac.wordpress.org/ticket/35895
161+
*/
162+
if ( isset( $this->customize_manager->nav_menus ) && ! current_user_can( 'edit_theme_options' ) ) {
163+
$hooks = array(
164+
'customize_register' => array(
165+
'callback' => array( $this->customize_manager->nav_menus, 'customize_register' ),
166+
'priority' => 11,
167+
),
168+
'customize_dynamic_setting_args' => array(
169+
'callback' => array( $this->customize_manager->nav_menus, 'filter_dynamic_setting_args' ),
170+
'priority' => 10,
171+
),
172+
'customize_dynamic_setting_class' => array(
173+
'callback' => array( $this->customize_manager->nav_menus, 'filter_dynamic_setting_class' ),
174+
'priority' => 10,
175+
),
176+
'wp_nav_menu_args' => array(
177+
'callback' => array( $this->customize_manager->nav_menus, 'filter_wp_nav_menu_args' ),
178+
'priority' => 1000,
179+
),
180+
'wp_nav_menu' => array(
181+
'callback' => array( $this->customize_manager->nav_menus, 'filter_wp_nav_menu' ),
182+
'priority' => 10,
183+
),
184+
);
185+
foreach ( $hooks as $hook_name => $hook_args ) {
186+
// Note that add_action()/has_action() are just aliases for add_filter()/has_filter().
187+
if ( ! has_filter( $hook_name, $hook_args['callback'] ) ) {
188+
add_filter( $hook_name, $hook_args['callback'], $hook_args['priority'], PHP_INT_MAX );
189+
}
190+
}
191+
}
192+
166193
// Preview a Snapshot.
167194
add_action( 'after_setup_theme', array( $this, 'set_post_values' ), 1 );
195+
if ( isset( $this->customize_manager->nav_menus ) ) {
196+
add_action( 'customize_register', array( $this, 'preview_early_nav_menus_in_customizer' ), 9 );
197+
}
168198
add_action( 'wp_loaded', array( $this, 'preview' ) );
169199

170200
/*
@@ -388,235 +418,6 @@ function suspend_kses_for_snapshot_revision_restore() {
388418
} );
389419
}
390420

391-
/**
392-
* Filter for displaying the Snapshot menu location values.
393-
*
394-
* @param array $menu_locations Default menu locations.
395-
* @return array Modified menu locations.
396-
*/
397-
public function filter_theme_mod_nav_menu_locations( $menu_locations ) {
398-
if ( false === $this->snapshot->is_preview() ) {
399-
return $menu_locations;
400-
}
401-
402-
$values = $this->snapshot->values();
403-
$locations = get_registered_nav_menus();
404-
405-
foreach ( $locations as $location => $name ) {
406-
if ( isset( $values[ 'nav_menu_locations[' . $location . ']' ] ) ) {
407-
$menu_locations[ $location ] = $values[ 'nav_menu_locations[' . $location . ']' ];
408-
}
409-
}
410-
411-
return $menu_locations;
412-
}
413-
414-
/**
415-
* Filter wp_get_nav_menus() to load Snapshot values.
416-
*
417-
* @see wp_get_nav_menus()
418-
*
419-
* @param array $menus Array of menus.
420-
* @return array Modified array of menus.
421-
*/
422-
public function filter_wp_get_nav_menus( $menus ) {
423-
if ( false === $this->snapshot->is_preview() ) {
424-
return $menus;
425-
}
426-
427-
$values = $this->snapshot->values();
428-
$removed = array();
429-
430-
foreach ( $values as $setting_id => $value ) {
431-
if ( preg_match( '/^nav_menu\[(?P<id>-?\d+)\]$/', $setting_id, $matches ) ) {
432-
if ( false !== $value ) {
433-
$menus[] = $this->get_nav_menu_object( $matches['id'], $value );
434-
} else {
435-
$removed[] = intval( $matches['id'] );
436-
}
437-
}
438-
}
439-
440-
if ( ! empty( $removed ) && ! empty( $menus ) ) {
441-
foreach ( $menus as $key => $term ) {
442-
if ( in_array( $term->term_id, $removed, true ) ) {
443-
unset( $menus[ $key ] );
444-
}
445-
}
446-
}
447-
448-
return array_values( $menus );
449-
}
450-
451-
/**
452-
* Filter wp_get_nav_menu_items() to load Snapshot values.
453-
*
454-
* @see wp_get_nav_menu_items()
455-
*
456-
* @param array $items An array of menu item post objects.
457-
* @param object $menu The menu object.
458-
* @param array $args An array of arguments used to retrieve menu item objects.
459-
* @return array Array of menu items.
460-
*/
461-
function filter_wp_get_nav_menu_items( $items, $menu, $args ) {
462-
if ( false === $this->snapshot->is_preview() ) {
463-
return $items;
464-
}
465-
466-
$values = $this->snapshot->values();
467-
$removed = array();
468-
469-
foreach ( $values as $setting_id => $value ) {
470-
if ( preg_match( '/^nav_menu_item\[(?P<id>-?\d+)\]$/', $setting_id, $matches ) && false === $value ) {
471-
$removed[] = intval( $matches['id'] );
472-
}
473-
}
474-
475-
if ( ! empty( $removed ) && ! empty( $items ) ) {
476-
foreach ( $items as $key => $post ) {
477-
if ( in_array( $post->ID, $removed, true ) ) {
478-
unset( $items[ $key ] );
479-
}
480-
}
481-
}
482-
483-
foreach ( $values as $setting_id => $item ) {
484-
if ( preg_match( \WP_Customize_Nav_Menu_Item_Setting::ID_PATTERN, $setting_id, $matches ) ) {
485-
if ( (int) $menu->term_id === (int) $item['nav_menu_term_id'] ) {
486-
$item['post_id'] = intval( $matches['id'] );
487-
$items[] = $this->value_as_wp_post_nav_menu_item( (object) $item );
488-
}
489-
}
490-
}
491-
492-
return array_values( $items );
493-
}
494-
495-
/**
496-
* Filter wp_get_nav_menu_object() to load Snapshot values.
497-
*
498-
* @see wp_get_nav_menu_object()
499-
*
500-
* @param object|null $menu_obj Object returned by wp_get_nav_menu_object().
501-
* @param string $menu_id ID of the nav_menu term. Requests by slug or name will be ignored.
502-
* @return object|null New menu object or null.
503-
*/
504-
function filter_wp_get_nav_menu_object( $menu_obj, $menu_id ) {
505-
if ( false === $this->snapshot->is_preview() ) {
506-
return $menu_obj;
507-
}
508-
509-
if ( false === $menu_obj && $menu_id < 0 ) {
510-
$values = $this->snapshot->values();
511-
if ( isset( $values[ 'nav_menu[' . $menu_id . ']' ] ) ) {
512-
$menu_obj = $this->get_nav_menu_object( $menu_id, $values[ 'nav_menu[' . $menu_id . ']' ] );
513-
}
514-
}
515-
516-
return $menu_obj;
517-
}
518-
519-
/**
520-
* Build a nav menu object from a Snapshot value.
521-
*
522-
* @param int $menu_id Menu ID.
523-
* @param array $value Menu value.
524-
* @return \WP_Term
525-
*/
526-
public function get_nav_menu_object( $menu_id, $value ) {
527-
$menu_obj = new \WP_Term( (object) $value );
528-
$menu_obj->term_id = $menu_obj->term_taxonomy_id = $menu_id;
529-
$menu_obj->taxonomy = 'nav_menu';
530-
$menu_obj->slug = sanitize_title( $menu_obj->name );
531-
532-
return $menu_obj;
533-
}
534-
535-
/**
536-
* Get the value emulated into a WP_Post and set up as a nav_menu_item.
537-
*
538-
* @param object $item Snapshot nav menu item.
539-
* @return WP_Post With wp_setup_nav_menu_item() applied.
540-
*/
541-
public function value_as_wp_post_nav_menu_item( $item ) {
542-
unset( $item->nav_menu_term_id );
543-
544-
$item->post_status = $item->status;
545-
unset( $item->status );
546-
547-
$item->post_type = 'nav_menu_item';
548-
$item->menu_order = $item->position;
549-
unset( $item->position );
550-
551-
if ( $item->title ) {
552-
$item->post_title = $item->title;
553-
}
554-
555-
$item->ID = $item->post_id;
556-
$item->db_id = $item->post_id;
557-
$post = new \WP_Post( (object) $item );
558-
559-
if ( empty( $post->post_author ) ) {
560-
$post->post_author = get_current_user_id();
561-
}
562-
563-
if ( ! isset( $post->type_label ) ) {
564-
if ( 'post_type' === $post->type ) {
565-
$object = get_post_type_object( $post->object );
566-
if ( $object ) {
567-
$post->type_label = $object->labels->singular_name;
568-
} else {
569-
$post->type_label = $post->object;
570-
}
571-
} elseif ( 'taxonomy' == $post->type ) {
572-
$object = get_taxonomy( $post->object );
573-
if ( $object ) {
574-
$post->type_label = $object->labels->singular_name;
575-
} else {
576-
$post->type_label = $post->object;
577-
}
578-
} else {
579-
$post->type_label = __( 'Custom Link', 'customize-snapshots' );
580-
}
581-
}
582-
583-
/** This filter is documented in wp-includes/nav-menu.php */
584-
$post->attr_title = apply_filters( 'nav_menu_attr_title', $post->attr_title );
585-
586-
/** This filter is documented in wp-includes/nav-menu.php */
587-
$post->description = apply_filters( 'nav_menu_description', wp_trim_words( $post->description, 200 ) );
588-
589-
/** This filter is documented in wp-includes/nav-menu.php */
590-
$post = apply_filters( 'wp_setup_nav_menu_item', $post );
591-
592-
return $post;
593-
}
594-
595-
/**
596-
* Register nav menus found in a Snapshot.
597-
*/
598-
public function customize_register_nav_menus() {
599-
if ( false === $this->snapshot->is_preview() ) {
600-
return;
601-
}
602-
603-
$menus = wp_get_nav_menus();
604-
605-
foreach ( $menus as $menu ) {
606-
if ( $menu->term_id < 0 ) {
607-
608-
// Create a section for each menu.
609-
$section_id = 'nav_menu[' . $menu->term_id . ']';
610-
$this->customize_manager->remove_section( $section_id );
611-
$this->customize_manager->add_section( new Customize_Snapshot_Nav_Menu_Section( $this->customize_manager, $section_id, array(
612-
'title' => html_entity_decode( $menu->name, ENT_QUOTES, get_bloginfo( 'charset' ) ),
613-
'priority' => 10,
614-
'panel' => 'nav_menus',
615-
) ) );
616-
}
617-
}
618-
}
619-
620421
/**
621422
* Remove edit bulk action for snapshots.
622423
*
@@ -1154,4 +955,33 @@ public function preview() {
1154955
}
1155956
}
1156957
}
958+
959+
/**
960+
* Preview nav menu settings early so that the sections and controls for snapshot values will be added properly.
961+
*
962+
* This must happen at `customize_register` priority prior to 11 which is when `WP_Customize_Nav_Menus::customize_register()` runs.
963+
* This is only relevant when accessing the Customizer app (customize.php), as this is where sections/controls matter.
964+
*
965+
* @see \WP_Customize_Nav_Menus::customize_register()
966+
*/
967+
public function preview_early_nav_menus_in_customizer() {
968+
if ( ! is_admin() ) {
969+
return;
970+
}
971+
972+
$this->customize_manager->add_dynamic_settings( array_keys( $this->snapshot()->data() ) );
973+
foreach ( $this->snapshot->settings() as $setting ) {
974+
$is_nav_menu_setting = (
975+
$setting instanceof \WP_Customize_Nav_Menu_Setting
976+
||
977+
$setting instanceof \WP_Customize_Nav_Menu_Item_Setting
978+
||
979+
preg_match( '/^nav_menu_locations\[/', $setting->id )
980+
);
981+
if ( $is_nav_menu_setting ) {
982+
$setting->preview();
983+
$setting->dirty = true;
984+
}
985+
}
986+
}
1157987
}

php/class-customize-snapshot-nav-menu-section.php

Lines changed: 0 additions & 39 deletions
This file was deleted.

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ Allow Customizer states to be drafted, and previewed with a private URL.
66

77
**Contributors:** [westonruter](https://profiles.wordpress.org/westonruter), [valendesigns](https://profiles.wordpress.org/valendesigns), [xwp](https://profiles.wordpress.org/xwp), [newscorpau](https://profiles.wordpress.org/newscorpau)
88
**Tags:** [customizer](https://wordpress.org/plugins/tags/customizer), [customize](https://wordpress.org/plugins/tags/customize), [snapshots](https://wordpress.org/plugins/tags/snapshots)
9-
**Requires at least:** 4.5
9+
**Requires at least:** 4.6-beta2
1010
**Tested up to:** trunk
1111
**Stable tag:** 0.4.0
1212
**License:** [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)
1313

14-
[![Build Status](https://travis-ci.org/xwp/wp-customize-snapshots.svg?branch=master)](https://travis-ci.org/xwp/wp-customize-snapshots) [![Coverage Status](https://coveralls.io/repos/xwp/wp-customize-snapshots/badge.svg?branch=master)](https://coveralls.io/github/xwp/wp-customize-snapshots) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com) [![devDependency Status](https://david-dm.org/xwp/wp-customize-snapshots/dev-status.svg)](https://david-dm.org/xwp/wp-customize-snapshots#info=devDependencies)
14+
[![Build Status](https://travis-ci.org/xwp/wp-customize-snapshots.svg?branch=master)](https://travis-ci.org/xwp/wp-customize-snapshots) [![Coverage Status](https://coveralls.io/repos/xwp/wp-customize-snapshots/badge.svg?branch=master)](https://coveralls.io/github/xwp/wp-customize-snapshots) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com) [![devDependency Status](https://david-dm.org/xwp/wp-customize-snapshots/dev-status.svg)](https://david-dm.org/xwp/wp-customize-snapshots#info=devDependencies)
1515

1616
## Description ##
1717

readme.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== Customize Snapshots ===
22
Contributors: westonruter, valendesigns, xwp, newscorpau
3-
Requires at least: 4.5
3+
Requires at least: 4.6-beta2
44
Tested up to: trunk
55
Stable tag: 0.4.0
66
License: GPLv2 or later

0 commit comments

Comments
 (0)