Make WordPress Core

03/21/2023 07:58:45 PM (13 months ago)

Code Modernization: Fix dynamic properties in WP_Admin_Bar.

To fix the dynamic properties, the following changes are included:

  • Removes WP_Admin_Bar::__get().
  • Declares menu as a property on the class, deprecates it, and initializes it to an empty array.
  • Removes the unused 'proto' dynamic property.

Dynamic (non-explicitly declared) properties are deprecated as of PHP 8.2 and are expected to become a fatal error in PHP 9.0.

Why remove the WP_Admin_Bar::__get() magic method?

The magic method is no longer needed.

The magic method only handled the menu and proto dynamic properties. Introducing a full set of magic methods is overkill for this class. Instead of having to maintain magic methods, this changeset instead directly addresses the 2 properties (see below).

Why declare the menu property on the class?

To simplify the code while maintaining backwards compatibility for extenders who are using this deprecated property.

The menu property was introduced during the 3.1.0 development cycle as a declared property [15671]. Its purpose was to internally hold the menu structure.

During the WP 3.3.0 development cycle, it was replaced by a new private property called nodes (see [19120]).

But breakage reports from extenders caused it to be restored. [19501] added the __get() magic method, i.e. for handling it as a dynamic property, and deprecated it.

We're not going to maintain compat for $menu. Suggest we make it array() and plugins will have to deal. We can throw a _deprecated_argument() and push them to use the new methods.

~ Source: see #19371 comment 17

A search of the plugins and themes repository shows that a few plugins are still using this deprecated property. To maintain backwards compatibility, menu is moved back to the class as a declared property, set to an empty array (as it's been since 3.3.0), and deprecated in the property's description.

Why remove the proto dynamic property?


  • It was not intended to be released in 3.1.
  • There are no usages of it in Core or in the's plugin or theme directories.
  • It should be safe to remove.

This property was first introduced in the WP 3.1.0 development cycle to replace the PROTO constant (see [16038]) for protocol handling for the admin bar's hyperlinks. [16077] replaced the property's usages with URL functions such as get_admin_url() and admin_url(). But it missed removing the property, which was no longer needed or used.

It was relocated to the __get() magic method as a dynamic property when the menu property was restored (see [19501]).

A search of's plugins and themes repositories shows no usages of the property. Core hasn't used it since the removed in [16038] before 3.1 final release. It should be safe to remove it, but committing very early in the 6.3 alpha cycle to give time for reports of usages, if there are any.


Follow-up to [19501], [19120], [16308], [16038], [15671].

Props antonvlasenko, hellofromTonya, jrf, markjaquith, desrosj, ironprogrammer, peterwilsoncc, SergeyBiryukov.
See #56876, #56034.

1 edited


  • trunk/tests/phpunit/tests/adminbar.php

    r54891 r55580  
    755755        );
    756756    }
     758    /**
     759     * This test ensures that WP_Admin_Bar::$proto is not defined (including magic methods).
     760     *
     761     * @ticket 56876
     762     * @coversNothing
     763     */
     764    public function test_proto_property_is_not_defined() {
     765        $admin_bar = new WP_Admin_Bar();
     766        $this->assertFalse( property_exists( $admin_bar, 'proto' ), 'WP_Admin_Bar::$proto should not be defined.' );
     767        $this->assertFalse( isset( $admin_bar->proto ), 'WP_Admin_Bar::$proto should not be defined.' );
     768    }
     770    /**
     771     * This test ensures that WP_Admin_Bar::$menu is declared as a "regular" class property.
     772     *
     773     * @ticket 56876
     774     * @coversNothing
     775     */
     776    public function test_menu_property_is_defined() {
     777        $admin_bar = new WP_Admin_Bar();
     778        $this->assertTrue( property_exists( $admin_bar, 'menu' ), 'WP_Admin_Bar::$proto property should be defined.' );
     780        $menu_property = new ReflectionProperty( WP_Admin_Bar::class, 'menu' );
     781        $this->assertTrue( $menu_property->isPublic(), 'WP_Admin_Bar::$menu should be public.' );
     783        $this->assertTrue( isset( $admin_bar->menu ), 'WP_Admin_Bar::$menu should be set.' );
     784        $this->assertSame( array(), $admin_bar->menu, 'WP_Admin_Bar::$menu should be equal to an empty array.' );
     785    }
Note: See TracChangeset for help on using the changeset viewer.