WordPress.org

Make WordPress Core

Changeset 43223


Ignore:
Timestamp:
05/10/2018 07:51:58 PM (2 years ago)
Author:
iandunn
Message:

Privacy: Replace intrusive policy update notice with menu bubbles.

Previously, when a plugin updated its suggested privacy policy text, an admin notice was shown on all screens in the Administration Panels. That was done in order to make sure that administrators were aware of it, so that they could update their policy if needed. That was a very heavy-handed and intrusive approach, though, which leads to a poor user experience, and notice fatigue.

An alternative approach is to use bubble notifications in the menu, similar to when plugins have updates that need to be installed. That still makes it obvious that something needs the administrator's attention, but is not as distracting as a notice.

The notice will still appear on the Privacy page, though, since it is relevant to that screen, and provides an explanation of why the bubble is appearing.

Props azaozz, xkon, iandunn.
Fixes #43954. See #43953.

Location:
trunk/src
Files:
6 edited

Legend:

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

    r43216 r43223  
    10901090
    10911091.tools-privacy-edit {
    1092     margin: 2.3em 0;
     1092    margin: 1.5em 0;
    10931093}
    10941094
  • trunk/src/wp-admin/includes/admin-filters.php

    r43185 r43223  
    139139
    140140// Privacy policy text changes check.
    141 add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 20 );
     141add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 100 );
    142142
    143143// Show a "postbox" with the text suggestions for a privacy policy.
     
    147147add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'add_suggested_content' ), 1 );
    148148
    149 // Stop checking for text changes after the policy page is updated.
     149// Update the cached policy info when the policy page is updated.
    150150add_action( 'post_updated', array( 'WP_Privacy_Policy_Content', '_policy_page_updated' ) );
  • trunk/src/wp-admin/includes/misc.php

    r43206 r43223  
    13211321        // The site doesn't have a privacy policy.
    13221322        if ( empty( $policy_page_id ) ) {
    1323             return;
     1323            return false;
    13241324        }
    13251325
    13261326        if ( ! current_user_can( 'edit_post', $policy_page_id ) ) {
    1327             return;
    1328         }
    1329 
    1330         // Also run when the option doesn't exist yet.
    1331         if ( get_option( '_wp_privacy_text_change_check' ) === 'no-check' ) {
    1332             return;
     1327            return false;
    13331328        }
    13341329
    13351330        $old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1331
     1332        // Updates are not relevant if the user has not reviewed any suggestions yet.
     1333        if ( empty( $old ) ) {
     1334            return false;
     1335        }
     1336
     1337        $cached = get_option( '_wp_suggested_policy_text_has_changed' );
     1338
     1339        /*
     1340         * When this function is called before `admin_init`, `self::$policy_content`
     1341         * has not been populated yet, so use the cached result from the last
     1342         * execution instead.
     1343         */
     1344        if ( ! did_action( 'admin_init' ) ) {
     1345            return 'changed' === $cached;
     1346        }
     1347
    13361348        $new = self::$policy_content;
    13371349
    13381350        // Remove the extra values added to the meta.
    13391351        foreach ( $old as $key => $data ) {
     1352            if ( ! empty( $data['removed'] ) ) {
     1353                unset( $old[ $key ] );
     1354                continue;
     1355            }
     1356
    13401357            $old[ $key ] = array(
    13411358                'plugin_name' => $data['plugin_name'],
     
    13441361        }
    13451362
     1363        // Normalize the order of texts, to facilitate comparison.
     1364        sort( $old );
     1365        sort( $new );
     1366
    13461367        // The == operator (equal, not identical) was used intentionally.
    13471368        // See http://php.net/manual/en/language.operators.array.php
    13481369        if ( $new != $old ) {
    13491370            // A plugin was activated or deactivated, or some policy text has changed.
    1350             // Show a notice on all screens in wp-admin.
     1371            // Show a notice on the relevant screens to inform the admin.
    13511372            add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'policy_text_changed_notice' ) );
     1373            $state = 'changed';
    13521374        } else {
    1353             // Stop checking.
    1354             update_option( '_wp_privacy_text_change_check', 'no-check' );
    1355         }
     1375            $state = 'not-changed';
     1376        }
     1377
     1378        // Cache the result for use before `admin_init` (see above).
     1379        if ( $cached !== $state ) {
     1380            update_option( '_wp_suggested_policy_text_has_changed', $state );
     1381        }
     1382
     1383        return 'changed' === $state;
    13561384    }
    13571385
    13581386    /**
    1359      * Output an admin notice when some privacy info has changed.
     1387     * Output a warning when some privacy info has changed.
    13601388     *
    13611389     * @since 4.9.6
     
    13631391    public static function policy_text_changed_notice() {
    13641392        global $post;
    1365         $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1393
     1394        $screen = get_current_screen()->id;
     1395
     1396        if ( 'privacy' !== $screen ) {
     1397            return;
     1398        }
    13661399
    13671400        ?>
    13681401        <div class="policy-text-updated notice notice-warning is-dismissible">
    13691402            <p><?php
    1370 
    1371                 _e( 'The suggested privacy policy text has changed.' );
    1372 
    1373                 if ( empty( $post ) || $post->ID != $policy_page_id ) {
    1374                     ?>
    1375                     <a href="<?php echo get_edit_post_link( $policy_page_id ); ?>"><?php _e( 'Edit the privacy policy.' ); ?></a>
    1376                     <?php
    1377                 }
    1378 
     1403                _e( 'The suggested privacy policy text has changed. Please update your privacy policy.' );
    13791404            ?></p>
    13801405        </div>
     
    13831408
    13841409    /**
    1385      * Stop checking for changed privacy info when the policy page is updated.
     1410     * Update the cached policy info when the policy page is updated.
    13861411     *
    13871412     * @since 4.9.6
     
    13951420        }
    13961421
    1397         // The policy page was updated.
    1398         // Stop checking for text changes.
    1399         update_option( '_wp_privacy_text_change_check', 'no-check' );
     1422        // Update the cache in case the user hasn't visited the policy guide.
     1423        self::get_suggested_policy_text();
    14001424
    14011425        // Remove updated|removed status.
     
    14971521                if ( ! empty( $new_data['plugin_name'] ) && ! empty( $new_data['policy_text'] ) ) {
    14981522                    $new_data['added'] = $time;
    1499                     array_unshift( $checked, $new_data );
     1523                    $checked[]         = $new_data;
    15001524                }
    15011525            }
     
    15121536                        'removed'     => $time,
    15131537                    );
    1514                     array_unshift( $checked, $data );
     1538
     1539                    $checked[] = $data;
    15151540                }
    15161541            }
     
    15241549                add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
    15251550            }
    1526         }
    1527 
    1528         // Stop checking for changes after the page has been loaded.
    1529         if ( get_option( '_wp_privacy_text_change_check' ) !== 'no-check' ) {
    1530             update_option( '_wp_privacy_text_change_check', 'no-check' );
    15311551        }
    15321552
  • trunk/src/wp-admin/menu.php

    r43155 r43223  
    264264}
    265265
    266 $menu[80]                               = array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
     266$change_notice = '';
     267if ( current_user_can( 'manage_privacy_options' ) && WP_Privacy_Policy_Content::text_change_check() ) {
     268    $change_notice = ' <span class="update-plugins 1"><span class="plugin-count">' . number_format_i18n( 1 ) . '</span></span>';
     269}
     270
     271// translators: %s is the update notification bubble, if updates are available.
     272$menu[80]                               = array( sprintf( __( 'Settings %s' ), $change_notice ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
    267273    $submenu['options-general.php'][10] = array( _x( 'General', 'settings screen' ), 'manage_options', 'options-general.php' );
    268274    $submenu['options-general.php'][15] = array( __( 'Writing' ), 'manage_options', 'options-writing.php' );
     
    271277    $submenu['options-general.php'][30] = array( __( 'Media' ), 'manage_options', 'options-media.php' );
    272278    $submenu['options-general.php'][40] = array( __( 'Permalinks' ), 'manage_options', 'options-permalink.php' );
    273     $submenu['options-general.php'][45] = array( __( 'Privacy' ), 'manage_privacy_options', 'privacy.php' );
     279    // translators: %s is the update notification bubble, if updates are available.
     280    $submenu['options-general.php'][45] = array( sprintf( __( 'Privacy %s' ), $change_notice ), 'manage_privacy_options', 'privacy.php' );
    274281
    275282$_wp_last_utility_menu = 80; // The index of the last top-level menu in the utility menu group
  • trunk/src/wp-includes/default-filters.php

    r43211 r43223  
    563563add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 );
    564564
    565 // Trigger the check for policy text changes after active plugins change.
    566 add_action( 'update_site_option_active_sitewide_plugins', '_wp_privacy_active_plugins_change' );
    567 add_action( 'update_option_active_plugins', '_wp_privacy_active_plugins_change' );
    568 
    569565unset( $filter, $action );
  • trunk/src/wp-includes/functions.php

    r43174 r43223  
    62506250
    62516251/**
    6252  * Trigger the check for policy text changes.
    6253  *
    6254  * @since 4.9.6
    6255  * @access private
    6256  */
    6257 function _wp_privacy_active_plugins_change() {
    6258     update_option( '_wp_privacy_text_change_check', 'check' );
    6259 }
    6260 
    6261 /**
    62626252 * Schedule a `WP_Cron` job to delete expired export files.
    62636253 *
Note: See TracChangeset for help on using the changeset viewer.