Make WordPress Core


Ignore:
Timestamp:
06/27/2023 03:25:00 PM (3 years ago)
Author:
audrasjb
Message:

Menus: Allow themes and plugins to pass HTML attributes to various Nav Walker outputs.

This introduces a new set of hooks that can be used to filter various HTML elements of the Nav Walker, in order to output the desired HTML attributes:

  • List items: nav_menu_item_attributes
  • Submenu <ul> element: nav_menu_submenu_attributes

Props davidwebca, danyk4, costdev, peterwilsoncc, audrasjb, oglekler.
Fixes #57140.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/menu/walker-nav-menu.php

    r55261 r56067  
    366366                $this->assertStringContainsString( 'rel="privacy-policy"', $output );
    367367        }
     368
     369        /**
     370         * Tests that `Walker_Nav_Menu::start_lvl()` applies 'nav_menu_submenu_attributes' filters.
     371         *
     372         * @ticket 57278
     373         *
     374         * @covers Walker_Nav_Menu::start_lvl
     375         */
     376        public function test_start_lvl_should_apply_nav_menu_submenu_attributes_filters() {
     377                $output = '';
     378                $args   = (object) array(
     379                        'before'      => '',
     380                        'after'       => '',
     381                        'link_before' => '',
     382                        'link_after'  => '',
     383                );
     384
     385                $filter = new MockAction();
     386                add_filter( 'nav_menu_submenu_attributes', array( $filter, 'filter' ) );
     387
     388                $this->walker->start_lvl( $output, 0, $args );
     389
     390                $this->assertSame( 1, $filter->get_call_count() );
     391        }
     392
     393        /**
     394         * Tests that `Walker_Nav_Menu::start_el()` applies 'nav_menu_item_attributes' filters.
     395         *
     396         * @ticket 57278
     397         *
     398         * @covers Walker_Nav_Menu::start_el
     399         */
     400        public function test_start_el_should_apply_nav_menu_item_attributes_filters() {
     401                $output  = '';
     402                $post_id = self::factory()->post->create();
     403                $item    = (object) array(
     404                        'ID'        => $post_id,
     405                        'object_id' => $post_id,
     406                        'title'     => get_the_title( $post_id ),
     407                        'target'    => '',
     408                        'xfn'       => '',
     409                        'current'   => false,
     410                );
     411                $args    = (object) array(
     412                        'before'      => '',
     413                        'after'       => '',
     414                        'link_before' => '',
     415                        'link_after'  => '',
     416                );
     417
     418                $filter = new MockAction();
     419                add_filter( 'nav_menu_item_attributes', array( $filter, 'filter' ) );
     420
     421                $this->walker->start_el( $output, $item, 0, $args );
     422
     423                $this->assertSame( 1, $filter->get_call_count() );
     424        }
     425
     426        /**
     427         * Tests that `Walker_Nav_Menu::build_atts()` builds attributes correctly.
     428         *
     429         * @ticket 57278
     430         *
     431         * @covers Walker_Nav_Menu::build_atts
     432         *
     433         * @dataProvider data_build_atts_should_build_attributes
     434         *
     435         * @param array  $atts     An array of HTML attribute key/value pairs.
     436         * @param string $expected The expected built attributes.
     437         */
     438        public function test_build_atts_should_build_attributes( $atts, $expected ) {
     439                $build_atts_reflection = new ReflectionMethod( $this->walker, 'build_atts' );
     440
     441                $build_atts_reflection->setAccessible( true );
     442                $actual = $build_atts_reflection->invoke( $this->walker, $atts );
     443                $build_atts_reflection->setAccessible( false );
     444
     445                $this->assertSame( $expected, $actual );
     446        }
     447
     448        /**
     449         * Data provider.
     450         *
     451         * @return array[]
     452         */
     453        public function data_build_atts_should_build_attributes() {
     454                return array(
     455                        'an empty attributes array'                   => array(
     456                                'atts'     => array(),
     457                                'expected' => '',
     458                        ),
     459                        'attributes containing a (bool) false value'  => array(
     460                                'atts'     => array( 'disabled' => false ),
     461                                'expected' => '',
     462                        ),
     463                        'attributes containing an empty string value' => array(
     464                                'atts'     => array( 'id' => '' ),
     465                                'expected' => '',
     466                        ),
     467                        'attributes containing a non-scalar value'    => array(
     468                                'atts'     => array( 'data-items' => new stdClass() ),
     469                                'expected' => '',
     470                        ),
     471                        'attributes containing a "href" -> should escape the URL' => array(
     472                                'atts'     => array( 'href' => 'https://example.org/A File With Spaces.pdf' ),
     473                                'expected' => ' href="https://example.org/A%20File%20With%20Spaces.pdf"',
     474                        ),
     475                        'attributes containing a non-"href" attribute -> should escape the value' => array(
     476                                'atts'     => array( 'id' => 'hello&goodbye' ),
     477                                'expected' => ' id="hello&amp;goodbye"',
     478                        ),
     479                );
     480        }
    368481}
Note: See TracChangeset for help on using the changeset viewer.