Make WordPress Core

Ticket #30737: 30737.5.diff

File 30737.5.diff, 26.2 KB (added by westonruter, 10 years ago)

Additional changes: https://github.com/xwp/wordpress-develop/compare/de06ebd...55c18ea

  • src/wp-admin/customize.php

    diff --git src/wp-admin/customize.php src/wp-admin/customize.php
    index 6bf3490..918f6b7 100644
    do_action( 'customize_controls_print_scripts' ); 
    163163        <div id="customize-preview" class="wp-full-overlay-main"></div>
    164164        <?php
    165165
    166         // Render control templates.
     166        // Render Panel, Section, and Control templates.
     167        $wp_customize->render_panel_templates();
     168        $wp_customize->render_section_templates();
    167169        $wp_customize->render_control_templates();
    168170
    169171        /**
    do_action( 'customize_controls_print_scripts' ); 
    247249
    248250        // Prepare Customize Setting objects to pass to JavaScript.
    249251        foreach ( $wp_customize->settings() as $id => $setting ) {
    250                 $settings['settings'][ $id ] = array(
    251                         'value'     => $setting->js_value(),
    252                         'transport' => $setting->transport,
    253                 );
     252                if ( $setting->check_capabilities() ) {
     253                        $settings['settings'][ $id ] = array(
     254                                'value'     => $setting->js_value(),
     255                                'transport' => $setting->transport,
     256                        );
     257                }
    254258        }
    255259
    256260        // Prepare Customize Control objects to pass to JavaScript.
    257261        foreach ( $wp_customize->controls() as $id => $control ) {
    258                 $settings['controls'][ $id ] = $control->json();
     262                if ( $control->check_capabilities() ) {
     263                        $settings['controls'][ $id ] = $control->json();
     264                }
    259265        }
    260266
    261267        // Prepare Customize Section objects to pass to JavaScript.
    262268        foreach ( $wp_customize->sections() as $id => $section ) {
    263                 $settings['sections'][ $id ] = $section->json();
     269                if ( $section->check_capabilities() ) {
     270                        $settings['sections'][ $id ] = $section->json();
     271                }
    264272        }
    265273
    266274        // Prepare Customize Panel objects to pass to JavaScript.
    267         foreach ( $wp_customize->panels() as $id => $panel ) {
    268                 $settings['panels'][ $id ] = $panel->json();
    269                 foreach ( $panel->sections as $section_id => $section ) {
    270                         $settings['sections'][ $section_id ] = $section->json();
     275        foreach ( $wp_customize->panels() as $panel_id => $panel ) {
     276                if ( $panel->check_capabilities() ) {
     277                        $settings['panels'][ $panel_id ] = $panel->json();
     278                        foreach ( $panel->sections as $section_id => $section ) {
     279                                if ( $section->check_capabilities() ) {
     280                                        $settings['sections'][ $section_id ] = $section->json();
     281                                }
     282                        }
    271283                }
    272284        }
    273285
  • src/wp-admin/js/customize-controls.js

    diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
    index b08f10f..01ad6f2 100644
     
    149149        Container = api.Class.extend({
    150150                defaultActiveArguments: { duration: 'fast', completeCallback: $.noop },
    151151                defaultExpandedArguments: { duration: 'fast', completeCallback: $.noop },
     152                containerType: 'container',
    152153
    153154                /**
    154155                 * @since 4.1.0
     
    161162                        container.id = id;
    162163                        container.params = {};
    163164                        $.extend( container, options || {} );
     165                        container.templateSelector = 'customize-' + container.containerType + '-' + container.params.type;
    164166                        container.container = $( container.params.content );
     167                        if ( 0 === container.container.length ) {
     168                                container.container = $( container.getContainer() );
     169                        }
    165170
    166171                        container.deferred = {
    167172                                embedded: new $.Deferred()
     
    359364                 * Bring the container into view and then expand this and bring it into view
    360365                 * @param {Object} [params]
    361366                 */
    362                 focus: focus
     367                focus: focus,
     368
     369                /**
     370                 * Return the container html, generated from its JS template, if it exists.
     371                 *
     372                 * @since 4.2.0
     373                 */
     374                getContainer: function () {
     375                        var template,
     376                                container = this;
     377
     378                        if ( 0 !== $( '#tmpl-' + container.templateSelector ).length ) {
     379                                template = wp.template( container.templateSelector );
     380                                if ( template && container.container ) {
     381                                        return template( container.params );
     382                                }
     383                        }
     384
     385                        return '<li></li>';
     386                }
    363387        });
    364388
    365389        /**
     
    369393         * @augments wp.customize.Class
    370394         */
    371395        api.Section = Container.extend({
     396                containerType: 'section',
    372397
    373398                /**
    374399                 * @since 4.1.0
     
    886911         * @augments wp.customize.Class
    887912         */
    888913        api.Panel = Container.extend({
     914                containerType: 'panel',
     915
    889916                /**
    890917                 * @since 4.1.0
    891918                 *
     
    912939
    913940                        if ( ! panel.container.parent().is( parentContainer ) ) {
    914941                                parentContainer.append( panel.container );
     942                                panel.renderContent();
    915943                        }
    916944                        panel.deferred.embedded.resolve();
    917945                },
     
    934962                                }
    935963                        });
    936964
    937                         meta = panel.container.find( '.panel-meta:first' );
    938 
    939                         meta.find( '> .accordion-section-title' ).on( 'click keydown', function( event ) {
     965                        panel.container.on( 'click keydown', '.panel-meta > .accordion-section-title', function( event ) {
    940966                                if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
    941967                                        return;
    942968                                }
    943969                                event.preventDefault(); // Keep this AFTER the key filter above
    944970
     971                                meta = panel.container.find( '.panel-meta' );
    945972                                if ( meta.hasClass( 'cannot-expand' ) ) {
    946973                                        return;
    947974                                }
     
    10631090                                panelTitle.focus();
    10641091                                container.scrollTop( 0 );
    10651092                        }
     1093                },
     1094
     1095                /**
     1096                 * Render the panel from its JS template, if it exists.
     1097                 *
     1098                 * The panel's container must already exist in the DOM.
     1099                 *
     1100                 * @since 4.2.0
     1101                 */
     1102                renderContent: function () {
     1103                        var template,
     1104                                panel = this;
     1105
     1106                        // Add the content to the container.
     1107                        if ( 0 !== $( '#tmpl-' + panel.templateSelector + '-content' ).length ) {
     1108                                template = wp.template( panel.templateSelector + '-content' );
     1109                                if ( template && panel.container ) {
     1110                                        panel.container.find( '.accordion-sub-container' ).html( template( panel.params ) );
     1111                                }
     1112                        }
    10661113                }
    10671114        });
    10681115
  • 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 182f842..287f2ae 100644
    class WP_Customize_Control { 
    521521         * @since 4.1.0
    522522         */
    523523        final public function print_template() {
    524                 ?>
    525                 <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
    526                         <?php $this->content_template(); ?>
    527                 </script>
    528                 <?php
     524                ?>
     525                <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
     526                        <?php $this->content_template(); ?>
     527                </script>
     528                <?php
    529529        }
    530530
    531531        /**
  • src/wp-includes/class-wp-customize-manager.php

    diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
    index ffdb3f3..9b23cc3 100644
    final class WP_Customize_Manager { 
    6060        protected $customized;
    6161
    6262        /**
    63          * Controls that may be rendered from JS templates.
     63         * Panel types that may be rendered from JS templates.
     64         *
     65         * @since 4.2.0
     66         * @access protected
     67         * @var array
     68         */
     69        protected $registered_panel_types = array();
     70
     71        /**
     72         * Section types that may be rendered from JS templates.
     73         *
     74         * @since 4.2.0
     75         * @access protected
     76         * @var array
     77         */
     78        protected $registered_section_types = array();
     79
     80        /**
     81         * Control types that may be rendered from JS templates.
    6482         *
    6583         * @since 4.1.0
    6684         * @access protected
    final class WP_Customize_Manager { 
    582600                }
    583601
    584602                foreach ( $this->settings as $id => $setting ) {
    585                         $settings['values'][ $id ] = $setting->js_value();
     603                        if ( $setting->check_capabilities() ) {
     604                                $settings['values'][ $id ] = $setting->js_value();
     605                        }
    586606                }
    587                 foreach ( $this->panels as $id => $panel ) {
    588                         $settings['activePanels'][ $id ] = $panel->active();
    589                         foreach ( $panel->sections as $id => $section ) {
    590                                 $settings['activeSections'][ $id ] = $section->active();
     607                foreach ( $this->panels as $panel_id => $panel ) {
     608                        if ( $panel->check_capabilities() ) {
     609                                $settings['activePanels'][ $panel_id ] = $panel->active();
     610                                foreach ( $panel->sections as $section_id => $section ) {
     611                                        if ( $section->check_capabilities() ) {
     612                                                $settings['activeSections'][ $section_id ] = $section->active();
     613                                        }
     614                                }
    591615                        }
    592616                }
    593617                foreach ( $this->sections as $id => $section ) {
    594                         $settings['activeSections'][ $id ] = $section->active();
     618                        if ( $section->check_capabilities() ) {
     619                                $settings['activeSections'][ $id ] = $section->active();
     620                        }
    595621                }
    596622                foreach ( $this->controls as $id => $control ) {
    597                         $settings['activeControls'][ $id ] = $control->active();
     623                        if ( $control->check_capabilities() ) {
     624                                $settings['activeControls'][ $id ] = $control->active();
     625                        }
    598626                }
    599627
    600628                ?>
    final class WP_Customize_Manager { 
    903931        }
    904932
    905933        /**
     934         * Register a customize panel type.
     935         *
     936         * Registered types are eligible to be rendered via JS and created dynamically.
     937         *
     938         * @since 4.2.0
     939         * @access public
     940         *
     941         * @param string $panel Name of a custom panel which is a subclass of
     942         *                        {@see WP_Customize_Panel}.
     943         */
     944        public function register_panel_type( $panel ) {
     945                $this->registered_panel_types[] = $panel;
     946        }
     947
     948        /**
     949         * Render JS templates for all registered panel types.
     950         *
     951         * @since 4.2.0
     952         * @access public
     953         */
     954        public function render_panel_templates() {
     955                foreach ( $this->registered_panel_types as $panel_type ) {
     956                        $panel = new $panel_type( $this, 'temp', array() );
     957                        $panel->print_template();
     958                }
     959        }
     960
     961        /**
    906962         * Add a customize section.
    907963         *
    908964         * @since 3.4.0
    final class WP_Customize_Manager { 
    9441000        }
    9451001
    9461002        /**
     1003         * Register a customize section type.
     1004         *
     1005         * Registered types are eligible to be rendered via JS and created dynamically.
     1006         *
     1007         * @since 4.2.0
     1008         * @access public
     1009         *
     1010         * @param string $section Name of a custom section which is a subclass of
     1011         *                        {@see WP_Customize_Section}.
     1012         */
     1013        public function register_section_type( $section ) {
     1014                $this->registered_section_types[] = $section;
     1015        }
     1016
     1017        /**
     1018         * Render JS templates for all registered section types.
     1019         *
     1020         * @since 4.2.0
     1021         * @access public
     1022         */
     1023        public function render_section_templates() {
     1024                foreach ( $this->registered_section_types as $section_type ) {
     1025                        $section = new $section_type( $this, 'temp', array() );
     1026                        $section->print_template();
     1027                }
     1028        }
     1029
     1030        /**
    9471031         * Add a customize control.
    9481032         *
    9491033         * @since 3.4.0
    final class WP_Customize_Manager { 
    11141198         */
    11151199        public function register_controls() {
    11161200
    1117                 /* Control Types (custom control classes) */
     1201                /* Panel, Section, and Control Types */
     1202                $this->register_panel_type( 'WP_Customize_Panel' );
     1203                $this->register_section_type( 'WP_Customize_Section' );
     1204                $this->register_section_type( 'WP_Customize_Sidebar_Section' );
    11181205                $this->register_control_type( 'WP_Customize_Color_Control' );
    11191206                $this->register_control_type( 'WP_Customize_Upload_Control' );
    11201207                $this->register_control_type( 'WP_Customize_Image_Control' );
  • src/wp-includes/class-wp-customize-panel.php

    diff --git src/wp-includes/class-wp-customize-panel.php src/wp-includes/class-wp-customize-panel.php
    index ee9f846..f2a8afe 100644
    class WP_Customize_Panel { 
    212212         * @return array The array to be exported to the client as JSON.
    213213         */
    214214        public function json() {
    215                 $array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'type' ) );
     215                $array = wp_array_slice_assoc( (array) $this, array( 'id', 'title', 'description', 'priority', 'type' ) );
    216216                $array['content'] = $this->get_content();
    217217                $array['active'] = $this->active();
    218218                $array['instanceNumber'] = $this->instance_number;
    class WP_Customize_Panel { 
    287287        }
    288288
    289289        /**
    290          * Render the panel container, and then its contents.
     290         * Render the panel container, and then its contents (via `this->render_content()`) in a subclass.
     291         *
     292         * Panel containers are now rendered in JS by default, see {@see WP_Customize_Panel::print_template()}.
    291293         *
    292294         * @since 4.0.0
    293295         * @access protected
    294296         */
    295         protected function render() {
    296                 $classes = 'accordion-section control-section control-panel control-panel-' . $this->type;
     297        protected function render() {}
     298
     299        /**
     300         * Render the panel UI in a subclass.
     301         *
     302         * Panel contents are now rendered in JS by default, see {@see WP_Customize_Panel::print_template()}.
     303         *
     304         * @since 4.1.0
     305         * @access protected
     306         */
     307        protected function render_content() {}
     308
     309        /**
     310         * Render the panel's JS templates.
     311         *
     312         * This function is only run for panel types that have been registered with
     313         * {@see WP_Customize_Manager::register_panel_type()}.
     314         *
     315         * @since 4.2.0
     316         */
     317        public function print_template() {
    297318                ?>
    298                 <li id="accordion-panel-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
     319                <script type="text/html" id="tmpl-customize-panel-<?php echo esc_attr( $this->type ); ?>-content">
     320                        <?php $this->content_template(); ?>
     321                </script>
     322                <script type="text/html" id="tmpl-customize-panel-<?php echo esc_attr( $this->type ); ?>">
     323                        <?php $this->render_template(); ?>
     324                </script>
     325        <?php
     326        }
     327
     328        /**
     329         * An Underscore (JS) template for rendering this panel's container.
     330         *
     331         * Class variables for this panel class are available in the `data` JS object;
     332         * export custom variables by overriding {@see WP_Customize_Panel::json()}.
     333         *
     334         * @see WP_Customize_Panel::print_template()
     335         *
     336         * @since 4.2.0
     337         */
     338        protected function render_template() {
     339                ?>
     340                <li id="accordion-panel-{{ data.id }}" class="accordion-section control-section control-panel control-panel-{{ data.type }}">
    299341                        <h3 class="accordion-section-title" tabindex="0">
    300                                 <?php echo esc_html( $this->title ); ?>
     342                                {{ data.title }}
    301343                                <span class="screen-reader-text"><?php _e( 'Press return or enter to open this panel' ); ?></span>
    302344                        </h3>
    303                         <ul class="accordion-sub-container control-panel-content">
    304                                 <?php $this->render_content(); ?>
    305                         </ul>
     345                        <ul class="accordion-sub-container control-panel-content"></ul>
    306346                </li>
    307347                <?php
    308348        }
    309349
    310350        /**
    311          * Render the sections that have been added to the panel.
     351         * An Underscore (JS) template for this panel's content (but not its container).
    312352         *
    313          * @since 4.1.0
    314          * @access protected
     353         * Class variables for this panel class are available in the `data` JS object;
     354         * export custom variables by overriding {@see WP_Customize_Panel::json()}.
     355         *
     356         * @see WP_Customize_Panel::print_template()
     357         *
     358         * @since 4.2.0
    315359         */
    316         protected function render_content() {
     360        protected function content_template() {
    317361                ?>
    318                 <li class="panel-meta accordion-section control-section<?php if ( empty( $this->description ) ) { echo ' cannot-expand'; } ?>">
     362                <li class="panel-meta accordion-section control-section<# if ( ! data.description ) { #> cannot-expand<# } #>">
    319363                        <div class="accordion-section-title" tabindex="0">
    320364                                <span class="preview-notice"><?php
    321365                                        /* translators: %s is the site/panel title in the Customizer */
    322                                         echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title">' . esc_html( $this->title ) . '</strong>' );
     366                                        echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title">{{ data.title }}</strong>' );
    323367                                ?></span>
    324368                        </div>
    325                         <?php if ( ! empty( $this->description ) ) : ?>
     369                        <# if ( data.description ) { #>
    326370                                <div class="accordion-section-content description">
    327                                         <?php echo $this->description; ?>
     371                                        {{{ data.description }}}
    328372                                </div>
    329                         <?php endif; ?>
     373                        <# } #>
    330374                </li>
    331375                <?php
    332376        }
  • src/wp-includes/class-wp-customize-section.php

    diff --git src/wp-includes/class-wp-customize-section.php src/wp-includes/class-wp-customize-section.php
    index b824173..ee61c2d 100644
    class WP_Customize_Section { 
    221221         * @return array The array to be exported to the client as JSON.
    222222         */
    223223        public function json() {
    224                 $array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'panel', 'type' ) );
     224                $array = wp_array_slice_assoc( (array) $this, array( 'id', 'title', 'description', 'priority', 'panel', 'type' ) );
    225225                $array['content'] = $this->get_content();
    226226                $array['active'] = $this->active();
    227227                $array['instanceNumber'] = $this->instance_number;
    class WP_Customize_Section { 
    249249        }
    250250
    251251        /**
    252          * Get the section's content template for insertion into the Customizer pane.
     252         * Get the section's content for insertion into the Customizer pane.
    253253         *
    254254         * @since 4.1.0
    255255         *
    class WP_Customize_Section { 
    295295        }
    296296
    297297        /**
    298          * Render the section, and the controls that have been added to it.
     298         * Render the section UI in a subclass.
     299         *
     300         * Sections are now rendered in JS by default, see {@see WP_Customize_Section::print_template()}.
    299301         *
    300302         * @since 3.4.0
    301303         */
    302         protected function render() {
    303                 $classes = 'accordion-section control-section control-section-' . $this->type;
     304        protected function render() {}
     305
     306        /**
     307         * Render the section's JS template.
     308         *
     309         * This function is only run for section types that have been registered with
     310         * {@see WP_Customize_Manager::register_section_type()}.
     311         *
     312         * @since 4.2.0
     313         */
     314        public function print_template() {
     315        ?>
     316                <script type="text/html" id="tmpl-customize-section-<?php echo $this->type; ?>">
     317                        <?php $this->render_template(); ?>
     318                </script>
     319        <?php
     320        }
     321
     322        /**
     323         * An Underscore (JS) template for rendering this section.
     324         *
     325         * Class variables for this section class are available in the `data` JS object;
     326         * export custom variables by overriding {@see WP_Customize_Section::json()}.
     327         *
     328         * @see WP_Customize_Section::print_template()
     329         *
     330         * @since 4.2.0
     331         */
     332        protected function render_template() {
    304333                ?>
    305                 <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
     334                <li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}">
    306335                        <h3 class="accordion-section-title" tabindex="0">
    307                                 <?php echo esc_html( $this->title ); ?>
     336                                {{ data.title }}
    308337                                <span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
    309338                        </h3>
    310339                        <ul class="accordion-section-content">
    311                                 <?php if ( ! empty( $this->description ) ) : ?>
     340                                <# if ( data.description ) { #>
    312341                                        <li class="customize-section-description-container">
    313                                                 <p class="description customize-section-description"><?php echo $this->description; ?></p>
     342                                                <p class="description customize-section-description">{{{ data.description }}}</p>
    314343                                        </li>
    315                                 <?php endif; ?>
     344                                <# } #>
    316345                        </ul>
    317346                </li>
    318347                <?php
  • new file tests/phpunit/tests/customize/panel.php

    diff --git tests/phpunit/tests/customize/panel.php tests/phpunit/tests/customize/panel.php
    new file mode 100644
    index 0000000..2eef623
    - +  
     1<?php
     2
     3/**
     4 * Tests for the WP_Customize_Manager class.
     5 *
     6 * @group customize
     7 */
     8class Tests_WP_Customize_Panel extends WP_UnitTestCase {
     9
     10        /**
     11         * @var WP_Customize_Manager
     12         */
     13        protected $manager;
     14
     15        function setUp() {
     16                parent::setUp();
     17                require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
     18                $GLOBALS['wp_customize'] = new WP_Customize_Manager();
     19                $this->manager = $GLOBALS['wp_customize'];
     20                $this->undefined = new stdClass();
     21        }
     22
     23        function tearDown() {
     24                $this->manager = null;
     25                unset( $GLOBALS['wp_customize'] );
     26                parent::tearDown();
     27        }
     28
     29        function test_construct_default_args() {
     30                $panel = new WP_Customize_Panel( $this->manager, 'foo' );
     31                $this->assertInternalType( 'int', $panel->instance_number );
     32                $this->assertEquals( $this->manager, $panel->manager );
     33                $this->assertEquals( 'foo', $panel->id );
     34                $this->assertEquals( 160, $panel->priority );
     35                $this->assertEquals( 'edit_theme_options', $panel->capability );
     36                $this->assertEquals( '', $panel->theme_supports );
     37                $this->assertEquals( '', $panel->title );
     38                $this->assertEquals( '', $panel->description );
     39                $this->assertEmpty( $panel->sections );
     40                $this->assertEquals( 'default', $panel->type );
     41                $this->assertEquals( array( $panel, 'active_callback' ), $panel->active_callback );
     42        }
     43
     44        function test_construct_custom_args() {
     45                $args = array(
     46                        'priority' => 200,
     47                        'capability' => 'edit_posts',
     48                        'theme_supports' => 'html5',
     49                        'title' => 'Hello World',
     50                        'description' => 'Lorem Ipsum',
     51                        'type' => 'horizontal',
     52                        'active_callback' => '__return_true',
     53                );
     54
     55                $panel = new WP_Customize_Panel( $this->manager, 'foo', $args );
     56                foreach ( $args as $key => $value ) {
     57                        $this->assertEquals( $value, $panel->$key );
     58                }
     59        }
     60
     61        function test_construct_custom_type() {
     62                $panel = new Custom_Panel_Test( $this->manager, 'foo' );
     63                $this->assertEquals( 'titleless', $panel->type );
     64        }
     65
     66        function test_active() {
     67                $panel = new WP_Customize_Panel( $this->manager, 'foo' );
     68                $this->assertTrue( $panel->active() );
     69
     70                $panel = new WP_Customize_Panel( $this->manager, 'foo', array(
     71                        'active_callback' => '__return_false',
     72                ) );
     73                $this->assertFalse( $panel->active() );
     74                add_filter( 'customize_panel_active', array( $this, 'filter_active_test' ), 10, 2 );
     75                $this->assertTrue( $panel->active() );
     76        }
     77
     78        /**
     79         * @param bool $active
     80         * @param WP_Customize_Panel $panel
     81         * @return bool
     82         */
     83        function filter_active_test( $active, $panel ) {
     84                $this->assertFalse( $active );
     85                $this->assertInstanceOf( 'WP_Customize_Panel', $panel );
     86                $active = true;
     87                return $active;
     88        }
     89
     90        function test_json() {
     91                $args = array(
     92                        'priority' => 200,
     93                        'capability' => 'edit_posts',
     94                        'theme_supports' => 'html5',
     95                        'title' => 'Hello World',
     96                        'description' => 'Lorem Ipsum',
     97                        'type' => 'horizontal',
     98                        'active_callback' => '__return_true',
     99                );
     100                $panel = new WP_Customize_Panel( $this->manager, 'foo', $args );
     101                $data = $panel->json();
     102                $this->assertEquals( 'foo', $data['id'] );
     103                foreach ( array( 'title', 'description', 'priority', 'type' ) as $key ) {
     104                        $this->assertEquals( $args[ $key ], $data[ $key ] );
     105                }
     106                $this->assertEmpty( $data['content'] );
     107                $this->assertTrue( $data['active'] );
     108                $this->assertInternalType( 'int', $data['instanceNumber'] );
     109        }
     110
     111        function test_check_capabilities() {
     112                $user_id = $this->factory->user->create( array( 'role' => 'administrator' ) );
     113                wp_set_current_user( $user_id );
     114
     115                $panel = new WP_Customize_Panel( $this->manager, 'foo' );
     116                $this->assertTrue( $panel->check_capabilities() );
     117                $old_cap = $panel->capability;
     118                $panel->capability = 'do_not_allow';
     119                $this->assertFalse( $panel->check_capabilities() );
     120                $panel->capability = $old_cap;
     121                $this->assertTrue( $panel->check_capabilities() );
     122                $panel->theme_supports = 'impossible_feature';
     123                $this->assertFalse( $panel->check_capabilities() );
     124        }
     125
     126        function test_get_content() {
     127                $panel = new WP_Customize_Panel( $this->manager, 'foo' );
     128                $this->assertEmpty( $panel->get_content() );
     129        }
     130
     131        function test_maybe_render() {
     132                wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
     133                $panel = new WP_Customize_Panel( $this->manager, 'bar' );
     134                $customize_render_panel_count = did_action( 'customize_render_panel' );
     135                add_action( 'customize_render_panel', array( $this, 'action_customize_render_panel_test' ) );
     136                ob_start();
     137                $panel->maybe_render();
     138                $content = ob_get_clean();
     139                $this->assertTrue( $panel->check_capabilities() );
     140                $this->assertEmpty( $content );
     141                $this->assertEquals( $customize_render_panel_count + 1, did_action( 'customize_render_panel' ), 'Unexpected did_action count for customize_render_panel' );
     142                $this->assertEquals( 1, did_action( "customize_render_panel_{$panel->id}" ), "Unexpected did_action count for customize_render_panel_{$panel->id}" );
     143        }
     144
     145        function action_customize_render_panel_test( $panel ) {
     146                $this->assertInstanceOf( 'WP_Customize_Panel', $panel );
     147        }
     148
     149        function test_print_templates_standard() {
     150                wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
     151
     152                $panel = new WP_Customize_Panel( $this->manager, 'baz' );
     153                ob_start();
     154                $panel->print_template();
     155                $content = ob_get_clean();
     156                $this->assertContains( '<script type="text/html" id="tmpl-customize-panel-default-content">', $content );
     157                $this->assertContains( 'accordion-section-title', $content );
     158                $this->assertContains( 'control-panel-content', $content );
     159                $this->assertContains( '<script type="text/html" id="tmpl-customize-panel-default">', $content );
     160                $this->assertContains( 'accordion-section-content', $content );
     161                $this->assertContains( 'preview-notice', $content );
     162        }
     163
     164
     165        function test_print_templates_custom() {
     166                wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
     167
     168                $panel = new Custom_Panel_Test( $this->manager, 'baz' );
     169                ob_start();
     170                $panel->print_template();
     171                $content = ob_get_clean();
     172                $this->assertContains( '<script type="text/html" id="tmpl-customize-panel-titleless-content">', $content );
     173                $this->assertNotContains( 'accordion-section-title', $content );
     174
     175                $this->assertContains( '<script type="text/html" id="tmpl-customize-panel-titleless">', $content );
     176                $this->assertNotContains( 'preview-notice', $content );
     177        }
     178}
     179
     180require_once ABSPATH . WPINC . '/class-wp-customize-panel.php';
     181class Custom_Panel_Test extends WP_Customize_Panel {
     182        public $type = 'titleless';
     183
     184        protected function render_template() {
     185                ?>
     186                <li id="accordion-panel-{{ data.id }}" class="accordion-section control-section control-panel control-panel-{{ data.type }}">
     187                        <ul class="accordion-sub-container control-panel-content"></ul>
     188                </li>
     189                <?php
     190        }
     191
     192        protected function content_template() {
     193                ?>
     194                <li class="panel-meta accordion-section control-section<# if ( ! data.description ) { #> cannot-expand<# } #>">
     195                        <# if ( data.description ) { #>
     196                                <div class="accordion-section-content description">
     197                                        {{{ data.description }}}
     198                                </div>
     199                        <# } #>
     200                </li>
     201                <?php
     202        }
     203
     204}
  • 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 cb8767f..54818d2 100644
    jQuery( window ).load( function (){ 
    109109                equal( section.panel(), 'fixture-panel' );
    110110        } );
    111111
     112        // @todo ensure that custom section type can be instantiated properly from the template
     113
    112114        module( 'Customizer Panel in Fixture' );
    113115        test( 'Fixture panel exists', function () {
    114116                ok( wp.customize.panel.has( 'fixture-panel' ) );
    jQuery( window ).load( function (){ 
    138140                ok( panel.expanded() );
    139141        } );
    140142
     143        // @todo ensure that custom panel type can be instantiated properly from the template
     144
    141145
    142146        module( 'Dynamically-created Customizer Setting Model' );
    143147        settingId = 'new_blogname';