Make WordPress Core

Changeset 50953


Ignore:
Timestamp:
05/23/2021 08:50:44 AM (4 years ago)
Author:
SergeyBiryukov
Message:

Widgets: Make sure WP_Widget constructor creates a correct id_base value for a namespaced widget class.

The id_base value is used for the widget's id and class attributes and also for the option name which stores the widget settings (unless the widget specifies a custom option_name value).

With this change, any backslashes in the id_base for a namespaced widget class are converted to hyphens, making it easier to style the output or target the widget with JavaScript.

This also avoids a preg_match(): Compilation failed PHP warning from next_widget_id_number() on the Widgets screen, previously caused by unescaped backslashes.

Props Mte90, hermpheus, rogerlos, welcher, SergeyBiryukov.
Fixes #44098.

Location:
trunk
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-widget.php

    r49946 r50953  
    161161     */
    162162    public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
    163         $this->id_base         = empty( $id_base ) ? preg_replace( '/(wp_)?widget_/', '', strtolower( get_class( $this ) ) ) : strtolower( $id_base );
     163        if ( ! empty( $id_base ) ) {
     164            $id_base = strtolower( $id_base );
     165        } else {
     166            $id_base = preg_replace( '/(wp_)?widget_/', '', strtolower( get_class( $this ) ) );
     167            $id_base = str_replace( '\\', '-', $id_base );
     168        }
     169
     170        $this->id_base         = $id_base;
    164171        $this->name            = $name;
    165172        $this->option_name     = 'widget_' . $this->id_base;
  • trunk/tests/phpunit/tests/widgets.php

    r49203 r50953  
    2424    function tearDown() {
    2525        global $wp_customize;
     26
    2627        $wp_customize = null;
    2728
     
    3738
    3839        $widget_class = 'WP_Widget_Search';
     40
    3941        register_widget( $widget_class );
    4042        $this->assertArrayHasKey( $widget_class, $wp_widget_factory->widgets );
     
    5355    function test_register_and_unregister_widget_instance() {
    5456        global $wp_widget_factory, $wp_registered_widgets;
     57
    5558        $this->assertEmpty( $wp_widget_factory->widgets );
    5659        $this->assertEmpty( $wp_registered_widgets );
     
    128131     */
    129132    function test_register_sidebars_single() {
    130 
    131133        global $wp_registered_sidebars;
    132134
     
    141143     */
    142144    function test_register_sidebars_multiple() {
    143 
    144145        global $wp_registered_sidebars;
    145146
     
    200201     */
    201202    function test_register_sidebar_with_string_id() {
    202 
    203203        global $wp_registered_sidebars;
    204204
     
    427427
    428428    /**
     429     * @ticket 44098
     430     * @see WP_Widget::__construct()
     431     * @dataProvider data_wp_widget_id_base
     432     */
     433    function test_wp_widget_id_base( $expected, $widget_class ) {
     434        require_once DIR_TESTDATA . '/widgets/custom-widget-classes.php';
     435
     436        $widget = new $widget_class( '', 'Foo' );
     437
     438        $this->assertSame( $expected, $widget->id_base );
     439    }
     440
     441    /**
     442     * Data provider.
     443     *
     444     * Passes the expected `id_base` value and the class name.
     445     *
     446     * @since 5.8.0
     447     *
     448     * @return array {
     449     *     @type array {
     450     *         @type string $expected     The expected `id_base` value to be returned.
     451     *         @type string $widget_class The widget class name for creating an instance.
     452     *     }
     453     * }
     454     */
     455    function data_wp_widget_id_base() {
     456        return array(
     457            array(
     458                'search',
     459                'WP_Widget_Search',
     460            ),
     461            array(
     462                'test-sub-sub-namespaced_widget',
     463                'Test\Sub\Sub\Namespaced_Widget',
     464            ),
     465            array(
     466                'non_namespaced_widget',
     467                'Non_Namespaced_Widget',
     468            ),
     469        );
     470    }
     471
     472    /**
    429473     * @see WP_Widget::get_field_name()
    430474     * @dataProvider data_wp_widget_get_field_name
     
    451495     */
    452496    function data_wp_widget_get_field_name() {
    453 
    454497        return array(
    455498            array(
Note: See TracChangeset for help on using the changeset viewer.