Skip to content

Commit

Permalink
Privacy: Replace intrusive policy update notice with menu bubbles.
Browse files Browse the repository at this point in the history
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.

Built from https://develop.svn.wordpress.org/trunk@43223


git-svn-id: http://core.svn.wordpress.org/trunk@43052 1a063a9b-81f0-0310-95a4-ce76da25c4cd
  • Loading branch information
iandunn committed May 10, 2018
1 parent 7b5f401 commit 8af721f
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 56 deletions.
2 changes: 1 addition & 1 deletion wp-admin/css/forms-rtl.css
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ table.form-table td .updated p {
}

.tools-privacy-edit {
margin: 2.3em 0;
margin: 1.5em 0;
}

.tools-privacy-policy-page span {
Expand Down
2 changes: 1 addition & 1 deletion wp-admin/css/forms-rtl.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion wp-admin/css/forms.css
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ table.form-table td .updated p {
}

.tools-privacy-edit {
margin: 2.3em 0;
margin: 1.5em 0;
}

.tools-privacy-policy-page span {
Expand Down
2 changes: 1 addition & 1 deletion wp-admin/css/forms.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion wp-admin/css/login-rtl.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion wp-admin/css/login.min.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions wp-admin/includes/admin-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@
add_action( 'wp_privacy_personal_data_export_file', 'wp_privacy_generate_personal_data_export_file', 10 );

// Privacy policy text changes check.
add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 20 );
add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 100 );

// Show a "postbox" with the text suggestions for a privacy policy.
add_action( 'edit_form_after_title', array( 'WP_Privacy_Policy_Content', 'notice' ) );

// Add the suggested policy text from WordPress.
add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'add_suggested_content' ), 1 );

// Stop checking for text changes after the policy page is updated.
// Update the cached policy info when the policy page is updated.
add_action( 'post_updated', array( 'WP_Privacy_Policy_Content', '_policy_page_updated' ) );
82 changes: 51 additions & 31 deletions wp-admin/includes/misc.php
Original file line number Diff line number Diff line change
Expand Up @@ -1320,69 +1320,94 @@ public static function text_change_check() {

// The site doesn't have a privacy policy.
if ( empty( $policy_page_id ) ) {
return;
return false;
}

if ( ! current_user_can( 'edit_post', $policy_page_id ) ) {
return;
return false;
}

// Also run when the option doesn't exist yet.
if ( get_option( '_wp_privacy_text_change_check' ) === 'no-check' ) {
return;
$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );

// Updates are not relevant if the user has not reviewed any suggestions yet.
if ( empty( $old ) ) {
return false;
}

$cached = get_option( '_wp_suggested_policy_text_has_changed' );

/*
* When this function is called before `admin_init`, `self::$policy_content`
* has not been populated yet, so use the cached result from the last
* execution instead.
*/
if ( ! did_action( 'admin_init' ) ) {
return 'changed' === $cached;
}

$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
$new = self::$policy_content;

// Remove the extra values added to the meta.
foreach ( $old as $key => $data ) {
if ( ! empty( $data['removed'] ) ) {
unset( $old[ $key ] );
continue;
}

$old[ $key ] = array(
'plugin_name' => $data['plugin_name'],
'policy_text' => $data['policy_text'],
);
}

// Normalize the order of texts, to facilitate comparison.
sort( $old );
sort( $new );

// The == operator (equal, not identical) was used intentionally.
// See http://php.net/manual/en/language.operators.array.php
if ( $new != $old ) {
// A plugin was activated or deactivated, or some policy text has changed.
// Show a notice on all screens in wp-admin.
// Show a notice on the relevant screens to inform the admin.
add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'policy_text_changed_notice' ) );
$state = 'changed';
} else {
// Stop checking.
update_option( '_wp_privacy_text_change_check', 'no-check' );
$state = 'not-changed';
}

// Cache the result for use before `admin_init` (see above).
if ( $cached !== $state ) {
update_option( '_wp_suggested_policy_text_has_changed', $state );
}

return 'changed' === $state;
}

/**
* Output an admin notice when some privacy info has changed.
* Output a warning when some privacy info has changed.
*
* @since 4.9.6
*/
public static function policy_text_changed_notice() {
global $post;
$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

$screen = get_current_screen()->id;

if ( 'privacy' !== $screen ) {
return;
}

?>
<div class="policy-text-updated notice notice-warning is-dismissible">
<p><?php

_e( 'The suggested privacy policy text has changed.' );

if ( empty( $post ) || $post->ID != $policy_page_id ) {
?>
<a href="<?php echo get_edit_post_link( $policy_page_id ); ?>"><?php _e( 'Edit the privacy policy.' ); ?></a>
<?php
}

_e( 'The suggested privacy policy text has changed. Please update your privacy policy.' );
?></p>
</div>
<?php
}

