WordPress.org

Make WordPress Core

Opened 4 years ago

Closed 4 years ago

#33411 closed defect (bug) (fixed)

remove_panel('nav_menus') action generates errors

Reported by: IstanbulMMV Owned by: westonruter
Milestone: 4.3.1 Priority: normal
Severity: normal Version: 4.3
Component: Customize Keywords: has-patch commit fixed-major
Focuses: javascript, administration Cc:
PR Number:

Description

After removing the nav_menus panel in the Customizer, all custom panels are rendered above the Active theme section regardless of the priority a custom panel has been allocated.

$wp_customize->remove_panel( 'nav_menus' ) also generates the php error "Trying to get property of non-object in /wp-includes/class-wp-customize-nav-menus.php on line 340"

Example code:

function custom_customize_register( $wp_customize ) {

        $wp_customize->remove_panel( 'nav_menus' );

	$wp_customize->remove_panel( 'widgets' ); // Works perfectly.

        $wp_customize->add_panel( 'contact_details', array(
                'title'         => __( 'Contact Details' ),
                'priority'      => 200,
        ) );

        $wp_customize->add_section( 'address_details', array(
                'title'         => __( 'Address Details' ),
                'panel'         => 'contact_details',
        ) );

        $wp_customize->add_setting( 'phone_number', array(
		'type'		=> 'option',
        ) );

        $wp_customize->add_control( 'phone_number', array(
                'label' 	=> __( 'Phone Number' ),
                'section'       => 'address_details',
        ) );

}
add_action( 'customize_register', 'custom_customize_register', 1000 );

Attachments (2)

33411.diff (463 bytes) - added by westonruter 4 years ago.
33411.alt.diff (1.5 KB) - added by westonruter 4 years ago.

Download all attachments as: .zip

Change History (19)

#1 follow-up: @celloexpressions
4 years ago

  • Keywords needs-patch added

Removing the panel probably isn't the best approach here since menus are more fully integrated with core (hence the notice). Temporary workarounds would be trying to change the capability set on the panel or adding an active callback filter that disables it, ie (untested):

$wp_customize->get_panel( 'nav_menus' )->active_callback = '__return_false';

We should investigate whether there's a way to avoid that error though.

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


4 years ago

#3 in reply to: ↑ 1 @IstanbulMMV
4 years ago

Replying to celloexpressions:

Removing the panel probably isn't the best approach here since menus are more fully integrated with core (hence the notice). Temporary workarounds would be trying to change the capability set on the panel or adding an active callback filter that disables it, ie (untested):

$wp_customize->get_panel( 'nav_menus' )->active_callback = '__return_false';

We should investigate whether there's a way to avoid that error though.

Many thanks Nick. Adding your suggested callback removed the menus panel and appears to have had no adverse affect on any custom panels. Much appreciated.

#4 follow-up: @AJClarke
4 years ago

The debug error isn't a huge deal, but removing the nav_menus also causes js errors which can break js-dependent controls.

@IstanbulMMV - Setting the a active_callback will simply hide the panel. It won't actually have any improvements in the Customizer loading time. Just so you know ;)

#5 in reply to: ↑ 4 @westonruter
4 years ago

  • Milestone changed from Awaiting Review to 4.3.1

Replying to AJClarke:

@IstanbulMMV - Setting the a active_callback will simply hide the panel. It won't actually have any improvements in the Customizer loading time. Just so you know ;)

If you really need to disable menus in the Customizer entirely, then you can just undo the actions/filters that are added by WP_Customize_Nav_Menus::__construct(), for instance with this plugin:

<?php
add_action( 'customize_register', function( $wp_customize ) {
        /** @var WP_Customize_Manager $wp_customize */
        remove_action( 'customize_controls_enqueue_scripts', array( $wp_customize->nav_menus, 'enqueue_scripts' ) );
        remove_action( 'customize_register', array( $wp_customize->nav_menus, 'customize_register' ), 11 );
        remove_filter( 'customize_dynamic_setting_args', array( $wp_customize->nav_menus, 'filter_dynamic_setting_args' ) );
        remove_filter( 'customize_dynamic_setting_class', array( $wp_customize->nav_menus, 'filter_dynamic_setting_class' ) );
        remove_action( 'customize_controls_print_footer_scripts', array( $wp_customize->nav_menus, 'print_templates' ) );
        remove_action( 'customize_controls_print_footer_scripts', array( $wp_customize->nav_menus, 'available_items_template' ) );
        remove_action( 'customize_preview_init', array( $wp_customize->nav_menus, 'customize_preview_init' ) );
}, 10 );

