Make WordPress Core

Changeset 38523


Ignore:
Timestamp:
09/06/2016 09:05:45 AM (8 years ago)
Author:
peterwilsoncc
Message:

Menus: Add white space option to wp_nav_menu() and wp_list_pages().

Adds an item_spacing option to the arguments array for the functions wp_nav_menu(), wp_list_pages(), and wp_page_menu(). item_spacing is a boolean accepting either preserve or discard.

Previously, certain CSS choices could result in a site's layout changing if wp_nav_menu() fell back to the default wp_list_pages() due to differences in the whitespace within the HTML. The new argument ensures a function outputs consistant HTML while maintaining backward compatibility.

Fixes #35206.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-walker-nav-menu.php

    r37640 r38523  
    5151     */
    5252    public function start_lvl( &$output, $depth = 0, $args = array() ) {
    53         $indent = str_repeat("\t", $depth);
    54         $output .= "\n$indent<ul class=\"sub-menu\">\n";
     53        if ( 'preserve' === $args->item_spacing ) {
     54            $t = "\t";
     55            $n = "\n";
     56        } else {
     57            $t = '';
     58            $n = '';
     59        }
     60        $indent = str_repeat( $t, $depth );
     61        $output .= "{$n}{$indent}<ul class=\"sub-menu\">{$n}";
    5562    }
    5663
     
    6774     */
    6875    public function end_lvl( &$output, $depth = 0, $args = array() ) {
    69         $indent = str_repeat("\t", $depth);
    70         $output .= "$indent</ul>\n";
     76        if ( 'preserve' === $args->item_spacing ) {
     77            $t = "\t";
     78            $n = "\n";
     79        } else {
     80            $t = '';
     81            $n = '';
     82        }
     83        $indent = str_repeat( $t, $depth );
     84        $output .= "$indent</ul>{$n}";
    7185    }
    7286
     
    86100     */
    87101    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    88         $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
     102        if ( 'preserve' === $args->item_spacing ) {
     103            $t = "\t";
     104            $n = "\n";
     105        } else {
     106            $t = '';
     107            $n = '';
     108        }
     109        $indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
    89110
    90111        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
     
    217238     */
    218239    public function end_el( &$output, $item, $depth = 0, $args = array() ) {
    219         $output .= "</li>\n";
     240        if ( 'preserve' === $args->item_spacing ) {
     241            $t = "\t";
     242            $n = "\n";
     243        } else {
     244            $t = '';
     245            $n = '';
     246        }
     247        $output .= "</li>{$n}";
    220248    }
    221249
  • trunk/src/wp-includes/class-walker-page.php

    r37518 r38523  
    5454     */
    5555    public function start_lvl( &$output, $depth = 0, $args = array() ) {
    56         $indent = str_repeat("\t", $depth);
    57         $output .= "\n$indent<ul class='children'>\n";
     56        if ( 'preserve' === $args['item_spacing'] ) {
     57            $t = "\t";
     58            $n = "\n";
     59        } else {
     60            $t = '';
     61            $n = '';
     62        }
     63        $indent = str_repeat( $t, $depth );
     64        $output .= "{$n}{$indent}<ul class='children'>{$n}";
    5865    }
    5966
     
    7279     */
    7380    public function end_lvl( &$output, $depth = 0, $args = array() ) {
    74         $indent = str_repeat("\t", $depth);
    75         $output .= "$indent</ul>\n";
     81        if ( 'preserve' === $args['item_spacing'] ) {
     82            $t = "\t";
     83            $n = "\n";
     84        } else {
     85            $t = '';
     86            $n = '';
     87        }
     88        $indent = str_repeat( $t, $depth );
     89        $output .= "{$indent}</ul>{$n}";
    7690    }
    7791
     
    90104     */
    91105    public function start_el( &$output, $page, $depth = 0, $args = array(), $current_page = 0 ) {
     106        if ( 'preserve' === $args['item_spacing'] ) {
     107            $t = "\t";
     108            $n = "\n";
     109        } else {
     110            $t = '';
     111            $n = '';
     112        }
    92113        if ( $depth ) {
    93             $indent = str_repeat( "\t", $depth );
     114            $indent = str_repeat( $t, $depth );
    94115        } else {
    95116            $indent = '';
     
    176197     */
    177198    public function end_el( &$output, $page, $depth = 0, $args = array() ) {
    178         $output .= "</li>\n";
     199        if ( 'preserve' === $args['item_spacing'] ) {
     200            $t = "\t";
     201            $n = "\n";
     202        } else {
     203            $t = '';
     204            $n = '';
     205        }
     206        $output .= "</li>{$n}";
    179207    }
    180208
  • trunk/src/wp-includes/nav-menu-template.php

    r38470 r38523  
    4141 *     @type string             $items_wrap      How the list items should be wrapped. Default is a ul with an id and class.
    4242 *                                               Uses printf() format with numbered placeholders.
     43 *     @type string             $item_spacing    Whether whitespace format the menu's HTML: 'discard' or 'preserve' (default).
    4344 * }
    4445 * @return object|false|void Menu output if $echo is false, false if there are no items or no menu was found.
     
    4849
    4950    $defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
    50     'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
     51    'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'item_spacing' => 'preserve',
    5152    'depth' => 0, 'walker' => '', 'theme_location' => '' );
    5253
    5354    $args = wp_parse_args( $args, $defaults );
     55
     56    if ( ! in_array( $args['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
     57        // invalid value, fall back to default.
     58        $args['item_spacing'] = $defaults['item_spacing'];
     59    }
     60
    5461    /**
    5562     * Filters the arguments used to display a navigation menu.
  • trunk/src/wp-includes/post-template.php

    r38371 r38523  
    11391139 *     @type string $title_li     List heading. Passing a null or empty value will result in no heading, and the list
    11401140 *                                will not be wrapped with unordered list `<ul>` tags. Default 'Pages'.
     1141 *     @type string $item_spacing Whether whitespace format the menu's HTML: 'discard' or 'preserve' (default).
    11411142 *     @type Walker $walker       Walker instance to use for listing pages. Default empty (Walker_Page).
    11421143 * }
     
    11501151        'title_li' => __( 'Pages' ), 'echo' => 1,
    11511152        'authors' => '', 'sort_column' => 'menu_order, post_title',
    1152         'link_before' => '', 'link_after' => '', 'walker' => '',
     1153        'link_before' => '', 'link_after' => '', 'item_spacing' => 'preserve', 'walker' => '',
    11531154    );
    11541155
    11551156    $r = wp_parse_args( $args, $defaults );
     1157
     1158    if ( ! in_array( $r['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
     1159        // invalid value, fall back to default.
     1160        $r['item_spacing'] = $defaults['item_spacing'];
     1161    }
    11561162
    11571163    $output = '';
     
    12311237 *     Optional. Arguments to generate a page menu. See wp_list_pages() for additional arguments.
    12321238 *
    1233  *     @type string          $sort_column How to short the list of pages. Accepts post column names.
    1234  *                                        Default 'menu_order, post_title'.
    1235  *     @type string          $menu_id     ID for the div containing the page list. Default is empty string.
    1236  *     @type string          $menu_class  Class to use for the element containing the page list. Default 'menu'.
    1237  *     @type string          $container   Element to use for the element containing the page list. Default 'div'.
    1238  *     @type bool            $echo        Whether to echo the list or return it. Accepts true (echo) or false (return).
    1239  *                                        Default true.
    1240  *     @type int|bool|string $show_home   Whether to display the link to the home page. Can just enter the text
    1241  *                                        you'd like shown for the home link. 1|true defaults to 'Home'.
    1242  *     @type string          $link_before The HTML or text to prepend to $show_home text. Default empty.
    1243  *     @type string          $link_after  The HTML or text to append to $show_home text. Default empty.
    1244  *     @type string          $before      The HTML or text to prepend to the menu. Default is '<ul>'.
    1245  *     @type string          $after       The HTML or text to append to the menu. Default is '</ul>'.
    1246  *     @type Walker          $walker      Walker instance to use for listing pages. Default empty (Walker_Page).
     1239 *     @type string          $sort_column  How to short the list of pages. Accepts post column names.
     1240 *                                         Default 'menu_order, post_title'.
     1241 *     @type string          $menu_id      ID for the div containing the page list. Default is empty string.
     1242 *     @type string          $menu_class   Class to use for the element containing the page list. Default 'menu'.
     1243 *     @type string          $container    Element to use for the element containing the page list. Default 'div'.
     1244 *     @type bool            $echo         Whether to echo the list or return it. Accepts true (echo) or false (return).
     1245 *                                         Default true.
     1246 *     @type int|bool|string $show_home    Whether to display the link to the home page. Can just enter the text
     1247 *                                         you'd like shown for the home link. 1|true defaults to 'Home'.
     1248 *     @type string          $link_before  The HTML or text to prepend to $show_home text. Default empty.
     1249 *     @type string          $link_after   The HTML or text to append to $show_home text. Default empty.
     1250 *     @type string          $before       The HTML or text to prepend to the menu. Default is '<ul>'.
     1251 *     @type string          $after        The HTML or text to append to the menu. Default is '</ul>'.
     1252 *     @type string          $item_spacing Whether whitespace format the menu's HTML: 'discard' or 'preserve' (default).
     1253 *     @type Walker          $walker       Walker instance to use for listing pages. Default empty (Walker_Page).
    12471254 * }
    12481255 * @return string|void HTML menu
     
    12501257function wp_page_menu( $args = array() ) {
    12511258    $defaults = array(
    1252         'sort_column' => 'menu_order, post_title',
    1253         'menu_id'     => '',
    1254         'menu_class'  => 'menu',
    1255         'container'   => 'div',
    1256         'echo'        => true,
    1257         'link_before' => '',
    1258         'link_after'  => '',
    1259         'before'      => '<ul>',
    1260         'after'       => '</ul>',
    1261         'walker'      => '',
     1259        'sort_column'  => 'menu_order, post_title',
     1260        'menu_id'      => '',
     1261        'menu_class'   => 'menu',
     1262        'container'    => 'div',
     1263        'echo'         => true,
     1264        'link_before'  => '',
     1265        'link_after'   => '',
     1266        'before'       => '<ul>',
     1267        'after'        => '</ul>',
     1268        'item_spacing' => 'discard',
     1269        'walker'       => '',
    12621270    );
    12631271    $args = wp_parse_args( $args, $defaults );
     1272
     1273    if ( ! in_array( $args['item_spacing'], array( 'preserve', 'discard' ) ) ) {
     1274        // invalid value, fall back to default.
     1275        $args['item_spacing'] = $defaults['item_spacing'];
     1276    }
     1277
     1278    if ( 'preserve' === $args['item_spacing'] ) {
     1279        $t = "\t";
     1280        $n = "\n";
     1281    } else {
     1282        $t = '';
     1283        $n = '';
     1284    }
    12641285
    12651286    /**
     
    13011322    $list_args['echo'] = false;
    13021323    $list_args['title_li'] = '';
    1303     $menu .= str_replace( array( "\r", "\n", "\t" ), '', wp_list_pages($list_args) );
     1324    $menu .= wp_list_pages( $list_args );
    13041325
    13051326    $container = sanitize_text_field( $args['container'] );
     
    13161337            'wp_page_menu' === $args['fallback_cb'] &&
    13171338            'ul' !== $container ) {
    1318             $args['before'] = '<ul>';
     1339            $args['before'] = "<ul>{$n}";
    13191340            $args['after'] = '</ul>';
    13201341        }
     
    13321353    }
    13331354
    1334     $menu = "<{$container}{$attrs}>" . $menu . "</{$container}>\n";
     1355    $menu = "<{$container}{$attrs}>" . $menu . "</{$container}>{$n}";
    13351356
    13361357    /**
  • trunk/tests/phpunit/tests/post/listPages.php

    r35242 r38523  
    1818        'link_after' => '',
    1919        'walker' => '',
     20        'item_spacing' => 'preserve',
    2021        'include'      => '',
    2122        'post_type'    => 'page',
     
    343344        $this->AssertEquals( $expected['exclude'], $actual );
    344345    }
     346
     347    function test_wp_list_pages_discarded_whitespace() {
     348        $args = array(
     349            'echo' => false,
     350            'item_spacing' => 'discard',
     351        );
     352        $expected['default'] = '<li class="pagenav">Pages<ul><li class="page_item page-item-1 page_item_has_children"><a href="' . get_permalink( 1 ) . '">Parent 1</a><ul class=\'children\'><li class="page_item page-item-4"><a href="' . get_permalink( 4 ) . '">Child 1</a></li><li class="page_item page-item-5"><a href="' . get_permalink( 5 ) . '">Child 2</a></li><li class="page_item page-item-6"><a href="' . get_permalink( 6 ) . '">Child 3</a></li></ul></li><li class="page_item page-item-2 page_item_has_children"><a href="' . get_permalink( 2 ) . '">Parent 2</a><ul class=\'children\'><li class="page_item page-item-7"><a href="' . get_permalink( 7 ) . '">Child 1</a></li><li class="page_item page-item-8"><a href="' . get_permalink( 8 ) . '">Child 2</a></li><li class="page_item page-item-9"><a href="' . get_permalink( 9 ) . '">Child 3</a></li></ul></li><li class="page_item page-item-3 page_item_has_children"><a href="' . get_permalink( 3 ) . '">Parent 3</a><ul class=\'children\'><li class="page_item page-item-10"><a href="' . get_permalink( 10 ) . '">Child 1</a></li><li class="page_item page-item-11"><a href="' . get_permalink( 11 ) . '">Child 2</a></li><li class="page_item page-item-12"><a href="' . get_permalink( 12 ) . '">Child 3</a></li></ul></li></ul></li>';
     353        $actual = wp_list_pages( $args );
     354        $this->AssertEquals( $expected['default'], $actual );
     355    }
    345356}
  • trunk/tests/phpunit/tests/post/nav-menu.php

    r38400 r38523  
    278278
    279279    /**
     280     * @ticket 35206
     281     */
     282    function test_wp_nav_menu_whitespace_options() {
     283        $post_id1 = self::factory()->post->create();
     284        $post_id2 = self::factory()->post->create();
     285        $post_id3 = self::factory()->post->create();
     286        $post_id4 = self::factory()->post->create();
     287
     288        $post_insert = wp_update_nav_menu_item( $this->menu_id, 0, array(
     289            'menu-item-type' => 'post_type',
     290            'menu-item-object' => 'post',
     291            'menu-item-object-id' => $post_id1,
     292            'menu-item-status' => 'publish'
     293        ) );
     294
     295        $post_inser2 = wp_update_nav_menu_item( $this->menu_id, 0, array(
     296            'menu-item-type' => 'post_type',
     297            'menu-item-object' => 'post',
     298            'menu-item-object-id' => $post_id2,
     299            'menu-item-status' => 'publish'
     300        ) );
     301
     302        $post_insert3 = wp_update_nav_menu_item( $this->menu_id, 0, array(
     303            'menu-item-type' => 'post_type',
     304            'menu-item-object' => 'post',
     305            'menu-item-parent-id' => $post_insert,
     306            'menu-item-object-id' => $post_id3,
     307            'menu-item-status' => 'publish'
     308        ) );
     309
     310        $post_insert4 = wp_update_nav_menu_item( $this->menu_id, 0, array(
     311            'menu-item-type' => 'post_type',
     312            'menu-item-object' => 'post',
     313            'menu-item-parent-id' => $post_insert,
     314            'menu-item-object-id' => $post_id4,
     315            'menu-item-status' => 'publish'
     316        ) );
     317
     318        // No whitespace suppression.
     319        $menu = wp_nav_menu( array(
     320            'echo' => false,
     321            'menu' => $this->menu_id,
     322        ) );
     323
     324        // The markup should include whitespace between <li>s
     325        $this->assertRegExp( '/\s<li.*>|<\/li>\s/U', $menu );
     326        $this->assertNotRegExp( '/<\/li><li.*>/U', $menu );
     327
     328
     329        // Whitepsace suppressed.
     330        $menu = wp_nav_menu( array(
     331            'echo'         => false,
     332            'item_spacing' => 'discard',
     333            'menu'         => $this->menu_id,
     334        ) );
     335
     336        // The markup should not include whitespace around <li>s
     337        $this->assertNotRegExp( '/\s<li.*>|<\/li>\s/U', $menu );
     338        $this->assertRegExp( '/><li.*>|<\/li></U', $menu );
     339    }
     340
     341    /*
    280342     * Confirm `wp_nav_menu()` and `Walker_Nav_Menu` passes an $args object to filters.
    281343     *
  • trunk/tests/phpunit/tests/post/template.php

    r35242 r38523  
    300300        $this->assertRegExp( '/<\/ul><\/div>/', $menu );
    301301
     302        // After falling back, the markup should include whitespace around <li>s
     303        $this->assertRegExp( '/\s<li.*>|<\/li>\s/U', $menu );
     304        $this->assertNotRegExp( '/><li.*>|<\/li></U', $menu );
     305
    302306        // No menus + wp_nav_menu() falls back to wp_page_menu(), this time without a container.
    303307        $menu = wp_nav_menu( array(
     
    308312        // After falling back, the empty 'container' argument should still return a container element.
    309313        $this->assertRegExp( '/<div class="menu">/', $menu );
     314
     315        // No menus + wp_nav_menu() falls back to wp_page_menu(), this time without white-space.
     316        $menu = wp_nav_menu( array(
     317            'echo'         => false,
     318            'item_spacing' => 'discard',
     319        ) );
     320
     321        // After falling back, the markup should not include whitespace around <li>s
     322        $this->assertNotRegExp( '/\s<li.*>|<\/li>\s/U', $menu );
     323        $this->assertRegExp( '/><li.*>|<\/li></U', $menu );
     324
    310325    }
    311326}
Note: See TracChangeset for help on using the changeset viewer.