Make WordPress Core

Changeset 38436

Timestamp:
08/29/2016 10:58:32 PM (8 years ago)
Author:
westonruter
Message:

Customize: Allow users to more seamlessly create page-based nav menus during customization.

Introduces the ability to create stubs for the various post types to add to a given menu. This eliminates the need to leave the customizer to first create the post in the admin and then return to managing menus. Only the title of the newly-created post can be supplied; the post content will be blank and will need to be provided in the normal edit post screen outside the customizer, unless a plugin enables a post editing in the customizer experience. When a post is created and added to a nav menu in the customizer, the newly created post that is added to a menu is given the auto-draft status, and if the changes are not published, the auto-draft post will be automatically deleted within 7 days via wp_delete_auto_drafts(). However, if the customizer changes are saved, then these nav menu item auto-draft post stubs will be transitioned to publish.

Includes portions of code from the Customize Posts <https://github.com/xwp/wp-customize-posts> and Front-end Editor <https://github.com/iseulde/wp-front-end-editor> plugins.

For more information, see https://make.wordpress.org/core/2016/06/16/feature-proposal-content-authorship-in-menus-with-live-preview/

Props celloexpressions, westonruter, valendesigns, afercia, melchoyce, mapk, iseulde, mrahmadawais.
Fixes #34923.

Location:
trunk
Files:
7 edited