But yes, otherwise there should be no JS error if the nav_menus panel is removed.

@westonruter
4 years ago

#6 @westonruter
4 years ago

  • Focuses javascript added
  • Keywords 2nd-opinion added

33411.diff adds short-circuiting to wp.customize.Menus.AvailableMenuItemsPanelView.initialize() if there is no nav_menus panel. This eliminates the JS error.

However, I'm not entirely sure that this is the right approach. If the nav menus are truly eliminated from the Customizer, then the overwhelming best approach is to undo the actions/filters that initialize it to begin with (as shown above), since this also has a performance improvement.

#7 @DrewAPicture
4 years ago

While balancing that we don't necessarily want to encourage people to remove core panels from the Customizer, I don't think we need to make it intentionally difficult either. I would expect remove_panel() to do what it implies – completely remove the panel from the equation. And that should go for any panel, realistically, core or not.

Having to unhook seven actions to accomplish what the method should already be capable of is not the kind of approach I think we should be promoting.

Consider for a moment that when the Toolbar was introduced (as the 'admin bar') in 3.1, a short-circuit filter was included to kill it on the front-end. I'm not suggesting we use filters in this context, but I am suggesting that this should easier.

If removing the panel or the section or the control from the array isn't enough, then maybe we need to look at a more comprehensive "unhooking" mechanism.

#8 follow-up: @westonruter
4 years ago

  • Keywords has-patch added; needs-patch removed

@DrewAPicture Great feedback. So yes, removing the panel shouldn't cause a JS error, so 33411.diff makes sense. However, to truly remove the Nav Menus entirely, another extension mechanism is needed to hook in earlier to be able to override which Customizer features get loaded. This is useful for disabling features, but it is perhaps even more useful for plugins to introduce new features, and even for feature plugins to swap out Customizer components altogether. With that in mind, take a look at 33411.alt.diff.

With that in place, you could disable menus in the Customizer just with this plugin:

<?php
add_action( 'customize_manager_construct', function( $wp_customize ) {
        $wp_customize->nav_menus = false;
} );

Nice and clean.

#9 in reply to: ↑ 8 @DrewAPicture
4 years ago

Replying to westonruter:

With that in place, you could disable menus in the Customizer just with this plugin:

<?php
add_action( 'customize_manager_construct', function( $wp_customize ) {
        $wp_customize->nav_menus = false;
} );

Nice and clean.

Very interesting. I wonder what if any potential downsides there might be in placing such a general hook this high up in the stack.

I'd almost be tempted use a dynamic hook with a whitelist based on the nav_menus and widgets properties to sort of lock it down to this specific context.

The whitelist could be expanded in the future without opening the door wide to the scenario that any general-purpose hook brings: having to support any number of unexpected use-cases down the road.

#10 follow-up: @westonruter
4 years ago

  • Milestone changed from 4.3.1 to 4.4

#11 in reply to: ↑ 10 @DrewAPicture
4 years ago

Replying to westonruter:

We should probably do the JS fix at least for 4.3.1, don't you think? Do we have the same or similar issues with removing widgets?

#12 @westonruter
4 years ago

  • Owner set to westonruter
  • Resolution set to fixed
  • Status changed from new to closed

In 33753:

Customizer: Prevent JS error during init when nav_menus panel is removed by plugin.

Fixes #33411 for trunk.

#13 @westonruter
4 years ago

  • Keywords commit added; 2nd-opinion removed
  • Milestone changed from 4.4 to 4.3.1
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for 4.3.1: [33753] needs to be cherry-picked into the 4.3 branch when it is open for business.

I'll open a separate ticket for the proposed customize_manager_construct hook.

#14 @DrewAPicture
4 years ago

  • Keywords fixed-major added

#15 @westonruter
4 years ago

For the proposed customize_manager_construct action, see #33552.

@DrewAPicture: No, there is no JS error when removing the widgets panel in the same way there is in 4.3 when removing the nav_menus panel.

#16 @SergeyBiryukov
4 years ago

#33648 was marked as a duplicate.

#17 @westonruter
4 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 33943:

Customizer: Prevent JS error during init when nav_menus panel is removed by plugin.

Cherry-picks [33753] onto 4.3 branch.
Fixes #33411 for 4.3.

Note: See TracTickets for help on using tickets.