Make WordPress Core

Changeset 55261


Ignore:
Timestamp:
02/07/2023 02:03:26 PM (17 months ago)
Author:
audrasjb
Message:

Privacy: Add rel="privacy-policy" to the Privacy Policy link.

This changeset adds a rel="privacy-policy" attribute to user-facing links to the Privacy Policy of the website, when a privacy policy page is set and available. While this rel value is still a RFC of the Link Types HTML specification, this changeset helps to make Privacy Policy link more discoverable for user agents and HTML parsers.

Props dshanske, audrasjb, bhavz-10, bookwyrm, faisal03, JeffPaul, peterwilsoncc, paapst, davidbaumwald, costdev, robinwpdeveloper, kawserz.
Fixes #56345.

Location:
trunk
Files:
4 edited

Legend:

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

    r54178 r55261  
    183183            $atts['rel'] = $menu_item->xfn;
    184184        }
    185         $atts['href']         = ! empty( $menu_item->url ) ? $menu_item->url : '';
     185
     186        if ( ! empty( $menu_item->url ) ) {
     187            if ( get_privacy_policy_url() === $menu_item->url ) {
     188                $atts['rel'] = empty( $atts['rel'] ) ? 'privacy-policy' : $atts['rel'] . ' privacy-policy';
     189            }
     190
     191            $atts['href'] = $menu_item->url;
     192        } else {
     193            $atts['href'] = '';
     194        }
     195
    186196        $atts['aria-current'] = $menu_item->current ? 'page' : '';
    187197
  • trunk/src/wp-includes/link-template.php

    r55239 r55261  
    46654665    if ( $privacy_policy_url && $page_title ) {
    46664666        $link = sprintf(
    4667             '<a class="privacy-policy-link" href="%s">%s</a>',
     4667            '<a class="privacy-policy-link" href="%s" rel="privacy-policy">%s</a>',
    46684668            esc_url( $privacy_policy_url ),
    46694669            esc_html( $page_title )
  • trunk/tests/phpunit/tests/link/getThePrivacyPolicyLink.php

    r54090 r55261  
    161161        return 'Policy: ' . $privacy_policy_url;
    162162    }
     163
     164    /**
     165     * Tests that `get_the_privacy_policy_link()` adds `rel="privacy-policy"`.
     166     *
     167     * @ticket 56345
     168     */
     169    public function test_get_the_privacy_policy_link_should_add_rel_privacy_policy() {
     170        update_option( 'wp_page_for_privacy_policy', self::$privacy_policy_page_id );
     171
     172        $this->assertStringContainsString( 'rel="privacy-policy"', get_the_privacy_policy_link() );
     173    }
    163174}
  • trunk/tests/phpunit/tests/menu/walker-nav-menu.php

    r54090 r55261  
    153153        );
    154154    }
     155
     156    /**
     157     * Tests that `Walker_Nav_Menu::start_el()` adds `rel="privacy-policy"`.
     158     *
     159     * @ticket 56345
     160     *
     161     * @covers Walker_Nav_Menu::start_el
     162     *
     163     * @dataProvider data_walker_nav_menu_start_el_should_add_rel_privacy_policy_to_privacy_policy_url
     164     *
     165     * @param string $expected The expected substring containing the "rel" attribute and value.
     166     * @param string $xfn      Optional. The XFN value. Default empty string.
     167     * @param string $target   Optional. The target value. Default empty string.
     168     */
     169    public function test_walker_nav_menu_start_el_should_add_rel_privacy_policy_to_privacy_policy_url( $expected, $xfn = '', $target = '' ) {
     170        $post_id = self::factory()->post->create(
     171            array(
     172                'post_type'   => 'page',
     173                'post_title'  => 'Test Privacy Policy',
     174                'post_status' => 'publish',
     175            )
     176        );
     177
     178        // Set the privacy policy page.
     179        update_option( 'wp_page_for_privacy_policy', $post_id );
     180        $privacy_policy_id = (int) get_option( 'wp_page_for_privacy_policy' );
     181
     182        $output = '';
     183
     184        $item = array(
     185            'ID'        => $privacy_policy_id,
     186            'object_id' => $privacy_policy_id,
     187            'title'     => 'Privacy Policy',
     188            'target'    => $target,
     189            'xfn'       => $xfn,
     190            'current'   => false,
     191            'url'       => get_privacy_policy_url(),
     192        );
     193
     194        $args = array(
     195            'before'      => '',
     196            'after'       => '',
     197            'link_before' => '',
     198            'link_after'  => '',
     199        );
     200
     201        $this->walker->start_el( $output, (object) $item, 0, (object) $args );
     202
     203        $this->assertStringContainsString( $expected, $output );
     204    }
     205
     206    /**
     207     * Data provider.
     208     *
     209     * @return array[]
     210     */
     211    public function data_walker_nav_menu_start_el_should_add_rel_privacy_policy_to_privacy_policy_url() {
     212        return array(
     213            'no xfn value'                          => array(
     214                'expected' => 'rel="privacy-policy"',
     215            ),
     216            'an xfn value'                          => array(
     217                'expected' => 'rel="nofollow privacy-policy"',
     218                'xfn'      => 'nofollow',
     219            ),
     220            'no xfn value and a target of "_blank"' => array(
     221                'expected' => 'rel="noopener privacy-policy"',
     222                'xfn'      => '',
     223                'target'   => '_blank',
     224            ),
     225            'an xfn value and a target of "_blank"' => array(
     226                'expected' => 'rel="nofollow privacy-policy"',
     227                'xfn'      => 'nofollow',
     228                'target'   => '_blank',
     229            ),
     230        );
     231    }
     232
     233    /**
     234     * Tests that `Walker_Nav_Menu::start_el()` does not add `rel="privacy-policy"` when no
     235     * privacy policy page exists.
     236     *
     237     * @ticket 56345
     238     *
     239     * @covers Walker_Nav_Menu::start_el
     240     */
     241    public function test_walker_nav_menu_start_el_should_not_add_rel_privacy_policy_when_no_privacy_policy_exists() {
     242        $post_id = self::factory()->post->create(
     243            array(
     244                'post_type'   => 'page',
     245                'post_title'  => 'Test Privacy Policy',
     246                'post_status' => 'publish',
     247            )
     248        );
     249
     250        // Do not set the privacy policy page.
     251
     252        $output = '';
     253
     254        $item = array(
     255            'ID'        => $post_id,
     256            'object_id' => $post_id,
     257            'title'     => 'Privacy Policy',
     258            'target'    => '',
     259            'xfn'       => '',
     260            'current'   => false,
     261            'url'       => get_the_permalink( $post_id ),
     262        );
     263
     264        $args = array(
     265            'before'      => '',
     266            'after'       => '',
     267            'link_before' => '',
     268            'link_after'  => '',
     269        );
     270
     271        $this->walker->start_el( $output, (object) $item, 0, (object) $args );
     272
     273        $this->assertStringNotContainsString( 'rel="privacy-policy"', $output );
     274    }
     275
     276    /**
     277     * Tests that `Walker_Nav_Menu::start_el()` does not add `rel="privacy-policy"` when no URL
     278     * is passed in the menu item object.
     279     *
     280     * @ticket 56345
     281     *
     282     * @covers Walker_Nav_Menu::start_el
     283     */
     284    public function test_walker_nav_menu_start_el_should_not_add_rel_privacy_policy_when_no_url_is_passed() {
     285        $post_id = self::factory()->post->create(
     286            array(
     287                'post_type'   => 'page',
     288                'post_title'  => 'Test Privacy Policy',
     289                'post_status' => 'publish',
     290            )
     291        );
     292
     293        // Set the privacy policy page.
     294        update_option( 'wp_page_for_privacy_policy', $post_id );
     295        $privacy_policy_id = (int) get_option( 'wp_page_for_privacy_policy' );
     296
     297        $output = '';
     298
     299        $item = array(
     300            'ID'        => $privacy_policy_id,
     301            'object_id' => $privacy_policy_id,
     302            'title'     => 'Privacy Policy',
     303            'target'    => '',
     304            'xfn'       => '',
     305            'current'   => false,
     306            // Do not pass URL.
     307        );
     308
     309        $args = array(
     310            'before'      => '',
     311            'after'       => '',
     312            'link_before' => '',
     313            'link_after'  => '',
     314        );
     315
     316        $this->walker->start_el( $output, (object) $item, 0, (object) $args );
     317
     318        $this->assertStringNotContainsString( 'rel="privacy-policy"', $output );
     319    }
     320
     321    /**
     322     * Tests that `Walker_Nav_Menu::start_el()` does not add `rel="privacy-policy"` when the
     323     * menu item's ID does not match the privacy policy page, but the URL does.
     324     *
     325     * @ticket 56345
     326     *
     327     * @covers Walker_Nav_Menu::start_el
     328     */
     329    public function test_walker_nav_menu_start_el_should_add_rel_privacy_policy_when_id_does_not_match_but_url_does() {
     330        $post_id = self::factory()->post->create(
     331            array(
     332                'post_type'   => 'page',
     333                'post_title'  => 'Test Privacy Policy',
     334                'post_status' => 'publish',
     335            )
     336        );
     337
     338        // Set the privacy policy page.
     339        update_option( 'wp_page_for_privacy_policy', $post_id );
     340        $privacy_policy_id = (int) get_option( 'wp_page_for_privacy_policy' );
     341
     342        $output = '';
     343
     344        // Ensure the ID does not match the privacy policy.
     345        $not_privacy_policy_id = $privacy_policy_id - 1;
     346
     347        $item = array(
     348            'ID'        => $not_privacy_policy_id,
     349            'object_id' => $not_privacy_policy_id,
     350            'title'     => 'Privacy Policy',
     351            'target'    => '',
     352            'xfn'       => '',
     353            'current'   => false,
     354            'url'       => get_privacy_policy_url(),
     355        );
     356
     357        $args = array(
     358            'before'      => '',
     359            'after'       => '',
     360            'link_before' => '',
     361            'link_after'  => '',
     362        );
     363
     364        $this->walker->start_el( $output, (object) $item, 0, (object) $args );
     365
     366        $this->assertStringContainsString( 'rel="privacy-policy"', $output );
     367    }
    155368}
Note: See TracChangeset for help on using the changeset viewer.