changeset 9 | 177826044cd9 |
parent 7 | cf61fcea0001 |
child 16 | a86126ab1dd4 |
8:c7c34916027a | 9:177826044cd9 |
---|---|
238 |
238 |
239 /** |
239 /** |
240 * Constructor. |
240 * Constructor. |
241 * |
241 * |
242 * @since 3.4.0 |
242 * @since 3.4.0 |
243 * @since 4.7.0 Added $args param. |
243 * @since 4.7.0 Added `$args` parameter. |
244 * |
244 * |
245 * @param array $args { |
245 * @param array $args { |
246 * Args. |
246 * Args. |
247 * |
247 * |
248 * @type null|string|false $changeset_uuid Changeset UUID, the `post_name` for the customize_changeset post containing the customized state. |
248 * @type null|string|false $changeset_uuid Changeset UUID, the `post_name` for the customize_changeset post containing the customized state. |
281 if ( ! isset( $args['messenger_channel'] ) && isset( $_REQUEST['customize_messenger_channel'] ) ) { |
281 if ( ! isset( $args['messenger_channel'] ) && isset( $_REQUEST['customize_messenger_channel'] ) ) { |
282 $args['messenger_channel'] = sanitize_key( wp_unslash( $_REQUEST['customize_messenger_channel'] ) ); |
282 $args['messenger_channel'] = sanitize_key( wp_unslash( $_REQUEST['customize_messenger_channel'] ) ); |
283 } |
283 } |
284 |
284 |
285 $this->original_stylesheet = get_stylesheet(); |
285 $this->original_stylesheet = get_stylesheet(); |
286 $this->theme = wp_get_theme( 0 === validate_file( $args['theme'] ) ? $args['theme'] : null ); |
286 $this->theme = wp_get_theme( 0 === validate_file( $args['theme'] ) ? $args['theme'] : null ); |
287 $this->messenger_channel = $args['messenger_channel']; |
287 $this->messenger_channel = $args['messenger_channel']; |
288 $this->_changeset_uuid = $args['changeset_uuid']; |
288 $this->_changeset_uuid = $args['changeset_uuid']; |
289 |
289 |
290 foreach ( array( 'settings_previewed', 'autosaved', 'branching' ) as $key ) { |
290 foreach ( array( 'settings_previewed', 'autosaved', 'branching' ) as $key ) { |
291 if ( isset( $args[ $key ] ) ) { |
291 if ( isset( $args[ $key ] ) ) { |
292 $this->$key = (bool) $args[ $key ]; |
292 $this->$key = (bool) $args[ $key ]; |
293 } |
293 } |
315 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-control.php' ); |
315 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-control.php' ); |
316 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-location-control.php' ); |
316 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-location-control.php' ); |
317 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' ); |
317 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' ); |
318 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-locations-control.php' ); |
318 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-locations-control.php' ); |
319 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' ); |
319 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' ); |
320 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' ); // @todo Remove in 5.0. See #42364. |
320 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' ); // @todo Remove in a future release. See #42364. |
321 |
321 |
322 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menus-panel.php' ); |
322 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menus-panel.php' ); |
323 |
323 |
324 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-themes-panel.php' ); |
324 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-themes-panel.php' ); |
325 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-themes-section.php' ); |
325 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-themes-section.php' ); |
326 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-sidebar-section.php' ); |
326 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-sidebar-section.php' ); |
327 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-section.php' ); |
327 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-section.php' ); |
328 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-section.php' ); // @todo Remove in 5.0. See #42364. |
328 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-section.php' ); // @todo Remove in a future release. See #42364. |
329 |
329 |
330 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-custom-css-setting.php' ); |
330 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-custom-css-setting.php' ); |
331 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-filter-setting.php' ); |
331 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-filter-setting.php' ); |
332 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-setting.php' ); |
332 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-setting.php' ); |
333 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-background-image-setting.php' ); |
333 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-background-image-setting.php' ); |
344 * |
344 * |
345 * @since 4.4.0 |
345 * @since 4.4.0 |
346 * |
346 * |
347 * @see WP_Customize_Manager::__construct() |
347 * @see WP_Customize_Manager::__construct() |
348 * |
348 * |
349 * @param array $components List of core components to load. |
349 * @param string[] $components Array of core components to load. |
350 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
350 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
351 */ |
351 */ |
352 $components = apply_filters( 'customize_loaded_components', $this->components, $this ); |
352 $components = apply_filters( 'customize_loaded_components', $this->components, $this ); |
353 |
353 |
354 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-selective-refresh.php' ); |
354 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-selective-refresh.php' ); |
363 require_once( ABSPATH . WPINC . '/class-wp-customize-nav-menus.php' ); |
363 require_once( ABSPATH . WPINC . '/class-wp-customize-nav-menus.php' ); |
364 $this->nav_menus = new WP_Customize_Nav_Menus( $this ); |
364 $this->nav_menus = new WP_Customize_Nav_Menus( $this ); |
365 } |
365 } |
366 |
366 |
367 add_action( 'setup_theme', array( $this, 'setup_theme' ) ); |
367 add_action( 'setup_theme', array( $this, 'setup_theme' ) ); |
368 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); |
368 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); |
369 |
369 |
370 // Do not spawn cron (especially the alternate cron) while running the Customizer. |
370 // Do not spawn cron (especially the alternate cron) while running the Customizer. |
371 remove_action( 'init', 'wp_cron' ); |
371 remove_action( 'init', 'wp_cron' ); |
372 |
372 |
373 // Do not run update checks when rendering the controls. |
373 // Do not run update checks when rendering the controls. |
374 remove_action( 'admin_init', '_maybe_update_core' ); |
374 remove_action( 'admin_init', '_maybe_update_core' ); |
375 remove_action( 'admin_init', '_maybe_update_plugins' ); |
375 remove_action( 'admin_init', '_maybe_update_plugins' ); |
376 remove_action( 'admin_init', '_maybe_update_themes' ); |
376 remove_action( 'admin_init', '_maybe_update_themes' ); |
377 |
377 |
378 add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); |
378 add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); |
379 add_action( 'wp_ajax_customize_trash', array( $this, 'handle_changeset_trash_request' ) ); |
379 add_action( 'wp_ajax_customize_trash', array( $this, 'handle_changeset_trash_request' ) ); |
380 add_action( 'wp_ajax_customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); |
380 add_action( 'wp_ajax_customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); |
381 add_action( 'wp_ajax_customize_load_themes', array( $this, 'handle_load_themes_request' ) ); |
381 add_action( 'wp_ajax_customize_load_themes', array( $this, 'handle_load_themes_request' ) ); |
382 add_filter( 'heartbeat_settings', array( $this, 'add_customize_screen_to_heartbeat_settings' ) ); |
382 add_filter( 'heartbeat_settings', array( $this, 'add_customize_screen_to_heartbeat_settings' ) ); |
383 add_filter( 'heartbeat_received', array( $this, 'check_changeset_lock_with_heartbeat' ), 10, 3 ); |
383 add_filter( 'heartbeat_received', array( $this, 'check_changeset_lock_with_heartbeat' ), 10, 3 ); |
384 add_action( 'wp_ajax_customize_override_changeset_lock', array( $this, 'handle_override_changeset_lock_request' ) ); |
384 add_action( 'wp_ajax_customize_override_changeset_lock', array( $this, 'handle_override_changeset_lock_request' ) ); |
385 add_action( 'wp_ajax_customize_dismiss_autosave_or_lock', array( $this, 'handle_dismiss_autosave_or_lock_request' ) ); |
385 add_action( 'wp_ajax_customize_dismiss_autosave_or_lock', array( $this, 'handle_dismiss_autosave_or_lock_request' ) ); |
386 |
386 |
387 add_action( 'customize_register', array( $this, 'register_controls' ) ); |
387 add_action( 'customize_register', array( $this, 'register_controls' ) ); |
388 add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first |
388 add_action( 'customize_register', array( $this, 'register_dynamic_settings' ), 11 ); // allow code to create settings first |
389 add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); |
389 add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); |
390 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) ); |
390 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) ); |
391 |
391 |
392 // Render Common, Panel, Section, and Control templates. |
392 // Render Common, Panel, Section, and Control templates. |
393 add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_panel_templates' ), 1 ); |
393 add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_panel_templates' ), 1 ); |
394 add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 ); |
394 add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 ); |
400 // Export the settings to JS via the _wpCustomizeSettings variable. |
400 // Export the settings to JS via the _wpCustomizeSettings variable. |
401 add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings' ), 1000 ); |
401 add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings' ), 1000 ); |
402 |
402 |
403 // Add theme update notices. |
403 // Add theme update notices. |
404 if ( current_user_can( 'install_themes' ) || current_user_can( 'update_themes' ) ) { |
404 if ( current_user_can( 'install_themes' ) || current_user_can( 'update_themes' ) ) { |
405 require_once ABSPATH . '/wp-admin/includes/update.php'; |
405 require_once ABSPATH . 'wp-admin/includes/update.php'; |
406 add_action( 'customize_controls_print_footer_scripts', 'wp_print_admin_notice_templates' ); |
406 add_action( 'customize_controls_print_footer_scripts', 'wp_print_admin_notice_templates' ); |
407 } |
407 } |
408 } |
408 } |
409 |
409 |
410 /** |
410 /** |
456 wp_print_scripts( array( 'customize-base' ) ); |
456 wp_print_scripts( array( 'customize-base' ) ); |
457 |
457 |
458 $settings = array( |
458 $settings = array( |
459 'messengerArgs' => array( |
459 'messengerArgs' => array( |
460 'channel' => $this->messenger_channel, |
460 'channel' => $this->messenger_channel, |
461 'url' => wp_customize_url(), |
461 'url' => wp_customize_url(), |
462 ), |
462 ), |
463 'error' => $ajax_message, |
463 'error' => $ajax_message, |
464 ); |
464 ); |
465 ?> |
465 ?> |
466 <script> |
466 <script> |
467 ( function( api, settings ) { |
467 ( function( api, settings ) { |
468 var preview = new api.Messenger( settings.messengerArgs ); |
468 var preview = new api.Messenger( settings.messengerArgs ); |
469 preview.send( 'iframe-loading-error', settings.error ); |
469 preview.send( 'iframe-loading-error', settings.error ); |
470 } )( wp.customize, <?php echo wp_json_encode( $settings ) ?> ); |
470 } )( wp.customize, <?php echo wp_json_encode( $settings ); ?> ); |
471 </script> |
471 </script> |
472 <?php |
472 <?php |
473 $message .= ob_get_clean(); |
473 $message .= ob_get_clean(); |
474 } |
474 } |
475 |
475 |
614 |
614 |
615 if ( empty( $this->_changeset_uuid ) ) { |
615 if ( empty( $this->_changeset_uuid ) ) { |
616 $changeset_uuid = null; |
616 $changeset_uuid = null; |
617 |
617 |
618 if ( ! $this->branching() && $this->is_theme_active() ) { |
618 if ( ! $this->branching() && $this->is_theme_active() ) { |
619 $unpublished_changeset_posts = $this->get_changeset_posts( array( |
619 $unpublished_changeset_posts = $this->get_changeset_posts( |
620 'post_status' => array_diff( get_post_stati(), array( 'auto-draft', 'publish', 'trash', 'inherit', 'private' ) ), |
620 array( |
621 'exclude_restore_dismissed' => false, |
621 'post_status' => array_diff( get_post_stati(), array( 'auto-draft', 'publish', 'trash', 'inherit', 'private' ) ), |
622 'author' => 'any', |
622 'exclude_restore_dismissed' => false, |
623 'posts_per_page' => 1, |
623 'author' => 'any', |
624 'order' => 'DESC', |
624 'posts_per_page' => 1, |
625 'orderby' => 'date', |
625 'order' => 'DESC', |
626 ) ); |
626 'orderby' => 'date', |
627 $unpublished_changeset_post = array_shift( $unpublished_changeset_posts ); |
627 ) |
628 ); |
|
629 $unpublished_changeset_post = array_shift( $unpublished_changeset_posts ); |
|
628 if ( ! empty( $unpublished_changeset_post ) && wp_is_uuid( $unpublished_changeset_post->post_name ) ) { |
630 if ( ! empty( $unpublished_changeset_post ) && wp_is_uuid( $unpublished_changeset_post->post_name ) ) { |
629 $changeset_uuid = $unpublished_changeset_post->post_name; |
631 $changeset_uuid = $unpublished_changeset_post->post_name; |
630 } |
632 } |
631 } |
633 } |
632 |
634 |
965 * |
967 * |
966 * @param string $uuid Changeset UUID. |
968 * @param string $uuid Changeset UUID. |
967 * @return int|null Returns post ID on success and null on failure. |
969 * @return int|null Returns post ID on success and null on failure. |
968 */ |
970 */ |
969 public function find_changeset_post_id( $uuid ) { |
971 public function find_changeset_post_id( $uuid ) { |
970 $cache_group = 'customize_changeset_post'; |
972 $cache_group = 'customize_changeset_post'; |
971 $changeset_post_id = wp_cache_get( $uuid, $cache_group ); |
973 $changeset_post_id = wp_cache_get( $uuid, $cache_group ); |
972 if ( $changeset_post_id && 'customize_changeset' === get_post_type( $changeset_post_id ) ) { |
974 if ( $changeset_post_id && 'customize_changeset' === get_post_type( $changeset_post_id ) ) { |
973 return $changeset_post_id; |
975 return $changeset_post_id; |
974 } |
976 } |
975 |
977 |
976 $changeset_post_query = new WP_Query( array( |
978 $changeset_post_query = new WP_Query( |
977 'post_type' => 'customize_changeset', |
979 array( |
978 'post_status' => get_post_stati(), |
980 'post_type' => 'customize_changeset', |
979 'name' => $uuid, |
981 'post_status' => get_post_stati(), |
980 'posts_per_page' => 1, |
982 'name' => $uuid, |
981 'no_found_rows' => true, |
983 'posts_per_page' => 1, |
982 'cache_results' => true, |
984 'no_found_rows' => true, |
983 'update_post_meta_cache' => false, |
985 'cache_results' => true, |
984 'update_post_term_cache' => false, |
986 'update_post_meta_cache' => false, |
985 'lazy_load_term_meta' => false, |
987 'update_post_term_cache' => false, |
986 ) ); |
988 'lazy_load_term_meta' => false, |
989 ) |
|
990 ); |
|
987 if ( ! empty( $changeset_post_query->posts ) ) { |
991 if ( ! empty( $changeset_post_query->posts ) ) { |
988 // Note: 'fields'=>'ids' is not being used in order to cache the post object as it will be needed. |
992 // Note: 'fields'=>'ids' is not being used in order to cache the post object as it will be needed. |
989 $changeset_post_id = $changeset_post_query->posts[0]->ID; |
993 $changeset_post_id = $changeset_post_query->posts[0]->ID; |
990 wp_cache_set( $uuid, $changeset_post_id, $cache_group ); |
994 wp_cache_set( $uuid, $changeset_post_id, $cache_group ); |
991 return $changeset_post_id; |
995 return $changeset_post_id; |
1010 * @return WP_Post[] Auto-draft changesets. |
1014 * @return WP_Post[] Auto-draft changesets. |
1011 */ |
1015 */ |
1012 protected function get_changeset_posts( $args = array() ) { |
1016 protected function get_changeset_posts( $args = array() ) { |
1013 $default_args = array( |
1017 $default_args = array( |
1014 'exclude_restore_dismissed' => true, |
1018 'exclude_restore_dismissed' => true, |
1015 'posts_per_page' => -1, |
1019 'posts_per_page' => -1, |
1016 'post_type' => 'customize_changeset', |
1020 'post_type' => 'customize_changeset', |
1017 'post_status' => 'auto-draft', |
1021 'post_status' => 'auto-draft', |
1018 'order' => 'DESC', |
1022 'order' => 'DESC', |
1019 'orderby' => 'date', |
1023 'orderby' => 'date', |
1020 'no_found_rows' => true, |
1024 'no_found_rows' => true, |
1021 'cache_results' => true, |
1025 'cache_results' => true, |
1022 'update_post_meta_cache' => false, |
1026 'update_post_meta_cache' => false, |
1023 'update_post_term_cache' => false, |
1027 'update_post_term_cache' => false, |
1024 'lazy_load_term_meta' => false, |
1028 'lazy_load_term_meta' => false, |
1025 ); |
1029 ); |
1026 if ( get_current_user_id() ) { |
1030 if ( get_current_user_id() ) { |
1027 $default_args['author'] = get_current_user_id(); |
1031 $default_args['author'] = get_current_user_id(); |
1028 } |
1032 } |
1029 $args = array_merge( $default_args, $args ); |
1033 $args = array_merge( $default_args, $args ); |
1030 |
1034 |
1031 if ( ! empty( $args['exclude_restore_dismissed'] ) ) { |
1035 if ( ! empty( $args['exclude_restore_dismissed'] ) ) { |
1032 unset( $args['exclude_restore_dismissed'] ); |
1036 unset( $args['exclude_restore_dismissed'] ); |
1033 $args['meta_query'] = array( |
1037 $args['meta_query'] = array( |
1034 array( |
1038 array( |
1035 'key' => '_customize_restore_dismissed', |
1039 'key' => '_customize_restore_dismissed', |
1036 'compare' => 'NOT EXISTS', |
1040 'compare' => 'NOT EXISTS', |
1037 ), |
1041 ), |
1038 ); |
1042 ); |
1039 } |
1043 } |
1040 |
1044 |
1046 * |
1050 * |
1047 * @since 4.9.0 |
1051 * @since 4.9.0 |
1048 * @return int The number of auto-drafts that were dismissed. |
1052 * @return int The number of auto-drafts that were dismissed. |
1049 */ |
1053 */ |
1050 protected function dismiss_user_auto_draft_changesets() { |
1054 protected function dismiss_user_auto_draft_changesets() { |
1051 $changeset_autodraft_posts = $this->get_changeset_posts( array( |
1055 $changeset_autodraft_posts = $this->get_changeset_posts( |
1052 'post_status' => 'auto-draft', |
1056 array( |
1053 'exclude_restore_dismissed' => true, |
1057 'post_status' => 'auto-draft', |
1054 'posts_per_page' => -1, |
1058 'exclude_restore_dismissed' => true, |
1055 ) ); |
1059 'posts_per_page' => -1, |
1056 $dismissed = 0; |
1060 ) |
1061 ); |
|
1062 $dismissed = 0; |
|
1057 foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) { |
1063 foreach ( $changeset_autodraft_posts as $autosave_autodraft_post ) { |
1058 if ( $autosave_autodraft_post->ID === $this->changeset_post_id() ) { |
1064 if ( $autosave_autodraft_post->ID === $this->changeset_post_id() ) { |
1059 continue; |
1065 continue; |
1060 } |
1066 } |
1061 if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) { |
1067 if ( update_post_meta( $autosave_autodraft_post->ID, '_customize_restore_dismissed', true ) ) { |
1196 |
1202 |
1197 $changeset_data = $this->get_changeset_post_data( $this->changeset_post_id() ); |
1203 $changeset_data = $this->get_changeset_post_data( $this->changeset_post_id() ); |
1198 } |
1204 } |
1199 |
1205 |
1200 $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array(); |
1206 $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array(); |
1201 $attachments = isset( $starter_content['attachments'] ) && ! empty( $this->nav_menus ) ? $starter_content['attachments'] : array(); |
1207 $attachments = isset( $starter_content['attachments'] ) && ! empty( $this->nav_menus ) ? $starter_content['attachments'] : array(); |
1202 $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array(); |
1208 $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array(); |
1203 $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array(); |
1209 $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array(); |
1204 $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array(); |
1210 $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array(); |
1205 $theme_mods = isset( $starter_content['theme_mods'] ) ? $starter_content['theme_mods'] : array(); |
1211 $theme_mods = isset( $starter_content['theme_mods'] ) ? $starter_content['theme_mods'] : array(); |
1206 |
1212 |
1207 // Widgets. |
1213 // Widgets. |
1208 $max_widget_numbers = array(); |
1214 $max_widget_numbers = array(); |
1209 foreach ( $sidebars_widgets as $sidebar_id => $widgets ) { |
1215 foreach ( $sidebars_widgets as $sidebar_id => $widgets ) { |
1210 $sidebar_widget_ids = array(); |
1216 $sidebar_widget_ids = array(); |
1220 } |
1226 } |
1221 |
1227 |
1222 // Find the max widget number for this type. |
1228 // Find the max widget number for this type. |
1223 $widget_numbers = array_keys( $settings ); |
1229 $widget_numbers = array_keys( $settings ); |
1224 if ( count( $widget_numbers ) > 0 ) { |
1230 if ( count( $widget_numbers ) > 0 ) { |
1225 $widget_numbers[] = 1; |
1231 $widget_numbers[] = 1; |
1226 $max_widget_numbers[ $id_base ] = call_user_func_array( 'max', $widget_numbers ); |
1232 $max_widget_numbers[ $id_base ] = call_user_func_array( 'max', $widget_numbers ); |
1227 } else { |
1233 } else { |
1228 $max_widget_numbers[ $id_base ] = 1; |
1234 $max_widget_numbers[ $id_base ] = 1; |
1229 } |
1235 } |
1230 } |
1236 } |
1231 $max_widget_numbers[ $id_base ] += 1; |
1237 $max_widget_numbers[ $id_base ] += 1; |
1232 |
1238 |
1233 $widget_id = sprintf( '%s-%d', $id_base, $max_widget_numbers[ $id_base ] ); |
1239 $widget_id = sprintf( '%s-%d', $id_base, $max_widget_numbers[ $id_base ] ); |
1234 $setting_id = sprintf( 'widget_%s[%d]', $id_base, $max_widget_numbers[ $id_base ] ); |
1240 $setting_id = sprintf( 'widget_%s[%d]', $id_base, $max_widget_numbers[ $id_base ] ); |
1235 |
1241 |
1236 $setting_value = $this->widgets->sanitize_widget_js_instance( $instance ); |
1242 $setting_value = $this->widgets->sanitize_widget_js_instance( $instance ); |
1237 if ( empty( $changeset_data[ $setting_id ] ) || ! empty( $changeset_data[ $setting_id ]['starter_content'] ) ) { |
1243 if ( empty( $changeset_data[ $setting_id ] ) || ! empty( $changeset_data[ $setting_id ]['starter_content'] ) ) { |
1238 $this->set_post_value( $setting_id, $setting_value ); |
1244 $this->set_post_value( $setting_id, $setting_value ); |
1253 $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, $changeset_data['nav_menus_created_posts']['value'] ); |
1259 $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, $changeset_data['nav_menus_created_posts']['value'] ); |
1254 } |
1260 } |
1255 |
1261 |
1256 // Make an index of all the posts needed and what their slugs are. |
1262 // Make an index of all the posts needed and what their slugs are. |
1257 $needed_posts = array(); |
1263 $needed_posts = array(); |
1258 $attachments = $this->prepare_starter_content_attachments( $attachments ); |
1264 $attachments = $this->prepare_starter_content_attachments( $attachments ); |
1259 foreach ( $attachments as $attachment ) { |
1265 foreach ( $attachments as $attachment ) { |
1260 $key = 'attachment:' . $attachment['post_name']; |
1266 $key = 'attachment:' . $attachment['post_name']; |
1261 $needed_posts[ $key ] = true; |
1267 $needed_posts[ $key ] = true; |
1262 } |
1268 } |
1263 foreach ( array_keys( $posts ) as $post_symbol ) { |
1269 foreach ( array_keys( $posts ) as $post_symbol ) { |
1264 if ( empty( $posts[ $post_symbol ]['post_name'] ) && empty( $posts[ $post_symbol ]['post_title'] ) ) { |
1270 if ( empty( $posts[ $post_symbol ]['post_name'] ) && empty( $posts[ $post_symbol ]['post_title'] ) ) { |
1265 unset( $posts[ $post_symbol ] ); |
1271 unset( $posts[ $post_symbol ] ); |
1285 $post_types = array_filter( array_merge( array( 'attachment' ), wp_list_pluck( $posts, 'post_type' ) ) ); |
1291 $post_types = array_filter( array_merge( array( 'attachment' ), wp_list_pluck( $posts, 'post_type' ) ) ); |
1286 |
1292 |
1287 // Re-use auto-draft starter content posts referenced in the current customized state. |
1293 // Re-use auto-draft starter content posts referenced in the current customized state. |
1288 $existing_starter_content_posts = array(); |
1294 $existing_starter_content_posts = array(); |
1289 if ( ! empty( $starter_content_auto_draft_post_ids ) ) { |
1295 if ( ! empty( $starter_content_auto_draft_post_ids ) ) { |
1290 $existing_posts_query = new WP_Query( array( |
1296 $existing_posts_query = new WP_Query( |
1291 'post__in' => $starter_content_auto_draft_post_ids, |
1297 array( |
1292 'post_status' => 'auto-draft', |
1298 'post__in' => $starter_content_auto_draft_post_ids, |
1293 'post_type' => $post_types, |
1299 'post_status' => 'auto-draft', |
1294 'posts_per_page' => -1, |
1300 'post_type' => $post_types, |
1295 ) ); |
1301 'posts_per_page' => -1, |
1302 ) |
|
1303 ); |
|
1296 foreach ( $existing_posts_query->posts as $existing_post ) { |
1304 foreach ( $existing_posts_query->posts as $existing_post ) { |
1297 $post_name = $existing_post->post_name; |
1305 $post_name = $existing_post->post_name; |
1298 if ( empty( $post_name ) ) { |
1306 if ( empty( $post_name ) ) { |
1299 $post_name = get_post_meta( $existing_post->ID, '_customize_draft_post_name', true ); |
1307 $post_name = get_post_meta( $existing_post->ID, '_customize_draft_post_name', true ); |
1300 } |
1308 } |
1302 } |
1310 } |
1303 } |
1311 } |
1304 |
1312 |
1305 // Re-use non-auto-draft posts. |
1313 // Re-use non-auto-draft posts. |
1306 if ( ! empty( $all_post_slugs ) ) { |
1314 if ( ! empty( $all_post_slugs ) ) { |
1307 $existing_posts_query = new WP_Query( array( |
1315 $existing_posts_query = new WP_Query( |
1308 'post_name__in' => $all_post_slugs, |
1316 array( |
1309 'post_status' => array_diff( get_post_stati(), array( 'auto-draft' ) ), |
1317 'post_name__in' => $all_post_slugs, |
1310 'post_type' => 'any', |
1318 'post_status' => array_diff( get_post_stati(), array( 'auto-draft' ) ), |
1311 'posts_per_page' => -1, |
1319 'post_type' => 'any', |
1312 ) ); |
1320 'posts_per_page' => -1, |
1321 ) |
|
1322 ); |
|
1313 foreach ( $existing_posts_query->posts as $existing_post ) { |
1323 foreach ( $existing_posts_query->posts as $existing_post ) { |
1314 $key = $existing_post->post_type . ':' . $existing_post->post_name; |
1324 $key = $existing_post->post_type . ':' . $existing_post->post_name; |
1315 if ( isset( $needed_posts[ $key ] ) && ! isset( $existing_starter_content_posts[ $key ] ) ) { |
1325 if ( isset( $needed_posts[ $key ] ) && ! isset( $existing_starter_content_posts[ $key ] ) ) { |
1316 $existing_starter_content_posts[ $key ] = $existing_post; |
1326 $existing_starter_content_posts[ $key ] = $existing_post; |
1317 } |
1327 } |
1322 if ( ! empty( $attachments ) ) { |
1332 if ( ! empty( $attachments ) ) { |
1323 |
1333 |
1324 $attachment_ids = array(); |
1334 $attachment_ids = array(); |
1325 |
1335 |
1326 foreach ( $attachments as $symbol => $attachment ) { |
1336 foreach ( $attachments as $symbol => $attachment ) { |
1327 $file_array = array( |
1337 $file_array = array( |
1328 'name' => $attachment['file_name'], |
1338 'name' => $attachment['file_name'], |
1329 ); |
1339 ); |
1330 $file_path = $attachment['file_path']; |
1340 $file_path = $attachment['file_path']; |
1331 $attachment_id = null; |
1341 $attachment_id = null; |
1332 $attached_file = null; |
1342 $attached_file = null; |
1333 if ( isset( $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ] ) ) { |
1343 if ( isset( $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ] ) ) { |
1334 $attachment_post = $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ]; |
1344 $attachment_post = $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ]; |
1335 $attachment_id = $attachment_post->ID; |
1345 $attachment_id = $attachment_post->ID; |
1336 $attached_file = get_attached_file( $attachment_id ); |
1346 $attached_file = get_attached_file( $attachment_id ); |
1337 if ( empty( $attached_file ) || ! file_exists( $attached_file ) ) { |
1347 if ( empty( $attached_file ) || ! file_exists( $attached_file ) ) { |
1338 $attachment_id = null; |
1348 $attachment_id = null; |
1339 $attached_file = null; |
1349 $attached_file = null; |
1340 } elseif ( $this->get_stylesheet() !== get_post_meta( $attachment_post->ID, '_starter_content_theme', true ) ) { |
1350 } elseif ( $this->get_stylesheet() !== get_post_meta( $attachment_post->ID, '_starter_content_theme', true ) ) { |
1341 |
1351 |
1348 |
1358 |
1349 // Insert the attachment auto-draft because it doesn't yet exist or the attached file is gone. |
1359 // Insert the attachment auto-draft because it doesn't yet exist or the attached file is gone. |
1350 if ( ! $attachment_id ) { |
1360 if ( ! $attachment_id ) { |
1351 |
1361 |
1352 // Copy file to temp location so that original file won't get deleted from theme after sideloading. |
1362 // Copy file to temp location so that original file won't get deleted from theme after sideloading. |
1353 $temp_file_name = wp_tempnam( basename( $file_path ) ); |
1363 $temp_file_name = wp_tempnam( wp_basename( $file_path ) ); |
1354 if ( $temp_file_name && copy( $file_path, $temp_file_name ) ) { |
1364 if ( $temp_file_name && copy( $file_path, $temp_file_name ) ) { |
1355 $file_array['tmp_name'] = $temp_file_name; |
1365 $file_array['tmp_name'] = $temp_file_name; |
1356 } |
1366 } |
1357 if ( empty( $file_array['tmp_name'] ) ) { |
1367 if ( empty( $file_array['tmp_name'] ) ) { |
1358 continue; |
1368 continue; |
1432 $this->set_post_value( $setting_id, array_unique( array_values( $starter_content_auto_draft_post_ids ) ) ); |
1442 $this->set_post_value( $setting_id, array_unique( array_values( $starter_content_auto_draft_post_ids ) ) ); |
1433 $this->pending_starter_content_settings_ids[] = $setting_id; |
1443 $this->pending_starter_content_settings_ids[] = $setting_id; |
1434 } |
1444 } |
1435 |
1445 |
1436 // Nav menus. |
1446 // Nav menus. |
1437 $placeholder_id = -1; |
1447 $placeholder_id = -1; |
1438 $reused_nav_menu_setting_ids = array(); |
1448 $reused_nav_menu_setting_ids = array(); |
1439 foreach ( $nav_menus as $nav_menu_location => $nav_menu ) { |
1449 foreach ( $nav_menus as $nav_menu_location => $nav_menu ) { |
1440 |
1450 |
1441 $nav_menu_term_id = null; |
1451 $nav_menu_term_id = null; |
1442 $nav_menu_setting_id = null; |
1452 $nav_menu_setting_id = null; |
1443 $matches = array(); |
1453 $matches = array(); |
1444 |
1454 |
1445 // Look for an existing placeholder menu with starter content to re-use. |
1455 // Look for an existing placeholder menu with starter content to re-use. |
1446 foreach ( $changeset_data as $setting_id => $setting_params ) { |
1456 foreach ( $changeset_data as $setting_id => $setting_params ) { |
1447 $can_reuse = ( |
1457 $can_reuse = ( |
1448 ! empty( $setting_params['starter_content'] ) |
1458 ! empty( $setting_params['starter_content'] ) |
1450 ! in_array( $setting_id, $reused_nav_menu_setting_ids, true ) |
1460 ! in_array( $setting_id, $reused_nav_menu_setting_ids, true ) |
1451 && |
1461 && |
1452 preg_match( '#^nav_menu\[(?P<nav_menu_id>-?\d+)\]$#', $setting_id, $matches ) |
1462 preg_match( '#^nav_menu\[(?P<nav_menu_id>-?\d+)\]$#', $setting_id, $matches ) |
1453 ); |
1463 ); |
1454 if ( $can_reuse ) { |
1464 if ( $can_reuse ) { |
1455 $nav_menu_term_id = intval( $matches['nav_menu_id'] ); |
1465 $nav_menu_term_id = intval( $matches['nav_menu_id'] ); |
1456 $nav_menu_setting_id = $setting_id; |
1466 $nav_menu_setting_id = $setting_id; |
1457 $reused_nav_menu_setting_ids[] = $setting_id; |
1467 $reused_nav_menu_setting_ids[] = $setting_id; |
1458 break; |
1468 break; |
1459 } |
1469 } |
1460 } |
1470 } |
1461 |
1471 |
1462 if ( ! $nav_menu_term_id ) { |
1472 if ( ! $nav_menu_term_id ) { |
1463 while ( isset( $changeset_data[ sprintf( 'nav_menu[%d]', $placeholder_id ) ] ) ) { |
1473 while ( isset( $changeset_data[ sprintf( 'nav_menu[%d]', $placeholder_id ) ] ) ) { |
1464 $placeholder_id--; |
1474 $placeholder_id--; |
1465 } |
1475 } |
1466 $nav_menu_term_id = $placeholder_id; |
1476 $nav_menu_term_id = $placeholder_id; |
1467 $nav_menu_setting_id = sprintf( 'nav_menu[%d]', $placeholder_id ); |
1477 $nav_menu_setting_id = sprintf( 'nav_menu[%d]', $placeholder_id ); |
1468 } |
1478 } |
1469 |
1479 |
1470 $this->set_post_value( $nav_menu_setting_id, array( |
1480 $this->set_post_value( |
1471 'name' => isset( $nav_menu['name'] ) ? $nav_menu['name'] : $nav_menu_location, |
1481 $nav_menu_setting_id, |
1472 ) ); |
1482 array( |
1483 'name' => isset( $nav_menu['name'] ) ? $nav_menu['name'] : $nav_menu_location, |
|
1484 ) |
|
1485 ); |
|
1473 $this->pending_starter_content_settings_ids[] = $nav_menu_setting_id; |
1486 $this->pending_starter_content_settings_ids[] = $nav_menu_setting_id; |
1474 |
1487 |
1475 // @todo Add support for menu_item_parent. |
1488 // @todo Add support for menu_item_parent. |
1476 $position = 0; |
1489 $position = 0; |
1477 foreach ( $nav_menu['items'] as $nav_menu_item ) { |
1490 foreach ( $nav_menu['items'] as $nav_menu_item ) { |
1483 |
1496 |
1484 if ( isset( $nav_menu_item['object_id'] ) ) { |
1497 if ( isset( $nav_menu_item['object_id'] ) ) { |
1485 if ( 'post_type' === $nav_menu_item['type'] && preg_match( '/^{{(?P<symbol>.+)}}$/', $nav_menu_item['object_id'], $matches ) && isset( $posts[ $matches['symbol'] ] ) ) { |
1498 if ( 'post_type' === $nav_menu_item['type'] && preg_match( '/^{{(?P<symbol>.+)}}$/', $nav_menu_item['object_id'], $matches ) && isset( $posts[ $matches['symbol'] ] ) ) { |
1486 $nav_menu_item['object_id'] = $posts[ $matches['symbol'] ]['ID']; |
1499 $nav_menu_item['object_id'] = $posts[ $matches['symbol'] ]['ID']; |
1487 if ( empty( $nav_menu_item['title'] ) ) { |
1500 if ( empty( $nav_menu_item['title'] ) ) { |
1488 $original_object = get_post( $nav_menu_item['object_id'] ); |
1501 $original_object = get_post( $nav_menu_item['object_id'] ); |
1489 $nav_menu_item['title'] = $original_object->post_title; |
1502 $nav_menu_item['title'] = $original_object->post_title; |
1490 } |
1503 } |
1491 } else { |
1504 } else { |
1492 continue; |
1505 continue; |
1493 } |
1506 } |
1538 } |
1551 } |
1539 } |
1552 } |
1540 |
1553 |
1541 // Handle header image as special case since setting has a legacy format. |
1554 // Handle header image as special case since setting has a legacy format. |
1542 if ( 'header_image' === $name ) { |
1555 if ( 'header_image' === $name ) { |
1543 $name = 'header_image_data'; |
1556 $name = 'header_image_data'; |
1544 $metadata = wp_get_attachment_metadata( $value ); |
1557 $metadata = wp_get_attachment_metadata( $value ); |
1545 if ( empty( $metadata ) ) { |
1558 if ( empty( $metadata ) ) { |
1546 continue; |
1559 continue; |
1547 } |
1560 } |
1548 $value = array( |
1561 $value = array( |
1549 'attachment_id' => $value, |
1562 'attachment_id' => $value, |
1550 'url' => wp_get_attachment_url( $value ), |
1563 'url' => wp_get_attachment_url( $value ), |
1551 'height' => $metadata['height'], |
1564 'height' => $metadata['height'], |
1552 'width' => $metadata['width'], |
1565 'width' => $metadata['width'], |
1553 ); |
1566 ); |
1554 } elseif ( 'background_image' === $name ) { |
1567 } elseif ( 'background_image' === $name ) { |
1555 $value = wp_get_attachment_url( $value ); |
1568 $value = wp_get_attachment_url( $value ); |
1556 } |
1569 } |
1557 |
1570 |
1606 } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) { |
1619 } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) { |
1607 $file_path = get_template_directory() . '/' . $attachment['file']; |
1620 $file_path = get_template_directory() . '/' . $attachment['file']; |
1608 } else { |
1621 } else { |
1609 continue; |
1622 continue; |
1610 } |
1623 } |
1611 $file_name = basename( $attachment['file'] ); |
1624 $file_name = wp_basename( $attachment['file'] ); |
1612 |
1625 |
1613 // Skip file types that are not recognized. |
1626 // Skip file types that are not recognized. |
1614 $checked_filetype = wp_check_filetype( $file_name ); |
1627 $checked_filetype = wp_check_filetype( $file_name ); |
1615 if ( empty( $checked_filetype['type'] ) ) { |
1628 if ( empty( $checked_filetype['type'] ) ) { |
1616 continue; |
1629 continue; |
1623 } else { |
1636 } else { |
1624 $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_name ) ); |
1637 $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_name ) ); |
1625 } |
1638 } |
1626 } |
1639 } |
1627 |
1640 |
1628 $attachment['file_name'] = $file_name; |
1641 $attachment['file_name'] = $file_name; |
1629 $attachment['file_path'] = $file_path; |
1642 $attachment['file_path'] = $file_path; |
1630 $prepared_attachments[ $symbol ] = $attachment; |
1643 $prepared_attachments[ $symbol ] = $attachment; |
1631 } |
1644 } |
1632 return $prepared_attachments; |
1645 return $prepared_attachments; |
1633 } |
1646 } |
1634 |
1647 |
1641 |
1654 |
1642 if ( empty( $this->pending_starter_content_settings_ids ) ) { |
1655 if ( empty( $this->pending_starter_content_settings_ids ) ) { |
1643 return; |
1656 return; |
1644 } |
1657 } |
1645 |
1658 |
1646 $this->save_changeset_post( array( |
1659 $this->save_changeset_post( |
1647 'data' => array_fill_keys( $this->pending_starter_content_settings_ids, array( 'starter_content' => true ) ), |
1660 array( |
1648 'starter_content' => true, |
1661 'data' => array_fill_keys( $this->pending_starter_content_settings_ids, array( 'starter_content' => true ) ), |
1649 ) ); |
1662 'starter_content' => true, |
1663 ) |
|
1664 ); |
|
1650 $this->saved_starter_content_changeset = true; |
1665 $this->saved_starter_content_changeset = true; |
1651 |
1666 |
1652 $this->pending_starter_content_settings_ids = array(); |
1667 $this->pending_starter_content_settings_ids = array(); |
1653 } |
1668 } |
1654 |
1669 |
1667 * state was exclusively sourced from `$_POST['customized']`. Nevertheless, |
1682 * state was exclusively sourced from `$_POST['customized']`. Nevertheless, |
1668 * the value returned will come from the current changeset post and from the |
1683 * the value returned will come from the current changeset post and from the |
1669 * incoming post data. |
1684 * incoming post data. |
1670 * |
1685 * |
1671 * @since 4.1.1 |
1686 * @since 4.1.1 |
1672 * @since 4.7.0 Added $args param and merging with changeset values and stashed theme mods. |
1687 * @since 4.7.0 Added `$args` parameter and merging with changeset values and stashed theme mods. |
1673 * |
1688 * |
1674 * @param array $args { |
1689 * @param array $args { |
1675 * Args. |
1690 * Args. |
1676 * |
1691 * |
1677 * @type bool $exclude_changeset Whether the changeset values should also be excluded. Defaults to false. |
1692 * @type bool $exclude_changeset Whether the changeset values should also be excluded. Defaults to false. |
1691 $values = array(); |
1706 $values = array(); |
1692 |
1707 |
1693 // Let default values be from the stashed theme mods if doing a theme switch and if no changeset is present. |
1708 // Let default values be from the stashed theme mods if doing a theme switch and if no changeset is present. |
1694 if ( ! $this->is_theme_active() ) { |
1709 if ( ! $this->is_theme_active() ) { |
1695 $stashed_theme_mods = get_option( 'customize_stashed_theme_mods' ); |
1710 $stashed_theme_mods = get_option( 'customize_stashed_theme_mods' ); |
1696 $stylesheet = $this->get_stylesheet(); |
1711 $stylesheet = $this->get_stylesheet(); |
1697 if ( isset( $stashed_theme_mods[ $stylesheet ] ) ) { |
1712 if ( isset( $stashed_theme_mods[ $stylesheet ] ) ) { |
1698 $values = array_merge( $values, wp_list_pluck( $stashed_theme_mods[ $stylesheet ], 'value' ) ); |
1713 $values = array_merge( $values, wp_list_pluck( $stashed_theme_mods[ $stylesheet ], 'value' ) ); |
1699 } |
1714 } |
1700 } |
1715 } |
1701 |
1716 |
1879 * |
1894 * |
1880 * @param array $headers Headers. |
1895 * @param array $headers Headers. |
1881 * @return array Headers. |
1896 * @return array Headers. |
1882 */ |
1897 */ |
1883 public function filter_iframe_security_headers( $headers ) { |
1898 public function filter_iframe_security_headers( $headers ) { |
1884 $customize_url = admin_url( 'customize.php' ); |
1899 $headers['X-Frame-Options'] = 'SAMEORIGIN'; |
1885 $headers['X-Frame-Options'] = 'ALLOW-FROM ' . $customize_url; |
1900 $headers['Content-Security-Policy'] = "frame-ancestors 'self'"; |
1886 $headers['Content-Security-Policy'] = 'frame-ancestors ' . preg_replace( '#^(\w+://[^/]+).+?$#', '$1', $customize_url ); |
|
1887 return $headers; |
1901 return $headers; |
1888 } |
1902 } |
1889 |
1903 |
1890 /** |
1904 /** |
1891 * Add customize state query params to a given URL if preview is allowed. |
1905 * Add customize state query params to a given URL if preview is allowed. |
1897 * @param string $url URL. |
1911 * @param string $url URL. |
1898 * @return string URL. |
1912 * @return string URL. |
1899 */ |
1913 */ |
1900 public function add_state_query_params( $url ) { |
1914 public function add_state_query_params( $url ) { |
1901 $parsed_original_url = wp_parse_url( $url ); |
1915 $parsed_original_url = wp_parse_url( $url ); |
1902 $is_allowed = false; |
1916 $is_allowed = false; |
1903 foreach ( $this->get_allowed_urls() as $allowed_url ) { |
1917 foreach ( $this->get_allowed_urls() as $allowed_url ) { |
1904 $parsed_allowed_url = wp_parse_url( $allowed_url ); |
1918 $parsed_allowed_url = wp_parse_url( $allowed_url ); |
1905 $is_allowed = ( |
1919 $is_allowed = ( |
1906 $parsed_allowed_url['scheme'] === $parsed_original_url['scheme'] |
1920 $parsed_allowed_url['scheme'] === $parsed_original_url['scheme'] |
1907 && |
1921 && |
1908 $parsed_allowed_url['host'] === $parsed_original_url['host'] |
1922 $parsed_allowed_url['host'] === $parsed_original_url['host'] |
1909 && |
1923 && |
1910 0 === strpos( $parsed_original_url['path'], $parsed_allowed_url['path'] ) |
1924 0 === strpos( $parsed_original_url['path'], $parsed_allowed_url['path'] ) |
1965 * Print CSS for loading indicators for the Customizer preview. |
1979 * Print CSS for loading indicators for the Customizer preview. |
1966 * |
1980 * |
1967 * @since 4.2.0 |
1981 * @since 4.2.0 |
1968 */ |
1982 */ |
1969 public function customize_preview_loading_style() { |
1983 public function customize_preview_loading_style() { |
1970 ?><style> |
1984 ?> |
1985 <style> |
|
1971 body.wp-customizer-unloading { |
1986 body.wp-customizer-unloading { |
1972 opacity: 0.25; |
1987 opacity: 0.25; |
1973 cursor: progress !important; |
1988 cursor: progress !important; |
1974 -webkit-transition: opacity 0.5s; |
1989 -webkit-transition: opacity 0.5s; |
1975 transition: opacity 0.5s; |
1990 transition: opacity 0.5s; |
1983 form.customize-unpreviewable button, |
1998 form.customize-unpreviewable button, |
1984 a.customize-unpreviewable, |
1999 a.customize-unpreviewable, |
1985 area.customize-unpreviewable { |
2000 area.customize-unpreviewable { |
1986 cursor: not-allowed !important; |
2001 cursor: not-allowed !important; |
1987 } |
2002 } |
1988 </style><?php |
2003 </style> |
2004 <?php |
|
1989 } |
2005 } |
1990 |
2006 |
1991 /** |
2007 /** |
1992 * Remove customize_messenger_channel query parameter from the preview window when it is not in an iframe. |
2008 * Remove customize_messenger_channel query parameter from the preview window when it is not in an iframe. |
1993 * |
2009 * |
2029 * Print JavaScript settings for preview frame. |
2045 * Print JavaScript settings for preview frame. |
2030 * |
2046 * |
2031 * @since 3.4.0 |
2047 * @since 3.4.0 |
2032 */ |
2048 */ |
2033 public function customize_preview_settings() { |
2049 public function customize_preview_settings() { |
2034 $post_values = $this->unsanitized_post_values( array( 'exclude_changeset' => true ) ); |
2050 $post_values = $this->unsanitized_post_values( array( 'exclude_changeset' => true ) ); |
2035 $setting_validities = $this->validate_setting_values( $post_values ); |
2051 $setting_validities = $this->validate_setting_values( $post_values ); |
2036 $exported_setting_validities = array_map( array( $this, 'prepare_setting_validity_for_js' ), $setting_validities ); |
2052 $exported_setting_validities = array_map( array( $this, 'prepare_setting_validity_for_js' ), $setting_validities ); |
2037 |
2053 |
2038 // Note that the REQUEST_URI is not passed into home_url() since this breaks subdirectory installations. |
2054 // Note that the REQUEST_URI is not passed into home_url() since this breaks subdirectory installations. |
2039 $self_url = empty( $_SERVER['REQUEST_URI'] ) ? home_url( '/' ) : esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); |
2055 $self_url = empty( $_SERVER['REQUEST_URI'] ) ? home_url( '/' ) : esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); |
2040 $state_query_params = array( |
2056 $state_query_params = array( |
2041 'customize_theme', |
2057 'customize_theme', |
2042 'customize_changeset_uuid', |
2058 'customize_changeset_uuid', |
2043 'customize_messenger_channel', |
2059 'customize_messenger_channel', |
2044 ); |
2060 ); |
2045 $self_url = remove_query_arg( $state_query_params, $self_url ); |
2061 $self_url = remove_query_arg( $state_query_params, $self_url ); |
2046 |
2062 |
2047 $allowed_urls = $this->get_allowed_urls(); |
2063 $allowed_urls = $this->get_allowed_urls(); |
2048 $allowed_hosts = array(); |
2064 $allowed_hosts = array(); |
2049 foreach ( $allowed_urls as $allowed_url ) { |
2065 foreach ( $allowed_urls as $allowed_url ) { |
2050 $parsed = wp_parse_url( $allowed_url ); |
2066 $parsed = wp_parse_url( $allowed_url ); |
2051 if ( empty( $parsed['host'] ) ) { |
2067 if ( empty( $parsed['host'] ) ) { |
2052 continue; |
2068 continue; |
2057 } |
2073 } |
2058 $allowed_hosts[] = $host; |
2074 $allowed_hosts[] = $host; |
2059 } |
2075 } |
2060 |
2076 |
2061 $switched_locale = switch_to_locale( get_user_locale() ); |
2077 $switched_locale = switch_to_locale( get_user_locale() ); |
2062 $l10n = array( |
2078 $l10n = array( |
2063 'shiftClickToEdit' => __( 'Shift-click to edit this element.' ), |
2079 'shiftClickToEdit' => __( 'Shift-click to edit this element.' ), |
2064 'linkUnpreviewable' => __( 'This link is not live-previewable.' ), |
2080 'linkUnpreviewable' => __( 'This link is not live-previewable.' ), |
2065 'formUnpreviewable' => __( 'This form is not live-previewable.' ), |
2081 'formUnpreviewable' => __( 'This form is not live-previewable.' ), |
2066 ); |
2082 ); |
2067 if ( $switched_locale ) { |
2083 if ( $switched_locale ) { |
2068 restore_previous_locale(); |
2084 restore_previous_locale(); |
2069 } |
2085 } |
2070 |
2086 |
2071 $settings = array( |
2087 $settings = array( |
2072 'changeset' => array( |
2088 'changeset' => array( |
2073 'uuid' => $this->changeset_uuid(), |
2089 'uuid' => $this->changeset_uuid(), |
2074 'autosaved' => $this->autosaved(), |
2090 'autosaved' => $this->autosaved(), |
2075 ), |
2091 ), |
2076 'timeouts' => array( |
2092 'timeouts' => array( |
2077 'selectiveRefresh' => 250, |
2093 'selectiveRefresh' => 250, |
2078 'keepAliveSend' => 1000, |
2094 'keepAliveSend' => 1000, |
2079 ), |
2095 ), |
2080 'theme' => array( |
2096 'theme' => array( |
2081 'stylesheet' => $this->get_stylesheet(), |
2097 'stylesheet' => $this->get_stylesheet(), |
2082 'active' => $this->is_theme_active(), |
2098 'active' => $this->is_theme_active(), |
2083 ), |
2099 ), |
2084 'url' => array( |
2100 'url' => array( |
2085 'self' => $self_url, |
2101 'self' => $self_url, |
2086 'allowed' => array_map( 'esc_url_raw', $this->get_allowed_urls() ), |
2102 'allowed' => array_map( 'esc_url_raw', $this->get_allowed_urls() ), |
2087 'allowedHosts' => array_unique( $allowed_hosts ), |
2103 'allowedHosts' => array_unique( $allowed_hosts ), |
2088 'isCrossDomain' => $this->is_cross_domain(), |
2104 'isCrossDomain' => $this->is_cross_domain(), |
2089 ), |
2105 ), |
2090 'channel' => $this->messenger_channel, |
2106 'channel' => $this->messenger_channel, |
2091 'activePanels' => array(), |
2107 'activePanels' => array(), |
2092 'activeSections' => array(), |
2108 'activeSections' => array(), |
2093 'activeControls' => array(), |
2109 'activeControls' => array(), |
2094 'settingValidities' => $exported_setting_validities, |
2110 'settingValidities' => $exported_setting_validities, |
2095 'nonce' => current_user_can( 'customize' ) ? $this->get_nonces() : array(), |
2111 'nonce' => current_user_can( 'customize' ) ? $this->get_nonces() : array(), |
2096 'l10n' => $l10n, |
2112 'l10n' => $l10n, |
2097 '_dirty' => array_keys( $post_values ), |
2113 '_dirty' => array_keys( $post_values ), |
2098 ); |
2114 ); |
2099 |
2115 |
2100 foreach ( $this->panels as $panel_id => $panel ) { |
2116 foreach ( $this->panels as $panel_id => $panel ) { |
2101 if ( $panel->check_capabilities() ) { |
2117 if ( $panel->check_capabilities() ) { |
2102 $settings['activePanels'][ $panel_id ] = $panel->active(); |
2118 $settings['activePanels'][ $panel_id ] = $panel->active(); |
2231 * |
2247 * |
2232 * @param $current_theme {@internal Parameter is not used} |
2248 * @param $current_theme {@internal Parameter is not used} |
2233 * @return string Theme name. |
2249 * @return string Theme name. |
2234 */ |
2250 */ |
2235 public function current_theme( $current_theme ) { |
2251 public function current_theme( $current_theme ) { |
2236 return $this->theme()->display('Name'); |
2252 return $this->theme()->display( 'Name' ); |
2237 } |
2253 } |
2238 |
2254 |
2239 /** |
2255 /** |
2240 * Validates setting values. |
2256 * Validates setting values. |
2241 * |
2257 * |
2257 * @type bool $validate_capability Whether the setting capability will be checked. |
2273 * @type bool $validate_capability Whether the setting capability will be checked. |
2258 * } |
2274 * } |
2259 * @return array Mapping of setting IDs to return value of validate method calls, either `true` or `WP_Error`. |
2275 * @return array Mapping of setting IDs to return value of validate method calls, either `true` or `WP_Error`. |
2260 */ |
2276 */ |
2261 public function validate_setting_values( $setting_values, $options = array() ) { |
2277 public function validate_setting_values( $setting_values, $options = array() ) { |
2262 $options = wp_parse_args( $options, array( |
2278 $options = wp_parse_args( |
2263 'validate_capability' => false, |
2279 $options, |
2264 'validate_existence' => false, |
2280 array( |
2265 ) ); |
2281 'validate_capability' => false, |
2282 'validate_existence' => false, |
|
2283 ) |
|
2284 ); |
|
2266 |
2285 |
2267 $validities = array(); |
2286 $validities = array(); |
2268 foreach ( $setting_values as $setting_id => $unsanitized_value ) { |
2287 foreach ( $setting_values as $setting_id => $unsanitized_value ) { |
2269 $setting = $this->get_setting( $setting_id ); |
2288 $setting = $this->get_setting( $setting_id ); |
2270 if ( ! $setting ) { |
2289 if ( ! $setting ) { |
2282 $validity = $setting->validate( $unsanitized_value ); |
2301 $validity = $setting->validate( $unsanitized_value ); |
2283 } |
2302 } |
2284 if ( ! is_wp_error( $validity ) ) { |
2303 if ( ! is_wp_error( $validity ) ) { |
2285 /** This filter is documented in wp-includes/class-wp-customize-setting.php */ |
2304 /** This filter is documented in wp-includes/class-wp-customize-setting.php */ |
2286 $late_validity = apply_filters( "customize_validate_{$setting->id}", new WP_Error(), $unsanitized_value, $setting ); |
2305 $late_validity = apply_filters( "customize_validate_{$setting->id}", new WP_Error(), $unsanitized_value, $setting ); |
2287 if ( ! empty( $late_validity->errors ) ) { |
2306 if ( is_wp_error( $late_validity ) && $late_validity->has_errors() ) { |
2288 $validity = $late_validity; |
2307 $validity = $late_validity; |
2289 } |
2308 } |
2290 } |
2309 } |
2291 if ( ! is_wp_error( $validity ) ) { |
2310 if ( ! is_wp_error( $validity ) ) { |
2292 $value = $setting->sanitize( $unsanitized_value ); |
2311 $value = $setting->sanitize( $unsanitized_value ); |
2321 if ( is_wp_error( $validity ) ) { |
2340 if ( is_wp_error( $validity ) ) { |
2322 $notification = array(); |
2341 $notification = array(); |
2323 foreach ( $validity->errors as $error_code => $error_messages ) { |
2342 foreach ( $validity->errors as $error_code => $error_messages ) { |
2324 $notification[ $error_code ] = array( |
2343 $notification[ $error_code ] = array( |
2325 'message' => join( ' ', $error_messages ), |
2344 'message' => join( ' ', $error_messages ), |
2326 'data' => $validity->get_error_data( $error_code ), |
2345 'data' => $validity->get_error_data( $error_code ), |
2327 ); |
2346 ); |
2328 } |
2347 } |
2329 return $notification; |
2348 return $notification; |
2330 } else { |
2349 } else { |
2331 return true; |
2350 return true; |
2351 if ( ! check_ajax_referer( $action, 'nonce', false ) ) { |
2370 if ( ! check_ajax_referer( $action, 'nonce', false ) ) { |
2352 wp_send_json_error( 'invalid_nonce' ); |
2371 wp_send_json_error( 'invalid_nonce' ); |
2353 } |
2372 } |
2354 |
2373 |
2355 $changeset_post_id = $this->changeset_post_id(); |
2374 $changeset_post_id = $this->changeset_post_id(); |
2356 $is_new_changeset = empty( $changeset_post_id ); |
2375 $is_new_changeset = empty( $changeset_post_id ); |
2357 if ( $is_new_changeset ) { |
2376 if ( $is_new_changeset ) { |
2358 if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->create_posts ) ) { |
2377 if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->create_posts ) ) { |
2359 wp_send_json_error( 'cannot_create_changeset_post' ); |
2378 wp_send_json_error( 'cannot_create_changeset_post' ); |
2360 } |
2379 } |
2361 } else { |
2380 } else { |
2378 if ( isset( $_POST['customize_changeset_title'] ) ) { |
2397 if ( isset( $_POST['customize_changeset_title'] ) ) { |
2379 $changeset_title = sanitize_text_field( wp_unslash( $_POST['customize_changeset_title'] ) ); |
2398 $changeset_title = sanitize_text_field( wp_unslash( $_POST['customize_changeset_title'] ) ); |
2380 } |
2399 } |
2381 |
2400 |
2382 // Validate changeset status param. |
2401 // Validate changeset status param. |
2383 $is_publish = null; |
2402 $is_publish = null; |
2384 $changeset_status = null; |
2403 $changeset_status = null; |
2385 if ( isset( $_POST['customize_changeset_status'] ) ) { |
2404 if ( isset( $_POST['customize_changeset_status'] ) ) { |
2386 $changeset_status = wp_unslash( $_POST['customize_changeset_status'] ); |
2405 $changeset_status = wp_unslash( $_POST['customize_changeset_status'] ); |
2387 if ( ! get_post_status_object( $changeset_status ) || ! in_array( $changeset_status, array( 'draft', 'pending', 'publish', 'future' ), true ) ) { |
2406 if ( ! get_post_status_object( $changeset_status ) || ! in_array( $changeset_status, array( 'draft', 'pending', 'publish', 'future' ), true ) ) { |
2388 wp_send_json_error( 'bad_customize_changeset_status', 400 ); |
2407 wp_send_json_error( 'bad_customize_changeset_status', 400 ); |
2401 */ |
2420 */ |
2402 $changeset_date_gmt = null; |
2421 $changeset_date_gmt = null; |
2403 if ( isset( $_POST['customize_changeset_date'] ) ) { |
2422 if ( isset( $_POST['customize_changeset_date'] ) ) { |
2404 $changeset_date = wp_unslash( $_POST['customize_changeset_date'] ); |
2423 $changeset_date = wp_unslash( $_POST['customize_changeset_date'] ); |
2405 if ( preg_match( '/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/', $changeset_date ) ) { |
2424 if ( preg_match( '/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/', $changeset_date ) ) { |
2406 $mm = substr( $changeset_date, 5, 2 ); |
2425 $mm = substr( $changeset_date, 5, 2 ); |
2407 $jj = substr( $changeset_date, 8, 2 ); |
2426 $jj = substr( $changeset_date, 8, 2 ); |
2408 $aa = substr( $changeset_date, 0, 4 ); |
2427 $aa = substr( $changeset_date, 0, 4 ); |
2409 $valid_date = wp_checkdate( $mm, $jj, $aa, $changeset_date ); |
2428 $valid_date = wp_checkdate( $mm, $jj, $aa, $changeset_date ); |
2410 if ( ! $valid_date ) { |
2429 if ( ! $valid_date ) { |
2411 wp_send_json_error( 'bad_customize_changeset_date', 400 ); |
2430 wp_send_json_error( 'bad_customize_changeset_date', 400 ); |
2412 } |
2431 } |
2413 $changeset_date_gmt = get_gmt_from_date( $changeset_date ); |
2432 $changeset_date_gmt = get_gmt_from_date( $changeset_date ); |
2419 $changeset_date_gmt = gmdate( 'Y-m-d H:i:s', $timestamp ); |
2438 $changeset_date_gmt = gmdate( 'Y-m-d H:i:s', $timestamp ); |
2420 } |
2439 } |
2421 } |
2440 } |
2422 |
2441 |
2423 $lock_user_id = null; |
2442 $lock_user_id = null; |
2424 $autosave = ! empty( $_POST['customize_changeset_autosave'] ); |
2443 $autosave = ! empty( $_POST['customize_changeset_autosave'] ); |
2425 if ( ! $is_new_changeset ) { |
2444 if ( ! $is_new_changeset ) { |
2426 $lock_user_id = wp_check_post_lock( $this->changeset_post_id() ); |
2445 $lock_user_id = wp_check_post_lock( $this->changeset_post_id() ); |
2427 } |
2446 } |
2428 |
2447 |
2429 // Force request to autosave when changeset is locked. |
2448 // Force request to autosave when changeset is locked. |
2430 if ( $lock_user_id && ! $autosave ) { |
2449 if ( $lock_user_id && ! $autosave ) { |
2431 $autosave = true; |
2450 $autosave = true; |
2432 $changeset_status = null; |
2451 $changeset_status = null; |
2433 $changeset_date_gmt = null; |
2452 $changeset_date_gmt = null; |
2434 } |
2453 } |
2435 |
2454 |
2436 if ( $autosave && ! defined( 'DOING_AUTOSAVE' ) ) { // Back-compat. |
2455 if ( $autosave && ! defined( 'DOING_AUTOSAVE' ) ) { // Back-compat. |
2437 define( 'DOING_AUTOSAVE', true ); |
2456 define( 'DOING_AUTOSAVE', true ); |
2438 } |
2457 } |
2439 |
2458 |
2440 $autosaved = false; |
2459 $autosaved = false; |
2441 $r = $this->save_changeset_post( array( |
2460 $r = $this->save_changeset_post( |
2442 'status' => $changeset_status, |
2461 array( |
2443 'title' => $changeset_title, |
2462 'status' => $changeset_status, |
2444 'date_gmt' => $changeset_date_gmt, |
2463 'title' => $changeset_title, |
2445 'data' => $input_changeset_data, |
2464 'date_gmt' => $changeset_date_gmt, |
2446 'autosave' => $autosave, |
2465 'data' => $input_changeset_data, |
2447 ) ); |
2466 'autosave' => $autosave, |
2467 ) |
|
2468 ); |
|
2448 if ( $autosave && ! is_wp_error( $r ) ) { |
2469 if ( $autosave && ! is_wp_error( $r ) ) { |
2449 $autosaved = true; |
2470 $autosaved = true; |
2450 } |
2471 } |
2451 |
2472 |
2452 // If the changeset was locked and an autosave request wasn't itself an error, then now explicitly return with a failure. |
2473 // If the changeset was locked and an autosave request wasn't itself an error, then now explicitly return with a failure. |
2461 } |
2482 } |
2462 |
2483 |
2463 if ( is_wp_error( $r ) ) { |
2484 if ( is_wp_error( $r ) ) { |
2464 $response = array( |
2485 $response = array( |
2465 'message' => $r->get_error_message(), |
2486 'message' => $r->get_error_message(), |
2466 'code' => $r->get_error_code(), |
2487 'code' => $r->get_error_code(), |
2467 ); |
2488 ); |
2468 if ( is_array( $r->get_error_data() ) ) { |
2489 if ( is_array( $r->get_error_data() ) ) { |
2469 $response = array_merge( $response, $r->get_error_data() ); |
2490 $response = array_merge( $response, $r->get_error_data() ); |
2470 } else { |
2491 } else { |
2471 $response['data'] = $r->get_error_data(); |
2492 $response['data'] = $r->get_error_data(); |
2472 } |
2493 } |
2473 } else { |
2494 } else { |
2474 $response = $r; |
2495 $response = $r; |
2475 $changeset_post = get_post( $this->changeset_post_id() ); |
2496 $changeset_post = get_post( $this->changeset_post_id() ); |
2476 |
2497 |
2477 // Dismiss all other auto-draft changeset posts for this user (they serve like autosave revisions), as there should only be one. |
2498 // Dismiss all other auto-draft changeset posts for this user (they serve like autosave revisions), as there should only be one. |
2478 if ( $is_new_changeset ) { |
2499 if ( $is_new_changeset ) { |
2479 $this->dismiss_user_auto_draft_changesets(); |
2500 $this->dismiss_user_auto_draft_changesets(); |
2547 */ |
2568 */ |
2548 function save_changeset_post( $args = array() ) { |
2569 function save_changeset_post( $args = array() ) { |
2549 |
2570 |
2550 $args = array_merge( |
2571 $args = array_merge( |
2551 array( |
2572 array( |
2552 'status' => null, |
2573 'status' => null, |
2553 'title' => null, |
2574 'title' => null, |
2554 'data' => array(), |
2575 'data' => array(), |
2555 'date_gmt' => null, |
2576 'date_gmt' => null, |
2556 'user_id' => get_current_user_id(), |
2577 'user_id' => get_current_user_id(), |
2557 'starter_content' => false, |
2578 'starter_content' => false, |
2558 'autosave' => false, |
2579 'autosave' => false, |
2559 ), |
2580 ), |
2560 $args |
2581 $args |
2561 ); |
2582 ); |
2562 |
2583 |
2563 $changeset_post_id = $this->changeset_post_id(); |
2584 $changeset_post_id = $this->changeset_post_id(); |
2564 $existing_changeset_data = array(); |
2585 $existing_changeset_data = array(); |
2565 if ( $changeset_post_id ) { |
2586 if ( $changeset_post_id ) { |
2566 $existing_status = get_post_status( $changeset_post_id ); |
2587 $existing_status = get_post_status( $changeset_post_id ); |
2567 if ( 'publish' === $existing_status || 'trash' === $existing_status ) { |
2588 if ( 'publish' === $existing_status || 'trash' === $existing_status ) { |
2568 return new WP_Error( |
2589 return new WP_Error( |
2624 } |
2645 } |
2625 } |
2646 } |
2626 |
2647 |
2627 // The request was made via wp.customize.previewer.save(). |
2648 // The request was made via wp.customize.previewer.save(). |
2628 $update_transactionally = (bool) $args['status']; |
2649 $update_transactionally = (bool) $args['status']; |
2629 $allow_revision = (bool) $args['status']; |
2650 $allow_revision = (bool) $args['status']; |
2630 |
2651 |
2631 // Amend post values with any supplied data. |
2652 // Amend post values with any supplied data. |
2632 foreach ( $args['data'] as $setting_id => $setting_params ) { |
2653 foreach ( $args['data'] as $setting_id => $setting_params ) { |
2633 if ( is_array( $setting_params ) && array_key_exists( 'value', $setting_params ) ) { |
2654 if ( is_array( $setting_params ) && array_key_exists( 'value', $setting_params ) ) { |
2634 $this->set_post_value( $setting_id, $setting_params['value'] ); // Add to post values so that they can be validated and sanitized. |
2655 $this->set_post_value( $setting_id, $setting_params['value'] ); // Add to post values so that they can be validated and sanitized. |
2635 } |
2656 } |
2636 } |
2657 } |
2637 |
2658 |
2638 // Note that in addition to post data, this will include any stashed theme mods. |
2659 // Note that in addition to post data, this will include any stashed theme mods. |
2639 $post_values = $this->unsanitized_post_values( array( |
2660 $post_values = $this->unsanitized_post_values( |
2640 'exclude_changeset' => true, |
2661 array( |
2641 'exclude_post_data' => false, |
2662 'exclude_changeset' => true, |
2642 ) ); |
2663 'exclude_post_data' => false, |
2664 ) |
|
2665 ); |
|
2643 $this->add_dynamic_settings( array_keys( $post_values ) ); // Ensure settings get created even if they lack an input value. |
2666 $this->add_dynamic_settings( array_keys( $post_values ) ); // Ensure settings get created even if they lack an input value. |
2644 |
2667 |
2645 /* |
2668 /* |
2646 * Get list of IDs for settings that have values different from what is currently |
2669 * Get list of IDs for settings that have values different from what is currently |
2647 * saved in the changeset. By skipping any values that are already the same, the |
2670 * saved in the changeset. By skipping any values that are already the same, the |
2684 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
2707 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
2685 */ |
2708 */ |
2686 do_action( 'customize_save_validation_before', $this ); |
2709 do_action( 'customize_save_validation_before', $this ); |
2687 |
2710 |
2688 // Validate settings. |
2711 // Validate settings. |
2689 $validated_values = array_merge( |
2712 $validated_values = array_merge( |
2690 array_fill_keys( array_keys( $args['data'] ), null ), // Make sure existence/capability checks are done on value-less setting updates. |
2713 array_fill_keys( array_keys( $args['data'] ), null ), // Make sure existence/capability checks are done on value-less setting updates. |
2691 $post_values |
2714 $post_values |
2692 ); |
2715 ); |
2693 $setting_validities = $this->validate_setting_values( $validated_values, array( |
2716 $setting_validities = $this->validate_setting_values( |
2694 'validate_capability' => true, |
2717 $validated_values, |
2695 'validate_existence' => true, |
2718 array( |
2696 ) ); |
2719 'validate_capability' => true, |
2720 'validate_existence' => true, |
|
2721 ) |
|
2722 ); |
|
2697 $invalid_setting_count = count( array_filter( $setting_validities, 'is_wp_error' ) ); |
2723 $invalid_setting_count = count( array_filter( $setting_validities, 'is_wp_error' ) ); |
2698 |
2724 |
2699 /* |
2725 /* |
2700 * Short-circuit if there are invalid settings the update is transactional. |
2726 * Short-circuit if there are invalid settings the update is transactional. |
2701 * A changeset update is transactional when a status is supplied in the request. |
2727 * A changeset update is transactional when a status is supplied in the request. |
2702 */ |
2728 */ |
2703 if ( $update_transactionally && $invalid_setting_count > 0 ) { |
2729 if ( $update_transactionally && $invalid_setting_count > 0 ) { |
2704 $response = array( |
2730 $response = array( |
2705 'setting_validities' => $setting_validities, |
2731 'setting_validities' => $setting_validities, |
2706 /* translators: %s: number of invalid settings */ |
2732 /* translators: %s: number of invalid settings */ |
2707 'message' => sprintf( _n( 'Unable to save due to %s invalid setting.', 'Unable to save due to %s invalid settings.', $invalid_setting_count ), number_format_i18n( $invalid_setting_count ) ), |
2733 'message' => sprintf( _n( 'Unable to save due to %s invalid setting.', 'Unable to save due to %s invalid settings.', $invalid_setting_count ), number_format_i18n( $invalid_setting_count ) ), |
2708 ); |
2734 ); |
2709 return new WP_Error( 'transaction_fail', '', $response ); |
2735 return new WP_Error( 'transaction_fail', '', $response ); |
2710 } |
2736 } |
2711 |
2737 |
2712 // Obtain/merge data for changeset. |
2738 // Obtain/merge data for changeset. |
2713 $original_changeset_data = $this->get_changeset_post_data( $changeset_post_id ); |
2739 $original_changeset_data = $this->get_changeset_post_data( $changeset_post_id ); |
2714 $data = $original_changeset_data; |
2740 $data = $original_changeset_data; |
2715 if ( is_wp_error( $data ) ) { |
2741 if ( is_wp_error( $data ) ) { |
2716 $data = array(); |
2742 $data = array(); |
2717 } |
2743 } |
2718 |
2744 |
2719 // Ensure that all post values are included in the changeset data. |
2745 // Ensure that all post values are included in the changeset data. |
2760 } |
2786 } |
2761 |
2787 |
2762 $data[ $changeset_setting_id ] = array_merge( |
2788 $data[ $changeset_setting_id ] = array_merge( |
2763 $merged_setting_params, |
2789 $merged_setting_params, |
2764 array( |
2790 array( |
2765 'type' => $setting->type, |
2791 'type' => $setting->type, |
2766 'user_id' => $args['user_id'], |
2792 'user_id' => $args['user_id'], |
2767 'date_modified_gmt' => current_time( 'mysql', true ), |
2793 'date_modified_gmt' => current_time( 'mysql', true ), |
2768 ) |
2794 ) |
2769 ); |
2795 ); |
2770 |
2796 |
2771 // Clear starter_content flag in data if changeset is not explicitly being updated for starter content. |
2797 // Clear starter_content flag in data if changeset is not explicitly being updated for starter content. |
2774 } |
2800 } |
2775 } |
2801 } |
2776 } |
2802 } |
2777 |
2803 |
2778 $filter_context = array( |
2804 $filter_context = array( |
2779 'uuid' => $this->changeset_uuid(), |
2805 'uuid' => $this->changeset_uuid(), |
2780 'title' => $args['title'], |
2806 'title' => $args['title'], |
2781 'status' => $args['status'], |
2807 'status' => $args['status'], |
2782 'date_gmt' => $args['date_gmt'], |
2808 'date_gmt' => $args['date_gmt'], |
2783 'post_id' => $changeset_post_id, |
2809 'post_id' => $changeset_post_id, |
2784 'previous_data' => is_wp_error( $original_changeset_data ) ? array() : $original_changeset_data, |
2810 'previous_data' => is_wp_error( $original_changeset_data ) ? array() : $original_changeset_data, |
2785 'manager' => $this, |
2811 'manager' => $this, |
2786 ); |
2812 ); |
2787 |
2813 |
2788 /** |
2814 /** |
2789 * Filters the settings' data that will be persisted into the changeset. |
2815 * Filters the settings' data that will be persisted into the changeset. |
2790 * |
2816 * |
2820 $json_options = 0; |
2846 $json_options = 0; |
2821 if ( defined( 'JSON_UNESCAPED_SLASHES' ) ) { |
2847 if ( defined( 'JSON_UNESCAPED_SLASHES' ) ) { |
2822 $json_options |= JSON_UNESCAPED_SLASHES; // Introduced in PHP 5.4. This is only to improve readability as slashes needn't be escaped in storage. |
2848 $json_options |= JSON_UNESCAPED_SLASHES; // Introduced in PHP 5.4. This is only to improve readability as slashes needn't be escaped in storage. |
2823 } |
2849 } |
2824 $json_options |= JSON_PRETTY_PRINT; // Also introduced in PHP 5.4, but WP defines constant for back compat. See WP Trac #30139. |
2850 $json_options |= JSON_PRETTY_PRINT; // Also introduced in PHP 5.4, but WP defines constant for back compat. See WP Trac #30139. |
2825 $post_array = array( |
2851 $post_array = array( |
2826 'post_content' => wp_json_encode( $data, $json_options ), |
2852 'post_content' => wp_json_encode( $data, $json_options ), |
2827 ); |
2853 ); |
2828 if ( $args['title'] ) { |
2854 if ( $args['title'] ) { |
2829 $post_array['post_title'] = $args['title']; |
2855 $post_array['post_title'] = $args['title']; |
2830 } |
2856 } |
2831 if ( $changeset_post_id ) { |
2857 if ( $changeset_post_id ) { |
2832 $post_array['ID'] = $changeset_post_id; |
2858 $post_array['ID'] = $changeset_post_id; |
2833 } else { |
2859 } else { |
2834 $post_array['post_type'] = 'customize_changeset'; |
2860 $post_array['post_type'] = 'customize_changeset'; |
2835 $post_array['post_name'] = $this->changeset_uuid(); |
2861 $post_array['post_name'] = $this->changeset_uuid(); |
2836 $post_array['post_status'] = 'auto-draft'; |
2862 $post_array['post_status'] = 'auto-draft'; |
2837 } |
2863 } |
2838 if ( $args['status'] ) { |
2864 if ( $args['status'] ) { |
2839 $post_array['post_status'] = $args['status']; |
2865 $post_array['post_status'] = $args['status']; |
2840 } |
2866 } |
2841 |
2867 |
2842 // Reset post date to now if we are publishing, otherwise pass post_date_gmt and translate for post_date. |
2868 // Reset post date to now if we are publishing, otherwise pass post_date_gmt and translate for post_date. |
2843 if ( 'publish' === $args['status'] ) { |
2869 if ( 'publish' === $args['status'] ) { |
2844 $post_array['post_date_gmt'] = '0000-00-00 00:00:00'; |
2870 $post_array['post_date_gmt'] = '0000-00-00 00:00:00'; |
2845 $post_array['post_date'] = '0000-00-00 00:00:00'; |
2871 $post_array['post_date'] = '0000-00-00 00:00:00'; |
2846 } elseif ( $args['date_gmt'] ) { |
2872 } elseif ( $args['date_gmt'] ) { |
2847 $post_array['post_date_gmt'] = $args['date_gmt']; |
2873 $post_array['post_date_gmt'] = $args['date_gmt']; |
2848 $post_array['post_date'] = get_date_from_gmt( $args['date_gmt'] ); |
2874 $post_array['post_date'] = get_date_from_gmt( $args['date_gmt'] ); |
2849 } elseif ( $changeset_post_id && 'auto-draft' === get_post_status( $changeset_post_id ) ) { |
2875 } elseif ( $changeset_post_id && 'auto-draft' === get_post_status( $changeset_post_id ) ) { |
2850 /* |
2876 /* |
2851 * Keep bumping the date for the auto-draft whenever it is modified; |
2877 * Keep bumping the date for the auto-draft whenever it is modified; |
2852 * this extends its life, preserving it from garbage-collection via |
2878 * this extends its life, preserving it from garbage-collection via |
2853 * wp_delete_auto_drafts(). |
2879 * wp_delete_auto_drafts(). |
2854 */ |
2880 */ |
2855 $post_array['post_date'] = current_time( 'mysql' ); |
2881 $post_array['post_date'] = current_time( 'mysql' ); |
2856 $post_array['post_date_gmt'] = ''; |
2882 $post_array['post_date_gmt'] = ''; |
2857 } |
2883 } |
2858 |
2884 |
2859 $this->store_changeset_revision = $allow_revision; |
2885 $this->store_changeset_revision = $allow_revision; |
2860 add_filter( 'wp_save_post_revision_post_has_changed', array( $this, '_filter_revision_post_has_changed' ), 5, 3 ); |
2886 add_filter( 'wp_save_post_revision_post_has_changed', array( $this, '_filter_revision_post_has_changed' ), 5, 3 ); |
2861 |
2887 |
2862 // Update the changeset post. The publish_customize_changeset action will cause the settings in the changeset to be saved via WP_Customize_Setting::save(). |
2888 /* |
2889 * Update the changeset post. The publish_customize_changeset action |
|
2890 * will cause the settings in the changeset to be saved via |
|
2891 * WP_Customize_Setting::save(). |
|
2892 */ |
|
2893 |
|
2894 // Prevent content filters from corrupting JSON in post_content. |
|
2863 $has_kses = ( false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ) ); |
2895 $has_kses = ( false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ) ); |
2864 if ( $has_kses ) { |
2896 if ( $has_kses ) { |
2865 kses_remove_filters(); // Prevent KSES from corrupting JSON in post_content. |
2897 kses_remove_filters(); |
2898 } |
|
2899 $has_targeted_link_rel_filters = ( false !== has_filter( 'content_save_pre', 'wp_targeted_link_rel' ) ); |
|
2900 if ( $has_targeted_link_rel_filters ) { |
|
2901 wp_remove_targeted_link_rel_filters(); |
|
2866 } |
2902 } |
2867 |
2903 |
2868 // Note that updating a post with publish status will trigger WP_Customize_Manager::publish_changeset_values(). |
2904 // Note that updating a post with publish status will trigger WP_Customize_Manager::publish_changeset_values(). |
2869 if ( $changeset_post_id ) { |
2905 if ( $changeset_post_id ) { |
2870 if ( $args['autosave'] && 'auto-draft' !== get_post_status( $changeset_post_id ) ) { |
2906 if ( $args['autosave'] && 'auto-draft' !== get_post_status( $changeset_post_id ) ) { |
2871 // See _wp_translate_postdata() for why this is required as it will use the edit_post meta capability. |
2907 // See _wp_translate_postdata() for why this is required as it will use the edit_post meta capability. |
2872 add_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10, 4 ); |
2908 add_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10, 4 ); |
2873 $post_array['post_ID'] = $post_array['ID']; |
2909 $post_array['post_ID'] = $post_array['ID']; |
2874 $post_array['post_type'] = 'customize_changeset'; |
2910 $post_array['post_type'] = 'customize_changeset'; |
2875 $r = wp_create_post_autosave( wp_slash( $post_array ) ); |
2911 $r = wp_create_post_autosave( wp_slash( $post_array ) ); |
2876 remove_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10 ); |
2912 remove_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10 ); |
2877 } else { |
2913 } else { |
2878 $post_array['edit_date'] = true; // Prevent date clearing. |
2914 $post_array['edit_date'] = true; // Prevent date clearing. |
2879 $r = wp_update_post( wp_slash( $post_array ), true ); |
2915 $r = wp_update_post( wp_slash( $post_array ), true ); |
2880 |
2916 |
2881 // Delete autosave revision for user when the changeset is updated. |
2917 // Delete autosave revision for user when the changeset is updated. |
2882 if ( ! empty( $args['user_id'] ) ) { |
2918 if ( ! empty( $args['user_id'] ) ) { |
2883 $autosave_draft = wp_get_post_autosave( $changeset_post_id, $args['user_id'] ); |
2919 $autosave_draft = wp_get_post_autosave( $changeset_post_id, $args['user_id'] ); |
2884 if ( $autosave_draft ) { |
2920 if ( $autosave_draft ) { |
2890 $r = wp_insert_post( wp_slash( $post_array ), true ); |
2926 $r = wp_insert_post( wp_slash( $post_array ), true ); |
2891 if ( ! is_wp_error( $r ) ) { |
2927 if ( ! is_wp_error( $r ) ) { |
2892 $this->_changeset_post_id = $r; // Update cached post ID for the loaded changeset. |
2928 $this->_changeset_post_id = $r; // Update cached post ID for the loaded changeset. |
2893 } |
2929 } |
2894 } |
2930 } |
2931 |
|
2932 // Restore removed content filters. |
|
2895 if ( $has_kses ) { |
2933 if ( $has_kses ) { |
2896 kses_init_filters(); |
2934 kses_init_filters(); |
2897 } |
2935 } |
2936 if ( $has_targeted_link_rel_filters ) { |
|
2937 wp_init_targeted_link_rel_filters(); |
|
2938 } |
|
2939 |
|
2898 $this->_changeset_data = null; // Reset so WP_Customize_Manager::changeset_data() will re-populate with updated contents. |
2940 $this->_changeset_data = null; // Reset so WP_Customize_Manager::changeset_data() will re-populate with updated contents. |
2899 |
2941 |
2900 remove_filter( 'wp_save_post_revision_post_has_changed', array( $this, '_filter_revision_post_has_changed' ) ); |
2942 remove_filter( 'wp_save_post_revision_post_has_changed', array( $this, '_filter_revision_post_has_changed' ) ); |
2901 |
2943 |
2902 $response = array( |
2944 $response = array( |
2963 |
3005 |
2964 $post->post_status = $new_status; |
3006 $post->post_status = $new_status; |
2965 wp_transition_post_status( $new_status, $old_status, $post ); |
3007 wp_transition_post_status( $new_status, $old_status, $post ); |
2966 |
3008 |
2967 /** This action is documented in wp-includes/post.php */ |
3009 /** This action is documented in wp-includes/post.php */ |
3010 do_action( "edit_post_{$post->post_type}", $post->ID, $post ); |
|
3011 |
|
3012 /** This action is documented in wp-includes/post.php */ |
|
2968 do_action( 'edit_post', $post->ID, $post ); |
3013 do_action( 'edit_post', $post->ID, $post ); |
2969 |
3014 |
2970 /** This action is documented in wp-includes/post.php */ |
3015 /** This action is documented in wp-includes/post.php */ |
2971 do_action( "save_post_{$post->post_type}", $post->ID, $post, true ); |
3016 do_action( "save_post_{$post->post_type}", $post->ID, $post, true ); |
2972 |
3017 |
2997 if ( ! $this->is_preview() ) { |
3042 if ( ! $this->is_preview() ) { |
2998 wp_send_json_error( 'not_preview' ); |
3043 wp_send_json_error( 'not_preview' ); |
2999 } |
3044 } |
3000 |
3045 |
3001 if ( ! check_ajax_referer( 'trash_customize_changeset', 'nonce', false ) ) { |
3046 if ( ! check_ajax_referer( 'trash_customize_changeset', 'nonce', false ) ) { |
3002 wp_send_json_error( array( |
3047 wp_send_json_error( |
3003 'code' => 'invalid_nonce', |
3048 array( |
3004 'message' => __( 'There was an authentication problem. Please reload and try again.' ), |
3049 'code' => 'invalid_nonce', |
3005 ) ); |
3050 'message' => __( 'There was an authentication problem. Please reload and try again.' ), |
3051 ) |
|
3052 ); |
|
3006 } |
3053 } |
3007 |
3054 |
3008 $changeset_post_id = $this->changeset_post_id(); |
3055 $changeset_post_id = $this->changeset_post_id(); |
3009 |
3056 |
3010 if ( ! $changeset_post_id ) { |
3057 if ( ! $changeset_post_id ) { |
3011 wp_send_json_error( array( |
3058 wp_send_json_error( |
3012 'message' => __( 'No changes saved yet, so there is nothing to trash.' ), |
3059 array( |
3013 'code' => 'non_existent_changeset', |
3060 'message' => __( 'No changes saved yet, so there is nothing to trash.' ), |
3014 ) ); |
3061 'code' => 'non_existent_changeset', |
3062 ) |
|
3063 ); |
|
3015 return; |
3064 return; |
3016 } |
3065 } |
3017 |
3066 |
3018 if ( $changeset_post_id && ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->delete_post, $changeset_post_id ) ) { |
3067 if ( $changeset_post_id && ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->delete_post, $changeset_post_id ) ) { |
3019 wp_send_json_error( array( |
3068 wp_send_json_error( |
3020 'code' => 'changeset_trash_unauthorized', |
3069 array( |
3021 'message' => __( 'Unable to trash changes.' ), |
3070 'code' => 'changeset_trash_unauthorized', |
3022 ) ); |
3071 'message' => __( 'Unable to trash changes.' ), |
3072 ) |
|
3073 ); |
|
3023 } |
3074 } |
3024 |
3075 |
3025 if ( 'trash' === get_post_status( $changeset_post_id ) ) { |
3076 if ( 'trash' === get_post_status( $changeset_post_id ) ) { |
3026 wp_send_json_error( array( |
3077 wp_send_json_error( |
3027 'message' => __( 'Changes have already been trashed.' ), |
3078 array( |
3028 'code' => 'changeset_already_trashed', |
3079 'message' => __( 'Changes have already been trashed.' ), |
3029 ) ); |
3080 'code' => 'changeset_already_trashed', |
3081 ) |
|
3082 ); |
|
3030 return; |
3083 return; |
3031 } |
3084 } |
3032 |
3085 |
3033 $r = $this->trash_changeset_post( $changeset_post_id ); |
3086 $r = $this->trash_changeset_post( $changeset_post_id ); |
3034 if ( ! ( $r instanceof WP_Post ) ) { |
3087 if ( ! ( $r instanceof WP_Post ) ) { |
3035 wp_send_json_error( array( |
3088 wp_send_json_error( |
3036 'code' => 'changeset_trash_failure', |
3089 array( |
3037 'message' => __( 'Unable to trash changes.' ), |
3090 'code' => 'changeset_trash_failure', |
3038 ) ); |
3091 'message' => __( 'Unable to trash changes.' ), |
3039 } |
3092 ) |
3040 |
3093 ); |
3041 wp_send_json_success( array( |
3094 } |
3042 'message' => __( 'Changes trashed successfully.' ), |
3095 |
3043 ) ); |
3096 wp_send_json_success( |
3097 array( |
|
3098 'message' => __( 'Changes trashed successfully.' ), |
|
3099 ) |
|
3100 ); |
|
3044 } |
3101 } |
3045 |
3102 |
3046 /** |
3103 /** |
3047 * Re-map 'edit_post' meta cap for a customize_changeset post to be the same as 'customize' maps. |
3104 * Re-map 'edit_post' meta cap for a customize_changeset post to be the same as 'customize' maps. |
3048 * |
3105 * |
3056 * @since 4.9.0 |
3113 * @since 4.9.0 |
3057 * @link https://core.trac.wordpress.org/ticket/40922 |
3114 * @link https://core.trac.wordpress.org/ticket/40922 |
3058 * @see WP_Customize_Manager::save_changeset_post() |
3115 * @see WP_Customize_Manager::save_changeset_post() |
3059 * @see _wp_translate_postdata() |
3116 * @see _wp_translate_postdata() |
3060 * |
3117 * |
3061 * @param array $caps Returns the user's actual capabilities. |
3118 * @param string[] $caps Array of the user's capabilities. |
3062 * @param string $cap Capability name. |
3119 * @param string $cap Capability name. |
3063 * @param int $user_id The user ID. |
3120 * @param int $user_id The user ID. |
3064 * @param array $args Adds the context to the cap. Typically the object ID. |
3121 * @param array $args Adds the context to the cap. Typically the object ID. |
3065 * @return array Capabilities. |
3122 * @return array Capabilities. |
3066 */ |
3123 */ |
3067 public function grant_edit_post_capability_for_changeset( $caps, $cap, $user_id, $args ) { |
3124 public function grant_edit_post_capability_for_changeset( $caps, $cap, $user_id, $args ) { |
3068 if ( 'edit_post' === $cap && ! empty( $args[0] ) && 'customize_changeset' === get_post_type( $args[0] ) ) { |
3125 if ( 'edit_post' === $cap && ! empty( $args[0] ) && 'customize_changeset' === get_post_type( $args[0] ) ) { |
3069 $post_type_obj = get_post_type_object( 'customize_changeset' ); |
3126 $post_type_obj = get_post_type_object( 'customize_changeset' ); |
3070 $caps = map_meta_cap( $post_type_obj->cap->$cap, $user_id ); |
3127 $caps = map_meta_cap( $post_type_obj->cap->$cap, $user_id ); |
3071 } |
3128 } |
3072 return $caps; |
3129 return $caps; |
3073 } |
3130 } |
3074 |
3131 |
3075 /** |
3132 /** |
3110 } |
3167 } |
3111 $lock = get_post_meta( $changeset_post_id, '_edit_lock', true ); |
3168 $lock = get_post_meta( $changeset_post_id, '_edit_lock', true ); |
3112 $lock = explode( ':', $lock ); |
3169 $lock = explode( ':', $lock ); |
3113 |
3170 |
3114 if ( $lock && ! empty( $lock[1] ) ) { |
3171 if ( $lock && ! empty( $lock[1] ) ) { |
3115 $user_id = intval( $lock[1] ); |
3172 $user_id = intval( $lock[1] ); |
3116 $current_user_id = get_current_user_id(); |
3173 $current_user_id = get_current_user_id(); |
3117 if ( $user_id === $current_user_id ) { |
3174 if ( $user_id === $current_user_id ) { |
3118 $lock = sprintf( '%s:%s', time(), $user_id ); |
3175 $lock = sprintf( '%s:%s', time(), $user_id ); |
3119 update_post_meta( $changeset_post_id, '_edit_lock', $lock ); |
3176 update_post_meta( $changeset_post_id, '_edit_lock', $lock ); |
3120 } |
3177 } |
3151 $lock_user = get_userdata( $user_id ); |
3208 $lock_user = get_userdata( $user_id ); |
3152 if ( ! $lock_user ) { |
3209 if ( ! $lock_user ) { |
3153 return null; |
3210 return null; |
3154 } |
3211 } |
3155 return array( |
3212 return array( |
3156 'id' => $lock_user->ID, |
3213 'id' => $lock_user->ID, |
3157 'name' => $lock_user->display_name, |
3214 'name' => $lock_user->display_name, |
3158 'avatar' => get_avatar_url( $lock_user->ID, array( 'size' => 128 ) ), |
3215 'avatar' => get_avatar_url( $lock_user->ID, array( 'size' => 128 ) ), |
3159 ); |
3216 ); |
3160 } |
3217 } |
3161 |
3218 |
3162 /** |
3219 /** |
3205 if ( ! $this->is_preview() ) { |
3262 if ( ! $this->is_preview() ) { |
3206 wp_send_json_error( 'not_preview', 400 ); |
3263 wp_send_json_error( 'not_preview', 400 ); |
3207 } |
3264 } |
3208 |
3265 |
3209 if ( ! check_ajax_referer( 'customize_override_changeset_lock', 'nonce', false ) ) { |
3266 if ( ! check_ajax_referer( 'customize_override_changeset_lock', 'nonce', false ) ) { |
3210 wp_send_json_error( array( |
3267 wp_send_json_error( |
3211 'code' => 'invalid_nonce', |
3268 array( |
3212 'message' => __( 'Security check failed.' ), |
3269 'code' => 'invalid_nonce', |
3213 ) ); |
3270 'message' => __( 'Security check failed.' ), |
3271 ) |
|
3272 ); |
|
3214 } |
3273 } |
3215 |
3274 |
3216 $changeset_post_id = $this->changeset_post_id(); |
3275 $changeset_post_id = $this->changeset_post_id(); |
3217 |
3276 |
3218 if ( empty( $changeset_post_id ) ) { |
3277 if ( empty( $changeset_post_id ) ) { |
3219 wp_send_json_error( array( |
3278 wp_send_json_error( |
3220 'code' => 'no_changeset_found_to_take_over', |
3279 array( |
3221 'message' => __( 'No changeset found to take over' ), |
3280 'code' => 'no_changeset_found_to_take_over', |
3222 ) ); |
3281 'message' => __( 'No changeset found to take over' ), |
3282 ) |
|
3283 ); |
|
3223 } |
3284 } |
3224 |
3285 |
3225 if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->edit_post, $changeset_post_id ) ) { |
3286 if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->edit_post, $changeset_post_id ) ) { |
3226 wp_send_json_error( array( |
3287 wp_send_json_error( |
3227 'code' => 'cannot_remove_changeset_lock', |
3288 array( |
3228 'message' => __( 'Sorry, you are not allowed to take over.' ), |
3289 'code' => 'cannot_remove_changeset_lock', |
3229 ) ); |
3290 'message' => __( 'Sorry, you are not allowed to take over.' ), |
3291 ) |
|
3292 ); |
|
3230 } |
3293 } |
3231 |
3294 |
3232 $this->set_changeset_lock( $changeset_post_id, true ); |
3295 $this->set_changeset_lock( $changeset_post_id, true ); |
3233 |
3296 |
3234 wp_send_json_success( 'changeset_taken_over' ); |
3297 wp_send_json_success( 'changeset_taken_over' ); |
3304 $this->_changeset_uuid = $changeset_post->post_name; |
3367 $this->_changeset_uuid = $changeset_post->post_name; |
3305 $previous_changeset_data = $this->_changeset_data; |
3368 $previous_changeset_data = $this->_changeset_data; |
3306 $this->_changeset_data = $publishing_changeset_data; |
3369 $this->_changeset_data = $publishing_changeset_data; |
3307 |
3370 |
3308 // Parse changeset data to identify theme mod settings and user IDs associated with settings to be saved. |
3371 // Parse changeset data to identify theme mod settings and user IDs associated with settings to be saved. |
3309 $setting_user_ids = array(); |
3372 $setting_user_ids = array(); |
3310 $theme_mod_settings = array(); |
3373 $theme_mod_settings = array(); |
3311 $namespace_pattern = '/^(?P<stylesheet>.+?)::(?P<setting_id>.+)$/'; |
3374 $namespace_pattern = '/^(?P<stylesheet>.+?)::(?P<setting_id>.+)$/'; |
3312 $matches = array(); |
3375 $matches = array(); |
3313 foreach ( $this->_changeset_data as $raw_setting_id => $setting_params ) { |
3376 foreach ( $this->_changeset_data as $raw_setting_id => $setting_params ) { |
3314 $actual_setting_id = null; |
3377 $actual_setting_id = null; |
3315 $is_theme_mod_setting = ( |
3378 $is_theme_mod_setting = ( |
3316 isset( $setting_params['value'] ) |
3379 isset( $setting_params['value'] ) |
3317 && |
3380 && |
3318 isset( $setting_params['type'] ) |
3381 isset( $setting_params['type'] ) |
3319 && |
3382 && |
3338 if ( $actual_setting_id && isset( $setting_params['user_id'] ) ) { |
3401 if ( $actual_setting_id && isset( $setting_params['user_id'] ) ) { |
3339 $setting_user_ids[ $actual_setting_id ] = $setting_params['user_id']; |
3402 $setting_user_ids[ $actual_setting_id ] = $setting_params['user_id']; |
3340 } |
3403 } |
3341 } |
3404 } |
3342 |
3405 |
3343 $changeset_setting_values = $this->unsanitized_post_values( array( |
3406 $changeset_setting_values = $this->unsanitized_post_values( |
3344 'exclude_post_data' => true, |
3407 array( |
3345 'exclude_changeset' => false, |
3408 'exclude_post_data' => true, |
3346 ) ); |
3409 'exclude_changeset' => false, |
3347 $changeset_setting_ids = array_keys( $changeset_setting_values ); |
3410 ) |
3411 ); |
|
3412 $changeset_setting_ids = array_keys( $changeset_setting_values ); |
|
3348 $this->add_dynamic_settings( $changeset_setting_ids ); |
3413 $this->add_dynamic_settings( $changeset_setting_ids ); |
3349 |
3414 |
3350 /** |
3415 /** |
3351 * Fires once the theme has switched in the Customizer, but before settings |
3416 * Fires once the theme has switched in the Customizer, but before settings |
3352 * have been saved. |
3417 * have been saved. |
3366 $original_setting_capabilities = array(); |
3431 $original_setting_capabilities = array(); |
3367 foreach ( $changeset_setting_ids as $setting_id ) { |
3432 foreach ( $changeset_setting_ids as $setting_id ) { |
3368 $setting = $this->get_setting( $setting_id ); |
3433 $setting = $this->get_setting( $setting_id ); |
3369 if ( $setting && ! isset( $setting_user_ids[ $setting_id ] ) ) { |
3434 if ( $setting && ! isset( $setting_user_ids[ $setting_id ] ) ) { |
3370 $original_setting_capabilities[ $setting->id ] = $setting->capability; |
3435 $original_setting_capabilities[ $setting->id ] = $setting->capability; |
3371 $setting->capability = 'exist'; |
3436 $setting->capability = 'exist'; |
3372 } |
3437 } |
3373 } |
3438 } |
3374 |
3439 |
3375 $original_user_id = get_current_user_id(); |
3440 $original_user_id = get_current_user_id(); |
3376 foreach ( $changeset_setting_ids as $setting_id ) { |
3441 foreach ( $changeset_setting_ids as $setting_id ) { |
3433 if ( false !== strpos( $revision->post_name, "{$changeset_post_id}-autosave" ) ) { |
3498 if ( false !== strpos( $revision->post_name, "{$changeset_post_id}-autosave" ) ) { |
3434 $wpdb->update( |
3499 $wpdb->update( |
3435 $wpdb->posts, |
3500 $wpdb->posts, |
3436 array( |
3501 array( |
3437 'post_status' => 'auto-draft', |
3502 'post_status' => 'auto-draft', |
3438 'post_type' => 'customize_changeset', |
3503 'post_type' => 'customize_changeset', |
3439 'post_name' => wp_generate_uuid4(), |
3504 'post_name' => wp_generate_uuid4(), |
3440 'post_parent' => 0, |
3505 'post_parent' => 0, |
3441 ), |
3506 ), |
3442 array( |
3507 array( |
3443 'ID' => $revision->ID, |
3508 'ID' => $revision->ID, |
3444 ) |
3509 ) |
3478 $theme_mod_settings |
3543 $theme_mod_settings |
3479 ); |
3544 ); |
3480 } |
3545 } |
3481 |
3546 |
3482 $autoload = false; |
3547 $autoload = false; |
3483 $result = update_option( 'customize_stashed_theme_mods', $stashed_theme_mod_settings, $autoload ); |
3548 $result = update_option( 'customize_stashed_theme_mods', $stashed_theme_mod_settings, $autoload ); |
3484 if ( ! $result ) { |
3549 if ( ! $result ) { |
3485 return false; |
3550 return false; |
3486 } |
3551 } |
3487 return $stashed_theme_mod_settings; |
3552 return $stashed_theme_mod_settings; |
3488 } |
3553 } |
3518 if ( ! check_ajax_referer( 'customize_dismiss_autosave_or_lock', 'nonce', false ) ) { |
3583 if ( ! check_ajax_referer( 'customize_dismiss_autosave_or_lock', 'nonce', false ) ) { |
3519 wp_send_json_error( 'invalid_nonce', 403 ); |
3584 wp_send_json_error( 'invalid_nonce', 403 ); |
3520 } |
3585 } |
3521 |
3586 |
3522 $changeset_post_id = $this->changeset_post_id(); |
3587 $changeset_post_id = $this->changeset_post_id(); |
3523 $dismiss_lock = ! empty( $_POST['dismiss_lock'] ); |
3588 $dismiss_lock = ! empty( $_POST['dismiss_lock'] ); |
3524 $dismiss_autosave = ! empty( $_POST['dismiss_autosave'] ); |
3589 $dismiss_autosave = ! empty( $_POST['dismiss_autosave'] ); |
3525 |
3590 |
3526 if ( $dismiss_lock ) { |
3591 if ( $dismiss_lock ) { |
3527 if ( empty( $changeset_post_id ) && ! $dismiss_autosave ) { |
3592 if ( empty( $changeset_post_id ) && ! $dismiss_autosave ) { |
3528 wp_send_json_error( 'no_changeset_to_dismiss_lock', 404 ); |
3593 wp_send_json_error( 'no_changeset_to_dismiss_lock', 404 ); |
3529 } |
3594 } |
3577 * @param WP_Customize_Setting|string $id Customize Setting object, or ID. |
3642 * @param WP_Customize_Setting|string $id Customize Setting object, or ID. |
3578 * @param array $args { |
3643 * @param array $args { |
3579 * Optional. Array of properties for the new WP_Customize_Setting. Default empty array. |
3644 * Optional. Array of properties for the new WP_Customize_Setting. Default empty array. |
3580 * |
3645 * |
3581 * @type string $type Type of the setting. Default 'theme_mod'. |
3646 * @type string $type Type of the setting. Default 'theme_mod'. |
3582 * Default 160. |
|
3583 * @type string $capability Capability required for the setting. Default 'edit_theme_options' |
3647 * @type string $capability Capability required for the setting. Default 'edit_theme_options' |
3584 * @type string|array $theme_supports Theme features required to support the panel. Default is none. |
3648 * @type string|array $theme_supports Theme features required to support the panel. Default is none. |
3585 * @type string $default Default value for the setting. Default is empty string. |
3649 * @type string $default Default value for the setting. Default is empty string. |
3586 * @type string $transport Options for rendering the live preview of changes in Theme Customizer. |
3650 * @type string $transport Options for rendering the live preview of changes in Customizer. |
3587 * Using 'refresh' makes the change visible by reloading the whole preview. |
3651 * Using 'refresh' makes the change visible by reloading the whole preview. |
3588 * Using 'postMessage' allows a custom JavaScript to handle live changes. |
3652 * Using 'postMessage' allows a custom JavaScript to handle live changes. |
3589 * @link https://developer.wordpress.org/themes/customize-api |
3653 * @link https://developer.wordpress.org/themes/customize-api |
3590 * Default is 'refresh' |
3654 * Default is 'refresh' |
3591 * @type callable $validate_callback Server-side validation callback for the setting's value. |
3655 * @type callable $validate_callback Server-side validation callback for the setting's value. |
3592 * @type callable $sanitize_callback Callback to filter a Customize setting value in un-slashed form. |
3656 * @type callable $sanitize_callback Callback to filter a Customize setting value in un-slashed form. |
3593 * @type callable $sanitize_js_callback Callback to convert a Customize PHP setting value to a value that is |
3657 * @type callable $sanitize_js_callback Callback to convert a Customize PHP setting value to a value that is |
3594 * JSON serializable. |
3658 * JSON serializable. |
3635 // Skip settings already created |
3699 // Skip settings already created |
3636 if ( $this->get_setting( $setting_id ) ) { |
3700 if ( $this->get_setting( $setting_id ) ) { |
3637 continue; |
3701 continue; |
3638 } |
3702 } |
3639 |
3703 |
3640 $setting_args = false; |
3704 $setting_args = false; |
3641 $setting_class = 'WP_Customize_Setting'; |
3705 $setting_class = 'WP_Customize_Setting'; |
3642 |
3706 |
3643 /** |
3707 /** |
3644 * Filters a dynamic setting's constructor args. |
3708 * Filters a dynamic setting's constructor args. |
3645 * |
3709 * |
3755 */ |
3819 */ |
3756 public function remove_panel( $id ) { |
3820 public function remove_panel( $id ) { |
3757 // Removing core components this way is _doing_it_wrong(). |
3821 // Removing core components this way is _doing_it_wrong(). |
3758 if ( in_array( $id, $this->components, true ) ) { |
3822 if ( in_array( $id, $this->components, true ) ) { |
3759 /* translators: 1: panel id, 2: link to 'customize_loaded_components' filter reference */ |
3823 /* translators: 1: panel id, 2: link to 'customize_loaded_components' filter reference */ |
3760 $message = sprintf( __( 'Removing %1$s manually will cause PHP warnings. Use the %2$s filter instead.' ), |
3824 $message = sprintf( |
3825 __( 'Removing %1$s manually will cause PHP warnings. Use the %2$s filter instead.' ), |
|
3761 $id, |
3826 $id, |
3762 '<a href="' . esc_url( 'https://developer.wordpress.org/reference/hooks/customize_loaded_components/' ) . '"><code>customize_loaded_components</code></a>' |
3827 '<a href="' . esc_url( 'https://developer.wordpress.org/reference/hooks/customize_loaded_components/' ) . '"><code>customize_loaded_components</code></a>' |
3763 ); |
3828 ); |
3764 |
3829 |
3765 _doing_it_wrong( __METHOD__, $message, '4.5.0' ); |
3830 _doing_it_wrong( __METHOD__, $message, '4.5.0' ); |
3834 * |
3899 * |
3835 * @param string $id Section ID. |
3900 * @param string $id Section ID. |
3836 * @return WP_Customize_Section|void The section, if set. |
3901 * @return WP_Customize_Section|void The section, if set. |
3837 */ |
3902 */ |
3838 public function get_section( $id ) { |
3903 public function get_section( $id ) { |
3839 if ( isset( $this->sections[ $id ] ) ) |
3904 if ( isset( $this->sections[ $id ] ) ) { |
3840 return $this->sections[ $id ]; |
3905 return $this->sections[ $id ]; |
3906 } |
|
3841 } |
3907 } |
3842 |
3908 |
3843 /** |
3909 /** |
3844 * Remove a customize section. |
3910 * Remove a customize section. |
3845 * |
3911 * |
3925 * |
3991 * |
3926 * @param string $id ID of the control. |
3992 * @param string $id ID of the control. |
3927 * @return WP_Customize_Control|void The control object, if set. |
3993 * @return WP_Customize_Control|void The control object, if set. |
3928 */ |
3994 */ |
3929 public function get_control( $id ) { |
3995 public function get_control( $id ) { |
3930 if ( isset( $this->controls[ $id ] ) ) |
3996 if ( isset( $this->controls[ $id ] ) ) { |
3931 return $this->controls[ $id ]; |
3997 return $this->controls[ $id ]; |
3998 } |
|
3932 } |
3999 } |
3933 |
4000 |
3934 /** |
4001 /** |
3935 * Remove a customize control. |
4002 * Remove a customize control. |
3936 * |
4003 * |
3963 */ |
4030 */ |
3964 public function render_control_templates() { |
4031 public function render_control_templates() { |
3965 if ( $this->branching() ) { |
4032 if ( $this->branching() ) { |
3966 $l10n = array( |
4033 $l10n = array( |
3967 /* translators: %s: User who is customizing the changeset in customizer. */ |
4034 /* translators: %s: User who is customizing the changeset in customizer. */ |
3968 'locked' => __( '%s is already customizing this changeset. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ), |
4035 'locked' => __( '%s is already customizing this changeset. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ), |
3969 /* translators: %s: User who is customizing the changeset in customizer. */ |
4036 /* translators: %s: User who is customizing the changeset in customizer. */ |
3970 'locked_allow_override' => __( '%s is already customizing this changeset. Do you want to take over?' ), |
4037 'locked_allow_override' => __( '%s is already customizing this changeset. Do you want to take over?' ), |
3971 ); |
4038 ); |
3972 } else { |
4039 } else { |
3973 $l10n = array( |
4040 $l10n = array( |
3974 /* translators: %s: User who is customizing the changeset in customizer. */ |
4041 /* translators: %s: User who is customizing the changeset in customizer. */ |
3975 'locked' => __( '%s is already customizing this site. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ), |
4042 'locked' => __( '%s is already customizing this site. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ), |
3976 /* translators: %s: User who is customizing the changeset in customizer. */ |
4043 /* translators: %s: User who is customizing the changeset in customizer. */ |
3977 'locked_allow_override' => __( '%s is already customizing this site. Do you want to take over?' ), |
4044 'locked_allow_override' => __( '%s is already customizing this site. Do you want to take over?' ), |
3978 ); |
4045 ); |
3979 } |
4046 } |
3980 |
4047 |
3981 foreach ( $this->registered_control_types as $control_type ) { |
4048 foreach ( $this->registered_control_types as $control_type ) { |
3982 $control = new $control_type( $this, 'temp', array( |
4049 $control = new $control_type( |
3983 'settings' => array(), |
4050 $this, |
3984 ) ); |
4051 'temp', |
4052 array( |
|
4053 'settings' => array(), |
|
4054 ) |
|
4055 ); |
|
3985 $control->print_template(); |
4056 $control->print_template(); |
3986 } |
4057 } |
3987 ?> |
4058 ?> |
3988 |
4059 |
3989 <script type="text/html" id="tmpl-customize-control-default-content"> |
4060 <script type="text/html" id="tmpl-customize-control-default-content"> |
4194 <div class="customize-control-notifications-container"></div> |
4265 <div class="customize-control-notifications-container"></div> |
4195 <div class="preview-link-wrapper"> |
4266 <div class="preview-link-wrapper"> |
4196 <label for="{{ elementPrefix }}customize-preview-link-input" class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></label> |
4267 <label for="{{ elementPrefix }}customize-preview-link-input" class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></label> |
4197 <a href="" target=""> |
4268 <a href="" target=""> |
4198 <span class="preview-control-element" data-component="url"></span> |
4269 <span class="preview-control-element" data-component="url"></span> |
4199 <span class="screen-reader-text"><?php _e( '(opens in a new window)' ); ?></span> |
4270 <span class="screen-reader-text"><?php _e( '(opens in a new tab)' ); ?></span> |
4200 </a> |
4271 </a> |
4201 <input id="{{ elementPrefix }}customize-preview-link-input" readonly tabindex="-1" class="preview-control-element" data-component="input"> |
4272 <input id="{{ elementPrefix }}customize-preview-link-input" readonly tabindex="-1" class="preview-control-element" data-component="input"> |
4202 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button> |
4273 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button> |
4203 </div> |
4274 </div> |
4204 </script> |
4275 </script> |
4251 * |
4322 * |
4252 * @since 3.4.0 |
4323 * @since 3.4.0 |
4253 */ |
4324 */ |
4254 public function prepare_controls() { |
4325 public function prepare_controls() { |
4255 |
4326 |
4256 $controls = array(); |
4327 $controls = array(); |
4257 $this->controls = wp_list_sort( $this->controls, array( |
4328 $this->controls = wp_list_sort( |
4258 'priority' => 'ASC', |
4329 $this->controls, |
4259 'instance_number' => 'ASC', |
4330 array( |
4260 ), 'ASC', true ); |
4331 'priority' => 'ASC', |
4332 'instance_number' => 'ASC', |
|
4333 ), |
|
4334 'ASC', |
|
4335 true |
|
4336 ); |
|
4261 |
4337 |
4262 foreach ( $this->controls as $id => $control ) { |
4338 foreach ( $this->controls as $id => $control ) { |
4263 if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) { |
4339 if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) { |
4264 continue; |
4340 continue; |
4265 } |
4341 } |
4266 |
4342 |
4267 $this->sections[ $control->section ]->controls[] = $control; |
4343 $this->sections[ $control->section ]->controls[] = $control; |
4268 $controls[ $id ] = $control; |
4344 $controls[ $id ] = $control; |
4269 } |
4345 } |
4270 $this->controls = $controls; |
4346 $this->controls = $controls; |
4271 |
4347 |
4272 // Prepare sections. |
4348 // Prepare sections. |
4273 $this->sections = wp_list_sort( $this->sections, array( |
4349 $this->sections = wp_list_sort( |
4274 'priority' => 'ASC', |
4350 $this->sections, |
4275 'instance_number' => 'ASC', |
4351 array( |
4276 ), 'ASC', true ); |
4352 'priority' => 'ASC', |
4277 $sections = array(); |
4353 'instance_number' => 'ASC', |
4354 ), |
|
4355 'ASC', |
|
4356 true |
|
4357 ); |
|
4358 $sections = array(); |
|
4278 |
4359 |
4279 foreach ( $this->sections as $section ) { |
4360 foreach ( $this->sections as $section ) { |
4280 if ( ! $section->check_capabilities() ) { |
4361 if ( ! $section->check_capabilities() ) { |
4281 continue; |
4362 continue; |
4282 } |
4363 } |
4283 |
4364 |
4284 |
4365 $section->controls = wp_list_sort( |
4285 $section->controls = wp_list_sort( $section->controls, array( |
4366 $section->controls, |
4286 'priority' => 'ASC', |
4367 array( |
4287 'instance_number' => 'ASC', |
4368 'priority' => 'ASC', |
4288 ) ); |
4369 'instance_number' => 'ASC', |
4370 ) |
|
4371 ); |
|
4289 |
4372 |
4290 if ( ! $section->panel ) { |
4373 if ( ! $section->panel ) { |
4291 // Top-level section. |
4374 // Top-level section. |
4292 $sections[ $section->id ] = $section; |
4375 $sections[ $section->id ] = $section; |
4293 } else { |
4376 } else { |
4298 } |
4381 } |
4299 } |
4382 } |
4300 $this->sections = $sections; |
4383 $this->sections = $sections; |
4301 |
4384 |
4302 // Prepare panels. |
4385 // Prepare panels. |
4303 $this->panels = wp_list_sort( $this->panels, array( |
4386 $this->panels = wp_list_sort( |
4304 'priority' => 'ASC', |
4387 $this->panels, |
4305 'instance_number' => 'ASC', |
4388 array( |
4306 ), 'ASC', true ); |
4389 'priority' => 'ASC', |
4307 $panels = array(); |
4390 'instance_number' => 'ASC', |
4391 ), |
|
4392 'ASC', |
|
4393 true |
|
4394 ); |
|
4395 $panels = array(); |
|
4308 |
4396 |
4309 foreach ( $this->panels as $panel ) { |
4397 foreach ( $this->panels as $panel ) { |
4310 if ( ! $panel->check_capabilities() ) { |
4398 if ( ! $panel->check_capabilities() ) { |
4311 continue; |
4399 continue; |
4312 } |
4400 } |
4313 |
4401 |
4314 $panel->sections = wp_list_sort( $panel->sections, array( |
4402 $panel->sections = wp_list_sort( |
4403 $panel->sections, |
|
4404 array( |
|
4405 'priority' => 'ASC', |
|
4406 'instance_number' => 'ASC', |
|
4407 ), |
|
4408 'ASC', |
|
4409 true |
|
4410 ); |
|
4411 $panels[ $panel->id ] = $panel; |
|
4412 } |
|
4413 $this->panels = $panels; |
|
4414 |
|
4415 // Sort panels and top-level sections together. |
|
4416 $this->containers = array_merge( $this->panels, $this->sections ); |
|
4417 $this->containers = wp_list_sort( |
|
4418 $this->containers, |
|
4419 array( |
|
4315 'priority' => 'ASC', |
4420 'priority' => 'ASC', |
4316 'instance_number' => 'ASC', |
4421 'instance_number' => 'ASC', |
4317 ), 'ASC', true ); |
4422 ), |
4318 $panels[ $panel->id ] = $panel; |
4423 'ASC', |
4319 } |
4424 true |
4320 $this->panels = $panels; |
4425 ); |
4321 |
|
4322 // Sort panels and top-level sections together. |
|
4323 $this->containers = array_merge( $this->panels, $this->sections ); |
|
4324 $this->containers = wp_list_sort( $this->containers, array( |
|
4325 'priority' => 'ASC', |
|
4326 'instance_number' => 'ASC', |
|
4327 ), 'ASC', true ); |
|
4328 } |
4426 } |
4329 |
4427 |
4330 /** |
4428 /** |
4331 * Enqueue scripts for customize controls. |
4429 * Enqueue scripts for customize controls. |
4332 * |
4430 * |
4337 $control->enqueue(); |
4435 $control->enqueue(); |
4338 } |
4436 } |
4339 |
4437 |
4340 if ( ! is_multisite() && ( current_user_can( 'install_themes' ) || current_user_can( 'update_themes' ) || current_user_can( 'delete_themes' ) ) ) { |
4438 if ( ! is_multisite() && ( current_user_can( 'install_themes' ) || current_user_can( 'update_themes' ) || current_user_can( 'delete_themes' ) ) ) { |
4341 wp_enqueue_script( 'updates' ); |
4439 wp_enqueue_script( 'updates' ); |
4342 wp_localize_script( 'updates', '_wpUpdatesItemCounts', array( |
4440 wp_localize_script( |
4343 'totals' => wp_get_update_data(), |
4441 'updates', |
4344 ) ); |
4442 '_wpUpdatesItemCounts', |
4443 array( |
|
4444 'totals' => wp_get_update_data(), |
|
4445 ) |
|
4446 ); |
|
4345 } |
4447 } |
4346 } |
4448 } |
4347 |
4449 |
4348 /** |
4450 /** |
4349 * Determine whether the user agent is iOS. |
4451 * Determine whether the user agent is iOS. |
4383 * @since 4.4.0 |
4485 * @since 4.4.0 |
4384 * |
4486 * |
4385 * @param string $preview_url URL to be previewed. |
4487 * @param string $preview_url URL to be previewed. |
4386 */ |
4488 */ |
4387 public function set_preview_url( $preview_url ) { |
4489 public function set_preview_url( $preview_url ) { |
4388 $preview_url = esc_url_raw( $preview_url ); |
4490 $preview_url = esc_url_raw( $preview_url ); |
4389 $this->preview_url = wp_validate_redirect( $preview_url, home_url( '/' ) ); |
4491 $this->preview_url = wp_validate_redirect( $preview_url, home_url( '/' ) ); |
4390 } |
4492 } |
4391 |
4493 |
4392 /** |
4494 /** |
4393 * Get the initial URL to be previewed. |
4495 * Get the initial URL to be previewed. |
4412 * |
4514 * |
4413 * @return bool Whether cross-domain. |
4515 * @return bool Whether cross-domain. |
4414 */ |
4516 */ |
4415 public function is_cross_domain() { |
4517 public function is_cross_domain() { |
4416 $admin_origin = wp_parse_url( admin_url() ); |
4518 $admin_origin = wp_parse_url( admin_url() ); |
4417 $home_origin = wp_parse_url( home_url() ); |
4519 $home_origin = wp_parse_url( home_url() ); |
4418 $cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) ); |
4520 $cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) ); |
4419 return $cross_domain; |
4521 return $cross_domain; |
4420 } |
4522 } |
4421 |
4523 |
4422 /** |
4524 /** |
4443 /** |
4545 /** |
4444 * Filters the list of URLs allowed to be clicked and followed in the Customizer preview. |
4546 * Filters the list of URLs allowed to be clicked and followed in the Customizer preview. |
4445 * |
4547 * |
4446 * @since 3.4.0 |
4548 * @since 3.4.0 |
4447 * |
4549 * |
4448 * @param array $allowed_urls An array of allowed URLs. |
4550 * @param string[] $allowed_urls An array of allowed URLs. |
4449 */ |
4551 */ |
4450 $allowed_urls = array_unique( apply_filters( 'customize_allowed_urls', $allowed_urls ) ); |
4552 $allowed_urls = array_unique( apply_filters( 'customize_allowed_urls', $allowed_urls ) ); |
4451 |
4553 |
4452 return $allowed_urls; |
4554 return $allowed_urls; |
4453 } |
4555 } |
4471 * @since 4.4.0 |
4573 * @since 4.4.0 |
4472 * |
4574 * |
4473 * @param string $return_url URL for return link. |
4575 * @param string $return_url URL for return link. |
4474 */ |
4576 */ |
4475 public function set_return_url( $return_url ) { |
4577 public function set_return_url( $return_url ) { |
4476 $return_url = esc_url_raw( $return_url ); |
4578 $return_url = esc_url_raw( $return_url ); |
4477 $return_url = remove_query_arg( wp_removable_query_args(), $return_url ); |
4579 $return_url = remove_query_arg( wp_removable_query_args(), $return_url ); |
4478 $return_url = wp_validate_redirect( $return_url ); |
4580 $return_url = wp_validate_redirect( $return_url ); |
4479 $this->return_url = $return_url; |
4581 $this->return_url = $return_url; |
4480 } |
4582 } |
4481 |
4583 |
4482 /** |
4584 /** |
4483 * Get URL to link the user to when closing the Customizer. |
4585 * Get URL to link the user to when closing the Customizer. |
4485 * @since 4.4.0 |
4587 * @since 4.4.0 |
4486 * |
4588 * |
4487 * @return string URL for link to close Customizer. |
4589 * @return string URL for link to close Customizer. |
4488 */ |
4590 */ |
4489 public function get_return_url() { |
4591 public function get_return_url() { |
4490 $referer = wp_get_referer(); |
4592 $referer = wp_get_referer(); |
4491 $excluded_referer_basenames = array( 'customize.php', 'wp-login.php' ); |
4593 $excluded_referer_basenames = array( 'customize.php', 'wp-login.php' ); |
4492 |
4594 |
4493 if ( $this->return_url ) { |
4595 if ( $this->return_url ) { |
4494 $return_url = $this->return_url; |
4596 $return_url = $this->return_url; |
4495 } else if ( $referer && ! in_array( basename( parse_url( $referer, PHP_URL_PATH ) ), $excluded_referer_basenames, true ) ) { |
4597 } elseif ( $referer && ! in_array( wp_basename( parse_url( $referer, PHP_URL_PATH ) ), $excluded_referer_basenames, true ) ) { |
4496 $return_url = $referer; |
4598 $return_url = $referer; |
4497 } else if ( $this->preview_url ) { |
4599 } elseif ( $this->preview_url ) { |
4498 $return_url = $this->preview_url; |
4600 $return_url = $this->preview_url; |
4499 } else { |
4601 } else { |
4500 $return_url = home_url( '/' ); |
4602 $return_url = home_url( '/' ); |
4501 } |
4603 } |
4502 return $return_url; |
4604 return $return_url; |
4543 * |
4645 * |
4544 * @return array Nonces. |
4646 * @return array Nonces. |
4545 */ |
4647 */ |
4546 public function get_nonces() { |
4648 public function get_nonces() { |
4547 $nonces = array( |
4649 $nonces = array( |
4548 'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ), |
4650 'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ), |
4549 'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ), |
4651 'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ), |
4550 'switch_themes' => wp_create_nonce( 'switch_themes' ), |
4652 'switch_themes' => wp_create_nonce( 'switch_themes' ), |
4551 'dismiss_autosave_or_lock' => wp_create_nonce( 'customize_dismiss_autosave_or_lock' ), |
4653 'dismiss_autosave_or_lock' => wp_create_nonce( 'customize_dismiss_autosave_or_lock' ), |
4552 'override_lock' => wp_create_nonce( 'customize_override_changeset_lock' ), |
4654 'override_lock' => wp_create_nonce( 'customize_override_changeset_lock' ), |
4553 'trash' => wp_create_nonce( 'trash_customize_changeset' ), |
4655 'trash' => wp_create_nonce( 'trash_customize_changeset' ), |
4554 ); |
4656 ); |
4555 |
4657 |
4556 /** |
4658 /** |
4557 * Filters nonces for Customizer. |
4659 * Filters nonces for Customizer. |
4558 * |
4660 * |
4559 * @since 4.2.0 |
4661 * @since 4.2.0 |
4560 * |
4662 * |
4561 * @param array $nonces Array of refreshed nonces for save and |
4663 * @param string[] $nonces Array of refreshed nonces for save and |
4562 * preview actions. |
4664 * preview actions. |
4563 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
4665 * @param WP_Customize_Manager $this WP_Customize_Manager instance. |
4564 */ |
4666 */ |
4565 $nonces = apply_filters( 'customize_refresh_nonces', $nonces, $this ); |
4667 $nonces = apply_filters( 'customize_refresh_nonces', $nonces, $this ); |
4566 |
4668 |
4572 * |
4674 * |
4573 * @since 4.4.0 |
4675 * @since 4.4.0 |
4574 */ |
4676 */ |
4575 public function customize_pane_settings() { |
4677 public function customize_pane_settings() { |
4576 |
4678 |
4577 $login_url = add_query_arg( array( |
4679 $login_url = add_query_arg( |
4578 'interim-login' => 1, |
4680 array( |
4579 'customize-login' => 1, |
4681 'interim-login' => 1, |
4580 ), wp_login_url() ); |
4682 'customize-login' => 1, |
4683 ), |
|
4684 wp_login_url() |
|
4685 ); |
|
4581 |
4686 |
4582 // Ensure dirty flags are set for modified settings. |
4687 // Ensure dirty flags are set for modified settings. |
4583 foreach ( array_keys( $this->unsanitized_post_values() ) as $setting_id ) { |
4688 foreach ( array_keys( $this->unsanitized_post_values() ) as $setting_id ) { |
4584 $setting = $this->get_setting( $setting_id ); |
4689 $setting = $this->get_setting( $setting_id ); |
4585 if ( $setting ) { |
4690 if ( $setting ) { |
4586 $setting->dirty = true; |
4691 $setting->dirty = true; |
4587 } |
4692 } |
4588 } |
4693 } |
4589 |
4694 |
4590 $autosave_revision_post = null; |
4695 $autosave_revision_post = null; |
4591 $autosave_autodraft_post = null; |
4696 $autosave_autodraft_post = null; |
4592 $changeset_post_id = $this->changeset_post_id(); |
4697 $changeset_post_id = $this->changeset_post_id(); |
4593 if ( ! $this->saved_starter_content_changeset && ! $this->autosaved() ) { |
4698 if ( ! $this->saved_starter_content_changeset && ! $this->autosaved() ) { |
4594 if ( $changeset_post_id ) { |
4699 if ( $changeset_post_id ) { |
4595 if ( is_user_logged_in() ) { |
4700 if ( is_user_logged_in() ) { |
4596 $autosave_revision_post = wp_get_post_autosave( $changeset_post_id, get_current_user_id() ); |
4701 $autosave_revision_post = wp_get_post_autosave( $changeset_post_id, get_current_user_id() ); |
4597 } |
4702 } |
4598 } else { |
4703 } else { |
4599 $autosave_autodraft_posts = $this->get_changeset_posts( array( |
4704 $autosave_autodraft_posts = $this->get_changeset_posts( |
4600 'posts_per_page' => 1, |
4705 array( |
4601 'post_status' => 'auto-draft', |
4706 'posts_per_page' => 1, |
4602 'exclude_restore_dismissed' => true, |
4707 'post_status' => 'auto-draft', |
4603 ) ); |
4708 'exclude_restore_dismissed' => true, |
4709 ) |
|
4710 ); |
|
4604 if ( ! empty( $autosave_autodraft_posts ) ) { |
4711 if ( ! empty( $autosave_autodraft_posts ) ) { |
4605 $autosave_autodraft_post = array_shift( $autosave_autodraft_posts ); |
4712 $autosave_autodraft_post = array_shift( $autosave_autodraft_posts ); |
4606 } |
4713 } |
4607 } |
4714 } |
4608 } |
4715 } |
4612 // @todo Include all of the status labels here from script-loader.php, and then allow it to be filtered. |
4719 // @todo Include all of the status labels here from script-loader.php, and then allow it to be filtered. |
4613 $status_choices = array(); |
4720 $status_choices = array(); |
4614 if ( $current_user_can_publish ) { |
4721 if ( $current_user_can_publish ) { |
4615 $status_choices[] = array( |
4722 $status_choices[] = array( |
4616 'status' => 'publish', |
4723 'status' => 'publish', |
4617 'label' => __( 'Publish' ), |
4724 'label' => __( 'Publish' ), |
4618 ); |
4725 ); |
4619 } |
4726 } |
4620 $status_choices[] = array( |
4727 $status_choices[] = array( |
4621 'status' => 'draft', |
4728 'status' => 'draft', |
4622 'label' => __( 'Save Draft' ), |
4729 'label' => __( 'Save Draft' ), |
4623 ); |
4730 ); |
4624 if ( $current_user_can_publish ) { |
4731 if ( $current_user_can_publish ) { |
4625 $status_choices[] = array( |
4732 $status_choices[] = array( |
4626 'status' => 'future', |
4733 'status' => 'future', |
4627 'label' => _x( 'Schedule', 'customizer changeset action/button label' ), |
4734 'label' => _x( 'Schedule', 'customizer changeset action/button label' ), |
4628 ); |
4735 ); |
4629 } |
4736 } |
4630 |
4737 |
4631 // Prepare Customizer settings to pass to JavaScript. |
4738 // Prepare Customizer settings to pass to JavaScript. |
4632 $changeset_post = null; |
4739 $changeset_post = null; |
4648 if ( $this->changeset_post_id() ) { |
4755 if ( $this->changeset_post_id() ) { |
4649 $lock_user_id = wp_check_post_lock( $this->changeset_post_id() ); |
4756 $lock_user_id = wp_check_post_lock( $this->changeset_post_id() ); |
4650 } |
4757 } |
4651 |
4758 |
4652 $settings = array( |
4759 $settings = array( |
4653 'changeset' => array( |
4760 'changeset' => array( |
4654 'uuid' => $this->changeset_uuid(), |
4761 'uuid' => $this->changeset_uuid(), |
4655 'branching' => $this->branching(), |
4762 'branching' => $this->branching(), |
4656 'autosaved' => $this->autosaved(), |
4763 'autosaved' => $this->autosaved(), |
4657 'hasAutosaveRevision' => ! empty( $autosave_revision_post ), |
4764 'hasAutosaveRevision' => ! empty( $autosave_revision_post ), |
4658 'latestAutoDraftUuid' => $autosave_autodraft_post ? $autosave_autodraft_post->post_name : null, |
4765 'latestAutoDraftUuid' => $autosave_autodraft_post ? $autosave_autodraft_post->post_name : null, |
4659 'status' => $changeset_post ? $changeset_post->post_status : '', |
4766 'status' => $changeset_post ? $changeset_post->post_status : '', |
4660 'currentUserCanPublish' => $current_user_can_publish, |
4767 'currentUserCanPublish' => $current_user_can_publish, |
4661 'publishDate' => $initial_date, |
4768 'publishDate' => $initial_date, |
4662 'statusChoices' => $status_choices, |
4769 'statusChoices' => $status_choices, |
4663 'lockUser' => $lock_user_id ? $this->get_lock_user_data( $lock_user_id ) : null, |
4770 'lockUser' => $lock_user_id ? $this->get_lock_user_data( $lock_user_id ) : null, |
4664 ), |
4771 ), |
4665 'initialServerDate' => $current_time, |
4772 'initialServerDate' => $current_time, |
4666 'dateFormat' => get_option( 'date_format' ), |
4773 'dateFormat' => get_option( 'date_format' ), |
4667 'timeFormat' => get_option( 'time_format' ), |
4774 'timeFormat' => get_option( 'time_format' ), |
4668 'initialServerTimestamp' => floor( microtime( true ) * 1000 ), |
4775 'initialServerTimestamp' => floor( microtime( true ) * 1000 ), |
4669 'initialClientTimestamp' => -1, // To be set with JS below. |
4776 'initialClientTimestamp' => -1, // To be set with JS below. |
4670 'timeouts' => array( |
4777 'timeouts' => array( |
4671 'windowRefresh' => 250, |
4778 'windowRefresh' => 250, |
4672 'changesetAutoSave' => AUTOSAVE_INTERVAL * 1000, |
4779 'changesetAutoSave' => AUTOSAVE_INTERVAL * 1000, |
4673 'keepAliveCheck' => 2500, |
4780 'keepAliveCheck' => 2500, |
4674 'reflowPaneContents' => 100, |
4781 'reflowPaneContents' => 100, |
4675 'previewFrameSensitivity' => 2000, |
4782 'previewFrameSensitivity' => 2000, |
4676 ), |
4783 ), |
4677 'theme' => array( |
4784 'theme' => array( |
4678 'stylesheet' => $this->get_stylesheet(), |
4785 'stylesheet' => $this->get_stylesheet(), |
4679 'active' => $this->is_theme_active(), |
4786 'active' => $this->is_theme_active(), |
4680 '_canInstall' => current_user_can( 'install_themes' ), |
4787 '_canInstall' => current_user_can( 'install_themes' ), |
4681 ), |
4788 ), |
4682 'url' => array( |
4789 'url' => array( |
4683 'preview' => esc_url_raw( $this->get_preview_url() ), |
4790 'preview' => esc_url_raw( $this->get_preview_url() ), |
4684 'return' => esc_url_raw( $this->get_return_url() ), |
4791 'return' => esc_url_raw( $this->get_return_url() ), |
4685 'parent' => esc_url_raw( admin_url() ), |
4792 'parent' => esc_url_raw( admin_url() ), |
4686 'activated' => esc_url_raw( home_url( '/' ) ), |
4793 'activated' => esc_url_raw( home_url( '/' ) ), |
4687 'ajax' => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ), |
4794 'ajax' => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ), |
4688 'allowed' => array_map( 'esc_url_raw', $this->get_allowed_urls() ), |
4795 'allowed' => array_map( 'esc_url_raw', $this->get_allowed_urls() ), |
4689 'isCrossDomain' => $this->is_cross_domain(), |
4796 'isCrossDomain' => $this->is_cross_domain(), |
4690 'home' => esc_url_raw( home_url( '/' ) ), |
4797 'home' => esc_url_raw( home_url( '/' ) ), |
4691 'login' => esc_url_raw( $login_url ), |
4798 'login' => esc_url_raw( $login_url ), |
4692 ), |
4799 ), |
4693 'browser' => array( |
4800 'browser' => array( |
4694 'mobile' => wp_is_mobile(), |
4801 'mobile' => wp_is_mobile(), |
4695 'ios' => $this->is_ios(), |
4802 'ios' => $this->is_ios(), |
4696 ), |
4803 ), |
4697 'panels' => array(), |
4804 'panels' => array(), |
4698 'sections' => array(), |
4805 'sections' => array(), |
4699 'nonce' => $this->get_nonces(), |
4806 'nonce' => $this->get_nonces(), |
4700 'autofocus' => $this->get_autofocus(), |
4807 'autofocus' => $this->get_autofocus(), |
4701 'documentTitleTmpl' => $this->get_document_title_template(), |
4808 'documentTitleTmpl' => $this->get_document_title_template(), |
4702 'previewableDevices' => $this->get_previewable_devices(), |
4809 'previewableDevices' => $this->get_previewable_devices(), |
4703 'l10n' => array( |
4810 'l10n' => array( |
4704 'confirmDeleteTheme' => __( 'Are you sure you want to delete this theme?' ), |
4811 'confirmDeleteTheme' => __( 'Are you sure you want to delete this theme?' ), |
4705 /* translators: %d: number of theme search results, which cannot currently consider singular vs. plural forms */ |
4812 /* translators: %d: number of theme search results, which cannot currently consider singular vs. plural forms */ |
4706 'themeSearchResults' => __( '%d themes found' ), |
4813 'themeSearchResults' => __( '%d themes found' ), |
4707 /* translators: %d: number of themes being displayed, which cannot currently consider singular vs. plural forms */ |
4814 /* translators: %d: number of themes being displayed, which cannot currently consider singular vs. plural forms */ |
4708 'announceThemeCount' => __( 'Displaying %d themes' ), |
4815 'announceThemeCount' => __( 'Displaying %d themes' ), |
4709 /* translators: %s: theme name */ |
4816 /* translators: %s: theme name */ |
4710 'announceThemeDetails' => __( 'Showing details for theme: %s' ), |
4817 'announceThemeDetails' => __( 'Showing details for theme: %s' ), |
4711 ), |
4818 ), |
4712 ); |
4819 ); |
4713 |
4820 |
4770 wp_json_encode( $control->json() ) |
4877 wp_json_encode( $control->json() ) |
4771 ); |
4878 ); |
4772 } |
4879 } |
4773 } |
4880 } |
4774 echo "})( _wpCustomizeSettings.controls );\n"; |
4881 echo "})( _wpCustomizeSettings.controls );\n"; |
4775 ?> |
4882 ?> |
4776 </script> |
4883 </script> |
4777 <?php |
4884 <?php |
4778 } |
4885 } |
4779 |
4886 |
4780 /** |
4887 /** |
4785 * @return array List of devices with labels and default setting. |
4892 * @return array List of devices with labels and default setting. |
4786 */ |
4893 */ |
4787 public function get_previewable_devices() { |
4894 public function get_previewable_devices() { |
4788 $devices = array( |
4895 $devices = array( |
4789 'desktop' => array( |
4896 'desktop' => array( |
4790 'label' => __( 'Enter desktop preview mode' ), |
4897 'label' => __( 'Enter desktop preview mode' ), |
4791 'default' => true, |
4898 'default' => true, |
4792 ), |
4899 ), |
4793 'tablet' => array( |
4900 'tablet' => array( |
4794 'label' => __( 'Enter tablet preview mode' ), |
4901 'label' => __( 'Enter tablet preview mode' ), |
4795 ), |
4902 ), |
4796 'mobile' => array( |
4903 'mobile' => array( |
4797 'label' => __( 'Enter mobile preview mode' ), |
4904 'label' => __( 'Enter mobile preview mode' ), |
4798 ), |
4905 ), |
4799 ); |
4906 ); |
4800 |
4907 |
4801 /** |
4908 /** |
4819 */ |
4926 */ |
4820 public function register_controls() { |
4927 public function register_controls() { |
4821 |
4928 |
4822 /* Themes (controls are loaded via ajax) */ |
4929 /* Themes (controls are loaded via ajax) */ |
4823 |
4930 |
4824 $this->add_panel( new WP_Customize_Themes_Panel( $this, 'themes', array( |
4931 $this->add_panel( |
4825 'title' => $this->theme()->display( 'Name' ), |
4932 new WP_Customize_Themes_Panel( |
4826 'description' => ( |
4933 $this, |
4827 '<p>' . __( 'Looking for a theme? You can search or browse the WordPress.org theme directory, install and preview themes, then activate them right here.' ) . '</p>' . |
4934 'themes', |
4828 '<p>' . __( 'While previewing a new theme, you can continue to tailor things like widgets and menus, and explore theme-specific options.' ) . '</p>' |
4935 array( |
4829 ), |
4936 'title' => $this->theme()->display( 'Name' ), |
4830 'capability' => 'switch_themes', |
4937 'description' => ( |
4831 'priority' => 0, |
4938 '<p>' . __( 'Looking for a theme? You can search or browse the WordPress.org theme directory, install and preview themes, then activate them right here.' ) . '</p>' . |
4832 ) ) ); |
4939 '<p>' . __( 'While previewing a new theme, you can continue to tailor things like widgets and menus, and explore theme-specific options.' ) . '</p>' |
4833 |
4940 ), |
4834 $this->add_section( new WP_Customize_Themes_Section( $this, 'installed_themes', array( |
4941 'capability' => 'switch_themes', |
4835 'title' => __( 'Installed themes' ), |
4942 'priority' => 0, |
4836 'action' => 'installed', |
4943 ) |
4837 'capability' => 'switch_themes', |
4944 ) |
4838 'panel' => 'themes', |
4945 ); |
4839 'priority' => 0, |
4946 |
4840 ) ) ); |
4947 $this->add_section( |
4948 new WP_Customize_Themes_Section( |
|
4949 $this, |
|
4950 'installed_themes', |
|
4951 array( |
|
4952 'title' => __( 'Installed themes' ), |
|
4953 'action' => 'installed', |
|
4954 'capability' => 'switch_themes', |
|
4955 'panel' => 'themes', |
|
4956 'priority' => 0, |
|
4957 ) |
|
4958 ) |
|
4959 ); |
|
4841 |
4960 |
4842 if ( ! is_multisite() ) { |
4961 if ( ! is_multisite() ) { |
4843 $this->add_section( new WP_Customize_Themes_Section( $this, 'wporg_themes', array( |
4962 $this->add_section( |
4844 'title' => __( 'WordPress.org themes' ), |
4963 new WP_Customize_Themes_Section( |
4845 'action' => 'wporg', |
4964 $this, |
4846 'filter_type' => 'remote', |
4965 'wporg_themes', |
4847 'capability' => 'install_themes', |
4966 array( |
4848 'panel' => 'themes', |
4967 'title' => __( 'WordPress.org themes' ), |
4849 'priority' => 5, |
4968 'action' => 'wporg', |
4850 ) ) ); |
4969 'filter_type' => 'remote', |
4970 'capability' => 'install_themes', |
|
4971 'panel' => 'themes', |
|
4972 'priority' => 5, |
|
4973 ) |
|
4974 ) |
|
4975 ); |
|
4851 } |
4976 } |
4852 |
4977 |
4853 // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience). |
4978 // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience). |
4854 $this->add_setting( new WP_Customize_Filter_Setting( $this, 'active_theme', array( |
4979 $this->add_setting( |
4855 'capability' => 'switch_themes', |
4980 new WP_Customize_Filter_Setting( |
4856 ) ) ); |
4981 $this, |
4982 'active_theme', |
|
4983 array( |
|
4984 'capability' => 'switch_themes', |
|
4985 ) |
|
4986 ) |
|
4987 ); |
|
4857 |
4988 |
4858 /* Site Identity */ |
4989 /* Site Identity */ |
4859 |
4990 |
4860 $this->add_section( 'title_tagline', array( |
4991 $this->add_section( |
4861 'title' => __( 'Site Identity' ), |
4992 'title_tagline', |
4862 'priority' => 20, |
4993 array( |
4863 ) ); |
4994 'title' => __( 'Site Identity' ), |
4864 |
4995 'priority' => 20, |
4865 $this->add_setting( 'blogname', array( |
4996 ) |
4866 'default' => get_option( 'blogname' ), |
4997 ); |
4867 'type' => 'option', |
4998 |
4868 'capability' => 'manage_options', |
4999 $this->add_setting( |
4869 ) ); |
5000 'blogname', |
4870 |
5001 array( |
4871 $this->add_control( 'blogname', array( |
5002 'default' => get_option( 'blogname' ), |
4872 'label' => __( 'Site Title' ), |
5003 'type' => 'option', |
4873 'section' => 'title_tagline', |
5004 'capability' => 'manage_options', |
4874 ) ); |
5005 ) |
4875 |
5006 ); |
4876 $this->add_setting( 'blogdescription', array( |
5007 |
4877 'default' => get_option( 'blogdescription' ), |
5008 $this->add_control( |
4878 'type' => 'option', |
5009 'blogname', |
4879 'capability' => 'manage_options', |
5010 array( |
4880 ) ); |
5011 'label' => __( 'Site Title' ), |
4881 |
5012 'section' => 'title_tagline', |
4882 $this->add_control( 'blogdescription', array( |
5013 ) |
4883 'label' => __( 'Tagline' ), |
5014 ); |
4884 'section' => 'title_tagline', |
5015 |
4885 ) ); |
5016 $this->add_setting( |
5017 'blogdescription', |
|
5018 array( |
|
5019 'default' => get_option( 'blogdescription' ), |
|
5020 'type' => 'option', |
|
5021 'capability' => 'manage_options', |
|
5022 ) |
|
5023 ); |
|
5024 |
|
5025 $this->add_control( |
|
5026 'blogdescription', |
|
5027 array( |
|
5028 'label' => __( 'Tagline' ), |
|
5029 'section' => 'title_tagline', |
|
5030 ) |
|
5031 ); |
|
4886 |
5032 |
4887 // Add a setting to hide header text if the theme doesn't support custom headers. |
5033 // Add a setting to hide header text if the theme doesn't support custom headers. |
4888 if ( ! current_theme_supports( 'custom-header', 'header-text' ) ) { |
5034 if ( ! current_theme_supports( 'custom-header', 'header-text' ) ) { |
4889 $this->add_setting( 'header_text', array( |
5035 $this->add_setting( |
4890 'theme_supports' => array( 'custom-logo', 'header-text' ), |
5036 'header_text', |
4891 'default' => 1, |
5037 array( |
4892 'sanitize_callback' => 'absint', |
5038 'theme_supports' => array( 'custom-logo', 'header-text' ), |
4893 ) ); |
5039 'default' => 1, |
4894 |
5040 'sanitize_callback' => 'absint', |
4895 $this->add_control( 'header_text', array( |
5041 ) |
5042 ); |
|
5043 |
|
5044 $this->add_control( |
|
5045 'header_text', |
|
5046 array( |
|
5047 'label' => __( 'Display Site Title and Tagline' ), |
|
5048 'section' => 'title_tagline', |
|
5049 'settings' => 'header_text', |
|
5050 'type' => 'checkbox', |
|
5051 ) |
|
5052 ); |
|
5053 } |
|
5054 |
|
5055 $this->add_setting( |
|
5056 'site_icon', |
|
5057 array( |
|
5058 'type' => 'option', |
|
5059 'capability' => 'manage_options', |
|
5060 'transport' => 'postMessage', // Previewed with JS in the Customizer controls window. |
|
5061 ) |
|
5062 ); |
|
5063 |
|
5064 $this->add_control( |
|
5065 new WP_Customize_Site_Icon_Control( |
|
5066 $this, |
|
5067 'site_icon', |
|
5068 array( |
|
5069 'label' => __( 'Site Icon' ), |
|
5070 'description' => sprintf( |
|
5071 '<p>' . __( 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. Upload one here!' ) . '</p>' . |
|
5072 /* translators: %s: site icon size in pixels */ |
|
5073 '<p>' . __( 'Site Icons should be square and at least %s pixels.' ) . '</p>', |
|
5074 '<strong>512 × 512</strong>' |
|
5075 ), |
|
5076 'section' => 'title_tagline', |
|
5077 'priority' => 60, |
|
5078 'height' => 512, |
|
5079 'width' => 512, |
|
5080 ) |
|
5081 ) |
|
5082 ); |
|
5083 |
|
5084 $this->add_setting( |
|
5085 'custom_logo', |
|
5086 array( |
|
5087 'theme_supports' => array( 'custom-logo' ), |
|
5088 'transport' => 'postMessage', |
|
5089 ) |
|
5090 ); |
|
5091 |
|
5092 $custom_logo_args = get_theme_support( 'custom-logo' ); |
|
5093 $this->add_control( |
|
5094 new WP_Customize_Cropped_Image_Control( |
|
5095 $this, |
|
5096 'custom_logo', |
|
5097 array( |
|
5098 'label' => __( 'Logo' ), |
|
5099 'section' => 'title_tagline', |
|
5100 'priority' => 8, |
|
5101 'height' => $custom_logo_args[0]['height'], |
|
5102 'width' => $custom_logo_args[0]['width'], |
|
5103 'flex_height' => $custom_logo_args[0]['flex-height'], |
|
5104 'flex_width' => $custom_logo_args[0]['flex-width'], |
|
5105 'button_labels' => array( |
|
5106 'select' => __( 'Select logo' ), |
|
5107 'change' => __( 'Change logo' ), |
|
5108 'remove' => __( 'Remove' ), |
|
5109 'default' => __( 'Default' ), |
|
5110 'placeholder' => __( 'No logo selected' ), |
|
5111 'frame_title' => __( 'Select logo' ), |
|
5112 'frame_button' => __( 'Choose logo' ), |
|
5113 ), |
|
5114 ) |
|
5115 ) |
|
5116 ); |
|
5117 |
|
5118 $this->selective_refresh->add_partial( |
|
5119 'custom_logo', |
|
5120 array( |
|
5121 'settings' => array( 'custom_logo' ), |
|
5122 'selector' => '.custom-logo-link', |
|
5123 'render_callback' => array( $this, '_render_custom_logo_partial' ), |
|
5124 'container_inclusive' => true, |
|
5125 ) |
|
5126 ); |
|
5127 |
|
5128 /* Colors */ |
|
5129 |
|
5130 $this->add_section( |
|
5131 'colors', |
|
5132 array( |
|
5133 'title' => __( 'Colors' ), |
|
5134 'priority' => 40, |
|
5135 ) |
|
5136 ); |
|
5137 |
|
5138 $this->add_setting( |
|
5139 'header_textcolor', |
|
5140 array( |
|
5141 'theme_supports' => array( 'custom-header', 'header-text' ), |
|
5142 'default' => get_theme_support( 'custom-header', 'default-text-color' ), |
|
5143 |
|
5144 'sanitize_callback' => array( $this, '_sanitize_header_textcolor' ), |
|
5145 'sanitize_js_callback' => 'maybe_hash_hex_color', |
|
5146 ) |
|
5147 ); |
|
5148 |
|
5149 // Input type: checkbox |
|
5150 // With custom value |
|
5151 $this->add_control( |
|
5152 'display_header_text', |
|
5153 array( |
|
5154 'settings' => 'header_textcolor', |
|
4896 'label' => __( 'Display Site Title and Tagline' ), |
5155 'label' => __( 'Display Site Title and Tagline' ), |
4897 'section' => 'title_tagline', |
5156 'section' => 'title_tagline', |
4898 'settings' => 'header_text', |
|
4899 'type' => 'checkbox', |
5157 'type' => 'checkbox', |
4900 ) ); |
5158 'priority' => 40, |
4901 } |
5159 ) |
4902 |
5160 ); |
4903 $this->add_setting( 'site_icon', array( |
5161 |
4904 'type' => 'option', |
5162 $this->add_control( |
4905 'capability' => 'manage_options', |
5163 new WP_Customize_Color_Control( |
4906 'transport' => 'postMessage', // Previewed with JS in the Customizer controls window. |
5164 $this, |
4907 ) ); |
5165 'header_textcolor', |
4908 |
5166 array( |
4909 $this->add_control( new WP_Customize_Site_Icon_Control( $this, 'site_icon', array( |
5167 'label' => __( 'Header Text Color' ), |
4910 'label' => __( 'Site Icon' ), |
5168 'section' => 'colors', |
4911 'description' => sprintf( |
5169 ) |
4912 '<p>' . __( 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. Upload one here!' ) . '</p>' . |
5170 ) |
4913 /* translators: %s: site icon size in pixels */ |
5171 ); |
4914 '<p>' . __( 'Site Icons should be square and at least %s pixels.' ) . '</p>', |
|
4915 '<strong>512 × 512</strong>' |
|
4916 ), |
|
4917 'section' => 'title_tagline', |
|
4918 'priority' => 60, |
|
4919 'height' => 512, |
|
4920 'width' => 512, |
|
4921 ) ) ); |
|
4922 |
|
4923 $this->add_setting( 'custom_logo', array( |
|
4924 'theme_supports' => array( 'custom-logo' ), |
|
4925 'transport' => 'postMessage', |
|
4926 ) ); |
|
4927 |
|
4928 $custom_logo_args = get_theme_support( 'custom-logo' ); |
|
4929 $this->add_control( new WP_Customize_Cropped_Image_Control( $this, 'custom_logo', array( |
|
4930 'label' => __( 'Logo' ), |
|
4931 'section' => 'title_tagline', |
|
4932 'priority' => 8, |
|
4933 'height' => $custom_logo_args[0]['height'], |
|
4934 'width' => $custom_logo_args[0]['width'], |
|
4935 'flex_height' => $custom_logo_args[0]['flex-height'], |
|
4936 'flex_width' => $custom_logo_args[0]['flex-width'], |
|
4937 'button_labels' => array( |
|
4938 'select' => __( 'Select logo' ), |
|
4939 'change' => __( 'Change logo' ), |
|
4940 'remove' => __( 'Remove' ), |
|
4941 'default' => __( 'Default' ), |
|
4942 'placeholder' => __( 'No logo selected' ), |
|
4943 'frame_title' => __( 'Select logo' ), |
|
4944 'frame_button' => __( 'Choose logo' ), |
|
4945 ), |
|
4946 ) ) ); |
|
4947 |
|
4948 $this->selective_refresh->add_partial( 'custom_logo', array( |
|
4949 'settings' => array( 'custom_logo' ), |
|
4950 'selector' => '.custom-logo-link', |
|
4951 'render_callback' => array( $this, '_render_custom_logo_partial' ), |
|
4952 'container_inclusive' => true, |
|
4953 ) ); |
|
4954 |
|
4955 /* Colors */ |
|
4956 |
|
4957 $this->add_section( 'colors', array( |
|
4958 'title' => __( 'Colors' ), |
|
4959 'priority' => 40, |
|
4960 ) ); |
|
4961 |
|
4962 $this->add_setting( 'header_textcolor', array( |
|
4963 'theme_supports' => array( 'custom-header', 'header-text' ), |
|
4964 'default' => get_theme_support( 'custom-header', 'default-text-color' ), |
|
4965 |
|
4966 'sanitize_callback' => array( $this, '_sanitize_header_textcolor' ), |
|
4967 'sanitize_js_callback' => 'maybe_hash_hex_color', |
|
4968 ) ); |
|
4969 |
|
4970 // Input type: checkbox |
|
4971 // With custom value |
|
4972 $this->add_control( 'display_header_text', array( |
|
4973 'settings' => 'header_textcolor', |
|
4974 'label' => __( 'Display Site Title and Tagline' ), |
|
4975 'section' => 'title_tagline', |
|
4976 'type' => 'checkbox', |
|
4977 'priority' => 40, |
|
4978 ) ); |
|
4979 |
|
4980 $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array( |
|
4981 'label' => __( 'Header Text Color' ), |
|
4982 'section' => 'colors', |
|
4983 ) ) ); |
|
4984 |
5172 |
4985 // Input type: Color |
5173 // Input type: Color |
4986 // With sanitize_callback |
5174 // With sanitize_callback |
4987 $this->add_setting( 'background_color', array( |
5175 $this->add_setting( |
4988 'default' => get_theme_support( 'custom-background', 'default-color' ), |
5176 'background_color', |
4989 'theme_supports' => 'custom-background', |
5177 array( |
4990 |
5178 'default' => get_theme_support( 'custom-background', 'default-color' ), |
4991 'sanitize_callback' => 'sanitize_hex_color_no_hash', |
5179 'theme_supports' => 'custom-background', |
4992 'sanitize_js_callback' => 'maybe_hash_hex_color', |
5180 |
4993 ) ); |
5181 'sanitize_callback' => 'sanitize_hex_color_no_hash', |
4994 |
5182 'sanitize_js_callback' => 'maybe_hash_hex_color', |
4995 $this->add_control( new WP_Customize_Color_Control( $this, 'background_color', array( |
5183 ) |
4996 'label' => __( 'Background Color' ), |
5184 ); |
4997 'section' => 'colors', |
5185 |
4998 ) ) ); |
5186 $this->add_control( |
5187 new WP_Customize_Color_Control( |
|
5188 $this, |
|
5189 'background_color', |
|
5190 array( |
|
5191 'label' => __( 'Background Color' ), |
|
5192 'section' => 'colors', |
|
5193 ) |
|
5194 ) |
|
5195 ); |
|
4999 |
5196 |
5000 /* Custom Header */ |
5197 /* Custom Header */ |
5001 |
5198 |
5002 if ( current_theme_supports( 'custom-header', 'video' ) ) { |
5199 if ( current_theme_supports( 'custom-header', 'video' ) ) { |
5003 $title = __( 'Header Media' ); |
5200 $title = __( 'Header Media' ); |
5004 $description = '<p>' . __( 'If you add a video, the image will be used as a fallback while the video loads.' ) . '</p>'; |
5201 $description = '<p>' . __( 'If you add a video, the image will be used as a fallback while the video loads.' ) . '</p>'; |
5005 |
5202 |
5006 $width = absint( get_theme_support( 'custom-header', 'width' ) ); |
5203 $width = absint( get_theme_support( 'custom-header', 'width' ) ); |
5007 $height = absint( get_theme_support( 'custom-header', 'height' ) ); |
5204 $height = absint( get_theme_support( 'custom-header', 'height' ) ); |
5008 if ( $width && $height ) { |
5205 if ( $width && $height ) { |
5009 $control_description = sprintf( |
5206 $control_description = sprintf( |
5010 /* translators: 1: .mp4, 2: header size in pixels */ |
5207 /* translators: 1: .mp4, 2: header size in pixels */ |
5011 __( 'Upload your video in %1$s format and minimize its file size for best results. Your theme recommends dimensions of %2$s pixels.' ), |
5208 __( 'Upload your video in %1$s format and minimize its file size for best results. Your theme recommends dimensions of %2$s pixels.' ), |
5026 '<code>.mp4</code>', |
5223 '<code>.mp4</code>', |
5027 sprintf( '<strong>%s</strong>', $height ) |
5224 sprintf( '<strong>%s</strong>', $height ) |
5028 ); |
5225 ); |
5029 } |
5226 } |
5030 } else { |
5227 } else { |
5031 $title = __( 'Header Image' ); |
5228 $title = __( 'Header Image' ); |
5032 $description = ''; |
5229 $description = ''; |
5033 $control_description = ''; |
5230 $control_description = ''; |
5034 } |
5231 } |
5035 |
5232 |
5036 $this->add_section( 'header_image', array( |
5233 $this->add_section( |
5037 'title' => $title, |
5234 'header_image', |
5038 'description' => $description, |
5235 array( |
5039 'theme_supports' => 'custom-header', |
5236 'title' => $title, |
5040 'priority' => 60, |
5237 'description' => $description, |
5041 ) ); |
5238 'theme_supports' => 'custom-header', |
5042 |
5239 'priority' => 60, |
5043 $this->add_setting( 'header_video', array( |
5240 ) |
5044 'theme_supports' => array( 'custom-header', 'video' ), |
5241 ); |
5045 'transport' => 'postMessage', |
5242 |
5046 'sanitize_callback' => 'absint', |
5243 $this->add_setting( |
5047 'validate_callback' => array( $this, '_validate_header_video' ), |
5244 'header_video', |
5048 ) ); |
5245 array( |
5049 |
5246 'theme_supports' => array( 'custom-header', 'video' ), |
5050 $this->add_setting( 'external_header_video', array( |
5247 'transport' => 'postMessage', |
5051 'theme_supports' => array( 'custom-header', 'video' ), |
5248 'sanitize_callback' => 'absint', |
5052 'transport' => 'postMessage', |
5249 'validate_callback' => array( $this, '_validate_header_video' ), |
5053 'sanitize_callback' => array( $this, '_sanitize_external_header_video' ), |
5250 ) |
5054 'validate_callback' => array( $this, '_validate_external_header_video' ), |
5251 ); |
5055 ) ); |
5252 |
5056 |
5253 $this->add_setting( |
5057 $this->add_setting( new WP_Customize_Filter_Setting( $this, 'header_image', array( |
5254 'external_header_video', |
5058 'default' => sprintf( get_theme_support( 'custom-header', 'default-image' ), get_template_directory_uri(), get_stylesheet_directory_uri() ), |
5255 array( |
5059 'theme_supports' => 'custom-header', |
5256 'theme_supports' => array( 'custom-header', 'video' ), |
5060 ) ) ); |
5257 'transport' => 'postMessage', |
5061 |
5258 'sanitize_callback' => array( $this, '_sanitize_external_header_video' ), |
5062 $this->add_setting( new WP_Customize_Header_Image_Setting( $this, 'header_image_data', array( |
5259 'validate_callback' => array( $this, '_validate_external_header_video' ), |
5063 'theme_supports' => 'custom-header', |
5260 ) |
5064 ) ) ); |
5261 ); |
5262 |
|
5263 $this->add_setting( |
|
5264 new WP_Customize_Filter_Setting( |
|
5265 $this, |
|
5266 'header_image', |
|
5267 array( |
|
5268 'default' => sprintf( get_theme_support( 'custom-header', 'default-image' ), get_template_directory_uri(), get_stylesheet_directory_uri() ), |
|
5269 'theme_supports' => 'custom-header', |
|
5270 ) |
|
5271 ) |
|
5272 ); |
|
5273 |
|
5274 $this->add_setting( |
|
5275 new WP_Customize_Header_Image_Setting( |
|
5276 $this, |
|
5277 'header_image_data', |
|
5278 array( |
|
5279 'theme_supports' => 'custom-header', |
|
5280 ) |
|
5281 ) |
|
5282 ); |
|
5065 |
5283 |
5066 /* |
5284 /* |
5067 * Switch image settings to postMessage when video support is enabled since |
5285 * Switch image settings to postMessage when video support is enabled since |
5068 * it entails that the_custom_header_markup() will be used, and thus selective |
5286 * it entails that the_custom_header_markup() will be used, and thus selective |
5069 * refresh can be utilized. |
5287 * refresh can be utilized. |
5070 */ |
5288 */ |
5071 if ( current_theme_supports( 'custom-header', 'video' ) ) { |
5289 if ( current_theme_supports( 'custom-header', 'video' ) ) { |
5072 $this->get_setting( 'header_image' )->transport = 'postMessage'; |
5290 $this->get_setting( 'header_image' )->transport = 'postMessage'; |
5073 $this->get_setting( 'header_image_data' )->transport = 'postMessage'; |
5291 $this->get_setting( 'header_image_data' )->transport = 'postMessage'; |
5074 } |
5292 } |
5075 |
5293 |
5076 $this->add_control( new WP_Customize_Media_Control( $this, 'header_video', array( |
5294 $this->add_control( |
5077 'theme_supports' => array( 'custom-header', 'video' ), |
5295 new WP_Customize_Media_Control( |
5078 'label' => __( 'Header Video' ), |
5296 $this, |
5079 'description' => $control_description, |
5297 'header_video', |
5080 'section' => 'header_image', |
5298 array( |
5081 'mime_type' => 'video', |
5299 'theme_supports' => array( 'custom-header', 'video' ), |
5082 'active_callback' => 'is_header_video_active', |
5300 'label' => __( 'Header Video' ), |
5083 ) ) ); |
5301 'description' => $control_description, |
5084 |
5302 'section' => 'header_image', |
5085 $this->add_control( 'external_header_video', array( |
5303 'mime_type' => 'video', |
5086 'theme_supports' => array( 'custom-header', 'video' ), |
5304 'active_callback' => 'is_header_video_active', |
5087 'type' => 'url', |
5305 ) |
5088 'description' => __( 'Or, enter a YouTube URL:' ), |
5306 ) |
5089 'section' => 'header_image', |
5307 ); |
5090 'active_callback' => 'is_header_video_active', |
5308 |
5091 ) ); |
5309 $this->add_control( |
5310 'external_header_video', |
|
5311 array( |
|
5312 'theme_supports' => array( 'custom-header', 'video' ), |
|
5313 'type' => 'url', |
|
5314 'description' => __( 'Or, enter a YouTube URL:' ), |
|
5315 'section' => 'header_image', |
|
5316 'active_callback' => 'is_header_video_active', |
|
5317 ) |
|
5318 ); |
|
5092 |
5319 |
5093 $this->add_control( new WP_Customize_Header_Image_Control( $this ) ); |
5320 $this->add_control( new WP_Customize_Header_Image_Control( $this ) ); |
5094 |
5321 |
5095 $this->selective_refresh->add_partial( 'custom_header', array( |
5322 $this->selective_refresh->add_partial( |
5096 'selector' => '#wp-custom-header', |
5323 'custom_header', |
5097 'render_callback' => 'the_custom_header_markup', |
5324 array( |
5098 'settings' => array( 'header_video', 'external_header_video', 'header_image' ), // The image is used as a video fallback here. |
5325 'selector' => '#wp-custom-header', |
5099 'container_inclusive' => true, |
5326 'render_callback' => 'the_custom_header_markup', |
5100 ) ); |
5327 'settings' => array( 'header_video', 'external_header_video', 'header_image' ), // The image is used as a video fallback here. |
5328 'container_inclusive' => true, |
|
5329 ) |
|
5330 ); |
|
5101 |
5331 |
5102 /* Custom Background */ |
5332 /* Custom Background */ |
5103 |
5333 |
5104 $this->add_section( 'background_image', array( |
5334 $this->add_section( |
5105 'title' => __( 'Background Image' ), |
5335 'background_image', |
5106 'theme_supports' => 'custom-background', |
5336 array( |
5107 'priority' => 80, |
5337 'title' => __( 'Background Image' ), |
5108 ) ); |
5338 'theme_supports' => 'custom-background', |
5109 |
5339 'priority' => 80, |
5110 $this->add_setting( 'background_image', array( |
5340 ) |
5111 'default' => get_theme_support( 'custom-background', 'default-image' ), |
5341 ); |
5112 'theme_supports' => 'custom-background', |
5342 |
5113 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5343 $this->add_setting( |
5114 ) ); |
5344 'background_image', |
5115 |
5345 array( |
5116 $this->add_setting( new WP_Customize_Background_Image_Setting( $this, 'background_image_thumb', array( |
5346 'default' => get_theme_support( 'custom-background', 'default-image' ), |
5117 'theme_supports' => 'custom-background', |
5347 'theme_supports' => 'custom-background', |
5118 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5348 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5119 ) ) ); |
5349 ) |
5350 ); |
|
5351 |
|
5352 $this->add_setting( |
|
5353 new WP_Customize_Background_Image_Setting( |
|
5354 $this, |
|
5355 'background_image_thumb', |
|
5356 array( |
|
5357 'theme_supports' => 'custom-background', |
|
5358 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
|
5359 ) |
|
5360 ) |
|
5361 ); |
|
5120 |
5362 |
5121 $this->add_control( new WP_Customize_Background_Image_Control( $this ) ); |
5363 $this->add_control( new WP_Customize_Background_Image_Control( $this ) ); |
5122 |
5364 |
5123 $this->add_setting( 'background_preset', array( |
5365 $this->add_setting( |
5124 'default' => get_theme_support( 'custom-background', 'default-preset' ), |
5366 'background_preset', |
5125 'theme_supports' => 'custom-background', |
5367 array( |
5126 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5368 'default' => get_theme_support( 'custom-background', 'default-preset' ), |
5127 ) ); |
5369 'theme_supports' => 'custom-background', |
5128 |
5370 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5129 $this->add_control( 'background_preset', array( |
5371 ) |
5130 'label' => _x( 'Preset', 'Background Preset' ), |
5372 ); |
5131 'section' => 'background_image', |
5373 |
5132 'type' => 'select', |
5374 $this->add_control( |
5133 'choices' => array( |
5375 'background_preset', |
5134 'default' => _x( 'Default', 'Default Preset' ), |
5376 array( |
5135 'fill' => __( 'Fill Screen' ), |
5377 'label' => _x( 'Preset', 'Background Preset' ), |
5136 'fit' => __( 'Fit to Screen' ), |
5378 'section' => 'background_image', |
5137 'repeat' => _x( 'Repeat', 'Repeat Image' ), |
5379 'type' => 'select', |
5138 'custom' => _x( 'Custom', 'Custom Preset' ), |
5380 'choices' => array( |
5139 ), |
5381 'default' => _x( 'Default', 'Default Preset' ), |
5140 ) ); |
5382 'fill' => __( 'Fill Screen' ), |
5141 |
5383 'fit' => __( 'Fit to Screen' ), |
5142 $this->add_setting( 'background_position_x', array( |
5384 'repeat' => _x( 'Repeat', 'Repeat Image' ), |
5143 'default' => get_theme_support( 'custom-background', 'default-position-x' ), |
5385 'custom' => _x( 'Custom', 'Custom Preset' ), |
5144 'theme_supports' => 'custom-background', |
5386 ), |
5145 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5387 ) |
5146 ) ); |
5388 ); |
5147 |
5389 |
5148 $this->add_setting( 'background_position_y', array( |
5390 $this->add_setting( |
5149 'default' => get_theme_support( 'custom-background', 'default-position-y' ), |
5391 'background_position_x', |
5150 'theme_supports' => 'custom-background', |
5392 array( |
5151 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5393 'default' => get_theme_support( 'custom-background', 'default-position-x' ), |
5152 ) ); |
5394 'theme_supports' => 'custom-background', |
5153 |
5395 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5154 $this->add_control( new WP_Customize_Background_Position_Control( $this, 'background_position', array( |
5396 ) |
5155 'label' => __( 'Image Position' ), |
5397 ); |
5156 'section' => 'background_image', |
5398 |
5157 'settings' => array( |
5399 $this->add_setting( |
5158 'x' => 'background_position_x', |
5400 'background_position_y', |
5159 'y' => 'background_position_y', |
5401 array( |
5160 ), |
5402 'default' => get_theme_support( 'custom-background', 'default-position-y' ), |
5161 ) ) ); |
5403 'theme_supports' => 'custom-background', |
5162 |
5404 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5163 $this->add_setting( 'background_size', array( |
5405 ) |
5164 'default' => get_theme_support( 'custom-background', 'default-size' ), |
5406 ); |
5165 'theme_supports' => 'custom-background', |
5407 |
5166 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5408 $this->add_control( |
5167 ) ); |
5409 new WP_Customize_Background_Position_Control( |
5168 |
5410 $this, |
5169 $this->add_control( 'background_size', array( |
5411 'background_position', |
5170 'label' => __( 'Image Size' ), |
5412 array( |
5171 'section' => 'background_image', |
5413 'label' => __( 'Image Position' ), |
5172 'type' => 'select', |
5414 'section' => 'background_image', |
5173 'choices' => array( |
5415 'settings' => array( |
5174 'auto' => __( 'Original' ), |
5416 'x' => 'background_position_x', |
5175 'contain' => __( 'Fit to Screen' ), |
5417 'y' => 'background_position_y', |
5176 'cover' => __( 'Fill Screen' ), |
5418 ), |
5177 ), |
5419 ) |
5178 ) ); |
5420 ) |
5179 |
5421 ); |
5180 $this->add_setting( 'background_repeat', array( |
5422 |
5181 'default' => get_theme_support( 'custom-background', 'default-repeat' ), |
5423 $this->add_setting( |
5182 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5424 'background_size', |
5183 'theme_supports' => 'custom-background', |
5425 array( |
5184 ) ); |
5426 'default' => get_theme_support( 'custom-background', 'default-size' ), |
5185 |
5427 'theme_supports' => 'custom-background', |
5186 $this->add_control( 'background_repeat', array( |
5428 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5187 'label' => __( 'Repeat Background Image' ), |
5429 ) |
5188 'section' => 'background_image', |
5430 ); |
5189 'type' => 'checkbox', |
5431 |
5190 ) ); |
5432 $this->add_control( |
5191 |
5433 'background_size', |
5192 $this->add_setting( 'background_attachment', array( |
5434 array( |
5193 'default' => get_theme_support( 'custom-background', 'default-attachment' ), |
5435 'label' => __( 'Image Size' ), |
5194 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
5436 'section' => 'background_image', |
5195 'theme_supports' => 'custom-background', |
5437 'type' => 'select', |
5196 ) ); |
5438 'choices' => array( |
5197 |
5439 'auto' => __( 'Original' ), |
5198 $this->add_control( 'background_attachment', array( |
5440 'contain' => __( 'Fit to Screen' ), |
5199 'label' => __( 'Scroll with Page' ), |
5441 'cover' => __( 'Fill Screen' ), |
5200 'section' => 'background_image', |
5442 ), |
5201 'type' => 'checkbox', |
5443 ) |
5202 ) ); |
5444 ); |
5203 |
5445 |
5446 $this->add_setting( |
|
5447 'background_repeat', |
|
5448 array( |
|
5449 'default' => get_theme_support( 'custom-background', 'default-repeat' ), |
|
5450 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
|
5451 'theme_supports' => 'custom-background', |
|
5452 ) |
|
5453 ); |
|
5454 |
|
5455 $this->add_control( |
|
5456 'background_repeat', |
|
5457 array( |
|
5458 'label' => __( 'Repeat Background Image' ), |
|
5459 'section' => 'background_image', |
|
5460 'type' => 'checkbox', |
|
5461 ) |
|
5462 ); |
|
5463 |
|
5464 $this->add_setting( |
|
5465 'background_attachment', |
|
5466 array( |
|
5467 'default' => get_theme_support( 'custom-background', 'default-attachment' ), |
|
5468 'sanitize_callback' => array( $this, '_sanitize_background_setting' ), |
|
5469 'theme_supports' => 'custom-background', |
|
5470 ) |
|
5471 ); |
|
5472 |
|
5473 $this->add_control( |
|
5474 'background_attachment', |
|
5475 array( |
|
5476 'label' => __( 'Scroll with Page' ), |
|
5477 'section' => 'background_image', |
|
5478 'type' => 'checkbox', |
|
5479 ) |
|
5480 ); |
|
5204 |
5481 |
5205 // If the theme is using the default background callback, we can update |
5482 // If the theme is using the default background callback, we can update |
5206 // the background CSS using postMessage. |
5483 // the background CSS using postMessage. |
5207 if ( get_theme_support( 'custom-background', 'wp-head-callback' ) === '_custom_background_cb' ) { |
5484 if ( get_theme_support( 'custom-background', 'wp-head-callback' ) === '_custom_background_cb' ) { |
5208 foreach ( array( 'color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment' ) as $prop ) { |
5485 foreach ( array( 'color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment' ) as $prop ) { |
5214 * Static Front Page |
5491 * Static Front Page |
5215 * See also https://core.trac.wordpress.org/ticket/19627 which introduces the static-front-page theme_support. |
5492 * See also https://core.trac.wordpress.org/ticket/19627 which introduces the static-front-page theme_support. |
5216 * The following replicates behavior from options-reading.php. |
5493 * The following replicates behavior from options-reading.php. |
5217 */ |
5494 */ |
5218 |
5495 |
5219 $this->add_section( 'static_front_page', array( |
5496 $this->add_section( |
5220 'title' => __( 'Homepage Settings' ), |
5497 'static_front_page', |
5221 'priority' => 120, |
5498 array( |
5222 'description' => __( 'You can choose what’s displayed on the homepage of your site. It can be posts in reverse chronological order (classic blog), or a fixed/static page. To set a static homepage, you first need to create two Pages. One will become the homepage, and the other will be where your posts are displayed.' ), |
5499 'title' => __( 'Homepage Settings' ), |
5223 'active_callback' => array( $this, 'has_published_pages' ), |
5500 'priority' => 120, |
5224 ) ); |
5501 'description' => __( 'You can choose what’s displayed on the homepage of your site. It can be posts in reverse chronological order (classic blog), or a fixed/static page. To set a static homepage, you first need to create two Pages. One will become the homepage, and the other will be where your posts are displayed.' ), |
5225 |
5502 'active_callback' => array( $this, 'has_published_pages' ), |
5226 $this->add_setting( 'show_on_front', array( |
5503 ) |
5227 'default' => get_option( 'show_on_front' ), |
5504 ); |
5228 'capability' => 'manage_options', |
5505 |
5229 'type' => 'option', |
5506 $this->add_setting( |
5230 ) ); |
5507 'show_on_front', |
5231 |
5508 array( |
5232 $this->add_control( 'show_on_front', array( |
5509 'default' => get_option( 'show_on_front' ), |
5233 'label' => __( 'Your homepage displays' ), |
5510 'capability' => 'manage_options', |
5234 'section' => 'static_front_page', |
5511 'type' => 'option', |
5235 'type' => 'radio', |
5512 ) |
5236 'choices' => array( |
5513 ); |
5237 'posts' => __( 'Your latest posts' ), |
5514 |
5238 'page' => __( 'A static page' ), |
5515 $this->add_control( |
5239 ), |
5516 'show_on_front', |
5240 ) ); |
5517 array( |
5241 |
5518 'label' => __( 'Your homepage displays' ), |
5242 $this->add_setting( 'page_on_front', array( |
5519 'section' => 'static_front_page', |
5243 'type' => 'option', |
5520 'type' => 'radio', |
5244 'capability' => 'manage_options', |
5521 'choices' => array( |
5245 ) ); |
5522 'posts' => __( 'Your latest posts' ), |
5246 |
5523 'page' => __( 'A static page' ), |
5247 $this->add_control( 'page_on_front', array( |
5524 ), |
5248 'label' => __( 'Homepage' ), |
5525 ) |
5249 'section' => 'static_front_page', |
5526 ); |
5250 'type' => 'dropdown-pages', |
5527 |
5251 'allow_addition' => true, |
5528 $this->add_setting( |
5252 ) ); |
5529 'page_on_front', |
5253 |
5530 array( |
5254 $this->add_setting( 'page_for_posts', array( |
5531 'type' => 'option', |
5255 'type' => 'option', |
5532 'capability' => 'manage_options', |
5256 'capability' => 'manage_options', |
5533 ) |
5257 ) ); |
5534 ); |
5258 |
5535 |
5259 $this->add_control( 'page_for_posts', array( |
5536 $this->add_control( |
5260 'label' => __( 'Posts page' ), |
5537 'page_on_front', |
5261 'section' => 'static_front_page', |
5538 array( |
5262 'type' => 'dropdown-pages', |
5539 'label' => __( 'Homepage' ), |
5263 'allow_addition' => true, |
5540 'section' => 'static_front_page', |
5264 ) ); |
5541 'type' => 'dropdown-pages', |
5542 'allow_addition' => true, |
|
5543 ) |
|
5544 ); |
|
5545 |
|
5546 $this->add_setting( |
|
5547 'page_for_posts', |
|
5548 array( |
|
5549 'type' => 'option', |
|
5550 'capability' => 'manage_options', |
|
5551 ) |
|
5552 ); |
|
5553 |
|
5554 $this->add_control( |
|
5555 'page_for_posts', |
|
5556 array( |
|
5557 'label' => __( 'Posts page' ), |
|
5558 'section' => 'static_front_page', |
|
5559 'type' => 'dropdown-pages', |
|
5560 'allow_addition' => true, |
|
5561 ) |
|
5562 ); |
|
5265 |
5563 |
5266 /* Custom CSS */ |
5564 /* Custom CSS */ |
5267 $section_description = '<p>'; |
5565 $section_description = '<p>'; |
5268 $section_description .= __( 'Add your own CSS code here to customize the appearance and layout of your site.' ); |
5566 $section_description .= __( 'Add your own CSS code here to customize the appearance and layout of your site.' ); |
5269 $section_description .= sprintf( |
5567 $section_description .= sprintf( |
5270 ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text"> %3$s</span></a>', |
5568 ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text"> %3$s</span></a>', |
5271 esc_url( __( 'https://codex.wordpress.org/CSS' ) ), |
5569 esc_url( __( 'https://codex.wordpress.org/CSS' ) ), |
5272 __( 'Learn more about CSS' ), |
5570 __( 'Learn more about CSS' ), |
5273 /* translators: accessibility text */ |
5571 /* translators: accessibility text */ |
5274 __( '(opens in a new window)' ) |
5572 __( '(opens in a new tab)' ) |
5275 ); |
5573 ); |
5276 $section_description .= '</p>'; |
5574 $section_description .= '</p>'; |
5277 |
5575 |
5278 $section_description .= '<p id="editor-keyboard-trap-help-1">' . __( 'When using a keyboard to navigate:' ) . '</p>'; |
5576 $section_description .= '<p id="editor-keyboard-trap-help-1">' . __( 'When using a keyboard to navigate:' ) . '</p>'; |
5279 $section_description .= '<ul>'; |
5577 $section_description .= '<ul>'; |
5287 $section_description .= sprintf( |
5585 $section_description .= sprintf( |
5288 /* translators: 1: link to user profile, 2: additional link attributes, 3: accessibility text */ |
5586 /* translators: 1: link to user profile, 2: additional link attributes, 3: accessibility text */ |
5289 __( 'The edit field automatically highlights code syntax. You can disable this in your <a href="%1$s" %2$s>user profile%3$s</a> to work in plain text mode.' ), |
5587 __( 'The edit field automatically highlights code syntax. You can disable this in your <a href="%1$s" %2$s>user profile%3$s</a> to work in plain text mode.' ), |
5290 esc_url( get_edit_profile_url() ), |
5588 esc_url( get_edit_profile_url() ), |
5291 'class="external-link" target="_blank"', |
5589 'class="external-link" target="_blank"', |
5292 sprintf( '<span class="screen-reader-text"> %s</span>', |
5590 sprintf( |
5591 '<span class="screen-reader-text"> %s</span>', |
|
5293 /* translators: accessibility text */ |
5592 /* translators: accessibility text */ |
5294 __( '(opens in a new window)' ) |
5593 __( '(opens in a new tab)' ) |
5295 ) |
5594 ) |
5296 ); |
5595 ); |
5297 $section_description .= '</p>'; |
5596 $section_description .= '</p>'; |
5298 } |
5597 } |
5299 |
5598 |
5300 $section_description .= '<p class="section-description-buttons">'; |
5599 $section_description .= '<p class="section-description-buttons">'; |
5301 $section_description .= '<button type="button" class="button-link section-description-close">' . __( 'Close' ) . '</button>'; |
5600 $section_description .= '<button type="button" class="button-link section-description-close">' . __( 'Close' ) . '</button>'; |
5302 $section_description .= '</p>'; |
5601 $section_description .= '</p>'; |
5303 |
5602 |
5304 $this->add_section( 'custom_css', array( |
5603 $this->add_section( |
5305 'title' => __( 'Additional CSS' ), |
5604 'custom_css', |
5306 'priority' => 200, |
5605 array( |
5307 'description_hidden' => true, |
5606 'title' => __( 'Additional CSS' ), |
5308 'description' => $section_description, |
5607 'priority' => 200, |
5309 ) ); |
5608 'description_hidden' => true, |
5310 |
5609 'description' => $section_description, |
5311 $custom_css_setting = new WP_Customize_Custom_CSS_Setting( $this, sprintf( 'custom_css[%s]', get_stylesheet() ), array( |
5610 ) |
5312 'capability' => 'edit_css', |
5611 ); |
5313 'default' => '', |
5612 |
5314 ) ); |
5613 $custom_css_setting = new WP_Customize_Custom_CSS_Setting( |
5614 $this, |
|
5615 sprintf( 'custom_css[%s]', get_stylesheet() ), |
|
5616 array( |
|
5617 'capability' => 'edit_css', |
|
5618 'default' => '', |
|
5619 ) |
|
5620 ); |
|
5315 $this->add_setting( $custom_css_setting ); |
5621 $this->add_setting( $custom_css_setting ); |
5316 |
5622 |
5317 $this->add_control( new WP_Customize_Code_Editor_Control( $this, 'custom_css', array( |
5623 $this->add_control( |
5318 'label' => __( 'CSS code' ), |
5624 new WP_Customize_Code_Editor_Control( |
5319 'section' => 'custom_css', |
5625 $this, |
5320 'settings' => array( 'default' => $custom_css_setting->id ), |
5626 'custom_css', |
5321 'code_type' => 'text/css', |
5627 array( |
5322 'input_attrs' => array( |
5628 'label' => __( 'CSS code' ), |
5323 'aria-describedby' => 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4', |
5629 'section' => 'custom_css', |
5324 ), |
5630 'settings' => array( 'default' => $custom_css_setting->id ), |
5325 ) ) ); |
5631 'code_type' => 'text/css', |
5632 'input_attrs' => array( |
|
5633 'aria-describedby' => 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4', |
|
5634 ), |
|
5635 ) |
|
5636 ) |
|
5637 ); |
|
5326 } |
5638 } |
5327 |
5639 |
5328 /** |
5640 /** |
5329 * Return whether there are published pages. |
5641 * Return whether there are published pages. |
5330 * |
5642 * |
5373 |
5685 |
5374 if ( empty( $_POST['theme_action'] ) ) { |
5686 if ( empty( $_POST['theme_action'] ) ) { |
5375 wp_send_json_error( 'missing_theme_action' ); |
5687 wp_send_json_error( 'missing_theme_action' ); |
5376 } |
5688 } |
5377 $theme_action = sanitize_key( $_POST['theme_action'] ); |
5689 $theme_action = sanitize_key( $_POST['theme_action'] ); |
5378 $themes = array(); |
5690 $themes = array(); |
5379 $args = array(); |
5691 $args = array(); |
5380 |
5692 |
5381 // Define query filters based on user input. |
5693 // Define query filters based on user input. |
5382 if ( ! array_key_exists( 'search', $_POST ) ) { |
5694 if ( ! array_key_exists( 'search', $_POST ) ) { |
5383 $args['search'] = ''; |
5695 $args['search'] = ''; |
5384 } else { |
5696 } else { |
5402 if ( 'installed' === $theme_action ) { |
5714 if ( 'installed' === $theme_action ) { |
5403 |
5715 |
5404 // Load all installed themes from wp_prepare_themes_for_js(). |
5716 // Load all installed themes from wp_prepare_themes_for_js(). |
5405 $themes = array( 'themes' => wp_prepare_themes_for_js() ); |
5717 $themes = array( 'themes' => wp_prepare_themes_for_js() ); |
5406 foreach ( $themes['themes'] as &$theme ) { |
5718 foreach ( $themes['themes'] as &$theme ) { |
5407 $theme['type'] = 'installed'; |
5719 $theme['type'] = 'installed'; |
5408 $theme['active'] = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme['id'] ); |
5720 $theme['active'] = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme['id'] ); |
5409 } |
5721 } |
5410 |
|
5411 } elseif ( 'wporg' === $theme_action ) { |
5722 } elseif ( 'wporg' === $theme_action ) { |
5412 |
5723 |
5413 // Load WordPress.org themes from the .org API and normalize data to match installed theme objects. |
5724 // Load WordPress.org themes from the .org API and normalize data to match installed theme objects. |
5414 if ( ! current_user_can( 'install_themes' ) ) { |
5725 if ( ! current_user_can( 'install_themes' ) ) { |
5415 wp_die( -1 ); |
5726 wp_die( -1 ); |
5416 } |
5727 } |
5417 |
5728 |
5418 // Arguments for all queries. |
5729 // Arguments for all queries. |
5419 $wporg_args = array( |
5730 $wporg_args = array( |
5420 'per_page' => 100, |
5731 'per_page' => 100, |
5421 'fields' => array( |
5732 'fields' => array( |
5422 'screenshot_url' => true, |
5733 'reviews_url' => true, // Explicitly request the reviews URL to be linked from the customizer. |
5423 'description' => true, |
|
5424 'rating' => true, |
|
5425 'downloaded' => true, |
|
5426 'downloadlink' => true, |
|
5427 'last_updated' => true, |
|
5428 'homepage' => true, |
|
5429 'num_ratings' => true, |
|
5430 'tags' => true, |
|
5431 'parent' => true, |
|
5432 // 'extended_author' => true, @todo: WordPress.org throws a 500 server error when this is here. |
|
5433 ), |
5734 ), |
5434 ); |
5735 ); |
5435 |
5736 |
5436 $args = array_merge( $wporg_args, $args ); |
5737 $args = array_merge( $wporg_args, $args ); |
5437 |
5738 |
5444 if ( is_wp_error( $themes ) ) { |
5745 if ( is_wp_error( $themes ) ) { |
5445 wp_send_json_error(); |
5746 wp_send_json_error(); |
5446 } |
5747 } |
5447 |
5748 |
5448 // This list matches the allowed tags in wp-admin/includes/theme-install.php. |
5749 // This list matches the allowed tags in wp-admin/includes/theme-install.php. |
5449 $themes_allowedtags = array_fill_keys( |
5750 $themes_allowedtags = array_fill_keys( |
5450 array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ), |
5751 array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ), |
5451 array() |
5752 array() |
5452 ); |
5753 ); |
5453 $themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true ); |
5754 $themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true ); |
5454 $themes_allowedtags['acronym']['title'] = true; |
5755 $themes_allowedtags['acronym']['title'] = true; |
5455 $themes_allowedtags['abbr']['title'] = true; |
5756 $themes_allowedtags['abbr']['title'] = true; |
5456 $themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true ); |
5757 $themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true ); |
5457 |
5758 |
5458 // Prepare a list of installed themes to check against before the loop. |
5759 // Prepare a list of installed themes to check against before the loop. |
5459 $installed_themes = array(); |
5760 $installed_themes = array(); |
5460 $wp_themes = wp_get_themes(); |
5761 $wp_themes = wp_get_themes(); |
5461 foreach ( $wp_themes as $theme ) { |
5762 foreach ( $wp_themes as $theme ) { |
5462 $installed_themes[] = $theme->get_stylesheet(); |
5763 $installed_themes[] = $theme->get_stylesheet(); |
5463 } |
5764 } |
5464 $update_php = network_admin_url( 'update.php?action=install-theme' ); |
5765 $update_php = network_admin_url( 'update.php?action=install-theme' ); |
5465 |
5766 |
5466 // Set up properties for themes available on WordPress.org. |
5767 // Set up properties for themes available on WordPress.org. |
5467 foreach ( $themes->themes as &$theme ) { |
5768 foreach ( $themes->themes as &$theme ) { |
5468 $theme->install_url = add_query_arg( array( |
5769 $theme->install_url = add_query_arg( |
5469 'theme' => $theme->slug, |
5770 array( |
5470 '_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ), |
5771 'theme' => $theme->slug, |
5471 ), $update_php ); |
5772 '_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ), |
5773 ), |
|
5774 $update_php |
|
5775 ); |
|
5472 |
5776 |
5473 $theme->name = wp_kses( $theme->name, $themes_allowedtags ); |
5777 $theme->name = wp_kses( $theme->name, $themes_allowedtags ); |
5474 $theme->author = wp_kses( $theme->author, $themes_allowedtags ); |
|
5475 $theme->version = wp_kses( $theme->version, $themes_allowedtags ); |
5778 $theme->version = wp_kses( $theme->version, $themes_allowedtags ); |
5476 $theme->description = wp_kses( $theme->description, $themes_allowedtags ); |
5779 $theme->description = wp_kses( $theme->description, $themes_allowedtags ); |
5477 $theme->tags = implode( ', ', $theme->tags ); |
5780 $theme->stars = wp_star_rating( |
5478 $theme->stars = wp_star_rating( array( |
5781 array( |
5479 'rating' => $theme->rating, |
5782 'rating' => $theme->rating, |
5480 'type' => 'percent', |
5783 'type' => 'percent', |
5481 'number' => $theme->num_ratings, |
5784 'number' => $theme->num_ratings, |
5482 'echo' => false, |
5785 'echo' => false, |
5483 ) ); |
5786 ) |
5787 ); |
|
5484 $theme->num_ratings = number_format_i18n( $theme->num_ratings ); |
5788 $theme->num_ratings = number_format_i18n( $theme->num_ratings ); |
5485 $theme->preview_url = set_url_scheme( $theme->preview_url ); |
5789 $theme->preview_url = set_url_scheme( $theme->preview_url ); |
5486 |
5790 |
5487 // Handle themes that are already installed as installed themes. |
5791 // Handle themes that are already installed as installed themes. |
5488 if ( in_array( $theme->slug, $installed_themes, true ) ) { |
5792 if ( in_array( $theme->slug, $installed_themes, true ) ) { |
5495 $theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug ); |
5799 $theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug ); |
5496 |
5800 |
5497 // Map available theme properties to installed theme properties. |
5801 // Map available theme properties to installed theme properties. |
5498 $theme->id = $theme->slug; |
5802 $theme->id = $theme->slug; |
5499 $theme->screenshot = array( $theme->screenshot_url ); |
5803 $theme->screenshot = array( $theme->screenshot_url ); |
5500 $theme->authorAndUri = $theme->author; |
5804 $theme->authorAndUri = wp_kses( $theme->author['display_name'], $themes_allowedtags ); |
5501 // The .org API can return the full parent theme details if passed the 'parent' arg, or if passed the 'template' option it'll return that in the event it's a child theme. |
5805 |
5502 if ( isset( $theme->parent ) ) { |
5806 if ( isset( $theme->parent ) ) { |
5503 $theme->parent = $theme->parent['slug']; |
5807 $theme->parent = $theme->parent['slug']; |
5504 } else { |
5808 } else { |
5505 $theme->parent = false; |
5809 $theme->parent = false; |
5506 } |
5810 } |
5543 * |
5847 * |
5544 * @param string $color |
5848 * @param string $color |
5545 * @return mixed |
5849 * @return mixed |
5546 */ |
5850 */ |
5547 public function _sanitize_header_textcolor( $color ) { |
5851 public function _sanitize_header_textcolor( $color ) { |
5548 if ( 'blank' === $color ) |
5852 if ( 'blank' === $color ) { |
5549 return 'blank'; |
5853 return 'blank'; |
5854 } |
|
5550 |
5855 |
5551 $color = sanitize_hex_color_no_hash( $color ); |
5856 $color = sanitize_hex_color_no_hash( $color ); |
5552 if ( empty( $color ) ) |
5857 if ( empty( $color ) ) { |
5553 $color = get_theme_support( 'custom-header', 'default-text-color' ); |
5858 $color = get_theme_support( 'custom-header', 'default-text-color' ); |
5859 } |
|
5554 |
5860 |
5555 return $color; |
5861 return $color; |
5556 } |
5862 } |
5557 |
5863 |
5558 /** |
5864 /** |
5629 public function _validate_header_video( $validity, $value ) { |
5935 public function _validate_header_video( $validity, $value ) { |
5630 $video = get_attached_file( absint( $value ) ); |
5936 $video = get_attached_file( absint( $value ) ); |
5631 if ( $video ) { |
5937 if ( $video ) { |
5632 $size = filesize( $video ); |
5938 $size = filesize( $video ); |
5633 if ( 8 < $size / pow( 1024, 2 ) ) { // Check whether the size is larger than 8MB. |
5939 if ( 8 < $size / pow( 1024, 2 ) ) { // Check whether the size is larger than 8MB. |
5634 $validity->add( 'size_too_large', |
5940 $validity->add( |
5941 'size_too_large', |
|
5635 __( 'This video file is too large to use as a header video. Try a shorter video or optimize the compression settings and re-upload a file that is less than 8MB. Or, upload your video to YouTube and link it with the option below.' ) |
5942 __( 'This video file is too large to use as a header video. Try a shorter video or optimize the compression settings and re-upload a file that is less than 8MB. Or, upload your video to YouTube and link it with the option below.' ) |
5636 ); |
5943 ); |
5637 } |
5944 } |
5638 if ( '.mp4' !== substr( $video, -4 ) && '.mov' !== substr( $video, -4 ) ) { // Check for .mp4 or .mov format, which (assuming h.264 encoding) are the only cross-browser-supported formats. |
5945 if ( '.mp4' !== substr( $video, -4 ) && '.mov' !== substr( $video, -4 ) ) { // Check for .mp4 or .mov format, which (assuming h.264 encoding) are the only cross-browser-supported formats. |
5639 $validity->add( 'invalid_file_type', sprintf( |
5946 $validity->add( |
5640 /* translators: 1: .mp4, 2: .mov */ |
5947 'invalid_file_type', |
5641 __( 'Only %1$s or %2$s files may be used for header video. Please convert your video file and try again, or, upload your video to YouTube and link it with the option below.' ), |
5948 sprintf( |
5642 '<code>.mp4</code>', |
5949 /* translators: 1: .mp4, 2: .mov */ |
5643 '<code>.mov</code>' |
5950 __( 'Only %1$s or %2$s files may be used for header video. Please convert your video file and try again, or, upload your video to YouTube and link it with the option below.' ), |
5644 ) ); |
5951 '<code>.mp4</code>', |
5952 '<code>.mov</code>' |
|
5953 ) |
|
5954 ); |
|
5645 } |
5955 } |
5646 } |
5956 } |
5647 return $validity; |
5957 return $validity; |
5648 } |
5958 } |
5649 |
5959 |