WordPress.org

Make WordPress Core

Ticket #32474: 32474.diff

File 32474.diff, 12.9 KB (added by westonruter, 5 years ago)

https://github.com/xwp/wordpress-develop/pull/85

  • src/wp-includes/class-wp-customize-widgets.php

    diff --git src/wp-includes/class-wp-customize-widgets.php src/wp-includes/class-wp-customize-widgets.php
    index 2bd073e..fa4680a 100644
    final class WP_Customize_Widgets { 
    13801380
    13811381                $updated_widget = $this->call_widget_update( $widget_id ); // => {instance,form}
    13821382                if ( is_wp_error( $updated_widget ) ) {
    1383                         wp_send_json_error( $updated_widget->get_error_message() );
     1383                        wp_send_json_error( $updated_widget->get_error_code() );
    13841384                }
    13851385
    13861386                $form = $updated_widget['form'];
  • src/wp-includes/widgets.php

    diff --git src/wp-includes/widgets.php src/wp-includes/widgets.php
    index aed3cd8..d41ce31 100644
    class WP_Widget { 
    214214                $settings = $this->get_settings();
    215215                $empty = true;
    216216
    217                 if ( is_array($settings) ) {
    218                         foreach ( array_keys($settings) as $number ) {
    219                                 if ( is_numeric($number) ) {
    220                                         $this->_set($number);
    221                                         $this->_register_one($number);
     217                // When $settings is an array-like object, get an intrinsic array for use with array_keys().
     218                if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) {
     219                        $settings = $settings->getArrayCopy();
     220                }
     221
     222                if ( is_array( $settings ) ) {
     223                        foreach ( array_keys( $settings ) as $number ) {
     224                                if ( is_numeric( $number ) ) {
     225                                        $this->_set( $number );
     226                                        $this->_register_one( $number );
    222227                                        $empty = false;
    223228                                }
    224229                        }
    225230                }
    226231
    227232                if ( $empty ) {
    228                         // If there are none, we register the widget's existence with a
    229                         // generic template
    230                         $this->_set(1);
     233                        // If there are none, we register the widget's existence with a generic template.
     234                        $this->_set( 1 );
    231235                        $this->_register_one();
    232236                }
    233237        }
    class WP_Widget { 
    294298         * }
    295299         */
    296300        public function display_callback( $args, $widget_args = 1 ) {
    297                 if ( is_numeric($widget_args) )
     301                if ( is_numeric( $widget_args ) ) {
    298302                        $widget_args = array( 'number' => $widget_args );
     303                }
    299304
    300305                $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
    301306                $this->_set( $widget_args['number'] );
    302                 $instance = $this->get_settings();
     307                $instances = $this->get_settings();
    303308
    304                 if ( array_key_exists( $this->number, $instance ) ) {
    305                         $instance = $instance[$this->number];
     309                if ( isset( $instances[ $this->number ] ) ) {
     310                        $instance = $instances[ $this->number ];
    306311
    307312                        /**
    308313                         * Filter the settings for a particular widget instance.
    class WP_Widget { 
    424429         * @access public
    425430         *
    426431         * @param int|array $widget_args Widget instance number or array of widget arguments.
     432         * @return string|null
    427433         */
    428434        public function form_callback( $widget_args = 1 ) {
    429435                if ( is_numeric($widget_args) )
    class WP_Widget { 
    516522         */
    517523        public function get_settings() {
    518524
    519                 $settings = get_option($this->option_name);
     525                $settings = get_option( $this->option_name );
    520526
    521                 if ( false === $settings && isset($this->alt_option_name) )
    522                         $settings = get_option($this->alt_option_name);
     527                if ( false === $settings && isset( $this->alt_option_name ) ) {
     528                        $settings = get_option( $this->alt_option_name );
     529                }
    523530
    524                 if ( !is_array($settings) )
     531                if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {
    525532                        $settings = array();
     533                }
    526534
    527                 if ( !empty($settings) && !array_key_exists('_multiwidget', $settings) ) {
    528                         // old format, convert if single widget
    529                         $settings = wp_convert_widget_settings($this->id_base, $this->option_name, $settings);
     535                if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) {
     536                        // Old format, convert if single widget.
     537                        $settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings );
    530538                }
    531539
    532                 unset($settings['_multiwidget'], $settings['__i__']);
     540                unset( $settings['_multiwidget'], $settings['__i__'] );
    533541                return $settings;
    534542        }
    535543}
  • tests/phpunit/tests/widgets.php

    diff --git tests/phpunit/tests/widgets.php tests/phpunit/tests/widgets.php
    index f84ba3e..802edd9 100644
     
    11<?php
    22
    33/**
    4  * Test widget template tags
     4 * Test functions and classes for widgets and sidebars.
    55 *
    66 * @group widgets
    77 */
    88class Tests_Widgets extends WP_UnitTestCase {
    99
    10         function test_register_widget_core_widget() {
     10        function clean_up_global_scope() {
     11                global $wp_widget_factory, $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
    1112
    12                 global $wp_widget_factory;
    13 
    14                 unregister_widget( 'WP_Widget_Search' );
    15                 register_widget( 'WP_Widget_Search' );
    16 
    17                 $this->assertTrue( isset( $wp_widget_factory->widgets['WP_Widget_Search'] ) );
     13                $wp_registered_sidebars = array();
     14                $wp_registered_widgets = array();
     15                $wp_registered_widget_controls = array();
     16                $wp_registered_widget_updates = array();
     17                $wp_widget_factory->widgets = array();
    1818
     19                parent::clean_up_global_scope();
    1920        }
    2021
    21         function test_unregister_widget_core_widget() {
     22        function tearDown() {
     23                global $wp_customize;
     24                $wp_customize = null;
     25                parent::tearDown();
     26        }
    2227
     28        /**
     29         * @see register_widget()
     30         * @see unregister_widget()
     31         */
     32        function test_register_and_unregister_widget_core_widget() {
    2333                global $wp_widget_factory;
    2434
    25                 unregister_widget( 'WP_Widget_Search' );
    26 
    27                 $this->assertFalse( isset( $wp_widget_factory->widgets['WP_Widget_Search'] ) );
     35                $widget_class = 'WP_Widget_Search';
     36                register_widget( $widget_class );
     37                $this->assertArrayHasKey( $widget_class, $wp_widget_factory->widgets );
    2838
     39                unregister_widget( $widget_class );
     40                $this->assertArrayNotHasKey( $widget_class, $wp_widget_factory->widgets );
    2941        }
    3042
     43        /**
     44         * @see register_sidebars()
     45         */
    3146        function test_register_sidebars_single() {
    3247
    3348                global $wp_registered_sidebars;
    class Tests_Widgets extends WP_UnitTestCase { 
    3853
    3954        }
    4055
     56        /**
     57         * @see register_sidebars()
     58         */
    4159        function test_register_sidebars_multiple() {
    4260
    4361                global $wp_registered_sidebars;
    4462
     63                $result = array();
    4564                $num = 3;
    4665                $id_base = 'WP Unit Test';
    4766                register_sidebars( $num, array( 'name' => $id_base . ' %d' ) );
    4867
    4968                $names = wp_list_pluck( $wp_registered_sidebars, 'name' );
    5069                for ( $i = 1; $i <= $num; $i++ ) {
    51                         if ( in_array( "$id_base $i", $names ) )
     70                        if ( in_array( "$id_base $i", $names ) ) {
    5271                                $result[] = true;
     72                        }
    5373                }
    5474
    5575                $this->assertEquals( $num, count( $result ) );
    5676
    5777        }
    5878
    59         function test_register_sidebar() {
     79        /**
     80         * @see register_sidebar
     81         * @see unregister_sidebar
     82         */
     83        function test_register_and_unregister_sidebar() {
    6084
    6185                global $wp_registered_sidebars;
    6286
    63                 register_sidebar( array( 'id' => 'wp-unit-test' ) );
     87                $sidebar_id = 'wp-unit-test';
     88                register_sidebar( array( 'id' => $sidebar_id ) );
     89                $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
    6490
    65                 $this->assertTrue( isset( $wp_registered_sidebars['wp-unit-test'] ) );
     91                unregister_sidebar( $sidebar_id );
     92                $this->assertArrayNotHasKey( 'wp-unit-test', $wp_registered_sidebars );
     93        }
    6694
     95        /**
     96         * @see WP_Widget_Search::form()
     97         */
     98        function test_wp_widget_search_form() {
     99                $widget = new WP_Widget_Search( 'foo', 'Foo' );
     100                ob_start();
     101                $args = array(
     102                        'before_widget' => '<section>',
     103                        'after_widget' => "</section>\n",
     104                        'before_title' => '<h2>',
     105                        'after_title' => "</h2>\n",
     106                );
     107                $instance = array( 'title' => 'Buscar' );
     108                $widget->_set( 2 );
     109                $widget->widget( $args, $instance );
     110                $output = ob_get_clean();
     111                $this->assertNotContains( 'no-options-widget', $output );
     112                $this->assertContains( '<h2>Buscar</h2>', $output );
     113                $this->assertContains( '<section>', $output );
     114                $this->assertContains( '</section>', $output );
    67115        }
    68116
    69         function test_unregister_sidebar() {
     117        /**
     118         * @see WP_Widget::form()
     119         */
     120        function test_wp_widget_form() {
     121                $widget = new WP_Widget( 'foo', 'Foo' );
     122                ob_start();
     123                $retval = $widget->form( array() );
     124                $output = ob_get_clean();
     125                $this->assertEquals( 'noform', $retval );
     126                $this->assertContains( 'no-options-widget', $output );
     127        }
    70128
    71                 global $wp_registered_sidebars;
     129        /**
     130         * @see WP_Widget::__construct()
     131         */
     132        function test_wp_widget_constructor() {
     133                $id_base = 'foo';
     134                $name = 'Foo';
     135                $foo_widget = new WP_Widget( $id_base, $name );
     136
     137                $this->assertEquals( $id_base, $foo_widget->id_base );
     138                $this->assertEquals( $name, $foo_widget->name );
     139                $this->assertEquals( "widget_{$id_base}", $foo_widget->option_name );
     140                $this->assertArrayHasKey( 'classname', $foo_widget->widget_options );
     141                $this->assertEquals( "widget_{$id_base}", $foo_widget->widget_options['classname'] );
     142                $this->assertArrayHasKey( 'id_base', $foo_widget->control_options );
     143                $this->assertEquals( $id_base, $foo_widget->control_options['id_base'] );
     144
     145                $id_base = 'bar';
     146                $name = 'Bar';
     147                $widget_options = array(
     148                        'classname' => 'bar_classname',
     149                );
     150                $control_options = array(
     151                        'id_base' => 'bar_id_base',
     152                );
     153                $bar_widget = new WP_Widget( $id_base, $name, $widget_options, $control_options );
     154                $this->assertEquals( $widget_options['classname'], $bar_widget->widget_options['classname'] );
     155                $this->assertEquals( $control_options['id_base'], $bar_widget->control_options['id_base'] );
     156        }
     157
     158        /**
     159         * @see WP_Widget::get_field_name()
     160         */
     161        function test_wp_widget_get_field_name() {
     162                $widget = new WP_Widget( 'foo', 'Foo' );
     163                $widget->_set( 2 );
     164                $this->assertEquals( 'widget-foo[2][title]', $widget->get_field_name( 'title' ) );
     165        }
     166
     167        /**
     168         * @see WP_Widget::get_field_id()
     169         */
     170        function test_wp_widget_get_field_id() {
     171                $widget = new WP_Widget( 'foo', 'Foo' );
     172                $widget->_set( 2 );
     173                $this->assertEquals( 'widget-foo-2-title', $widget->get_field_id( 'title' ) );
     174        }
     175
     176        /**
     177         * @see WP_Widget::_register()
     178         */
     179        function test_wp_widget__register() {
     180                global $wp_registered_widgets;
    72181
    73                 unregister_sidebar( 'sidebar-1' );
     182                $settings = get_option( 'widget_search' );
     183                unset( $settings['_multiwidget'] );
     184                $this->assertArrayHasKey( 2, $settings );
    74185
    75                 $this->assertFalse( isset( $wp_registered_sidebars['sidebar-1'] ) );
     186                $this->assertEmpty( $wp_registered_widgets );
     187                wp_widgets_init();
    76188
     189                // Note: We cannot use array_keys() here because $settings could be an ArrayIterator
     190                foreach ( $settings as $widget_number => $instance ) {
     191                        $widget_id = "search-$widget_number";
     192                        $this->assertArrayHasKey( $widget_id, $wp_registered_widgets );
     193                }
     194        }
     195
     196        // @todo test WP_Widget::display_callback()
     197
     198        /**
     199         * @see WP_Widget::is_preview()
     200         */
     201        function test_wp_widget_is_preview() {
     202                global $wp_customize;
     203
     204                $widget = new WP_Widget( 'foo', 'Foo' );
     205
     206                $this->assertEmpty( $wp_customize );
     207                $this->assertFalse( $widget->is_preview() );
     208
     209                wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
     210                require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
     211                $wp_customize = new WP_Customize_Manager();
     212                $wp_customize->start_previewing_theme();
     213
     214                $this->assertTrue( $widget->is_preview() );
     215        }
     216
     217        // @todo test WP_Widget::update_callback()
     218        // @todo test WP_Widget::form_callback()
     219        // @todo test WP_Widget::_register_one()
     220
     221        /**
     222         * @see WP_Widget::get_settings()
     223         */
     224        function test_wp_widget_get_settings() {
     225                global $wp_registered_widgets;
     226
     227                $option_value = get_option( 'widget_search' );
     228                $this->assertArrayHasKey( '_multiwidget', $option_value );
     229                $this->assertEquals( 1, $option_value['_multiwidget'] );
     230                $this->assertArrayHasKey( 2, $option_value );
     231                $instance = $option_value[2];
     232                $this->assertInternalType( 'array', $instance );
     233                $this->assertArrayHasKey( 'title', $instance );
     234                unset( $option_value['_multiwidget'] );
     235
     236                wp_widgets_init();
     237
     238                /** @var WP_Widget_Search $wp_widget_search */
     239                $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
     240                $settings = $wp_widget_search->get_settings();
     241                // @todo $this->assertArrayNotHasKey( '_multiwidget', $settings ); ?
     242                $this->assertArrayHasKey( 2, $settings );
     243
     244                foreach ( $option_value as $widget_number => $instance ) {
     245                        $this->assertEquals( $settings[ $widget_number ], $option_value[ $widget_number ] );
     246                }
    77247        }
     248
     249        /**
     250         * @see WP_Widget::save_settings()
     251         */
     252        function test_wp_widget_save_settings() {
     253                global $wp_registered_widgets;
     254
     255                wp_widgets_init();
     256
     257                /** @var WP_Widget_Search $wp_widget_search */
     258                $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
     259
     260                $settings = $wp_widget_search->get_settings();
     261                $overridden_title = 'Unit Tested';
     262
     263                /*
     264                 * Note that if a plugin is filtering $settings to be an ArrayIterator,
     265                 * then doing this:
     266                 *     $settings[2]['title'] = $overridden_title;
     267                 * Will fail with this:
     268                 * > Indirect modification of overloaded element of X has no effect.
     269                 * So this is why the value must be obtained.
     270                 */
     271                $instance = $settings[2];
     272                $instance['title'] = $overridden_title;
     273                $settings[2] = $instance;
     274
     275                $wp_widget_search->save_settings( $settings );
     276
     277                $option_value = get_option( $wp_widget_search->option_name );
     278                $this->assertArrayHasKey( '_multiwidget', $option_value );
     279                $this->assertEquals( $overridden_title, $option_value[2]['title'] );
     280        }
     281
    78282}