WordPress.org

Make WordPress Core

Ticket #33898: 33898.2.diff

File 33898.2.diff, 18.8 KB (added by westonruter, 4 years ago)

Additional changes: https://github.com/xwp/wordpress-develop/compare/9591c75...a9126f3

  • 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..42b723d 100644
    final class WP_Customize_Manager { 
    139139                add_action( 'customize_register',                 array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first
    140140                add_action( 'customize_controls_init',            array( $this, 'prepare_controls' ) );
    141141                add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) );
     142
     143                // Render Panel, Section, and Control templates.
     144                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_panel_templates' ), 1 );
     145                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 );
     146                add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_control_templates' ), 1 );
     147
     148                // Export the settings to JS via the _wpCustomizeSettings variable.
     149                add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings' ), 1000 );
    142150        }
    143151
    144152        /**
    final class WP_Customize_Manager { 
    621629         */
    622630        public function customize_preview_settings() {
    623631                $settings = array(
    624                         'values'  => array(),
    625632                        'channel' => wp_unslash( $_POST['customize_messenger_channel'] ),
    626633                        'activePanels' => array(),
    627634                        'activeSections' => array(),
    final class WP_Customize_Manager { 
    638645                        );
    639646                }
    640647
    641                 foreach ( $this->settings as $id => $setting ) {
    642                         if ( $setting->check_capabilities() ) {
    643                                 $settings['values'][ $id ] = $setting->js_value();
    644                         }
    645                 }
    646648                foreach ( $this->panels as $panel_id => $panel ) {
    647649                        if ( $panel->check_capabilities() ) {
    648650                                $settings['activePanels'][ $panel_id ] = $panel->active();
    final class WP_Customize_Manager { 
    667669                ?>
    668670                <script type="text/javascript">
    669671                        var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
     672                        _wpCustomizeSettings.values = {};
     673                        (function( v ) {
     674                                <?php
     675                                /*
     676                                 * Serialize settings separately from the initial _wpCustomizeSettings
     677                                 * serialization in order to avoid a peak memory usage spike.
     678                                 * @todo We may not even need to export the values at all since the pane syncs them anyway.
     679                                 */
     680                                foreach ( $this->settings as $id => $setting ) {
     681                                        if ( $setting->check_capabilities() ) {
     682                                                printf(
     683                                                        "v[%s] = %s;\n",
     684                                                        wp_json_encode( $id ),
     685                                                        wp_json_encode( $setting->js_value() )
     686                                                );
     687                                        }
     688                                }
     689                                ?>
     690                        })( _wpCustomizeSettings.values );
    670691                </script>
    671692                <?php
    672693        }
    final class WP_Customize_Manager { 
    12651286        }
    12661287
    12671288        /**
     1289         * Return whether the user agent is iOS.
     1290         *
     1291         * @since 4.4.0
     1292         * @access public
     1293         *
     1294         * @return bool
     1295         */
     1296        public function is_ios() {
     1297                return wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] );
     1298        }
     1299
     1300        /**
     1301         * Get the template string for the Customizer pane document title.
     1302         *
     1303         * @since 4.4.0
     1304         * @access public
     1305         *
     1306         * @return string
     1307         */
     1308        public function get_document_title_template() {
     1309                if ( $this->is_theme_active() ) {
     1310                        $document_title_tmpl = _x( 'Customize: %s', 'Placeholder is the document title from the preview' );
     1311                } else {
     1312                        $document_title_tmpl = _x( 'Live Preview: %s', 'Placeholder is the document title from the preview' );
     1313                }
     1314                $document_title_tmpl = html_entity_decode( $document_title_tmpl, ENT_QUOTES, 'UTF-8' ); // Because exported to JS and assigned to document.title.
     1315                return $document_title_tmpl;
     1316        }
     1317
     1318        /**
     1319         * Initial URL being previewed.
     1320         *
     1321         * @since 4.4.0
     1322         * @access protected
     1323         * @var string
     1324         */
     1325        protected $preview_url;
     1326
     1327        /**
     1328         * Set the initial URL to be previewed.
     1329         *
     1330         * URL is validated.
     1331         *
     1332         * @since 4.4.0
     1333         * @access public
     1334         *
     1335         * @param string $preview_url  URL to be previewed.
     1336         */
     1337        public function set_preview_url( $preview_url ) {
     1338                $this->preview_url = wp_validate_redirect( $preview_url, home_url( '/' ) );
     1339        }
     1340
     1341        /**
     1342         * Get the initial URL to be previewed.
     1343         *
     1344         * @since 4.4.0
     1345         * @access public
     1346         *
     1347         * @return string
     1348         */
     1349        public function get_preview_url() {
     1350                if ( empty( $this->preview_url ) ) {
     1351                        $preview_url = home_url( '/' );
     1352                } else {
     1353                        $preview_url = $this->preview_url;
     1354                }
     1355                return $preview_url;
     1356        }
     1357
     1358        /**
     1359         * URL to link the user to when closing the Customizer.
     1360         *
     1361         * @since 4.4.0
     1362         * @access protected
     1363         *
     1364         * @var string
     1365         */
     1366        protected $return_url;
     1367
     1368        /**
     1369         * Set URL to link the user to when closing the Customizer.
     1370         *
     1371         * URL is validated.
     1372         *
     1373         * @since 4.4.0
     1374         * @access public
     1375         *
     1376         * @param string $return_url  URL for return link.
     1377         */
     1378        public function set_return_url( $return_url ) {
     1379                $return_url = remove_query_arg( wp_removable_query_args(), $return_url );
     1380                $return_url = wp_validate_redirect( $return_url );
     1381                $this->return_url = $return_url;
     1382        }
     1383
     1384        /**
     1385         * Get URL to link the user to when closing the Customizer.
     1386         *
     1387         * @since 4.4.0
     1388         * @access public
     1389         *
     1390         * @return string
     1391         */
     1392        public function get_return_url() {
     1393                if ( $this->return_url ) {
     1394                        $return_url = $this->return_url;
     1395                } else if ( $this->preview_url ) {
     1396                        $return_url = $this->preview_url;
     1397                } elseif ( current_user_can( 'edit_theme_options' ) || current_user_can( 'switch_themes' ) ) {
     1398                        $return_url = admin_url( 'themes.php' );
     1399                } else {
     1400                        $return_url = admin_url();
     1401                }
     1402                return $return_url;
     1403        }
     1404
     1405        /**
     1406         * Mapping of 'panel', 'section', 'control' to the ID which should be autofocused.
     1407         *
     1408         * @since 4.4.0
     1409         * @access public
     1410         *
     1411         * @var array
     1412         */
     1413        protected $autofocus = array();
     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