Make WordPress Core


Ignore:
Timestamp:
04/16/2018 08:52:18 AM (7 years ago)
Author:
azaozz
Message:

Privacy: add a postbox that is shown when editing the privacy policy page, and where plugins and core will output suggested content and additional privacy info. First run.

Props melchoyce, azaozz.
See #43620.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/misc.php

    r42875 r42980  
    12631263    }
    12641264}
     1265
     1266/**
     1267 * WP_Privacy_Policy_Content class.
     1268 * TODO: move this to a new file.
     1269 *
     1270 * @since 4.9.6
     1271 */
     1272final class WP_Privacy_Policy_Content {
     1273
     1274    private static $policy_content = array();
     1275
     1276    /**
     1277     * Constructor
     1278     *
     1279     * @since 4.9.6
     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 4.9.6
     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 4.9.6
     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 4.9.6
     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 4.9.6
     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 4.9.6
     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 default suggested privacy policy content.
     1608     *
     1609     * @since 4.9.6     
     1610     *
     1611     * @return string The defauld policy content.
     1612     */
     1613    public static function get_default_content() {
     1614        $content  = '<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";
     1615        $content .= '<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";
     1616        $content .= '<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";
     1617        $content .= '<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";
     1618
     1619        /**
     1620         * Filters the default content suggested for inclusion in a privacy policy.
     1621         *
     1622         * @since 4.9.6
     1623         *
     1624         * @param $content string The defauld policy content.
     1625         */
     1626        return apply_filters( 'wp_get_default_privcy_policy_content', $content );
     1627    }
     1628
     1629    /**
     1630     * Add the suggested privacy policy text to the policy postbox.
     1631     *
     1632     * @since 4.9.6
     1633     */
     1634    public static function add_suggested_content() {
     1635        $content = self::get_default_content();
     1636        wp_add_privacy_policy_content(  'WordPress', $content );
     1637    }
     1638}
Note: See TracChangeset for help on using the changeset viewer.