WordPress.org

Make WordPress Core

Ticket #35926: 35926.2.diff

File 35926.2.diff, 12.6 KB (added by westonruter, 5 years ago)
  • src/wp-admin/js/customize-controls.js

    diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
    index 270770d..e1021a3 100644
     
    15211521                        settings = $.map( control.params.settings, function( value ) {
    15221522                                return value;
    15231523                        });
    1524                         api.apply( api, settings.concat( function () {
    1525                                 var key;
    15261524
     1525                        if ( 0 === settings.length ) {
     1526                                control.setting = null;
    15271527                                control.settings = {};
    1528                                 for ( key in control.params.settings ) {
    1529                                         control.settings[ key ] = api( control.params.settings[ key ] );
    1530                                 }
     1528                                control.embed();
     1529                        } else {
     1530                                api.apply( api, settings.concat( function() {
     1531                                        var key;
    15311532
    1532                                 control.setting = control.settings['default'] || null;
     1533                                        control.settings = {};
     1534                                        for ( key in control.params.settings ) {
     1535                                                control.settings[ key ] = api( control.params.settings[ key ] );
     1536                                        }
    15331537
    1534                                 control.embed();
    1535                         }) );
     1538                                        control.setting = control.settings['default'] || null;
     1539
     1540                                        control.embed();
     1541                                }) );
     1542                        }
    15361543
    15371544                        // After the control is embedded on the page, invoke the "ready" method.
    15381545                        control.deferred.embedded.done( function () {
  • src/wp-includes/class-wp-customize-control.php

    diff --git src/wp-includes/class-wp-customize-control.php src/wp-includes/class-wp-customize-control.php
    index a892b10..52a8a91 100644
    class WP_Customize_Control { 
    6565        public $setting = 'default';
    6666
    6767        /**
     68         * Capability required to use this control.
     69         *
     70         * Normally this is empty and the capability is derived from the capabilities
     71         * of the associated `$settings`.
     72         *
     73         * @since 4.5.0
     74         * @access public
     75         * @var string
     76         */
     77        public $capability;
     78
     79        /**
    6880         * @access public
    6981         * @var int
    7082         */
    class WP_Customize_Control { 
    187199                $this->instance_number = self::$instance_count;
    188200
    189201                // Process settings.
    190                 if ( empty( $this->settings ) ) {
     202                if ( ! isset( $this->settings ) ) {
    191203                        $this->settings = $id;
    192204                }
    193205
    class WP_Customize_Control { 
    196208                        foreach ( $this->settings as $key => $setting ) {
    197209                                $settings[ $key ] = $this->manager->get_setting( $setting );
    198210                        }
    199                 } else {
     211                } else if ( is_string( $this->settings ) ) {
    200212                        $this->setting = $this->manager->get_setting( $this->settings );
    201213                        $settings['default'] = $this->setting;
    202214                }
    class WP_Customize_Control { 
    299311        }
    300312
    301313        /**
    302          * Check if the theme supports the control and check user capabilities.
     314         * Checks if the user can use this control.
     315         *
     316         * Returns false if the user cannot manipulate one of the associated settings,
     317         * or if one of the associated settings does not exist. Also returns false if
     318         * the associated section does not exist or if its capability check returns
     319         * false.
    303320         *
    304321         * @since 3.4.0
    305322         *
    306323         * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true.
    307324         */
    308325        final public function check_capabilities() {
     326                if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) {
     327                        return false;
     328                }
     329
    309330                foreach ( $this->settings as $setting ) {
    310                         if ( ! $setting->check_capabilities() )
     331                        if ( ! $setting || ! $setting->check_capabilities() ) {
    311332                                return false;
     333                        }
    312334                }
    313335
    314336                $section = $this->manager->get_section( $this->section );
    315                 if ( isset( $section ) && ! $section->check_capabilities() )
     337                if ( isset( $section ) && ! $section->check_capabilities() ) {
    316338                        return false;
     339                }
    317340
    318341                return true;
    319342        }
  • src/wp-includes/class-wp-customize-nav-menus.php

    diff --git src/wp-includes/class-wp-customize-nav-menus.php src/wp-includes/class-wp-customize-nav-menus.php
    index 627f57c..16ef385 100644
    final class WP_Customize_Nav_Menus { 
    606606                        'priority' => 999,
    607607                ) ) );
    608608
    609                 $this->manager->add_setting( 'new_menu_name', array(
    610                         'type'      => 'new_menu',
    611                         'default'   => '',
    612                         'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
    613                 ) );
    614 
    615609                $this->manager->add_control( 'new_menu_name', array(
    616610                        'label'       => '',
    617611                        'section'     => 'add_menu',
    618612                        'type'        => 'text',
     613                        'settings'    => array(),
    619614                        'input_attrs' => array(
    620615                                'class'       => 'menu-name-field',
    621616                                'placeholder' => __( 'New menu name' ),
    622617                        ),
    623618                ) );
    624619
    625                 $this->manager->add_setting( 'create_new_menu', array(
    626                         'type' => 'new_menu',
    627                 ) );
    628 
    629620                $this->manager->add_control( new WP_Customize_New_Menu_Control( $this->manager, 'create_new_menu', array(
    630                         'section' => 'add_menu',
     621                        'section'  => 'add_menu',
     622                        'settings' => array(),
    631623                ) ) );
    632624        }
    633625
    final class WP_Customize_Nav_Menus { 
    851843                                        'type'                => 'nav_menu_instance',
    852844                                        'render_callback'     => array( $this, 'render_nav_menu_partial' ),
    853845                                        'container_inclusive' => true,
     846                                        'settings'            => array(), // Empty because the nav menu instance may relate to a menu or a location.
     847                                        'capability'          => 'edit_theme_options',
    854848                                )
    855849                        );
    856850                }
  • 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 f65e7bf..69cfcc1 100644
    final class WP_Customize_Widgets { 
    14851485         */
    14861486        public function customize_dynamic_partial_args( $partial_args, $partial_id ) {
    14871487
    1488                 if ( preg_match( '/^widget\[.+\]$/', $partial_id ) ) {
     1488                if ( preg_match( '/^widget\[(?P<widget_id>.+)\]$/', $partial_id, $matches ) ) {
    14891489                        if ( false === $partial_args ) {
    14901490                                $partial_args = array();
    14911491                        }
    14921492                        $partial_args = array_merge(
    14931493                                $partial_args,
    14941494                                array(
    1495                                         'type' => 'widget',
    1496                                         'render_callback' => array( $this, 'render_widget_partial' ),
     1495                                        'type'                => 'widget',
     1496                                        'render_callback'     => array( $this, 'render_widget_partial' ),
    14971497                                        'container_inclusive' => true,
     1498                                        'settings'            => array( $this->get_setting_id( $matches['widget_id'] ) ),
     1499                                        'capability'          => 'edit_theme_options',
    14981500                                )
    14991501                        );
    15001502                }
  • src/wp-includes/customize/class-wp-customize-partial.php

    diff --git src/wp-includes/customize/class-wp-customize-partial.php src/wp-includes/customize/class-wp-customize-partial.php
    index 3cb410b..c27b3f0 100644
    class WP_Customize_Partial { 
    9090        public $primary_setting;
    9191
    9292        /**
     93         * Capability required to edit this partial.
     94         *
     95         * Normally this is empty and the capability is derived from the capabilities
     96         * of the associated `$settings`.
     97         *
     98         * @since 4.5.0
     99         * @access public
     100         * @var string
     101         */
     102        public $capability;
     103
     104        /**
    93105         * Render callback.
    94106         *
    95107         * @since 4.5.0
    class WP_Customize_Partial { 
    157169                }
    158170
    159171                // Process settings.
    160                 if ( empty( $this->settings ) ) {
     172                if ( ! isset( $this->settings ) ) {
    161173                        $this->settings = array( $id );
    162174                } else if ( is_string( $this->settings ) ) {
    163175                        $this->settings = array( $this->settings );
    class WP_Customize_Partial { 
    299311         *                    or if one of the associated settings does not exist.
    300312         */
    301313        final public function check_capabilities() {
     314                if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) {
     315                        return false;
     316                }
    302317                foreach ( $this->settings as $setting_id ) {
    303318                        $setting = $this->component->manager->get_setting( $setting_id );
    304319                        if ( ! $setting || ! $setting->check_capabilities() ) {
  • new file tests/phpunit/tests/customize/control.php

    diff --git tests/phpunit/tests/customize/control.php tests/phpunit/tests/customize/control.php
    new file mode 100644
    index 0000000..e6d1141
    - +  
     1<?php
     2/**
     3 * Test_WP_Customize_Control tests.
     4 *
     5 * @package WordPress
     6 */
     7
     8/**
     9 * Tests for the Test_WP_Customize_Control class.
     10 *
     11 * @todo This is missing dedicated tests for all but one of the methods.
     12 *
     13 * @group customize
     14 */
     15class Test_WP_Customize_Control extends WP_UnitTestCase {
     16
     17        /**
     18         * Manager.
     19         *
     20         * @var WP_Customize_Manager
     21         */
     22        public $wp_customize;
     23
     24        /**
     25         * Set up.
     26         */
     27        function setUp() {
     28                parent::setUp();
     29                require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
     30                // @codingStandardsIgnoreStart
     31                $GLOBALS['wp_customize'] = new WP_Customize_Manager();
     32                // @codingStandardsIgnoreEnd
     33                $this->wp_customize = $GLOBALS['wp_customize'];
     34        }
     35
     36        /**
     37         * Test WP_Customize_Control::check_capabilities().
     38         *
     39         * @see WP_Customize_Control::check_capabilities()
     40         */
     41        function test_check_capabilities() {
     42                wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     43                do_action( 'customize_register', $this->wp_customize );
     44                $control = new WP_Customize_Control( $this->wp_customize, 'blogname', array(
     45                        'settings' => array( 'blogname' ),
     46                ) );
     47                $this->assertTrue( $control->check_capabilities() );
     48
     49                $control = new WP_Customize_Control( $this->wp_customize, 'blogname', array(
     50                        'settings' => array( 'blogname', 'non_existing' ),
     51                ) );
     52                $this->assertFalse( $control->check_capabilities() );
     53
     54                $this->wp_customize->add_setting( 'top_secret_message', array(
     55                        'capability' => 'top_secret_clearance',
     56                ) );
     57                $control = new WP_Customize_Control( $this->wp_customize, 'blogname', array(
     58                        'settings' => array( 'blogname', 'top_secret_clearance' ),
     59                ) );
     60                $this->assertFalse( $control->check_capabilities() );
     61
     62                $control = new WP_Customize_Control( $this->wp_customize, 'no_setting', array(
     63                        'settings' => array(),
     64                ) );
     65                $this->assertTrue( $control->check_capabilities() );
     66
     67                $control = new WP_Customize_Control( $this->wp_customize, 'no_setting', array(
     68                        'settings' => array(),
     69                        'capability' => 'top_secret_clearance',
     70                ) );
     71                $this->assertFalse( $control->check_capabilities() );
     72
     73                $control = new WP_Customize_Control( $this->wp_customize, 'no_setting', array(
     74                        'settings' => array(),
     75                        'capability' => 'edit_theme_options',
     76                ) );
     77                $this->assertTrue( $control->check_capabilities() );
     78        }
     79
     80        /**
     81         * Tear down.
     82         */
     83        function tearDown() {
     84                $this->wp_customize = null;
     85                unset( $GLOBALS['wp_customize'] );
     86                parent::tearDown();
     87        }
     88}
  • tests/phpunit/tests/customize/partial.php

    diff --git tests/phpunit/tests/customize/partial.php tests/phpunit/tests/customize/partial.php
    index 9b08fc1..66cdfdb 100644
    class Test_WP_Customize_Partial extends WP_UnitTestCase { 
    325325                        'settings' => array( 'blogname', 'top_secret_clearance' ),
    326326                ) );
    327327                $this->assertFalse( $partial->check_capabilities() );
     328
     329                $partial = new WP_Customize_Partial( $this->selective_refresh, 'no_setting', array(
     330                        'settings' => array(),
     331                ) );
     332                $this->assertTrue( $partial->check_capabilities() );
     333
     334                $partial = new WP_Customize_Partial( $this->selective_refresh, 'no_setting', array(
     335                        'settings' => array(),
     336                        'capability' => 'top_secret_clearance',
     337                ) );
     338                $this->assertFalse( $partial->check_capabilities() );
     339
     340                $partial = new WP_Customize_Partial( $this->selective_refresh, 'no_setting', array(
     341                        'settings' => array(),
     342                        'capability' => 'edit_theme_options',
     343                ) );
     344                $this->assertTrue( $partial->check_capabilities() );
    328345        }
    329346
    330347        /**
  • tests/qunit/fixtures/customize-menus.js

    diff --git tests/qunit/fixtures/customize-menus.js tests/qunit/fixtures/customize-menus.js
    index 5fdd892..f3ac0a1 100755
    window._wpCustomizeSettings.controls.new_menu_name = { 
    394394        'description': '',
    395395        'instanceNumber': 46
    396396};
    397 window._wpCustomizeSettings.settings.new_menu_name = {
    398         'value': '',
    399         'transport': 'postMessage',
    400         'dirty': false
    401 };
    402397
    403398// From nav-menu.js
    404399window.wpNavMenu = {
  • tests/qunit/wp-admin/js/customize-controls.js

    diff --git tests/qunit/wp-admin/js/customize-controls.js tests/qunit/wp-admin/js/customize-controls.js
    index b274995..47d695c 100644
    jQuery( window ).load( function (){ 
    100100                equal( control.section(), 'fixture-section' );
    101101        } );
    102102
     103        module( 'Customizer control without associated settings' );
     104        test( 'Control can be created without settings', function() {
     105                var control = new wp.customize.Control( 'settingless', {
     106                        params: {
     107                                content: jQuery( '<li class="settingless">Hello World</li>' ),
     108                                section: 'fixture-section'
     109                        }
     110                } );
     111                wp.customize.control.add( control.id, control );
     112                equal( control.deferred.embedded.state(), 'resolved' );
     113                ok( null === control.setting );
     114                ok( jQuery.isEmptyObject( control.settings ) );
     115        } );
     116
    103117        // Begin sections.
    104118        module( 'Customizer Section in Fixture' );
    105119        test( 'Fixture section exists', function () {