WordPress.org

Make WordPress Core

Ticket #33898: 33898.3.diff

File 33898.3.diff, 19.0 KB (added by westonruter, 4 years ago)

Additional change: https://github.com/xwp/wordpress-develop/commit/9e719a39a76386906800110b4393403f7f66adfb

  • src/wp-admin/customize.php

    diff --git src/wp-admin/customize.php src/wp-admin/customize.php
    index 425af6f..aa949e5 100644
    if ( ! current_user_can( 'customize' ) ) { 
    2020        );
    2121}
    2222
    23 wp_reset_vars( array( 'url', 'return' ) );
    24 $url = wp_unslash( $url );
    25 $url = wp_validate_redirect( $url, home_url( '/' ) );
    26 if ( $return ) {
    27         $return = wp_unslash( $return );
    28         $return = remove_query_arg( wp_removable_query_args(), $return );
    29         $return = wp_validate_redirect( $return );
     23wp_reset_vars( array( 'url', 'return', 'autofocus' ) );
     24if ( ! empty( $url ) ) {
     25        $wp_customize->set_preview_url( wp_unslash( $url ) );
    3026}
    31 if ( ! $return ) {
    32         if ( $url ) {
    33                 $return = $url;
    34         } elseif ( current_user_can( 'edit_theme_options' ) || current_user_can( 'switch_themes' ) ) {
    35                 $return = admin_url( 'themes.php' );
    36         } else {
    37                 $return = admin_url();
    38         }
     27if ( ! empty( $return ) ) {
     28        $wp_customize->set_return_url( wp_unslash( $return ) );
     29}
     30if ( ! empty( $autofocus ) && is_array( $autofocus ) ) {
     31        $wp_customize->set_autofocus( wp_unslash( $autofocus ) );
    3932}
    4033
    4134/**
    if ( wp_is_mobile() ) : 
    8376        ?><meta name="viewport" id="viewport-meta" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=1.2" /><?php
    8477endif;
    8578
    86 $is_ios = wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] );
    87 
    88 if ( $is_ios ) {
     79if ( $wp_customize->is_ios() ) {
    8980        $body_class .= ' ios';
    9081}
    9182
    if ( is_rtl() ) { 
    9485}
    9586$body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
    9687
    97 if ( $wp_customize->is_theme_active() ) {
    98         $document_title_tmpl = _x( 'Customize: %s', 'Placeholder is the document title from the preview' );
    99 } else {
    100         $document_title_tmpl = _x( 'Live Preview: %s', 'Placeholder is the document title from the preview' );
    101 }
    102 $document_title_tmpl = html_entity_decode( $document_title_tmpl, ENT_QUOTES, 'UTF-8' ); // because exported to JS and assigned to document.title
    103 $admin_title = sprintf( $document_title_tmpl, __( 'Loading&hellip;' ) );
     88$admin_title = sprintf( $wp_customize->get_document_title_template(), __( 'Loading&hellip;' ) );
    10489
    10590?><title><?php echo $admin_title; ?></title>
    10691
    10792<script type="text/javascript">
    108 var ajaxurl = '<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>';
     93var ajaxurl = <?php echo wp_json_encode( admin_url( 'admin-ajax.php', 'relative' ) ); ?>;
    10994</script>
    11095
    11196<?php
    do_action( 'customize_controls_print_scripts' ); 
    137122                                <span class="controls"><?php _e( 'Customize' ); ?></span>
    138123                                <span class="preview"><?php _e( 'Preview' ); ?></span>
    139124                        </a>
    140                         <a class="customize-controls-close" href="<?php echo esc_url( $return ); ?>">
     125                        <a class="customize-controls-close" href="<?php echo esc_url( $wp_customize->get_return_url() ); ?>">
    141126                                <span class="screen-reader-text"><?php _e( 'Cancel' ); ?></span>
    142127                        </a>
    143128                </div>
    do_action( 'customize_controls_print_scripts' ); 
    172157        <div id="customize-preview" class="wp-full-overlay-main"></div>
    173158        <?php
    174159
    175         // Render Panel, Section, and Control templates.
    176         $wp_customize->render_panel_templates();
    177         $wp_customize->render_section_templates();
    178         $wp_customize->render_control_templates();
    179 
    180160        /**
    181          * Print Customizer control scripts in the footer.
     161         * Print templates, control scripts, and settings in the footer.
    182162         *
    183163         * @since 3.4.0
    184164         */
    185165        do_action( 'customize_controls_print_footer_scripts' );
    186 
    187         /*
    188          * If the frontend and the admin are served from the same domain, load the
    189          * preview over ssl if the Customizer is being loaded over ssl. This avoids
    190          * insecure content warnings. This is not attempted if the admin and frontend
    191          * are on different domains to avoid the case where the frontend doesn't have
    192          * ssl certs. Domain mapping plugins can allow other urls in these conditions
    193          * using the customize_allowed_urls filter.
    194          */
    195 
    196         $allowed_urls = array( home_url('/') );
    197         $admin_origin = parse_url( admin_url() );
    198         $home_origin  = parse_url( home_url() );
    199         $cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) );
    200 
    201         if ( is_ssl() && ! $cross_domain )
    202                 $allowed_urls[] = home_url( '/', 'https' );
    203 
    204         /**
    205          * Filter the list of URLs allowed to be clicked and followed in the Customizer preview.
    206          *
    207          * @since 3.4.0
    208          *
    209          * @param array $allowed_urls An array of allowed URLs.
    210          */
    211         $allowed_urls = array_unique( apply_filters( 'customize_allowed_urls', $allowed_urls ) );
    212 
    213         $login_url = add_query_arg( array(
    214                 'interim-login' => 1,
    215                 'customize-login' => 1
    216         ), wp_login_url() );
    217 
    218         // Prepare Customizer settings to pass to JavaScript.
    219         $settings = array(
    220                 'theme'    => array(
    221                         'stylesheet' => $wp_customize->get_stylesheet(),
    222                         'active'     => $wp_customize->is_theme_active(),
    223                 ),
    224                 'url'      => array(
    225                         'preview'       => esc_url_raw( $url ? $url : home_url( '/' ) ),
    226                         'parent'        => esc_url_raw( admin_url() ),
    227                         'activated'     => esc_url_raw( home_url( '/' ) ),
    228                         'ajax'          => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ),
    229                         'allowed'       => array_map( 'esc_url_raw', $allowed_urls ),
    230                         'isCrossDomain' => $cross_domain,
    231                         'home'          => esc_url_raw( home_url( '/' ) ),
    232                         'login'         => esc_url_raw( $login_url ),
    233                 ),
    234                 'browser'  => array(
    235                         'mobile' => wp_is_mobile(),
    236                         'ios'    => $is_ios,
    237                 ),
    238                 'settings' => array(),
    239                 'controls' => array(),
    240                 'panels'   => array(),
    241                 'sections' => array(),
    242                 'nonce'    => array(
    243                         'save'    => wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() ),
    244                         'preview' => wp_create_nonce( 'preview-customize_' . $wp_customize->get_stylesheet() )
    245                 ),
    246                 'autofocus' => array(),
    247                 'documentTitleTmpl' => $document_title_tmpl,
    248         );
    249 
    250         // Prepare Customize Setting objects to pass to JavaScript.
    251         foreach ( $wp_customize->settings() as $id => $setting ) {
    252                 if ( $setting->check_capabilities() ) {
    253                         $settings['settings'][ $id ] = array(
    254                                 'value'     => $setting->js_value(),
    255                                 'transport' => $setting->transport,
    256                                 'dirty'     => $setting->dirty,
    257                         );
    258                 }
    259         }
    260 
    261         // Prepare Customize Control objects to pass to JavaScript.
    262         foreach ( $wp_customize->controls() as $id => $control ) {
    263                 if ( $control->check_capabilities() ) {
    264                         $settings['controls'][ $id ] = $control->json();
    265                 }
    266         }
    267 
    268         // Prepare Customize Section objects to pass to JavaScript.
    269         foreach ( $wp_customize->sections() as $id => $section ) {
    270                 if ( $section->check_capabilities() ) {
    271                         $settings['sections'][ $id ] = $section->json();
    272                 }
    273         }
    274 
    275         // Prepare Customize Panel objects to pass to JavaScript.
    276         foreach ( $wp_customize->panels() as $panel_id => $panel ) {
    277                 if ( $panel->check_capabilities() ) {
    278                         $settings['panels'][ $panel_id ] = $panel->json();
    279                         foreach ( $panel->sections as $section_id => $section ) {
    280                                 if ( $section->check_capabilities() ) {
    281                                         $settings['sections'][ $section_id ] = $section->json();
    282                                 }
    283                         }
    284                 }
    285         }
    286 
    287         // Pass to frontend the Customizer construct being deeplinked
    288         if ( isset( $_GET['autofocus'] ) ) {
    289                 $autofocus = wp_unslash( $_GET['autofocus'] );
    290                 if ( is_array( $autofocus ) ) {
    291                         foreach ( $autofocus as $type => $id ) {
    292                                 if ( isset( $settings[ $type . 's' ][ $id ] ) ) {
    293                                         $settings['autofocus'][ $type ] = $id;
    294                                 }
    295                         }
    296                 }
    297         }
    298 
    299166        ?>
    300         <script type="text/javascript">
    301                 var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
    302         </script>
    303167</div>
    304168</body>
    305169</html>
  • src/wp-includes/class-wp-customize-manager.php

    diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
    index 8742c34..ed62fbd 100644
    final class WP_Customize_Manager { 
    9494        protected $registered_control_types = array();
    9595
    9696        /**
     97         * Initial URL being previewed.
     98         *
     99         * @since 4.4.0
     100         * @access protected
     101         * @var string
     102         */
     103        protected $preview_url;
     104
     105        /**
     106         * URL to link the user to when closing the Customizer.
     107         *
     108         * @since 4.4.0
     109         * @access protected
     110         *
     111         * @var string
     112         */
     113        protected $return_url;
     114
     115        /**
     116         * Mapping of 'panel', 'section', 'control' to the ID which should be autofocused.
     117         *
     118         * @since 4.4.0
     119         * @access public
     120         *
     121         * @var array
     122         */
     123        protected $autofocus = array();
     124
     125        /**
    97126         * Unsanitized values for Customize Settings parsed from $_POST['customized'].
    98127         *
    99128         * @var array
    final class WP_Customize_Manager { 
    139168                add_action( 'customize_register',                 array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first
    140169                add_action( 'customize_controls_init',            array( $this, 'prepare_controls' ) );
    141170                add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) );
     171
     172                // Render Panel, Section, and Control templates.
     173                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_panel_templates' ), 1 );
     174                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 );
     175                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_control_templates' ), 1 );
     176
     177                // Export the settings to JS via the _wpCustomizeSettings variable.
     178                add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings' ), 1000 );
    142179        }
    143180
    144181        /**
    final class WP_Customize_Manager { 
    621658         */
    622659        public function customize_preview_settings() {
    623660                $settings = array(
    624                         'values'  => array(),
    625661                        'channel' => wp_unslash( $_POST['customize_messenger_channel'] ),
    626662                        'activePanels' => array(),
    627663                        'activeSections' => array(),
    final class WP_Customize_Manager { 
    638674                        );
    639675                }
    640676
    641                 foreach ( $this->settings as $id => $setting ) {
    642                         if ( $setting->check_capabilities() ) {
    643                                 $settings['values'][ $id ] = $setting->js_value();
    644                         }
    645                 }
    646677                foreach ( $this->panels as $panel_id => $panel ) {
    647678                        if ( $panel->check_capabilities() ) {
    648679                                $settings['activePanels'][ $panel_id ] = $panel->active();
    final class WP_Customize_Manager { 
    667698                ?>
    668699                <script type="text/javascript">
    669700                        var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
     701                        _wpCustomizeSettings.values = {};
     702                        (function( v ) {
     703                                <?php
     704                                /*
     705                                 * Serialize settings separately from the initial _wpCustomizeSettings
     706                                 * serialization in order to avoid a peak memory usage spike.
     707                                 * @todo We may not even need to export the values at all since the pane syncs them anyway.
     708                                 */
     709                                foreach ( $this->settings as $id => $setting ) {
     710                                        if ( $setting->check_capabilities() ) {
     711                                                printf(
     712                                                        "v[%s] = %s;\n",
     713                                                        wp_json_encode( $id ),
     714                                                        wp_json_encode( $setting->js_value() )
     715                                                );
     716                                        }
     717                                }
     718                                ?>
     719                        })( _wpCustomizeSettings.values );
    670720                </script>
    671721                <?php
    672722        }
    final class WP_Customize_Manager { 
    12651315        }
    12661316
    12671317        /**
     1318         * Return whether the user agent is iOS.
     1319         *
     1320         * @since 4.4.0
     1321         * @access public
     1322         *
     1323         * @return bool
     1324         */
     1325        public function is_ios() {
     1326                return wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] );
     1327        }
     1328
     1329        /**
     1330         * Get the template string for the Customizer pane document title.
     1331         *
     1332         * @since 4.4.0
     1333         * @access public
     1334         *
     1335         * @return string
     1336         */
     1337        public function get_document_title_template() {
     1338                if ( $this->is_theme_active() ) {
     1339                        $document_title_tmpl = _x( 'Customize: %s', 'Placeholder is the document title from the preview' );
     1340                } else {
     1341                        $document_title_tmpl = _x( 'Live Preview: %s', 'Placeholder is the document title from the preview' );
     1342                }
     1343                $document_title_tmpl = html_entity_decode( $document_title_tmpl, ENT_QUOTES, 'UTF-8' ); // Because exported to JS and assigned to document.title.
     1344                return $document_title_tmpl;
     1345        }
     1346
     1347        /**
     1348         * Set the initial URL to be previewed.
     1349         *
     1350         * URL is validated.
     1351         *
     1352         * @since 4.4.0
     1353         * @access public
     1354         *
     1355         * @param string $preview_url  URL to be previewed.
     1356         */
     1357        public function set_preview_url( $preview_url ) {
     1358                $this->preview_url = wp_validate_redirect( $preview_url, home_url( '/' ) );
     1359        }
     1360
     1361        /**
     1362         * Get the initial URL to be previewed.
     1363         *
     1364         * @since 4.4.0
     1365         * @access public
     1366         *
     1367         * @return string
     1368         */
     1369        public function get_preview_url() {
     1370                if ( empty( $this->preview_url ) ) {
     1371                        $preview_url = home_url( '/' );
     1372                } else {
     1373                        $preview_url = $this->preview_url;
     1374                }
     1375                return $preview_url;
     1376        }
     1377
     1378        /**
     1379         * Set URL to link the user to when closing the Customizer.
     1380         *
     1381         * URL is validated.
     1382         *
     1383         * @since 4.4.0
     1384         * @access public
     1385         *
     1386         * @param string $return_url  URL for return link.
     1387         */
     1388        public function set_return_url( $return_url ) {
     1389                $return_url = remove_query_arg( wp_removable_query_args(), $return_url );
     1390                $return_url = wp_validate_redirect( $return_url );
     1391                $this->return_url = $return_url;
     1392        }
     1393
     1394        /**
     1395         * Get URL to link the user to when closing the Customizer.
     1396         *
     1397         * @since 4.4.0
     1398         * @access public
     1399         *
     1400         * @return string
     1401         */
     1402        public function get_return_url() {
     1403                if ( $this->return_url ) {
     1404                        $return_url = $this->return_url;
     1405                } else if ( $this->preview_url ) {
     1406                        $return_url = $this->preview_url;
     1407                } elseif ( current_user_can( 'edit_theme_options' ) || current_user_can( 'switch_themes' ) ) {
     1408                        $return_url = admin_url( 'themes.php' );
     1409                } else {
     1410                        $return_url = admin_url();
     1411                }
     1412                return $return_url;
     1413        }
     1414
     1415        /**
     1416         * Set the autofocused constructs.
     1417         *
     1418         * @param array $autofocus {
     1419         *     Mapping of 'panel', 'section', 'control' to the ID which should be autofocused.
     1420         *
     1421         *     @type string [$control]  ID for control to be autofocused.
     1422         *     @type string [$section]  ID for section to be autofocused.
     1423         *     @type string [$panel]    ID for panel to be autofocused.
     1424         * }
     1425         */
     1426        public function set_autofocus( $autofocus ) {
     1427                $this->autofocus = array_map( 'strval', wp_array_slice_assoc( $autofocus, array( 'panel', 'section', 'control' ) ) );
     1428        }
     1429
     1430        /**
     1431         * Get the autofocused constructs.
     1432         *
     1433         * @since 4.4.0
     1434         * @access public
     1435         *
     1436         * @return array {
     1437         *     Mapping of 'panel', 'section', 'control' to the ID which should be autofocused.
     1438         *
     1439         *     @type string [$control]  ID for control to be autofocused.
     1440         *     @type string [$section]  ID for section to be autofocused.
     1441         *     @type string [$panel]    ID for panel to be autofocused.
     1442         * }
     1443         */
     1444        public function get_autofocus() {
     1445                return $this->autofocus;
     1446        }
     1447
     1448        /**
     1449         * Print JavaScript settings for parent window.
     1450         *
     1451         * @since 4.3.0
     1452         */
     1453        public function customize_pane_settings() {
     1454                /*
     1455                 * If the frontend and the admin are served from the same domain, load the
     1456                 * preview over ssl if the Customizer is being loaded over ssl. This avoids
     1457                 * insecure content warnings. This is not attempted if the admin and frontend
     1458                 * are on different domains to avoid the case where the frontend doesn't have
     1459                 * ssl certs. Domain mapping plugins can allow other urls in these conditions
     1460                 * using the customize_allowed_urls filter.
     1461                 */
     1462
     1463                $allowed_urls = array( home_url( '/' ) );
     1464                $admin_origin = parse_url( admin_url() );
     1465                $home_origin  = parse_url( home_url() );
     1466                $cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
     1467
     1468                if ( is_ssl() && ! $cross_domain ) {
     1469                        $allowed_urls[] = home_url( '/', 'https' );
     1470                }
     1471
     1472                /**
     1473                 * Filter the list of URLs allowed to be clicked and followed in the Customizer preview.
     1474                 *
     1475                 * @since 3.4.0
     1476                 *
     1477                 * @param array $allowed_urls An array of allowed URLs.
     1478                 */
     1479                $allowed_urls = array_unique( apply_filters( 'customize_allowed_urls', $allowed_urls ) );
     1480
     1481                $login_url = add_query_arg( array(
     1482                        'interim-login' => 1,
     1483                        'customize-login' => 1,
     1484                ), wp_login_url() );
     1485
     1486                // Prepare Customizer settings to pass to JavaScript.
     1487                $settings = array(
     1488                        'theme'    => array(
     1489                                'stylesheet' => $this->get_stylesheet(),
     1490                                'active'     => $this->is_theme_active(),
     1491                        ),
     1492                        'url'      => array(
     1493                                'preview'       => esc_url_raw( $this->get_preview_url() ),
     1494                                'parent'        => esc_url_raw( admin_url() ),
     1495                                'activated'     => esc_url_raw( home_url( '/' ) ),
     1496                                'ajax'          => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ),
     1497                                'allowed'       => array_map( 'esc_url_raw', $allowed_urls ),
     1498                                'isCrossDomain' => $cross_domain,
     1499                                'home'          => esc_url_raw( home_url( '/' ) ),
     1500                                'login'         => esc_url_raw( $login_url ),
     1501                        ),
     1502                        'browser'  => array(
     1503                                'mobile' => wp_is_mobile(),
     1504                                'ios'    => $this->is_ios(),
     1505                        ),
     1506                        'panels'   => array(),
     1507                        'sections' => array(),
     1508                        'nonce'    => array(
     1509                                'save'    => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ),
     1510                                'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ),
     1511                        ),
     1512                        'autofocus' => array(),
     1513                        'documentTitleTmpl' => $this->get_document_title_template(),
     1514                );
     1515
     1516                // Prepare Customize Section objects to pass to JavaScript.
     1517                foreach ( $this->sections() as $id => $section ) {
     1518                        if ( $section->check_capabilities() ) {
     1519                                $settings['sections'][ $id ] = $section->json();
     1520                        }
     1521                }
     1522
     1523                // Prepare Customize Panel objects to pass to JavaScript.
     1524                foreach ( $this->panels() as $panel_id => $panel ) {
     1525                        if ( $panel->check_capabilities() ) {
     1526                                $settings['panels'][ $panel_id ] = $panel->json();
     1527                                foreach ( $panel->sections as $section_id => $section ) {
     1528                                        if ( $section->check_capabilities() ) {
     1529                                                $settings['sections'][ $section_id ] = $section->json();
     1530                                        }
     1531                                }
     1532                        }
     1533                }
     1534
     1535                // Pass to frontend the Customizer construct being deeplinked.
     1536                foreach ( $this->get_autofocus() as $type => $id ) {
     1537                        $can_autofocus = (
     1538                                ( 'control' === $type && $this->get_control( $id ) && $this->get_control( $id )->check_capabilities() )
     1539                                ||
     1540                                ( 'section' === $type && isset( $settings['sections'][ $id ] ) )
     1541                                ||
     1542                                ( 'panel' === $type && isset( $settings['panels'][ $id ] ) )
     1543                        );
     1544                        if ( $can_autofocus ) {
     1545                                $settings['autofocus'][ $type ] = $id;
     1546                        }
     1547                }
     1548
     1549                ?>
     1550                <script type="text/javascript">
     1551                        var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
     1552                        _wpCustomizeSettings.controls = {};
     1553                        _wpCustomizeSettings.settings = {};
     1554                        <?php
     1555
     1556                        // Serialize settings one by one to improve memory usage.
     1557                        echo "(function ( s ){\n";
     1558                        foreach ( $this->settings() as $setting ) {
     1559                                if ( $setting->check_capabilities() ) {
     1560                                        printf(
     1561                                                "s[%s] = %s;\n",
     1562                                                wp_json_encode( $setting->id ),
     1563                                                wp_json_encode( array(
     1564                                                        'value'     => $setting->js_value(),
     1565                                                        'transport' => $setting->transport,
     1566                                                        'dirty'     => $setting->dirty,
     1567                                                ) )
     1568                                        );
     1569                                }
     1570                        }
     1571                        echo "})( _wpCustomizeSettings.settings );\n";
     1572
     1573                        // Serialize controls one by one to improve memory usage.
     1574                        echo "(function ( c ){\n";
     1575                        foreach ( $this->controls() as $control ) {
     1576                                if ( $control->check_capabilities() ) {
     1577                                        printf(
     1578                                                "c[%s] = %s;\n",
     1579                                                wp_json_encode( $control->id ),
     1580                                                wp_json_encode( $control->json() )
     1581                                        );
     1582                                }
     1583                        }
     1584                        echo "})( _wpCustomizeSettings.controls );\n";
     1585                ?>
     1586                </script>
     1587                <?php
     1588        }
     1589
     1590        /**
    12681591         * Register some default controls.
    12691592         *
    12701593         * @since 3.4.0