WordPress.org

Make WordPress Core

Changeset 38906


Ignore:
Timestamp:
10/25/2016 06:30:27 AM (3 years ago)
Author:
westonruter
Message:

Customize: Allow page stubs to be created via dropdown-pages controls in the Static Front Page section.

This ability was previously added to nav menus via the available page items panel. The "Add New Page" button only appears when the allow_addition control param is supplied as true. Code is adapted from the Customize Posts feature plugin.

Props celloexpressions, westonruter.
See #38013, #34923.
Fixes #38164.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/customize-controls.css

    r38900 r38906  
    566566
    567567.customize-control select {
    568     min-width: 50%;
    569     max-width: 100%;
     568    width: 100%;
     569    max-width: 300px;
    570570    height: 28px;
    571571    line-height: 28px;
     
    588588    font-style: italic;
    589589    line-height: 18px;
     590    margin-top: 0;
    590591    margin-bottom: 5px;
    591592}
     
    673674    margin: 10px;
    674675    float: left;
     676}
     677
     678#available-menu-items .accordion-section-content .new-content-item,
     679.customize-control-dropdown-pages .new-content-item {
     680    width: -webkit-calc(100% - 30px);
     681    width: calc(100% - 30px);
     682    padding: 8px 15px;
     683    position: absolute;
     684    bottom: 0;
     685    z-index: 10;
     686    background: #eee;
     687    display: -webkit-box;
     688    display: -moz-box;
     689    display: -ms-flexbox;
     690    display: -webkit-flex;
     691    display: flex;
     692}
     693
     694.customize-control-dropdown-pages .new-content-item {
     695    width: 100%;
     696    max-width: 300px;
     697    padding: 5px 0 5px 1px;
     698    position: relative;
     699}
     700
     701#available-menu-items .new-content-item .create-item-input,
     702.customize-control-dropdown-pages .new-content-item .create-item-input {
     703    -webkit-box-flex: 10;
     704    -webkit-flex-grow: 10;
     705    -moz-box-flex: 10;
     706    -ms-flex-positive: 10;
     707    -ms-flex: 10;
     708    flex-grow: 10;
     709}
     710
     711#available-menu-items .new-content-item .add-content,
     712.customize-control-dropdown-pages .new-content-item .add-content {
     713    margin: 2px 0 2px 6px;
     714    -webkit-box-flex: 10;
     715    -webkit-flex-grow: 10;
     716    -moz-box-flex: 10;
     717    -ms-flex-positive: 10;
     718    -ms-flex: 10;
     719    flex-grow: 1;
     720}
     721
     722.customize-control-dropdown-pages .new-content-item .create-item-input.invalid {
     723    border: 1px solid #f00;
    675724}
    676725
  • trunk/src/wp-admin/css/customize-nav-menus.css

    r38853 r38906  
    573573}
    574574
    575 #available-menu-items .accordion-section-content .new-content-item {
    576     width: -webkit-calc(100% - 30px);
    577     width: calc(100% - 30px);
    578     padding: 8px 15px;
    579     position: absolute;
    580     bottom: 0;
    581     z-index: 10;
    582     background: #eee;
    583     display: -webkit-box;
    584     display: -moz-box;
    585     display: -ms-flexbox;
    586     display: -webkit-flex;
    587     display: flex;
    588 }
    589 
    590 #available-menu-items .new-content-item .create-item-input {
    591     -webkit-box-flex: 10;
    592     -webkit-flex-grow: 10;
    593     -moz-box-flex: 10;
    594     -ms-flex-positive: 10;
    595     -ms-flex: 10;
    596     flex-grow: 10;
    597     margin-left: 5px;
    598     padding: 4.5px;
    599 }
    600 #available-menu-items .new-content-item .add-content {
    601     padding-left: 6px;
    602     -webkit-box-flex: 10;
    603     -webkit-flex-grow: 10;
    604     -moz-box-flex: 10;
    605     -ms-flex-positive: 10;
    606     -ms-flex: 10;
    607     flex-grow: 1;
    608 }
    609 
    610575#available-menu-items .menu-item-tpl {
    611576    margin: 0;
  • trunk/src/wp-admin/js/customize-controls.js

    r38901 r38906  
    25172517         * Triggered when the control's markup has been injected into the DOM.
    25182518         *
    2519          * @abstract
    2520          */
    2521         ready: function() {},
     2519         * @returns {void}
     2520         */
     2521        ready: function() {
     2522            var control = this, newItem;
     2523            if ( 'dropdown-pages' === control.params.type && control.params.allow_addition ) {
     2524                newItem = control.container.find( '.new-content-item' );
     2525                newItem.hide(); // Hide in JS to preserve flex display when showing.
     2526                control.container.on( 'click', '.add-new-toggle', function( e ) {
     2527                    $( e.currentTarget ).slideUp( 180 );
     2528                    newItem.slideDown( 180 );
     2529                    newItem.find( '.create-item-input' ).focus();
     2530                });
     2531                control.container.on( 'click', '.add-content', function() {
     2532                    control.addNewPage();
     2533                });
     2534                control.container.on( 'keyup', '.create-item-input', function( e ) {
     2535                    if ( 13 === e.which ) { // Enter
     2536                        control.addNewPage();
     2537                    }
     2538                });
     2539            }
     2540        },
    25222541
    25232542        /**
     
    27372756                }
    27382757            }
     2758        },
     2759
     2760        /**
     2761         * Add a new page to a dropdown-pages control reusing menus code for this.
     2762         *
     2763         * @since 4.7.0
     2764         * @access private
     2765         * @returns {void}
     2766         */
     2767        addNewPage: function () {
     2768            var control = this, promise, toggle, container, input, title, select;
     2769
     2770            if ( 'dropdown-pages' !== control.params.type || ! control.params.allow_addition || ! api.Menus ) {
     2771                return;
     2772            }
     2773
     2774            toggle = control.container.find( '.add-new-toggle' );
     2775            container = control.container.find( '.new-content-item' );
     2776            input = control.container.find( '.create-item-input' );
     2777            title = input.val();
     2778            select = control.container.find( 'select' );
     2779
     2780            if ( ! title ) {
     2781                input.addClass( 'invalid' );
     2782                return;
     2783            }
     2784
     2785            input.removeClass( 'invalid' );
     2786            input.attr( 'disabled', 'disabled' );
     2787
     2788            // The menus functions add the page, publish when appropriate, and also add the new page to the dropdown-pages controls.
     2789            promise = api.Menus.insertAutoDraftPost( {
     2790                post_title: title,
     2791                post_type: 'page'
     2792            } );
     2793            promise.done( function( data ) {
     2794                var availableItem, $content, itemTemplate;
     2795
     2796                // Prepare the new page as an available menu item.
     2797                // See api.Menus.submitNew().
     2798                availableItem = new api.Menus.AvailableItemModel( {
     2799                    'id': 'post-' + data.post_id, // Used for available menu item Backbone models.
     2800                    'title': title,
     2801                    'type': 'page',
     2802                    'type_label': api.Menus.data.l10n.page_label,
     2803                    'object': 'post_type',
     2804                    'object_id': data.post_id,
     2805                    'url': data.url
     2806                } );
     2807
     2808                // Add the new item to the list of available menu items.
     2809                api.Menus.availableMenuItemsPanel.collection.add( availableItem );
     2810                $content = $( '#available-menu-items-post_type-page' ).find( '.available-menu-items-list' );
     2811                itemTemplate = wp.template( 'available-menu-item' );
     2812                $content.prepend( itemTemplate( availableItem.attributes ) );
     2813
     2814                // Focus the select control.
     2815                select.focus();
     2816                control.setting.set( String( data.post_id ) ); // Triggers a preview refresh and updates the setting.
     2817
     2818                // Reset the create page form.
     2819                container.slideUp( 180 );
     2820                toggle.slideDown( 180 );
     2821            } )
     2822            .always( function() {
     2823                input.val( '' ).removeAttr( 'disabled' );
     2824            } );
    27392825        }
    27402826    });
  • trunk/src/wp-admin/js/customize-nav-menus.js

    r38807 r38906  
    102102        request.done( function( response ) {
    103103            if ( response.post_id ) {
    104                 deferred.resolve( response );
    105104                api.Menus.insertedAutoDrafts.push( response.post_id );
    106105                api( 'nav_menus_created_posts' ).set( _.clone( api.Menus.insertedAutoDrafts ) );
     
    122121                    } );
    123122                }
     123                deferred.resolve( response );
    124124            }
    125125        } );
  • trunk/src/wp-includes/class-wp-customize-control.php

    r38624 r38906  
    114114     */
    115115    public $input_attrs = array();
     116
     117    /**
     118     * Show UI for adding new content, currently only used for the dropdown-pages control.
     119     *
     120     * @since 4.7.0
     121     * @access public
     122     * @var array
     123     */
     124    public $allow_addition = false;
    116125
    117126    /**
     
    297306        $this->json['description'] = $this->description;
    298307        $this->json['instanceNumber'] = $this->instance_number;
     308
     309        if ( 'dropdown-pages' === $this->type ) {
     310            $this->json['allow_addition'] = $this->allow_addition;
     311        }
    299312    }
    300313
     
    555568                // Hackily add in the data link parameter.
    556569                $dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown );
     570
     571                // Even more hacikly add auto-draft page stubs.
     572                // @todo Eventually this should be removed in favor of the pages being injected into the underlying get_pages() call. See <https://github.com/xwp/wp-customize-posts/pull/250>.
     573                $nav_menus_created_posts_setting = $this->manager->get_setting( 'nav_menus_created_posts' );
     574                if ( $nav_menus_created_posts_setting && current_user_can( 'publish_pages' ) ) {
     575                    $auto_draft_page_options = '';
     576                    foreach ( $nav_menus_created_posts_setting->value() as $auto_draft_page_id ) {
     577                        $post = get_post( $auto_draft_page_id );
     578                        if ( $post && 'page' === $post->post_type ) {
     579                            $auto_draft_page_options .= sprintf( '<option value="%1$s">%2$s</option>', esc_attr( $post->ID ), esc_html( $post->post_title ) );
     580                        }
     581                    }
     582                    if ( $auto_draft_page_options ) {
     583                        $dropdown = str_replace( '</select>', $auto_draft_page_options . '</select>', $dropdown );
     584                    }
     585                }
     586
    557587                echo $dropdown;
    558588                ?>
    559589                </label>
    560                 <?php
     590                <?php if ( $this->allow_addition && current_user_can( 'publish_pages' ) && current_user_can( 'edit_theme_options' ) ) : // Currently tied to menus functionality. ?>
     591                    <button type="button" class="button add-new-toggle"><?php echo get_post_type_object( 'page' )->labels->add_new_item; ?></button>
     592                    <div class="new-content-item">
     593                        <label for="create-input-<?php echo $this->id; ?>"><span class="screen-reader-text"><?php _e( 'New page title' ); ?></span></label>
     594                        <input type="text" id="create-input-<?php echo $this->id; ?>" class="create-item-input" placeholder="<?php esc_attr_e( 'New page title&hellip;' ); ?>">
     595                        <button type="button" class="button add-content"><?php _e( 'Add' ); ?></button>
     596                    </div>
     597                <?php endif;
    561598                break;
    562599            default:
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r38887 r38906  
    33573357            'section' => 'static_front_page',
    33583358            'type' => 'dropdown-pages',
     3359            'allow_addition' => true,
    33593360        ) );
    33603361
     
    33683369            'section' => 'static_front_page',
    33693370            'type' => 'dropdown-pages',
     3371            'allow_addition' => true,
    33703372        ) );
    33713373
  • trunk/src/wp-includes/class-wp-customize-nav-menus.php

    r38810 r38906  
    371371                'unnamed'           => _x( '(unnamed)', 'Missing menu name.' ),
    372372                'custom_label'      => __( 'Custom Link' ),
     373                'page_label'        => get_post_type_object( 'page' )->labels->singular_name,
    373374                /* translators: %s: menu location */
    374375                'menuLocation'      => _x( '(Currently set to: %s)', 'menu' ),
  • trunk/tests/phpunit/tests/customize/control.php

    r38858 r38906  
    2727    function setUp() {
    2828        parent::setUp();
     29        wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
    2930        require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
    3031        // @codingStandardsIgnoreStart
     
    4041     */
    4142    function test_check_capabilities() {
    42         wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
    4343        do_action( 'customize_register', $this->wp_customize );
    4444        $control = new WP_Customize_Control( $this->wp_customize, 'blogname', array(
     
    7979
    8080    /**
     81     * @ticket 38164
     82     */
     83    function test_dropdown_pages() {
     84        do_action( 'customize_register', $this->wp_customize );
     85
     86        $this->assertInstanceOf( 'WP_Customize_Nav_Menus', $this->wp_customize->nav_menus );
     87        $nav_menus_created_posts_setting = $this->wp_customize->get_setting( 'nav_menus_created_posts' );
     88        $this->assertInstanceOf( 'WP_Customize_Filter_Setting', $nav_menus_created_posts_setting );
     89        $page_on_front_control = $this->wp_customize->get_control( 'page_on_front' );
     90
     91        // Ensure the add-new-toggle is absent if allow_addition param is not set.
     92        $page_on_front_control->allow_addition = false;
     93        ob_start();
     94        $page_on_front_control->maybe_render();
     95        $content = ob_get_clean();
     96        $this->assertNotContains( 'add-new-toggle', $content );
     97
     98        // Ensure the add-new-toggle is absent if allow_addition param is set.
     99        $page_on_front_control->allow_addition = true;
     100        ob_start();
     101        $page_on_front_control->maybe_render();
     102        $content = ob_get_clean();
     103        $this->assertContains( 'add-new-toggle', $content );
     104
     105        // Ensure that dropdown-pages delect is rendered even if there are no pages published (yet).
     106        foreach ( get_pages() as $page ) {
     107            wp_delete_post( $page->ID );
     108        }
     109        $page_on_front_control->allow_addition = true;
     110        ob_start();
     111        $page_on_front_control->maybe_render();
     112        $content = ob_get_clean();
     113        $this->assertContains( '<option value="0">', $content, 'Dropdown-pages renders select even without any pages published.' );
     114
     115        // Ensure that auto-draft pages are included if they are among the nav_menus_created_posts.
     116        $auto_draft_page_id = $this->factory()->post->create( array(
     117            'post_type' => 'page',
     118            'post_status' => 'auto-draft',
     119            'post_title' => 'Auto Draft Page',
     120        ) );
     121        $this->factory()->post->create( array(
     122            'post_type' => 'page',
     123            'post_status' => 'auto-draft',
     124            'post_title' => 'Orphan Auto Draft Page',
     125        ) );
     126        $auto_draft_post_id = $this->factory()->post->create( array(
     127            'post_type' => 'post',
     128            'post_status' => 'auto-draft',
     129            'post_title' => 'Auto Draft Post',
     130        ) );
     131        $this->wp_customize->set_post_value( $nav_menus_created_posts_setting->id, array( $auto_draft_page_id, $auto_draft_post_id ) );
     132        $nav_menus_created_posts_setting->preview();
     133        ob_start();
     134        $page_on_front_control->maybe_render();
     135        $content = ob_get_clean();
     136        $this->assertContains( sprintf( '<option value="%d">Auto Draft Page</option>', $auto_draft_page_id ), $content );
     137        $this->assertNotContains( 'Auto Draft Post', $content );
     138        $this->assertNotContains( 'Orphan Auto Draft Page', $content );
     139    }
     140
     141    /**
    81142     * Tear down.
    82143     */
Note: See TracChangeset for help on using the changeset viewer.