Ticket #33898: 33898.3.diff
File 33898.3.diff, 19.0 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..ed62fbd 100644
final class WP_Customize_Manager { 94 94 protected $registered_control_types = array(); 95 95 96 96 /** 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 /** 97 126 * Unsanitized values for Customize Settings parsed from $_POST['customized']. 98 127 * 99 128 * @var array … … final class WP_Customize_Manager { 139 168 add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first 140 169 add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); 141 170 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 ); 142 179 } 143 180 144 181 /** … … final class WP_Customize_Manager { 621 658 */ 622 659 public function customize_preview_settings() { 623 660 $settings = array( 624 'values' => array(),625 661 'channel' => wp_unslash( $_POST['customize_messenger_channel'] ), 626 662 'activePanels' => array(), 627 663 'activeSections' => array(), … … final class WP_Customize_Manager { 638 674 ); 639 675 } 640 676 641 foreach ( $this->settings as $id => $setting ) {642 if ( $setting->check_capabilities() ) {643 $settings['values'][ $id ] = $setting->js_value();644 }645 }646 677 foreach ( $this->panels as $panel_id => $panel ) { 647 678 if ( $panel->check_capabilities() ) { 648 679 $settings['activePanels'][ $panel_id ] = $panel->active(); … … final class WP_Customize_Manager { 667 698 ?> 668 699 <script type="text/javascript"> 669 700 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 ); 670 720 </script> 671 721 <?php 672 722 } … … final class WP_Customize_Manager { 1265 1315 } 1266 1316 1267 1317 /** 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 /** 1268 1591 * Register some default controls. 1269 1592 * 1270 1593 * @since 3.4.0