Make WordPress Core

Changeset 43225


Ignore:
Timestamp:
05/10/2018 08:07:11 PM (7 years ago)
Author:
azaozz
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.
Merges [43223] to the 4.9 branch.
Fixes #43954. See #43953.

Location:
branches/4.9
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/4.9

  • branches/4.9/src/wp-admin/css/forms.css

    r43217 r43225  
    10901090
    10911091.tools-privacy-edit {
    1092     margin: 2.3em 0;
     1092    margin: 1.5em 0;
    10931093}
    10941094
  • branches/4.9/src/wp-admin/includes/admin-filters.php

    r43204 r43225  
    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' ) );
    151151
  • branches/4.9/src/wp-admin/includes/misc.php

    r43207 r43225  
    12721272        // The site doesn't have a privacy policy.
    12731273        if ( empty( $policy_page_id ) ) {
    1274             return;
     1274            return false;
    12751275        }
    12761276
    12771277        if ( ! current_user_can( 'edit_post', $policy_page_id ) ) {
    1278             return;
    1279         }
    1280 
    1281         // Also run when the option doesn't exist yet.
    1282         if ( get_option( '_wp_privacy_text_change_check' ) === 'no-check' ) {
    1283             return;
     1278            return false;
    12841279        }
    12851280
    12861281        $old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1282
     1283        // Updates are not relevant if the user has not reviewed any suggestions yet.
     1284        if ( empty( $old ) ) {
     1285            return false;
     1286        }
     1287
     1288        $cached = get_option( '_wp_suggested_policy_text_has_changed' );
     1289
     1290        /*
     1291         * When this function is called before `admin_init`, `self::$policy_content`
     1292         * has not been populated yet, so use the cached result from the last
     1293         * execution instead.
     1294         */
     1295        if ( ! did_action( 'admin_init' ) ) {
     1296            return 'changed' === $cached;
     1297        }
     1298
    12871299        $new = self::$policy_content;
    12881300
    12891301        // Remove the extra values added to the meta.
    12901302        foreach ( $old as $key => $data ) {
     1303            if ( ! empty( $data['removed'] ) ) {
     1304                unset( $old[ $key ] );
     1305                continue;
     1306            }
     1307
    12911308            $old[ $key ] = array(
    12921309                'plugin_name' => $data['plugin_name'],
     
    12951312        }
    12961313
     1314        // Normalize the order of texts, to facilitate comparison.
     1315        sort( $old );
     1316        sort( $new );
     1317
    12971318        // The == operator (equal, not identical) was used intentionally.
    12981319        // See http://php.net/manual/en/language.operators.array.php
    12991320        if ( $new != $old ) {
    13001321            // A plugin was activated or deactivated, or some policy text has changed.
    1301             // Show a notice on all screens in wp-admin.
     1322            // Show a notice on the relevant screens to inform the admin.
    13021323            add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'policy_text_changed_notice' ) );
     1324            $state = 'changed';
    13031325        } else {
    1304             // Stop checking.
    1305             update_option( '_wp_privacy_text_change_check', 'no-check' );
    1306         }
     1326            $state = 'not-changed';
     1327        }
     1328
     1329        // Cache the result for use before `admin_init` (see above).
     1330        if ( $cached !== $state ) {
     1331            update_option( '_wp_suggested_policy_text_has_changed', $state );
     1332        }
     1333
     1334        return 'changed' === $state;
    13071335    }
    13081336
    13091337    /**
    1310      * Output an admin notice when some privacy info has changed.
     1338     * Output a warning when some privacy info has changed.
    13111339     *
    13121340     * @since 4.9.6
     
    13141342    public static function policy_text_changed_notice() {
    13151343        global $post;
    1316         $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1344
     1345        $screen = get_current_screen()->id;
     1346
     1347        if ( 'privacy' !== $screen ) {
     1348            return;
     1349        }
    13171350
    13181351        ?>
    13191352        <div class="policy-text-updated notice notice-warning is-dismissible">
    13201353            <p><?php
    1321 
    1322                 _e( 'The suggested privacy policy text has changed.' );
    1323 
    1324                 if ( empty( $post ) || $post->ID != $policy_page_id ) {
    1325                     ?>
    1326                     <a href="<?php echo get_edit_post_link( $policy_page_id ); ?>"><?php _e( 'Edit the privacy policy.' ); ?></a>
    1327                     <?php
    1328                 }
    1329 
     1354                _e( 'The suggested privacy policy text has changed. Please update your privacy policy.' );
    13301355            ?></p>
    13311356        </div>
     
    13341359
    13351360    /**
    1336      * Stop checking for changed privacy info when the policy page is updated.
     1361     * Update the cached policy info when the policy page is updated.
    13371362     *
    13381363     * @since 4.9.6
     
    13461371        }
    13471372
    1348         // The policy page was updated.
    1349         // Stop checking for text changes.
    1350         update_option( '_wp_privacy_text_change_check', 'no-check' );
     1373        // Update the cache in case the user hasn't visited the policy guide.
     1374        self::get_suggested_policy_text();
    13511375
    13521376        // Remove updated|removed status.
     
    14481472                if ( ! empty( $new_data['plugin_name'] ) && ! empty( $new_data['policy_text'] ) ) {
    14491473                    $new_data['added'] = $time;
    1450                     array_unshift( $checked, $new_data );
     1474                    $checked[]         = $new_data;
    14511475                }
    14521476            }
     
    14631487                        'removed'     => $time,
    14641488                    );
    1465                     array_unshift( $checked, $data );
     1489
     1490                    $checked[] = $data;
    14661491                }
    14671492            }
     
    14751500                add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
    14761501            }
    1477         }
    1478 
    1479         // Stop checking for changes after the page has been loaded.
    1480         if ( get_option( '_wp_privacy_text_change_check' ) !== 'no-check' ) {
    1481             update_option( '_wp_privacy_text_change_check', 'no-check' );
    14821502        }
    14831503
  • branches/4.9/src/wp-admin/menu.php

    r43156 r43225  
    250250        $submenu['tools.php'][50] = array(__('Network Setup'), 'setup_network', 'network.php');
    251251
    252 $menu[80] = array( __('Settings'), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
    253     $submenu['options-general.php'][10] = array(_x('General', 'settings screen'), 'manage_options', 'options-general.php');
    254     $submenu['options-general.php'][15] = array(__('Writing'), 'manage_options', 'options-writing.php');
    255     $submenu['options-general.php'][20] = array(__('Reading'), 'manage_options', 'options-reading.php');
    256     $submenu['options-general.php'][25] = array(__('Discussion'), 'manage_options', 'options-discussion.php');
    257     $submenu['options-general.php'][30] = array(__('Media'), 'manage_options', 'options-media.php');
    258     $submenu['options-general.php'][40] = array(__('Permalinks'), 'manage_options', 'options-permalink.php');
    259     $submenu['options-general.php'][45] = array( __( 'Privacy' ), 'manage_privacy_options', 'privacy.php' );
     252$change_notice = '';
     253if ( current_user_can( 'manage_privacy_options' ) && WP_Privacy_Policy_Content::text_change_check() ) {
     254    $change_notice = ' <span class="update-plugins 1"><span class="plugin-count">' . number_format_i18n( 1 ) . '</span></span>';
     255}
     256
     257// translators: %s is the update notification bubble, if updates are available.
     258$menu[80]                               = array( sprintf( __( 'Settings %s' ), $change_notice ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
     259    $submenu['options-general.php'][10] = array( _x( 'General', 'settings screen' ), 'manage_options', 'options-general.php' );
     260    $submenu['options-general.php'][15] = array( __( 'Writing' ), 'manage_options', 'options-writing.php' );
     261    $submenu['options-general.php'][20] = array( __( 'Reading' ), 'manage_options', 'options-reading.php' );
     262    $submenu['options-general.php'][25] = array( __( 'Discussion' ), 'manage_options', 'options-discussion.php' );
     263    $submenu['options-general.php'][30] = array( __( 'Media' ), 'manage_options', 'options-media.php' );
     264    $submenu['options-general.php'][40] = array( __( 'Permalinks' ), 'manage_options', 'options-permalink.php' );
     265    // translators: %s is the update notification bubble, if updates are available.
     266    $submenu['options-general.php'][45] = array( sprintf( __( 'Privacy %s' ), $change_notice ), 'manage_privacy_options', 'privacy.php' );
    260267
    261268$_wp_last_utility_menu = 80; // The index of the last top-level menu in the utility menu group
  • branches/4.9/src/wp-includes/default-filters.php

    r43215 r43225  
    536536add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 );
    537537
    538 // Trigger the check for policy text changes after active plugins change.
    539 add_action( 'update_site_option_active_sitewide_plugins', '_wp_privacy_active_plugins_change' );
    540 add_action( 'update_option_active_plugins', '_wp_privacy_active_plugins_change' );
    541 
    542538unset( $filter, $action );
  • branches/4.9/src/wp-includes/functions.php

    r43163 r43225  
    59385938
    59395939/**
    5940  * Trigger the check for policy text changes.
    5941  *
    5942  * @since 4.9.6
    5943  * @access private
    5944  */
    5945 function _wp_privacy_active_plugins_change() {
    5946     update_option( '_wp_privacy_text_change_check', 'check' );
    5947 }
    5948 
    5949 /**
    59505940 * Schedule a `WP_Cron` job to delete expired export files.
    59515941 *
Note: See TracChangeset for help on using the changeset viewer.