Ticket #33898: 33898.2.diff
File 33898.2.diff, 18.8 KB (added by , 10 years ago) |
---|
-
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' ) ) { 20 20 ); 21 21 } 22 22 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 ); 23 wp_reset_vars( array( 'url', 'return', 'autofocus' ) ); 24 if ( ! empty( $url ) ) { 25 $wp_customize->set_preview_url( wp_unslash( $url ) ); 30 26 } 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 } 27 if ( ! empty( $return ) ) { 28 $wp_customize->set_return_url( wp_unslash( $return ) ); 29 } 30 if ( ! empty( $autofocus ) && is_array( $autofocus ) ) { 31 $wp_customize->set_autofocus( wp_unslash( $autofocus ) ); 39 32 } 40 33 41 34 /** … … if ( wp_is_mobile() ) : 83 76 ?><meta name="viewport" id="viewport-meta" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=1.2" /><?php 84 77 endif; 85 78 86 $is_ios = wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] ); 87 88 if ( $is_ios ) { 79 if ( $wp_customize->is_ios() ) { 89 80 $body_class .= ' ios'; 90 81 } 91 82 … … if ( is_rtl() ) { 94 85 } 95 86 $body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); 96 87 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…' ) ); 88 $admin_title = sprintf( $wp_customize->get_document_title_template(), __( 'Loading…' ) ); 104 89 105 90 ?><title><?php echo $admin_title; ?></title> 106 91 107 92 <script type="text/javascript"> 108 var ajaxurl = '<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>';93 var ajaxurl = <?php echo wp_json_encode( admin_url( 'admin-ajax.php', 'relative' ) ); ?>; 109 94 </script> 110 95 111 96 <?php … … do_action( 'customize_controls_print_scripts' ); 137 122 <span class="controls"><?php _e( 'Customize' ); ?></span> 138 123 <span class="preview"><?php _e( 'Preview' ); ?></span> 139 124 </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() ); ?>"> 141 126 <span class="screen-reader-text"><?php _e( 'Cancel' ); ?></span> 142 127 </a> 143 128 </div> … … do_action( 'customize_controls_print_scripts' ); 172 157 <div id="customize-preview" class="wp-full-overlay-main"></div> 173 158 <?php 174 159 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 180 160 /** 181 * Print Customizer control scripts in the footer.161 * Print templates, control scripts, and settings in the footer. 182 162 * 183 163 * @since 3.4.0 184 164 */ 185 165 do_action( 'customize_controls_print_footer_scripts' ); 186 187 /*188 * If the frontend and the admin are served from the same domain, load the189 * preview over ssl if the Customizer is being loaded over ssl. This avoids190 * insecure content warnings. This is not attempted if the admin and frontend191 * are on different domains to avoid the case where the frontend doesn't have192 * ssl certs. Domain mapping plugins can allow other urls in these conditions193 * 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.0208 *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' => 1216 ), 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 deeplinked288 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 299 166 ?> 300 <script type="text/javascript">301 var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;302 </script>303 167 </div> 304 168 </body> 305 169 </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 { 139 139 add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first 140 140 add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); 141 141 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 ); 142 150 } 143 151 144 152 /** … … final class WP_Customize_Manager { 621 629 */ 622 630 public function customize_preview_settings() { 623 631 $settings = array( 624 'values' => array(),625 632 'channel' => wp_unslash( $_POST['customize_messenger_channel'] ), 626 633 'activePanels' => array(), 627 634 'activeSections' => array(), … … final class WP_Customize_Manager { 638 645 ); 639 646 } 640 647 641 foreach ( $this->settings as $id => $setting ) {642 if ( $setting->check_capabilities() ) {643 $settings['values'][ $id ] = $setting->js_value();644 }645 }646 648 foreach ( $this->panels as $panel_id => $panel ) { 647 649 if ( $panel->check_capabilities() ) { 648 650 $settings['activePanels'][ $panel_id ] = $panel->active(); … … final class WP_Customize_Manager { 667 669 ?> 668 670 <script type="text/javascript"> 669 671 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 ); 670 691 </script> 671 692 <?php 672 693 } … … final class WP_Customize_Manager { 1265 1286 } 1266 1287 1267 1288 /** 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 /** 1268 1591 * Register some default controls. 1269 1592 * 1270 1593 * @since 3.4.0