/**
* Stop checking for changed privacy info when the policy page is updated.
* Update the cached policy info when the policy page is updated.
*
* @since 4.9.6
* @access private
Expand All @@ -1394,9 +1419,8 @@ public static function _policy_page_updated( $post_id ) {
return;
}

// The policy page was updated.
// Stop checking for text changes.
update_option( '_wp_privacy_text_change_check', 'no-check' );
// Update the cache in case the user hasn't visited the policy guide.
self::get_suggested_policy_text();

// Remove updated|removed status.
$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
Expand Down Expand Up @@ -1496,7 +1520,7 @@ public static function get_suggested_policy_text() {
foreach ( $new as $new_data ) {
if ( ! empty( $new_data['plugin_name'] ) && ! empty( $new_data['policy_text'] ) ) {
$new_data['added'] = $time;
array_unshift( $checked, $new_data );
$checked[] = $new_data;
}
}
$update_cache = true;
Expand All @@ -1511,7 +1535,8 @@ public static function get_suggested_policy_text() {
'policy_text' => $old_data['policy_text'],
'removed' => $time,
);
array_unshift( $checked, $data );

$checked[] = $data;
}
}
$update_cache = true;
Expand All @@ -1525,11 +1550,6 @@ public static function get_suggested_policy_text() {
}
}

// Stop checking for changes after the page has been loaded.
if ( get_option( '_wp_privacy_text_change_check' ) !== 'no-check' ) {
update_option( '_wp_privacy_text_change_check', 'no-check' );
}

return $checked;
}

Expand Down
11 changes: 9 additions & 2 deletions wp-admin/menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,21 @@ function _add_themes_utility_last() {
$submenu['tools.php'][50] = array( __( 'Network Setup' ), 'setup_network', 'network.php' );
}

$menu[80] = array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
$change_notice = '';
if ( current_user_can( 'manage_privacy_options' ) && WP_Privacy_Policy_Content::text_change_check() ) {
$change_notice = ' <span class="update-plugins 1"><span class="plugin-count">' . number_format_i18n( 1 ) . '</span></span>';
}

// translators: %s is the update notification bubble, if updates are available.
$menu[80] = array( sprintf( __( 'Settings %s' ), $change_notice ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
$submenu['options-general.php'][10] = array( _x( 'General', 'settings screen' ), 'manage_options', 'options-general.php' );
$submenu['options-general.php'][15] = array( __( 'Writing' ), 'manage_options', 'options-writing.php' );
$submenu['options-general.php'][20] = array( __( 'Reading' ), 'manage_options', 'options-reading.php' );
$submenu['options-general.php'][25] = array( __( 'Discussion' ), 'manage_options', 'options-discussion.php' );
$submenu['options-general.php'][30] = array( __( 'Media' ), 'manage_options', 'options-media.php' );
$submenu['options-general.php'][40] = array( __( 'Permalinks' ), 'manage_options', 'options-permalink.php' );
$submenu['options-general.php'][45] = array( __( 'Privacy' ), 'manage_privacy_options', 'privacy.php' );
// translators: %s is the update notification bubble, if updates are available.
$submenu['options-general.php'][45] = array( sprintf( __( 'Privacy %s' ), $change_notice ), 'manage_privacy_options', 'privacy.php' );

$_wp_last_utility_menu = 80; // The index of the last top-level menu in the utility menu group

Expand Down
4 changes: 0 additions & 4 deletions wp-includes/default-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,4 @@
// Capabilities
add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 );

// Trigger the check for policy text changes after active plugins change.
add_action( 'update_site_option_active_sitewide_plugins', '_wp_privacy_active_plugins_change' );
add_action( 'update_option_active_plugins', '_wp_privacy_active_plugins_change' );

unset( $filter, $action );
10 changes: 0 additions & 10 deletions wp-includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -6248,16 +6248,6 @@ function wp_privacy_anonymize_data( $type, $data = '' ) {
return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $type, $data );
}

/**
* Trigger the check for policy text changes.
*
* @since 4.9.6
* @access private
*/
function _wp_privacy_active_plugins_change() {
update_option( '_wp_privacy_text_change_check', 'check' );
}

/**
* Schedule a `WP_Cron` job to delete expired export files.
*
Expand Down
2 changes: 1 addition & 1 deletion wp-includes/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.0-alpha-43222';
$wp_version = '5.0-alpha-43223';

/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
Expand Down

0 comments on commit 8af721f

Please sign in to comment.