Legend:

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

    r38152 r38436  
    12201220
    12211221.add-new-widget:before,
    1222 .add-new-menu-item:before {
     1222.add-new-menu-item:before,
     1223#available-menu-items .new-content-item .add-content:before {
    12231224    content: "\f132";
    12241225    display: inline-block;
  • trunk/src/wp-admin/css/customize-nav-menus.css

    r38207 r38436  
    6060    float: right;
    6161    text-align: right;
     62
     63
     64
     65
    6266}
    6367
     
    498502}
    499503
    500 #available-menu-items .accordion-section-content {
     504#available-menu-items .at {
    501505    overflow-y: auto;
    502506    max-height: 200px; /* This gets set in JS to fit the screen size, and based on # of sections. */
     
    535539
    536540#available-menu-items .accordion-section-content {
     541
     542
     543
     544
     545
     546
     547
     548
     549
    537550    padding: 1px 15px 15px 15px;
    538     margin: 0;
    539     max-height: 290px;
     551}
     552
     553#available-menu-items .accordion-section-content .available-menu-items-list:only-child { /* Types that do not support new items for the current user */
     554    margin-bottom: 0;
     555}
     556
     557#new-custom-menu-item .accordion-section-content {
     558    padding: 0 15px 15px 15px;
     559}
     560
     561#available-menu-items .accordion-section-content .new-content-item {
     562    width: calc(100% - 30px);
     563    padding: 8px 15px;
     564    position: absolute;
     565    bottom: 0;
     566    z-index: 10;
     567    background: #eee;
     568    display: -webkit-box;
     569    display: -moz-box;
     570    display: -ms-flexbox;
     571    display: -webkit-flex;
     572    display: flex;
     573}
     574
     575#available-menu-items .new-content-item .create-item-input {
     576    -webkit-box-flex: 10;
     577    -webkit-flex-grow: 10;
     578    -moz-box-flex: 10;
     579    -ms-flex-positive: 10;
     580    -ms-flex: 10;
     581    flex-grow: 10;
     582    margin-left: 5px;
     583    padding: 4.5px;
     584}
     585#available-menu-items .new-content-item .add-content {
     586    padding-left: 6px;
     587    -webkit-box-flex: 10;
     588    -webkit-flex-grow: 10;
     589    -moz-box-flex: 10;
     590    -ms-flex-positive: 10;
     591    -ms-flex: 10;
     592    flex-grow: 1;
    540593}
    541594
     
    547600#custom-menu-item-url.invalid,
    548601.menu-name-field.invalid,
    549 .menu-name-field.invalid:focus {
     602.menu-name-field.invalid:focus,
     603#available-menu-items .new-content-item .create-item-input.invalid,
     604#available-menu-items .new-content-item .create-item-input.invalid:focus {
    550605    border: 1px solid #f00;
    551606}
  • trunk/src/wp-admin/js/customize-nav-menus.js

    r38301 r38436  
    8181    api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems );
    8282
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
    83124    /**
    84125     * wp.customize.Menus.AvailableMenuItemsPanelView
     
    101142            'click #custom-menu-item-submit': '_submitLink',
    102143            'keypress #custom-menu-item-name': '_submitLink',
     144
     145
    103146            'keydown': 'keyboardAccessible'
    104147        },
     
    116159        sectionContent: '',
    117160        loading: false,
     161
    118162
    119163        initialize: function() {
     
    125169
    126170            this.$search = $( '#menu-items-search' );
    127             this.sectionContent = this.$el.find( '.accordion-section-content' );
     171            this.sectionContent = this.$el.find( '.at' );
    128172
    129173            this.debounceSearch = _.debounce( self.search, 500 );
     
    161205            // Load more items.
    162206            this.sectionContent.scroll( function() {
    163                 var totalHeight = self.$el.find( '.accordion-section.open .accordion-section-content' ).prop( 'scrollHeight' ),
     207                var totalHeight = self.$el.find( '.accordion-section.open .at' ).prop( 'scrollHeight' ),
    164208                    visibleHeight = self.$el.find( '.accordion-section.open' ).height();
    165209
     
    338382                items = new api.Menus.AvailableItemCollection( items ); // @todo Why is this collection created and then thrown away?
    339383                self.collection.add( items.models );
    340                 typeInner = availableMenuItemContainer.find( '.accordion-section-content' );
     384                typeInner = availableMenuItemContainer.find( '.at' );
    341385                items.each(function( menuItem ) {
    342386                    typeInner.append( itemTemplate( menuItem.attributes ) );
     
    357401        // Adjust the height of each section of items to fit the screen.
    358402        itemSectionHeight: function() {
    359             var sections, totalHeight, accordionHeight, diff;
     403            var sections, totalHeight, accordionHeight, diff;
    360404            totalHeight = window.innerHeight;
    361405            sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' );
    362             accordionHeight =  46 * ( 2 + sections.length ) - 13; // Magic numbers.
     406            lists = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")' );
     407            accordionHeight =  46 * ( 1 + sections.length ) + 14; // Magic numbers.
    363408            diff = totalHeight - accordionHeight;
    364409            if ( 120 < diff && 290 > diff ) {
    365410                sections.css( 'max-height', diff );
     411
    366412            }
    367413        },
     
    455501            itemUrl.val( 'http://' );
    456502            itemName.val( '' );
     503
     504
     505
     506
     507
     508
     509
     510
     511
     512
     513
     514
     515
     516
     517
     518
     519
     520
     521
     522
     523
     524
     525
     526
     527
     528
     529
     530
     531
     532
     533
     534
     535
     536
     537
     538
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
     550
     551
     552
     553
     554
     555
     556
     557
     558
     559
     560
     561
     562
     563
     564
     565
     566
     567
     568
     569
     570
     571
     572
     573
     574
     575
     576
     577
     578
     579
     580
     581
     582
     583
     584
    457585        },
    458586
     
    25462674                api.Menus.applySavedData( data );
    25472675            }
     2676
     2677
     2678
    25482679        } );
    25492680
  • trunk/src/wp-includes/class-wp-customize-nav-menus.php

    r37900 r38436  
    5757        add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) );
    5858        add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) );
     59
    5960        add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    60 
    61         // Needs to run after core Navigation section is set up.
    6261        add_action( 'customize_register', array( $this, 'customize_register' ), 11 );
    63 
    6462        add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_dynamic_setting_args' ), 10, 2 );
    6563        add_filter( 'customize_dynamic_setting_class', array( $this, 'filter_dynamic_setting_class' ), 10, 3 );
     
    6765        add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) );
    6866        add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
     67
     68
    6969
    7070        // Selective Refresh partials.
     
    627627            'settings' => array(),
    628628        ) ) );
     629
     630
     631
     632
     633
     634
    629635    }
    630636
     
    649655     *
    650656     * @since 4.3.0
     657
    651658     * @access public
    652659     *
     
    661668                $item_types[] = array(
    662669                    'title'  => $post_type->labels->name,
    663                     'type'   => 'post_type',
     670                    'type_label' => $post_type->labels->singular_name,
     671                    'type' => 'post_type',
    664672                    'object' => $post_type->name,
    665673                );
     
    674682                }
    675683                $item_types[] = array(
    676                     'title'  => $taxonomy->labels->name,
    677                     'type'   => 'taxonomy',
     684                    'title' => $taxonomy->labels->name,
     685                    'type_label' => $taxonomy->labels->singular_name,
     686                    'type' => 'taxonomy',
    678687                    'object' => $taxonomy->name,
    679688                );
     
    685694         *
    686695         * @since 4.3.0
     696
    687697         *
    688698         * @param array $item_types Custom menu item types.
     
    691701
    692702        return $item_types;
     703
     704
     705
     706
     707
     708
     709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
     720
     721
     722
     723
     724
     725
     726
     727
     728
     729
     730
     731
     732
     733
     734
     735
     736
     737
     738
     739
     740
     741
     742
     743
     744
     745
     746
     747
     748
     749
     750
     751
     752
     753
     754
     755
     756
     757
     758
     759
     760
     761
     762
     763
     764
     765
     766
     767
     768
     769
     770
     771
     772
     773
     774
     775
     776
     777
     778
     779
     780
     781
     782
     783
     784
     785
     786
     787
     788
     789
     790
     791
     792
     793
     794
     795
     796
     797
     798
     799
     800
     801
     802
     803
     804
     805
     806
     807
     808
     809
     810
     811
     812
     813
     814
     815
    693816    }
    694817
     
    769892                </div>
    770893                <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button>
    771                 <ul class="accordion-section-content" data-type="search"></ul>
     894                <ul class="accordion-section-content" data-type="search"></ul>
    772895            </div>
    773896            <div id="new-custom-menu-item" class="accordion-section">
     
    798921            </div>
    799922            <?php
    800             // Containers for per-post-type item browsing; items added with JS.
     923
     924            // Containers for per-post-type item browsing; items are added with JS.
    801925            foreach ( $this->available_item_types() as $available_item_type ) {
    802926                $id = sprintf( 'available-menu-items-%s-%s', $available_item_type['type'], $available_item_type['object'] );
     
    814938                        </button>
    815939                    </h4>
    816                     <ul class="accordion-section-content" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>"></ul>
     940                    <div class="accordion-section-content">
     941                        <?php if ( 'post_type' === $available_item_type['type'] ) : ?>
     942                            <?php $post_type_obj = get_post_type_object( $available_item_type['object'] ); ?>
     943                            <?php if ( current_user_can( $post_type_obj->cap->create_posts ) && current_user_can( $post_type_obj->cap->publish_posts ) ) : ?>
     944                                <div class="new-content-item">
     945                                    <input type="text" class="create-item-input" placeholder="<?php
     946                                    /* translators: %s: Singular title of post type or taxonomy */
     947                                    printf( __( 'Create New %s' ), $post_type_obj->labels->singular_name ); ?>">
     948                                    <button type="button" class="button add-content"><?php _e( 'Add' ); ?></button>
     949                                </div>
     950                            <?php endif; ?>
     951                        <?php endif; ?>
     952                        <ul class="available-menu-items-list" data-type="<?php echo esc_attr( $available_item_type['type'] ); ?>" data-object="<?php echo esc_attr( $available_item_type['object'] ); ?>" data-type_label="<?php echo esc_attr( isset( $available_item_type['type_label'] ) ? $available_item_type['type_label'] : $available_item_type['type'] ); ?>"></ul>
     953                    </div>
    817954                </div>
    818955                <?php
     
    8791016        add_filter( 'wp_footer', array( $this, 'export_preview_data' ), 1 );
    8801017        add_filter( 'customize_render_partials_response', array( $this, 'export_partial_rendered_nav_menu_instances' ) );
     1018
     1019
     1020
     1021
     1022
     1023
     1024
     1025
     1026
     1027
     1028
     1029
     1030
     1031
     1032
     1033
     1034
     1035
     1036
     1037
     1038
     1039
     1040
     1041
     1042
     1043
     1044
     1045
     1046
     1047
     1048
     1049
     1050
     1051
     1052
     1053
     1054
     1055
     1056
     1057
     1058
     1059
     1060
     1061
     1062
     1063
     1064
     1065
     1066
     1067
     1068
     1069
     1070
     1071
     1072
     1073
     1074
     1075
     1076
     1077
     1078
     1079
     1080
     1081
    8811082    }
    8821083
  • trunk/src/wp-includes/class-wp-customize-setting.php

    r38411 r38436  
    499499     * Fetch and sanitize the $_POST value for the setting.
    500500     *
     501
     502
    501503     * @since 3.4.0
    502504     *
  • trunk/tests/phpunit/tests/ajax/CustomizeMenus.php

    r35244 r38436  
    527527        );
    528528    }
     529
     530
     531
     532
     533
     534
     535
     536
     537
     538
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
     550
     551
     552
     553
     554
     555
     556
     557
     558
     559
     560
     561
     562
     563
     564
     565
     566
     567
     568
     569
     570
     571
     572
     573
     574
     575
     576
     577
     578
     579
     580
     581
     582
     583
     584
     585
     586
     587
     588
     589
     590
     591
     592
     593
     594
     595
     596
     597
     598
     599
     600
     601
     602
     603
     604
     605
     606
     607
     608
     609
     610
     611
     612
     613
     614
     615
     616
     617
     618
     619
     620
     621
     622
     623
     624
     625
     626
     627
     628
     629
     630
     631
     632
     633
     634
     635
     636
     637
     638
    529639}
  • trunk/tests/phpunit/tests/customize/nav-menus.php

    r36889 r38436  
    4646    function filter_item_types( $items ) {
    4747        $items[] = array(
    48             'title'  => 'Custom',
    49             'type'   => 'custom_type',
     48            'title' => 'Custom',
     49            'type' => 'custom_type',
    5050            'object' => 'custom_object',
     51
    5152        );
    5253
     
    8586        $menus = new WP_Customize_Nav_Menus( $this->wp_customize );
    8687        $this->assertInstanceOf( 'WP_Customize_Manager', $menus->manager );
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
     100
     101
     102
    87103    }
    88104
     
    445461            'menu-item-status'    => 'publish',
    446462        ) );
    447         $setting = new WP_Customize_Nav_Menu_Item_Setting( $this->wp_customize, "nav_menu_item[$item_id]" );
    448         do_action( 'customize_register', $this->wp_customize );
     463        );
     464        );
    449465        $this->assertEquals( 'Primary', $this->wp_customize->get_section( "nav_menu[$menu_id]" )->title );
    450466        $this->assertEquals( 'Hello World', $this->wp_customize->get_control( "nav_menu_item[$item_id]" )->label );
     467
     468
     469
     470
     471
     472
    451473    }
    452474
     
    480502
    481503        $expected = array(
    482             array( 'title' => 'Posts', 'type' => 'post_type', 'object' => 'post' ),
    483             array( 'title' => 'Pages', 'type' => 'post_type', 'object' => 'page' ),
    484             array( 'title' => 'Categories', 'type' => 'taxonomy', 'object' => 'category' ),
    485             array( 'title' => 'Tags', 'type' => 'taxonomy', 'object' => 'post_tag' ),
     504            array( 'title' => 'Posts', 'type' => 'post_type', 'object' => 'post' ),
     505            array( 'title' => 'Pages', 'type' => 'post_type', 'object' => 'page' ),
     506            array( 'title' => 'Categories', 'type' => 'taxonomy', 'object' => 'category' ),
     507            array( 'title' => 'Tags', 'type' => 'taxonomy', 'object' => 'post_tag' ),
    486508        );
    487509
    488510        if ( current_theme_supports( 'post-formats' ) ) {
    489             $expected[] = array( 'title' => 'Format', 'type' => 'taxonomy', 'object' => 'post_format' );
     511            $expected[] = array( 'title' => 'Format', 'type' => 'taxonomy', 'object' => 'post_format' );
    490512        }
    491513
     
    493515
    494516        register_taxonomy( 'wptests_tax', array( 'post' ), array( 'labels' => array( 'name' => 'Foo' ) ) );
    495         $expected[] = array( 'title' => 'Foo', 'type' => 'taxonomy', 'object' => 'wptests_tax' );
     517        $expected[] = array( 'title' => 'Foo', 'type' => 'taxonomy', 'object' => 'wptests_tax' );
    496518
    497519        $this->assertEquals( $expected, $menus->available_item_types() );
    498520
    499         $expected[] = array( 'title' => 'Custom', 'type' => 'custom_type', 'object' => 'custom_object' );
     521        $expected[] = array( 'title' => 'Custom', 'type' => 'custom_type', 'object' => 'custom_object' );
    500522
    501523        add_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
     
    503525        remove_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
    504526
     527
     528
     529
     530
     531
     532
     533
     534
     535
     536
     537
     538
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
    505550    }
    506551
     
    554599                $this->assertContains( 'data-type="post_type"', $template );
    555600                $this->assertContains( 'data-object="' . esc_attr( $type->name ) . '"', $template );
     601
    556602            }
    557603        }
     
    564610                $this->assertContains( 'data-type="taxonomy"', $template );
    565611                $this->assertContains( 'data-object="' . esc_attr( $tax->name ) . '"', $template );
     612
    566613            }
    567614        }
     
    571618        $this->assertContains( 'data-type="custom_type"', $template );
    572619        $this->assertContains( 'data-object="custom_object"', $template );
     620
    573621    }
    574622
     
    608656        $this->assertEquals( 1000, has_filter( 'wp_nav_menu_args', array( $menus, 'filter_wp_nav_menu_args' ) ) );
    609657        $this->assertEquals( 10, has_filter( 'wp_nav_menu', array( $menus, 'filter_wp_nav_menu' ) ) );
     658
     659
     660
     661
     662
     663
     664
     665
     666
     667
     668
     669
     670
     671
     672
     673
     674
     675
     676
     677
     678
     679
     680
     681
     682
     683
     684
     685
     686
     687
     688
     689
     690
     691
     692
     693
     694
     695
     696
     697
     698
     699
     700
     701
     702
     703
     704
     705
     706
     707
     708
     709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
     720
     721
     722
     723
     724
     725
     726
     727
     728
     729
     730
     731
     732
     733
     734
     735
     736
     737
     738
     739
     740
     741
     742
     743
     744
     745
     746
     747
     748
     749
     750
     751
     752
    610753    }
    611754
Note: See TracChangeset for help on using the changeset viewer.