/**
  * Test WP_Customize_Selective_Refresh::handle_render_partials_request() to multiple partials can be requested at once.
  *
  * @see WP_Customize_Selective_Refresh::handle_render_partials_request()
  */
 function test_handle_render_partials_request_for_multiple_partials_placements()
 {
     $this->setup_valid_render_partials_request_environment();
     $this->wp_customize->selective_refresh->add_partial('test_blogname', array('settings' => array('blogname'), 'render_callback' => array($this, 'render_callback_blogname')));
     $this->wp_customize->selective_refresh->add_partial('test_blogdescription', array('settings' => array('blogdescription'), 'render_callback' => array($this, 'render_callback_blogdescription')));
     $placement_context_data = array();
     $_POST['partials'] = wp_slash(wp_json_encode(array('test_blogname' => array($placement_context_data), 'test_blogdescription' => array($placement_context_data, $placement_context_data))));
     $count_customize_render_partials_before = has_action('customize_render_partials_before');
     $count_customize_render_partials_after = has_action('customize_render_partials_after');
     ob_start();
     try {
         $this->expected_partial_ids = array('test_blogname', 'test_blogdescription');
         add_filter('customize_render_partials_response', array($this, 'filter_customize_render_partials_response'), 10, 3);
         add_action('customize_render_partials_before', array($this, 'handle_action_customize_render_partials_before'), 10, 2);
         add_action('customize_render_partials_after', array($this, 'handle_action_customize_render_partials_after'), 10, 2);
         $this->selective_refresh->handle_render_partials_request();
     } catch (WPDieException $e) {
         $this->assertEquals('', $e->getMessage());
     }
     $this->assertEquals($count_customize_render_partials_before + 1, has_action('customize_render_partials_before'));
     $this->assertEquals($count_customize_render_partials_after + 1, has_action('customize_render_partials_after'));
     $output = json_decode(ob_get_clean(), true);
     $this->assertEquals(array(get_bloginfo('name', 'display')), $output['data']['contents']['test_blogname']);
     $this->assertEquals(array_fill(0, 2, get_bloginfo('description', 'display')), $output['data']['contents']['test_blogdescription']);
 }
 /**
  * Register some default controls.
  *
  * @since 3.4.0
  */
 public function register_controls()
 {
     /* Panel, Section, and Control Types */
     $this->register_panel_type('WP_Customize_Panel');
     $this->register_section_type('WP_Customize_Section');
     $this->register_section_type('WP_Customize_Sidebar_Section');
     $this->register_control_type('WP_Customize_Color_Control');
     $this->register_control_type('WP_Customize_Media_Control');
     $this->register_control_type('WP_Customize_Upload_Control');
     $this->register_control_type('WP_Customize_Image_Control');
     $this->register_control_type('WP_Customize_Background_Image_Control');
     $this->register_control_type('WP_Customize_Cropped_Image_Control');
     $this->register_control_type('WP_Customize_Site_Icon_Control');
     $this->register_control_type('WP_Customize_Theme_Control');
     /* Themes */
     $this->add_section(new WP_Customize_Themes_Section($this, 'themes', array('title' => $this->theme()->display('Name'), 'capability' => 'switch_themes', 'priority' => 0)));
     // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience).
     $this->add_setting(new WP_Customize_Filter_Setting($this, 'active_theme', array('capability' => 'switch_themes')));
     require_once ABSPATH . 'wp-admin/includes/theme.php';
     // Theme Controls.
     // Add a control for the active/original theme.
     if (!$this->is_theme_active()) {
         $themes = wp_prepare_themes_for_js(array(wp_get_theme($this->original_stylesheet)));
         $active_theme = current($themes);
         $active_theme['isActiveTheme'] = true;
         $this->add_control(new WP_Customize_Theme_Control($this, $active_theme['id'], array('theme' => $active_theme, 'section' => 'themes', 'settings' => 'active_theme')));
     }
     $themes = wp_prepare_themes_for_js();
     foreach ($themes as $theme) {
         if ($theme['active'] || $theme['id'] === $this->original_stylesheet) {
             continue;
         }
         $theme_id = 'theme_' . $theme['id'];
         $theme['isActiveTheme'] = false;
         $this->add_control(new WP_Customize_Theme_Control($this, $theme_id, array('theme' => $theme, 'section' => 'themes', 'settings' => 'active_theme')));
     }
     /* Site Identity */
     $this->add_section('title_tagline', array('title' => __('Site Identity'), 'priority' => 20));
     $this->add_setting('blogname', array('default' => get_option('blogname'), 'type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('blogname', array('label' => __('Site Title'), 'section' => 'title_tagline'));
     $this->add_setting('blogdescription', array('default' => get_option('blogdescription'), 'type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('blogdescription', array('label' => __('Tagline'), 'section' => 'title_tagline'));
     // Add a setting to hide header text if the theme doesn't support custom headers.
     if (!current_theme_supports('custom-header', 'header-text')) {
         $this->add_setting('header_text', array('theme_supports' => array('custom-logo', 'header-text'), 'default' => 1, 'sanitize_callback' => 'absint'));
         $this->add_control('header_text', array('label' => __('Display Site Title and Tagline'), 'section' => 'title_tagline', 'settings' => 'header_text', 'type' => 'checkbox'));
     }
     $this->add_setting('site_icon', array('type' => 'option', 'capability' => 'manage_options', 'transport' => 'postMessage'));
     $this->add_control(new WP_Customize_Site_Icon_Control($this, 'site_icon', array('label' => __('Site Icon'), 'description' => sprintf(__('The Site Icon is used as a browser and app icon for your site. Icons must be square, and at least %s pixels wide and tall.'), '<strong>512</strong>'), 'section' => 'title_tagline', 'priority' => 60, 'height' => 512, 'width' => 512)));
     $this->add_setting('custom_logo', array('theme_supports' => array('custom-logo'), 'transport' => 'postMessage'));
     $custom_logo_args = get_theme_support('custom-logo');
     $this->add_control(new WP_Customize_Cropped_Image_Control($this, 'custom_logo', array('label' => __('Logo'), 'section' => 'title_tagline', 'priority' => 8, 'height' => $custom_logo_args[0]['height'], 'width' => $custom_logo_args[0]['width'], 'flex_height' => $custom_logo_args[0]['flex-height'], 'flex_width' => $custom_logo_args[0]['flex-width'], 'button_labels' => array('select' => __('Select logo'), 'change' => __('Change logo'), 'remove' => __('Remove'), 'default' => __('Default'), 'placeholder' => __('No logo selected'), 'frame_title' => __('Select logo'), 'frame_button' => __('Choose logo')))));
     $this->selective_refresh->add_partial('custom_logo', array('settings' => array('custom_logo'), 'selector' => '.custom-logo-link', 'render_callback' => array($this, '_render_custom_logo_partial'), 'container_inclusive' => true));
     /* Colors */
     $this->add_section('colors', array('title' => __('Colors'), 'priority' => 40));
     $this->add_setting('header_textcolor', array('theme_supports' => array('custom-header', 'header-text'), 'default' => get_theme_support('custom-header', 'default-text-color'), 'sanitize_callback' => array($this, '_sanitize_header_textcolor'), 'sanitize_js_callback' => 'maybe_hash_hex_color'));
     // Input type: checkbox
     // With custom value
     $this->add_control('display_header_text', array('settings' => 'header_textcolor', 'label' => __('Display Site Title and Tagline'), 'section' => 'title_tagline', 'type' => 'checkbox', 'priority' => 40));
     $this->add_control(new WP_Customize_Color_Control($this, 'header_textcolor', array('label' => __('Header Text Color'), 'section' => 'colors')));
     // Input type: Color
     // With sanitize_callback
     $this->add_setting('background_color', array('default' => get_theme_support('custom-background', 'default-color'), 'theme_supports' => 'custom-background', 'sanitize_callback' => 'sanitize_hex_color_no_hash', 'sanitize_js_callback' => 'maybe_hash_hex_color'));
     $this->add_control(new WP_Customize_Color_Control($this, 'background_color', array('label' => __('Background Color'), 'section' => 'colors')));
     /* Custom Header */
     $this->add_section('header_image', array('title' => __('Header Image'), 'theme_supports' => 'custom-header', 'priority' => 60));
     $this->add_setting(new WP_Customize_Filter_Setting($this, 'header_image', array('default' => get_theme_support('custom-header', 'default-image'), 'theme_supports' => 'custom-header')));
     $this->add_setting(new WP_Customize_Header_Image_Setting($this, 'header_image_data', array('theme_supports' => 'custom-header')));
     $this->add_control(new WP_Customize_Header_Image_Control($this));
     /* Custom Background */
     $this->add_section('background_image', array('title' => __('Background Image'), 'theme_supports' => 'custom-background', 'priority' => 80));
     $this->add_setting('background_image', array('default' => get_theme_support('custom-background', 'default-image'), 'theme_supports' => 'custom-background'));
     $this->add_setting(new WP_Customize_Background_Image_Setting($this, 'background_image_thumb', array('theme_supports' => 'custom-background')));
     $this->add_control(new WP_Customize_Background_Image_Control($this));
     $this->add_setting('background_repeat', array('default' => get_theme_support('custom-background', 'default-repeat'), 'theme_supports' => 'custom-background'));
     $this->add_control('background_repeat', array('label' => __('Background Repeat'), 'section' => 'background_image', 'type' => 'radio', 'choices' => array('no-repeat' => __('No Repeat'), 'repeat' => __('Tile'), 'repeat-x' => __('Tile Horizontally'), 'repeat-y' => __('Tile Vertically'))));
     $this->add_setting('background_position_x', array('default' => get_theme_support('custom-background', 'default-position-x'), 'theme_supports' => 'custom-background'));
     $this->add_control('background_position_x', array('label' => __('Background Position'), 'section' => 'background_image', 'type' => 'radio', 'choices' => array('left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'))));
     $this->add_setting('background_attachment', array('default' => get_theme_support('custom-background', 'default-attachment'), 'theme_supports' => 'custom-background'));
     $this->add_control('background_attachment', array('label' => __('Background Attachment'), 'section' => 'background_image', 'type' => 'radio', 'choices' => array('scroll' => __('Scroll'), 'fixed' => __('Fixed'))));
     // If the theme is using the default background callback, we can update
     // the background CSS using postMessage.
     if (get_theme_support('custom-background', 'wp-head-callback') === '_custom_background_cb') {
         foreach (array('color', 'image', 'position_x', 'repeat', 'attachment') as $prop) {
             $this->get_setting('background_' . $prop)->transport = 'postMessage';
         }
     }
     /* Static Front Page */
     // #WP19627
     // Replicate behavior from options-reading.php and hide front page options if there are no pages
     if (get_pages()) {
         $this->add_section('static_front_page', array('title' => __('Static Front Page'), 'priority' => 120, 'description' => __('Your theme supports a static front page.')));
         $this->add_setting('show_on_front', array('default' => get_option('show_on_front'), 'capability' => 'manage_options', 'type' => 'option'));
         $this->add_control('show_on_front', array('label' => __('Front page displays'), 'section' => 'static_front_page', 'type' => 'radio', 'choices' => array('posts' => __('Your latest posts'), 'page' => __('A static page'))));
         $this->add_setting('page_on_front', array('type' => 'option', 'capability' => 'manage_options'));
         $this->add_control('page_on_front', array('label' => __('Front page'), 'section' => 'static_front_page', 'type' => 'dropdown-pages'));
         $this->add_setting('page_for_posts', array('type' => 'option', 'capability' => 'manage_options'));
         $this->add_control('page_for_posts', array('label' => __('Posts page'), 'section' => 'static_front_page', 'type' => 'dropdown-pages'));
     }
 }
 /**
  * Register some default controls.
  *
  * @since 3.4.0
  */
 public function register_controls()
 {
     /* Panel, Section, and Control Types */
     $this->register_panel_type('WP_Customize_Panel');
     $this->register_section_type('WP_Customize_Section');
     $this->register_section_type('WP_Customize_Sidebar_Section');
     $this->register_control_type('WP_Customize_Color_Control');
     $this->register_control_type('WP_Customize_Media_Control');
     $this->register_control_type('WP_Customize_Upload_Control');
     $this->register_control_type('WP_Customize_Image_Control');
     $this->register_control_type('WP_Customize_Background_Image_Control');
     $this->register_control_type('WP_Customize_Background_Position_Control');
     $this->register_control_type('WP_Customize_Cropped_Image_Control');
     $this->register_control_type('WP_Customize_Site_Icon_Control');
     $this->register_control_type('WP_Customize_Theme_Control');
     /* Themes */
     $this->add_section(new WP_Customize_Themes_Section($this, 'themes', array('title' => $this->theme()->display('Name'), 'capability' => 'switch_themes', 'priority' => 0)));
     // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience).
     $this->add_setting(new WP_Customize_Filter_Setting($this, 'active_theme', array('capability' => 'switch_themes')));
     require_once ABSPATH . 'wp-admin/includes/theme.php';
     // Theme Controls.
     // Add a control for the active/original theme.
     if (!$this->is_theme_active()) {
         $themes = wp_prepare_themes_for_js(array(wp_get_theme($this->original_stylesheet)));
         $active_theme = current($themes);
         $active_theme['isActiveTheme'] = true;
         $this->add_control(new WP_Customize_Theme_Control($this, $active_theme['id'], array('theme' => $active_theme, 'section' => 'themes', 'settings' => 'active_theme')));
     }
     $themes = wp_prepare_themes_for_js();
     foreach ($themes as $theme) {
         if ($theme['active'] || $theme['id'] === $this->original_stylesheet) {
             continue;
         }
         $theme_id = 'theme_' . $theme['id'];
         $theme['isActiveTheme'] = false;
         $this->add_control(new WP_Customize_Theme_Control($this, $theme_id, array('theme' => $theme, 'section' => 'themes', 'settings' => 'active_theme')));
     }
     /* Site Identity */
     $this->add_section('title_tagline', array('title' => __('Site Identity'), 'priority' => 20));
     $this->add_setting('blogname', array('default' => get_option('blogname'), 'type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('blogname', array('label' => __('Site Title'), 'section' => 'title_tagline'));
     $this->add_setting('blogdescription', array('default' => get_option('blogdescription'), 'type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('blogdescription', array('label' => __('Tagline'), 'section' => 'title_tagline'));
     // Add a setting to hide header text if the theme doesn't support custom headers.
     if (!current_theme_supports('custom-header', 'header-text')) {
         $this->add_setting('header_text', array('theme_supports' => array('custom-logo', 'header-text'), 'default' => 1, 'sanitize_callback' => 'absint'));
         $this->add_control('header_text', array('label' => __('Display Site Title and Tagline'), 'section' => 'title_tagline', 'settings' => 'header_text', 'type' => 'checkbox'));
     }
     $this->add_setting('site_icon', array('type' => 'option', 'capability' => 'manage_options', 'transport' => 'postMessage'));
     $this->add_control(new WP_Customize_Site_Icon_Control($this, 'site_icon', array('label' => __('Site Icon'), 'description' => sprintf(__('The Site Icon is used as a browser and app icon for your site. Icons must be square, and at least %s pixels wide and tall.'), '<strong>512</strong>'), 'section' => 'title_tagline', 'priority' => 60, 'height' => 512, 'width' => 512)));
     $this->add_setting('custom_logo', array('theme_supports' => array('custom-logo'), 'transport' => 'postMessage'));
     $custom_logo_args = get_theme_support('custom-logo');
     $this->add_control(new WP_Customize_Cropped_Image_Control($this, 'custom_logo', array('label' => __('Logo'), 'section' => 'title_tagline', 'priority' => 8, 'height' => $custom_logo_args[0]['height'], 'width' => $custom_logo_args[0]['width'], 'flex_height' => $custom_logo_args[0]['flex-height'], 'flex_width' => $custom_logo_args[0]['flex-width'], 'button_labels' => array('select' => __('Select logo'), 'change' => __('Change logo'), 'remove' => __('Remove'), 'default' => __('Default'), 'placeholder' => __('No logo selected'), 'frame_title' => __('Select logo'), 'frame_button' => __('Choose logo')))));
     $this->selective_refresh->add_partial('custom_logo', array('settings' => array('custom_logo'), 'selector' => '.custom-logo-link', 'render_callback' => array($this, '_render_custom_logo_partial'), 'container_inclusive' => true));
     /* Colors */
     $this->add_section('colors', array('title' => __('Colors'), 'priority' => 40));
     $this->add_setting('header_textcolor', array('theme_supports' => array('custom-header', 'header-text'), 'default' => get_theme_support('custom-header', 'default-text-color'), 'sanitize_callback' => array($this, '_sanitize_header_textcolor'), 'sanitize_js_callback' => 'maybe_hash_hex_color'));
     // Input type: checkbox
     // With custom value
     $this->add_control('display_header_text', array('settings' => 'header_textcolor', 'label' => __('Display Site Title and Tagline'), 'section' => 'title_tagline', 'type' => 'checkbox', 'priority' => 40));
     $this->add_control(new WP_Customize_Color_Control($this, 'header_textcolor', array('label' => __('Header Text Color'), 'section' => 'colors')));
     // Input type: Color
     // With sanitize_callback
     $this->add_setting('background_color', array('default' => get_theme_support('custom-background', 'default-color'), 'theme_supports' => 'custom-background', 'sanitize_callback' => 'sanitize_hex_color_no_hash', 'sanitize_js_callback' => 'maybe_hash_hex_color'));
     $this->add_control(new WP_Customize_Color_Control($this, 'background_color', array('label' => __('Background Color'), 'section' => 'colors')));
     /* Custom Header */
     if (current_theme_supports('custom-header', 'video')) {
         $title = __('Header Media');
         $description = '<p>' . __('If you add a video, the image will be used as a fallback while the video loads.') . '</p>';
         // @todo Customizer sections should support having notifications just like controls do. See <https://core.trac.wordpress.org/ticket/38794>.
         $description .= '<div class="customize-control-notifications-container header-video-not-currently-previewable" style="display: none"><ul>';
         $description .= '<li class="notice notice-info">' . __('This theme doesn\'t support video headers on this page. Navigate to the front page or another page that supports video headers.') . '</li>';
         $description .= '</ul></div>';
         $width = absint(get_theme_support('custom-header', 'width'));
         $height = absint(get_theme_support('custom-header', 'height'));
         if ($width && $height) {
             $control_description = sprintf(__('Upload your video in %1$s format and minimize its file size for best results. Your theme recommends dimensions of %2$s pixels.'), '<code>.mp4</code>', sprintf('<strong>%s &times; %s</strong>', $width, $height));
         } elseif ($width) {
             $control_description = sprintf(__('Upload your video in %1$s format and minimize its file size for best results. Your theme recommends a width of %2$s pixels.'), '<code>.mp4</code>', sprintf('<strong>%s</strong>', $width));
         } else {
             $control_description = sprintf(__('Upload your video in %1$s format and minimize its file size for best results. Your theme recommends a height of %2$s pixels.'), '<code>.mp4</code>', sprintf('<strong>%s</strong>', $height));
         }
     } else {
         $title = __('Header Image');
         $description = '';
         $control_description = '';
     }
     $this->add_section('header_image', array('title' => $title, 'description' => $description, 'theme_supports' => 'custom-header', 'priority' => 60));
     $this->add_setting('header_video', array('theme_supports' => array('custom-header', 'video'), 'transport' => 'postMessage', 'sanitize_callback' => 'absint', 'validate_callback' => array($this, '_validate_header_video')));
     $this->add_setting('external_header_video', array('theme_supports' => array('custom-header', 'video'), 'transport' => 'postMessage', 'sanitize_callback' => 'esc_url_raw', 'validate_callback' => array($this, '_validate_external_header_video')));
     $this->add_setting(new WP_Customize_Filter_Setting($this, 'header_image', array('default' => sprintf(get_theme_support('custom-header', 'default-image'), get_template_directory_uri(), get_stylesheet_directory_uri()), 'theme_supports' => 'custom-header')));
     $this->add_setting(new WP_Customize_Header_Image_Setting($this, 'header_image_data', array('theme_supports' => 'custom-header')));
     /*
      * Switch image settings to postMessage when video support is enabled since
      * it entails that the_custom_header_markup() will be used, and thus selective
      * refresh can be utilized.
      */
     if (current_theme_supports('custom-header', 'video')) {
         $this->get_setting('header_image')->transport = 'postMessage';
         $this->get_setting('header_image_data')->transport = 'postMessage';
     }
     $this->add_control(new WP_Customize_Media_Control($this, 'header_video', array('theme_supports' => array('custom-header', 'video'), 'label' => __('Header Video'), 'description' => $control_description, 'section' => 'header_image', 'mime_type' => 'video', 'button_labels' => array('select' => __('Select Video'), 'change' => __('Change Video'), 'placeholder' => __('No video selected'), 'frame_title' => __('Select Video'), 'frame_button' => __('Choose Video')), 'active_callback' => 'is_header_video_active')));
     $this->add_control('external_header_video', array('theme_supports' => array('custom-header', 'video'), 'type' => 'url', 'description' => __('Or, enter a YouTube URL:'), 'section' => 'header_image', 'active_callback' => 'is_front_page'));
     $this->add_control(new WP_Customize_Header_Image_Control($this));
     $this->selective_refresh->add_partial('custom_header', array('selector' => '#wp-custom-header', 'render_callback' => 'the_custom_header_markup', 'settings' => array('header_video', 'external_header_video', 'header_image'), 'container_inclusive' => true));
     /* Custom Background */
     $this->add_section('background_image', array('title' => __('Background Image'), 'theme_supports' => 'custom-background', 'priority' => 80));
     $this->add_setting('background_image', array('default' => get_theme_support('custom-background', 'default-image'), 'theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting')));
     $this->add_setting(new WP_Customize_Background_Image_Setting($this, 'background_image_thumb', array('theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting'))));
     $this->add_control(new WP_Customize_Background_Image_Control($this));
     $this->add_setting('background_preset', array('default' => get_theme_support('custom-background', 'default-preset'), 'theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting')));
     $this->add_control('background_preset', array('label' => _x('Preset', 'Background Preset'), 'section' => 'background_image', 'type' => 'select', 'choices' => array('default' => _x('Default', 'Default Preset'), 'fill' => __('Fill Screen'), 'fit' => __('Fit to Screen'), 'repeat' => _x('Repeat', 'Repeat Image'), 'custom' => _x('Custom', 'Custom Preset'))));
     $this->add_setting('background_position_x', array('default' => get_theme_support('custom-background', 'default-position-x'), 'theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting')));
     $this->add_setting('background_position_y', array('default' => get_theme_support('custom-background', 'default-position-y'), 'theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting')));
     $this->add_control(new WP_Customize_Background_Position_Control($this, 'background_position', array('label' => __('Image Position'), 'section' => 'background_image', 'settings' => array('x' => 'background_position_x', 'y' => 'background_position_y'))));
     $this->add_setting('background_size', array('default' => get_theme_support('custom-background', 'default-size'), 'theme_supports' => 'custom-background', 'sanitize_callback' => array($this, '_sanitize_background_setting')));
     $this->add_control('background_size', array('label' => __('Image Size'), 'section' => 'background_image', 'type' => 'select', 'choices' => array('auto' => __('Original'), 'contain' => __('Fit to Screen'), 'cover' => __('Fill Screen'))));
     $this->add_setting('background_repeat', array('default' => get_theme_support('custom-background', 'default-repeat'), 'sanitize_callback' => array($this, '_sanitize_background_setting'), 'theme_supports' => 'custom-background'));
     $this->add_control('background_repeat', array('label' => __('Repeat Background Image'), 'section' => 'background_image', 'type' => 'checkbox'));
     $this->add_setting('background_attachment', array('default' => get_theme_support('custom-background', 'default-attachment'), 'sanitize_callback' => array($this, '_sanitize_background_setting'), 'theme_supports' => 'custom-background'));
     $this->add_control('background_attachment', array('label' => __('Scroll with Page'), 'section' => 'background_image', 'type' => 'checkbox'));
     // If the theme is using the default background callback, we can update
     // the background CSS using postMessage.
     if (get_theme_support('custom-background', 'wp-head-callback') === '_custom_background_cb') {
         foreach (array('color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment') as $prop) {
             $this->get_setting('background_' . $prop)->transport = 'postMessage';
         }
     }
     /*
      * Static Front Page
      * See also https://core.trac.wordpress.org/ticket/19627 which introduces the the static-front-page theme_support.
      * The following replicates behavior from options-reading.php.
      */
     $this->add_section('static_front_page', array('title' => __('Static Front Page'), 'priority' => 120, 'description' => __('Your theme supports a static front page.'), 'active_callback' => array($this, 'has_published_pages')));
     $this->add_setting('show_on_front', array('default' => get_option('show_on_front'), 'capability' => 'manage_options', 'type' => 'option'));
     $this->add_control('show_on_front', array('label' => __('Front page displays'), 'section' => 'static_front_page', 'type' => 'radio', 'choices' => array('posts' => __('Your latest posts'), 'page' => __('A static page'))));
     $this->add_setting('page_on_front', array('type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('page_on_front', array('label' => __('Front page'), 'section' => 'static_front_page', 'type' => 'dropdown-pages', 'allow_addition' => true));
     $this->add_setting('page_for_posts', array('type' => 'option', 'capability' => 'manage_options'));
     $this->add_control('page_for_posts', array('label' => __('Posts page'), 'section' => 'static_front_page', 'type' => 'dropdown-pages', 'allow_addition' => true));
     /* Custom CSS */
     $this->add_section('custom_css', array('title' => __('Additional CSS'), 'priority' => 200, 'description_hidden' => true, 'description' => sprintf('%s<br /><a href="%s" class="external-link" target="_blank">%s<span class="screen-reader-text">%s</span></a>', __('CSS allows you to customize the appearance and layout of your site with code. Separate CSS is saved for each of your themes. In the editing area the Tab key enters a tab character. To move below this area by pressing Tab, press the Esc key followed by the Tab key.'), esc_url(__('https://codex.wordpress.org/CSS')), __('Learn more about CSS'), __('(link opens in a new window)'))));
     $custom_css_setting = new WP_Customize_Custom_CSS_Setting($this, sprintf('custom_css[%s]', get_stylesheet()), array('capability' => 'edit_css', 'default' => sprintf("/*\n%s\n*/", __("You can add your own CSS here.\n\nClick the help icon above to learn more."))));
     $this->add_setting($custom_css_setting);
     $this->add_control('custom_css', array('type' => 'textarea', 'section' => 'custom_css', 'settings' => array('default' => $custom_css_setting->id), 'input_attrs' => array('class' => 'code')));
 }
 /**
  * Test WP_Customize_Selective_Refresh::is_render_partials_request().
  *
  * @see WP_Customize_Selective_Refresh::is_render_partials_request()
  */
 function test_is_render_partials_request()
 {
     $this->assertFalse($this->selective_refresh->is_render_partials_request());
     $_POST[WP_Customize_Selective_Refresh::RENDER_QUERY_VAR] = '1';
     $this->assertTrue($this->selective_refresh->is_render_partials_request());
 }