WordPress.org

Make WordPress Core

Ticket #43620: 43620.diff

File 43620.diff, 19.6 KB (added by azaozz, 20 months ago)
  • src/wp-admin/css/common.css

     
    29902990/* Metabox collapse arrow indicators */
    29912991.sidebar-name .toggle-indicator:before,
    29922992.js .meta-box-sortables .postbox .toggle-indicator:before,
    2993 .bulk-action-notice .toggle-indicator:before {
     2993.bulk-action-notice .toggle-indicator:before,
     2994.privacy-text-box .toggle-indicator:before {
    29942995        content: "\f142";
    29952996        display: inline-block;
    29962997        font: normal 20px/1 dashicons;
     
    30023003
    30033004.js .widgets-holder-wrap.closed .toggle-indicator:before,
    30043005.js .meta-box-sortables .postbox.closed .handlediv .toggle-indicator:before,
    3005 .bulk-action-notice .bulk-action-errors-collapsed .toggle-indicator:before {
     3006.bulk-action-notice .bulk-action-errors-collapsed .toggle-indicator:before,
     3007.privacy-text-box.closed .toggle-indicator:before {
    30063008        content: "\f140";
    30073009}
    30083010
  • src/wp-admin/css/edit.css

     
    646646        margin-bottom: 20px;
    647647}
    648648
     649/* Sugested text for privacy policy postbox */
     650.privacy-text-box {
     651        margin: 10px 0 0;
     652       
     653}
     654
     655.privacy-text-box-head {
     656        border-left: 4px solid #ffb900;
     657        border-bottom: 1px solid #e5e5e5;
     658        box-shadow: 0 1px 1px rgba(0,0,0,0.04);
     659       
     660}
     661
     662.privacy-text-box .privacy-text-box-head.hndle {
     663        cursor: pointer;
     664}
     665
     666.privacy-text-box-head p {
     667        padding: 0 12px 14px;
     668        margin: 0;
     669}
     670
     671.privacy-text-box-body {
     672        height: 320px;
     673        overflow: auto;
     674       
     675}
     676
     677#privacy-text-box .inside {
     678        margin: 0;
     679}
     680
     681.privacy-text-box h3 {
     682        font-size: 1em;
     683        margin: 1em 0;
     684}
     685
     686.privacy-text-section .privacy-text-copy-button {
     687        float: right;
     688        margin-top: -1.8em;
     689}
     690
     691.privacy-text-section {
     692        padding: 1px 14px 1px 12px;
     693        border-top: 1px solid #e3e3e3;
     694        border-left: 4px solid transparent;
     695}
     696
     697.privacy-text-section.text-updated {
     698        border-left-color: #46b450;
     699        background-color: #ecf7ed;
     700}
     701
     702.privacy-text-section.text-removed {
     703        border-left-color: #dc3232;
     704        background-color: #fbeaea;
     705}
     706
     707.closed .privacy-text-box-body {
     708        display: none;
     709}
     710
    649711/*------------------------------------------------------------------------------
    650712  11.1 - Custom Fields
    651713------------------------------------------------------------------------------*/
  • src/wp-admin/includes/admin-filters.php

     
    132132add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
    133133add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
    134134add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );
     135
     136// Privacy policy text changes check.
     137add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 20 );
     138
     139// Show a "postbox" with the text suggestions for a privacy policy.
     140add_action( 'edit_form_after_title', array( 'WP_Privacy_Policy_Content', 'privacy_policy_postbox' ) );
     141
     142// Add the suggested policy text from WordPress.
     143add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'suggested_privacy_policy_content' ), 15 );
     144
     145// Stop checking for text changes after the policy page is updated.
     146add_action( 'post_updated', array( 'WP_Privacy_Policy_Content', '_policy_page_updated' ) );
     147
  • src/wp-admin/includes/misc.php

     
    12621262                restore_previous_locale();
    12631263        }
    12641264}
     1265
     1266/**
     1267 * WP_Privacy_Policy_Content class.
     1268 * TODO: move this to a new file.
     1269 *
     1270 * @since 5.0.0
     1271 */
     1272final class WP_Privacy_Policy_Content {
     1273
     1274        private static $policy_content = array();
     1275
     1276        /**
     1277         * Constructor
     1278         *
     1279         * @since 5.0.0
     1280         */
     1281        private function __construct() {}
     1282
     1283        /**
     1284         * Add privacy information to the postbox shown when editing the privacy policy.
     1285         *
     1286         * Intended for use from `wp_add_privacy_policy_content()`.
     1287         *
     1288         * $since 5.0.0
     1289         *
     1290         * @param string $plugin_name The plugin'as name. Will be shown in the privacy policy metabox.
     1291         * @param string $policy_text The content that should appear in the site's privacy policy.
     1292         */
     1293        public static function add( $plugin_name, $policy_text ) {
     1294                if ( empty( $plugin_name ) || empty( $policy_text ) ) {
     1295                        return;
     1296                }
     1297
     1298                $data = array(
     1299                        'plugin_name' => $plugin_name,
     1300                        'policy_text' => $policy_text,
     1301                );
     1302
     1303                if ( ! in_array( $data, self::$policy_content, true ) ) {
     1304                        self::$policy_content[] = $data;
     1305                }
     1306        }
     1307
     1308        /**
     1309         * Quick check if any privacy info has changed.
     1310         *
     1311         * @since 5.0.0
     1312         */
     1313        public static function text_change_check() {
     1314
     1315                $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1316
     1317                // The site doesn't have a privacy policy.
     1318                if ( empty( $policy_page_id ) ) {
     1319                        return;
     1320                }
     1321
     1322                if ( ! current_user_can( 'edit_post', $policy_page_id ) ) {
     1323                        return;
     1324                }
     1325
     1326                // Also run when the option doesn't exist yet.
     1327                if ( get_option( '_wp_privacy_text_change_check' ) === 'no-check' ) {
     1328                        return;
     1329                }
     1330
     1331                $old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1332                $new = self::$policy_content;
     1333
     1334                // Remove the extra values added to the meta.
     1335                foreach ( $old as $key => $data ) {
     1336                        $old[ $key ] = array(
     1337                                'plugin_name' => $data['plugin_name'],
     1338                                'policy_text' => $data['policy_text'],
     1339                        );
     1340                }
     1341
     1342                // The == operator (equal, not identical) was used intentionally.
     1343                // See http://php.net/manual/en/language.operators.array.php
     1344                if ( $new != $old ) {
     1345                        // A plugin was activated or deactivated, or some policy text has changed.
     1346                        // Show a notice on all screens in wp-admin.
     1347                        add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'policy_text_changed_notice' ) );
     1348                } else {
     1349                        // Stop checking.
     1350                        update_option( '_wp_privacy_text_change_check', 'no-check' );
     1351                }
     1352        }
     1353
     1354        /**
     1355         * Output an admin notice when some privacy info has changed.
     1356         *
     1357         * @since 5.0.0
     1358         */
     1359        public static function policy_text_changed_notice() {
     1360                global $post;
     1361                $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1362
     1363                ?>
     1364                <div class="policy-text-updated notice notice-warning is-dismissible">
     1365                        <p><?php
     1366
     1367                                _e( 'The suggested privacy policy text has changed.' );
     1368
     1369                                if ( empty( $post ) || $post->ID != $policy_page_id ) {
     1370                                        ?>
     1371                                        <a href="<?php echo get_edit_post_link( $policy_page_id ); ?>"><?php _e( 'Edit the privacy policy.' ); ?></a>
     1372                                        <?php
     1373                                }
     1374
     1375                        ?></p>
     1376                </div>
     1377                <?php
     1378        }
     1379
     1380        /**
     1381         * Stop checking for changed privacy info when the policy page is updated.
     1382         *
     1383         * @since 5.0.0
     1384         * @access private
     1385         */
     1386        public static function _policy_page_updated( $post_id ) {
     1387                $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1388
     1389                if ( ! $policy_page_id || $policy_page_id !== (int) $post_id ) {
     1390                        return;
     1391                }
     1392
     1393                // The policy page was updated.
     1394                // Stop checking for text changes.
     1395                update_option( '_wp_privacy_text_change_check', 'no-check' );
     1396
     1397                // Remove updated|removed status.
     1398                $old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1399                $done = array();
     1400                $update_cache = false;
     1401
     1402                foreach ( $old as $old_key => $old_data ) {
     1403                        if ( ! empty( $old_data['removed'] ) ) {
     1404                                // Remove the old policy text.
     1405                                $update_cache = true;
     1406                                continue;
     1407                        }
     1408
     1409                        if ( ! empty( $old_data['updated'] ) ) {
     1410                                // 'updated' is now 'added'.
     1411                                $done[] = array(
     1412                                        'plugin_name' => $old_data['plugin_name'],
     1413                                        'policy_text' => $old_data['policy_text'],
     1414                                        'added'       => $old_data['updated'],
     1415                                );
     1416                                $update_cache = true;
     1417                        } else {
     1418                                $done[] = $old_data;
     1419                        }
     1420                }
     1421
     1422                if ( $update_cache ) {
     1423                        delete_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1424                        // Update the cache.
     1425                        foreach ( $done as $data ) {
     1426                                add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
     1427                        }
     1428                }
     1429        }
     1430
     1431        /**
     1432         * Check for updated, added or removed privacy policy information from plugins.
     1433         *
     1434         * Caches the current info in post_meta of the policy page.
     1435         *
     1436         * @since 5.0.0
     1437         *
     1438         * @return array The privacy policy text/informtion added by core and plugins.
     1439         */
     1440        public static function get_suggested_policy_text() {
     1441                $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1442                $new = self::$policy_content;
     1443                $old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1444                $checked = array();
     1445                $time = time();
     1446                $update_cache = false;
     1447
     1448                // Check for no-changes and updates.
     1449                foreach ( $new as $new_key => $new_data ) {
     1450                        foreach ( $old as $old_key => $old_data ) {
     1451                                $found = false;
     1452
     1453                                if ( $new_data['policy_text'] === $old_data['policy_text'] ) {
     1454                                        // Use the new plugin name in case it was changed, translated, etc.
     1455                                        if ( $old_data['plugin_name'] !== $new_data['plugin_name'] ) {
     1456                                                $old_data['plugin_name'] = $new_data['plugin_name'];
     1457                                                $update_cache = true;
     1458                                        }
     1459
     1460                                        // A plugin was re-activated.
     1461                                        if ( ! empty( $old_data['removed'] ) ) {
     1462                                                unset( $old_data['removed'] );
     1463                                                $old_data['added'] = $time;
     1464                                                $update_cache = true;
     1465                                        }
     1466
     1467                                        $checked[] = $old_data;
     1468                                        $found = true;
     1469                                } elseif ( $new_data['plugin_name'] === $old_data['plugin_name'] ) {
     1470                                        // The info for the policy was updated.
     1471                                        $checked[] = array(
     1472                                                'plugin_name' => $new_data['plugin_name'],
     1473                                                'policy_text' => $new_data['policy_text'],
     1474                                                'updated'     => $time,
     1475                                        );
     1476                                        $found = $update_cache = true;
     1477                                }
     1478
     1479                                if ( $found ) {
     1480                                        unset( $new[ $new_key ], $old[ $old_key ] );
     1481                                        continue 2;
     1482                                }
     1483                        }
     1484                }
     1485
     1486                if ( ! empty( $new ) ) {
     1487                        // A plugin was activated.
     1488                        foreach ( $new as $new_data ) {
     1489                                if ( ! empty( $new_data['plugin_name'] ) && ! empty( $new_data['policy_text'] ) ) {
     1490                                        $new_data['added'] = $time;
     1491                                        array_unshift( $checked, $new_data );
     1492                                }
     1493                        }
     1494                        $update_cache = true;
     1495                }
     1496
     1497                if ( ! empty( $old ) ) {
     1498                        // A plugin was deactivated.
     1499                        foreach ( $old as $old_data ) {
     1500                                if ( ! empty( $old_data['plugin_name'] ) && ! empty( $old_data['policy_text'] ) ) {
     1501                                        $data = array(
     1502                                                'plugin_name' => $old_data['plugin_name'],
     1503                                                'policy_text' => $old_data['policy_text'],
     1504                                                'removed'     => $time,
     1505                                        );
     1506                                        array_unshift( $checked, $data );
     1507                                }
     1508                        }
     1509                        $update_cache = true;
     1510                }
     1511
     1512                if ( $update_cache ) {
     1513                        delete_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
     1514                        // Update the cache.
     1515                        foreach ( $checked as $data ) {
     1516                                add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
     1517                        }
     1518                }
     1519
     1520                // Stop checking for changes after the postbox has been loaded.
     1521                // TODO make this user removable?
     1522                if ( get_option( '_wp_privacy_text_change_check' ) !== 'no-check' ) {
     1523                        update_option( '_wp_privacy_text_change_check', 'no-check' );
     1524                }
     1525
     1526                return $checked;
     1527        }
     1528
     1529        /**
     1530         * Output the postbox when editing the privacy policy page
     1531         *
     1532         * @since 5.0.0
     1533         *
     1534         * @param $post WP_Post The currently edited post.
     1535         */
     1536        public static function privacy_policy_postbox( $post ) {
     1537                if ( ! ( $post instanceof WP_Post ) ) {
     1538                        return;
     1539                }
     1540
     1541                $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     1542
     1543                if ( ! $policy_page_id || $policy_page_id != $post->ID ) {
     1544                        return;
     1545                }
     1546
     1547                $content_array = self::get_suggested_policy_text();
     1548
     1549                $content = '';
     1550                $date_format = get_option( 'date_format' );
     1551                $copy = __( 'Copy' );
     1552
     1553                foreach ( $content_array as $section ) {
     1554                        $class = $meta = '';
     1555
     1556                        if ( ! empty( $section['removed'] ) ) {
     1557                                $class = ' text-removed';
     1558                                $date = date_i18n( $date_format, $section['removed'] );
     1559                                $meta  = sprintf( __( 'Policy text removed %s.' ), $date );
     1560                        } elseif ( ! empty( $section['updated'] ) ) {
     1561                                $class = ' text-updated';
     1562                                $date = date_i18n( $date_format, $section['updated'] );
     1563                                $meta  = sprintf( __( 'Policy text last updated %s.' ), $date );
     1564                        } elseif ( ! empty( $section['added'] ) ) {
     1565                                $class = ' text-added';
     1566                                $date = date_i18n( $date_format, $section['added'] );
     1567                                $meta  = sprintf( __( 'Policy text added %s.' ), $date );
     1568                        }
     1569
     1570                        $content .= '<div class="privacy-text-section' . $class . '">';
     1571                        $content .= '<h3>' . $section['plugin_name'] . '</h3>';
     1572                        $content .= '<button type="button" class="privacy-text-copy-button button">';
     1573                        $content .= $copy;
     1574                        $content .= '<span class="screen-reader-text">' . sprintf( __( 'Copy suggested policy text from %s.' ), $section['plugin_name'] ) . '</span>';
     1575                        $content .= '</button>';
     1576
     1577                        if ( ! empty( $meta ) ) {
     1578                                $content .= '<span class="privacy-text-meta">' . $meta . '</span>';
     1579                        }
     1580
     1581                        $content .= '<div class="policy-text">' . $section['policy_text'] . '</div>';
     1582                        $content .= "</div>\n";
     1583                }
     1584
     1585                ?>
     1586                <div id="privacy-text-box" class="privacy-text-box postbox <?php echo postbox_classes( 'privacy-text-box', 'page' ); ?>">
     1587                        <button type="button" class="handlediv" aria-expanded="true">
     1588                                <span class="screen-reader-text"><?php _e( 'Toggle panel: Suggested privacy policy text' ); ?></span>
     1589                                <span class="toggle-indicator" aria-hidden="true"></span>
     1590                        </button>
     1591                        <div class="privacy-text-box-head hndle">
     1592                                <h2><?php _e( 'This suggested privacy policy text comes from plugins you have installed.' ); ?></h2>
     1593                                <p>
     1594                                        <?php _e( 'We suggest reviewing this text then copying and pasting it into your privacy policy page.' ); ?>
     1595                                        <?php _e( 'Please remember you are responsible for the policies you choose to adopt, so review the content and make any necessary edits.' ); ?>
     1596                                </p>
     1597                        </div>
     1598
     1599                        <div class="privacy-text-box-body">
     1600                                <?php echo $content; ?>
     1601                        </div>
     1602                </div>
     1603                <?php
     1604        }
     1605
     1606        /**
     1607         * Return the suggested text for a privacy policy.
     1608         *
     1609         * @since 5.0.0
     1610         */
     1611        public static function suggested_privacy_policy_content() {
     1612                $suggested_text = '<p>' . __( 'Lorem ipsum dolor sit amet consectetuer id elit enim neque est. Sodales tincidunt Nulla leo penatibus Vestibulum adipiscing est cursus Nam Vestibulum. Orci Vivamus mollis eget pretium dictumst Donec Integer auctor sociis rutrum. Mauris felis Donec neque cursus tellus odio adipiscing netus elit Donec. Vestibulum Cras ligula vitae pretium Curabitur eros Nam Lorem eros non. Sed id mauris justo tristique orci neque eleifend lacus lorem.' ) . "</p>\n";
     1613                $suggested_text .= '<p>' . __( 'Sed consequat Nullam et vel platea semper id mauris Nam eget. Sem neque a amet eu ipsum id dignissim neque eu pulvinar. Mauris nulla egestas et laoreet penatibus ipsum lobortis convallis congue libero. Tortor nibh pellentesque tellus odio Morbi cursus eros tincidunt tincidunt sociis. Egestas at In Donec mi dignissim Nam rutrum felis metus Maecenas. Sed tellus consectetuer.' ) . "</p>\n";
     1614                $suggested_text .= '<p>' . __( 'Justo orci pulvinar mauris tincidunt sed Pellentesque dis sapien tempor ligula. Dolor laoreet fames eros accumsan Integer feugiat nec augue Phasellus rutrum. Id Sed facilisi elit mus nulla at dapibus ut enim sociis. Fringilla ridiculus dui justo eu Maecenas ipsum ut aliquet magna non. Id magna adipiscing Vestibulum Curabitur vel pretium ac justo platea neque. Maecenas Donec Quisque urna interdum.' ) . "</p>\n";
     1615                $suggested_text .= '<p>' . __( 'Tellus sagittis leo adipiscing ante facilisis Aliquam tellus at at elit. Ut dignissim tempus eu Fusce Vestibulum at eros ante dis tempus. Sed libero orci at id ut pretium metus adipiscing justo malesuada. In tempus vitae commodo libero In neque sagittis turpis In In. Eleifend elit dis ac eros urna auctor semper quis odio pretium. Ut Aenean cursus.' ) . "</p>\n";
     1616
     1617                wp_add_privacy_policy_content(  'WordPress', $suggested_text );
     1618        }
     1619}
  • src/wp-admin/includes/plugin.php

     
    20142014        wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
    20152015        include( WP_PLUGIN_DIR . '/' . $plugin );
    20162016}
     2017
     2018/**
     2019 * Helper function for adding plugin specific information to the postbox shown when editing the privacy policy.
     2020 *
     2021 * Intended for use with the `'admin_init'` action.
     2022 *
     2023 * $since 5.0.0
     2024 *
     2025 * @param string $plugin_name The plugin's name. Will be shown in the privacy policy metabox.
     2026 * @param string $policy_text The content that should appear in the site's privacy policy.
     2027 *                            For more information see the Plugins Handbook https://developer.wordpress.org/plugins/.
     2028 */
     2029function wp_add_privacy_policy_content( $plugin_name, $policy_text ) {
     2030        if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) {
     2031                require_once( ABSPATH . 'wp-admin/includes/misc.php' );
     2032        }
     2033
     2034        WP_Privacy_Policy_Content::add( $plugin_name, $policy_text );
     2035}
  • src/wp-admin/js/post.js

     
    12671267
    12681268                update();
    12691269        } );
     1270
     1271        // Privacy policy postbox, copy button.
     1272        $( document ).on( 'click', function( event ) {
     1273                var $target = $( event.target );
     1274                var node, range;
     1275
     1276                if ( $target.is( 'button.privacy-text-copy-button' ) ) {
     1277                        node = $target.parent().find( 'div.policy-text' )[0];
     1278
     1279                        if ( node ) {
     1280                                try {
     1281                                        window.getSelection().removeAllRanges();
     1282                                        range = document.createRange(); 
     1283                                        range.selectNode( node ); 
     1284                                        window.getSelection().addRange( range );
     1285
     1286                                        document.execCommand( 'copy' );
     1287                                        window.getSelection().removeAllRanges();
     1288                                } catch ( er ) {}
     1289                        }
     1290                }
     1291        });
     1292
    12701293} )( jQuery, new wp.utils.WordCounter() );
  • src/wp-includes/default-filters.php

     
    552552// Capabilities
    553553add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 );
    554554
     555// Trigger the check for policy text changes after active plugins change.
     556add_action( 'update_site_option_active_sitewide_plugins', '_wp_privacy_active_plugins_change' );
     557add_action( 'update_option_active_plugins', '_wp_privacy_active_plugins_change' );
     558
    555559unset( $filter, $action );
  • src/wp-includes/functions.php

     
    61276127                ), $email_change_email['message'], $email_change_email['headers']
    61286128        );
    61296129}
     6130
     6131/**
     6132 * Trigger the check for policy text changes.
     6133 *
     6134 * @since 5.0.0
     6135 * @access private
     6136 */
     6137function _wp_privacy_active_plugins_change() {
     6138        update_option( '_wp_privacy_text_change_check', 'check' );
     6139}
  • src/wp-includes/link-template.php

     
    42734273         */
    42744274        return apply_filters( 'parent_theme_file_path', $path, $file );
    42754275}
     4276
     4277/**
     4278 * Retrieves the URL to the privacy policy page.
     4279 *
     4280 * @since 5.0.0
     4281 *
     4282 * @return string The URL to the privacy policy page. Empty string if it doesn't exist.
     4283 */
     4284function get_privacy_policy_url() {
     4285        $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
     4286
     4287        if ( empty( $policy_page_id ) ) {
     4288                return '';
     4289        }
     4290
     4291        return get_permalink( $policy_page_id );
     4292}