WordPress 4.0
[autoinstalls/wordpress.git] / wp-includes / class-wp-customize-manager.php
index 8ed4e699a5b5da4072108dccde2c6e73aceb2125..4465a80545c5bfcef01059d320dd6300b2b43921 100644 (file)
@@ -16,7 +16,7 @@
  */
 final class WP_Customize_Manager {
        /**
-        * An instance of the theme that is being customized.
+        * An instance of the theme being previewed.
         *
         * @var WP_Theme
         */
@@ -30,8 +30,7 @@ final class WP_Customize_Manager {
        protected $original_stylesheet;
 
        /**
-        * Whether filters have been set to change the active theme to the theme being
-        * customized.
+        * Whether this is a Customizer pageload.
         *
         * @var boolean
         */
@@ -44,9 +43,11 @@ final class WP_Customize_Manager {
         */
        public $widgets;
 
-       protected $settings = array();
-       protected $sections = array();
-       protected $controls = array();
+       protected $settings   = array();
+       protected $containers = array();
+       protected $panels     = array();
+       protected $sections   = array();
+       protected $controls   = array();
 
        protected $nonce_tick;
 
@@ -66,6 +67,7 @@ final class WP_Customize_Manager {
         */
        public function __construct() {
                require( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
+               require( ABSPATH . WPINC . '/class-wp-customize-panel.php' );
                require( ABSPATH . WPINC . '/class-wp-customize-section.php' );
                require( ABSPATH . WPINC . '/class-wp-customize-control.php' );
                require( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
@@ -156,8 +158,9 @@ final class WP_Customize_Manager {
 
                show_admin_bar( false );
 
-               if ( ! current_user_can( 'edit_theme_options' ) )
+               if ( ! current_user_can( 'customize' ) ) {
                        $this->wp_die( -1 );
+               }
 
                $this->original_stylesheet = get_stylesheet();
 
@@ -181,7 +184,6 @@ final class WP_Customize_Manager {
                                $this->wp_die( -1 );
                }
 
-               // All good, let's do some internal business to preview the theme.
                $this->start_previewing_theme();
        }
 
@@ -190,7 +192,7 @@ final class WP_Customize_Manager {
         *
         * @since 3.4.0
         */
-       function after_setup_theme() {
+       public function after_setup_theme() {
                if ( ! $this->doing_ajax() && ! validate_current_theme() ) {
                        wp_redirect( 'themes.php?broken=true' );
                        exit;
@@ -198,7 +200,8 @@ final class WP_Customize_Manager {
        }
 
        /**
-        * Start previewing the selected theme by adding filters to change the current theme.
+        * If the theme to be previewed isn't the active theme, add filter callbacks
+        * to swap it out at runtime.
         *
         * @since 3.4.0
         */
@@ -303,6 +306,17 @@ final class WP_Customize_Manager {
                return $this->controls;
        }
 
+       /**
+        * Get the registered containers.
+        *
+        * @since 4.0.0
+        *
+        * @return array
+        */
+       public function containers() {
+               return $this->containers;
+       }
+
        /**
         * Get the registered sections.
         *
@@ -314,6 +328,18 @@ final class WP_Customize_Manager {
                return $this->sections;
        }
 
+       /**
+        * Get the registered panels.
+        *
+        * @since 4.0.0
+        * @access public
+        *
+        * @return array Panels.
+        */
+       public function panels() {
+               return $this->panels;
+       }
+
        /**
         * Checks if the current theme is active.
         *
@@ -394,6 +420,7 @@ final class WP_Customize_Manager {
                $this->prepare_controls();
 
                wp_enqueue_script( 'customize-preview' );
+               add_action( 'wp', array( $this, 'customize_preview_override_404_status' ) );
                add_action( 'wp_head', array( $this, 'customize_preview_base' ) );
                add_action( 'wp_head', array( $this, 'customize_preview_html5' ) );
                add_action( 'wp_footer', array( $this, 'customize_preview_settings' ), 20 );
@@ -415,6 +442,19 @@ final class WP_Customize_Manager {
                do_action( 'customize_preview_init', $this );
        }
 
+       /**
+        * Prevent sending a 404 status when returning the response for the customize
+        * preview, since it causes the jQuery AJAX to fail. Send 200 instead.
+        *
+        * @since 4.0.0
+        * @access public
+        */
+       public function customize_preview_override_404_status() {
+               if ( is_404() ) {
+                       status_header( 200 );
+               }
+       }
+
        /**
         * Print base element for preview frame.
         *
@@ -450,7 +490,8 @@ final class WP_Customize_Manager {
        public function customize_preview_settings() {
                $settings = array(
                        'values'  => array(),
-                       'channel' => esc_js( $_POST['customize_messenger_channel'] ),
+                       'channel' => wp_unslash( $_POST['customize_messenger_channel'] ),
+                       'activeControls' => array(),
                );
 
                if ( 2 == $this->nonce_tick ) {
@@ -463,6 +504,9 @@ final class WP_Customize_Manager {
                foreach ( $this->settings as $id => $setting ) {
                        $settings['values'][ $id ] = $setting->js_value();
                }
+               foreach ( $this->controls as $id => $control ) {
+                       $settings['activeControls'][ $id ] = $control->active();
+               }
 
                ?>
                <script type="text/javascript">
@@ -647,6 +691,53 @@ final class WP_Customize_Manager {
                unset( $this->settings[ $id ] );
        }
 
+       /**
+        * Add a customize panel.
+        *
+        * @since 4.0.0
+        * @access public
+        *
+        * @param WP_Customize_Panel|string $id   Customize Panel object, or Panel ID.
+        * @param array                     $args Optional. Panel arguments. Default empty array.
+        */
+       public function add_panel( $id, $args = array() ) {
+               if ( is_a( $id, 'WP_Customize_Panel' ) ) {
+                       $panel = $id;
+               }
+               else {
+                       $panel = new WP_Customize_Panel( $this, $id, $args );
+               }
+
+               $this->panels[ $panel->id ] = $panel;
+       }
+
+       /**
+        * Retrieve a customize panel.
+        *
+        * @since 4.0.0
+        * @access public
+        *
+        * @param string $id Panel ID to get.
+        * @return WP_Customize_Panel Requested panel instance.
+        */
+       public function get_panel( $id ) {
+               if ( isset( $this->panels[ $id ] ) ) {
+                       return $this->panels[ $id ];
+               }
+       }
+
+       /**
+        * Remove a customize panel.
+        *
+        * @since 4.0.0
+        * @access public
+        *
+        * @param string $id Panel ID to remove.
+        */
+       public function remove_panel( $id ) {
+               unset( $this->panels[ $id ] );
+       }
+
        /**
         * Add a customize section.
         *
@@ -749,7 +840,7 @@ final class WP_Customize_Manager {
        }
 
        /**
-        * Prepare settings and sections.
+        * Prepare panels, sections, and controls.
         *
         * For each, check if required related components exist,
         * whether the user has the necessary capabilities,
@@ -763,8 +854,9 @@ final class WP_Customize_Manager {
                $controls = array();
 
                foreach ( $this->controls as $id => $control ) {
-                       if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() )
+                       if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) {
                                continue;
+                       }
 
                        $this->sections[ $control->section ]->controls[] = $control;
                        $controls[ $id ] = $control;
@@ -778,13 +870,43 @@ final class WP_Customize_Manager {
                $sections = array();
 
                foreach ( $this->sections as $section ) {
-                       if ( ! $section->check_capabilities() || ! $section->controls )
+                       if ( ! $section->check_capabilities() || ! $section->controls ) {
                                continue;
+                       }
 
                        usort( $section->controls, array( $this, '_cmp_priority' ) );
-                       $sections[] = $section;
+
+                       if ( ! $section->panel ) {
+                               // Top-level section.
+                               $sections[] = $section;
+                       } else {
+                               // This section belongs to a panel.
+                               if ( isset( $this->panels [ $section->panel ] ) ) {
+                                       $this->panels[ $section->panel ]->sections[] = $section;
+                               }
+                       }
                }
                $this->sections = $sections;
+
+               // Prepare panels.
+               // Reversing makes uasort sort by time added when conflicts occur.
+               $this->panels = array_reverse( $this->panels );
+               uasort( $this->panels, array( $this, '_cmp_priority' ) );
+               $panels = array();
+
+               foreach ( $this->panels as $panel ) {
+                       if ( ! $panel->check_capabilities() || ! $panel->sections ) {
+                               continue;
+                       }
+
+                       usort( $panel->sections, array( $this, '_cmp_priority' ) );
+                       $panels[] = $panel;
+               }
+               $this->panels = $panels;
+
+               // Sort panels and top-level sections together.
+               $this->containers = array_merge( $this->panels, $this->sections );
+               uasort( $this->containers, array( $this, '_cmp_priority' ) );
        }
 
        /**
@@ -919,7 +1041,7 @@ final class WP_Customize_Manager {
                $this->add_control( new WP_Customize_Background_Image_Control( $this ) );
 
                $this->add_setting( 'background_repeat', array(
-                       'default'        => 'repeat',
+                       'default'        => get_theme_support( 'custom-background', 'default-repeat' ),
                        'theme_supports' => 'custom-background',
                ) );
 
@@ -936,7 +1058,7 @@ final class WP_Customize_Manager {
                ) );
 
                $this->add_setting( 'background_position_x', array(
-                       'default'        => 'left',
+                       'default'        => get_theme_support( 'custom-background', 'default-position-x' ),
                        'theme_supports' => 'custom-background',
                ) );
 
@@ -952,7 +1074,7 @@ final class WP_Customize_Manager {
                ) );
 
                $this->add_setting( 'background_attachment', array(
-                       'default'        => 'fixed',
+                       'default'        => get_theme_support( 'custom-background', 'default-attachment' ),
                        'theme_supports' => 'custom-background',
                ) );
 
@@ -961,8 +1083,8 @@ final class WP_Customize_Manager {
                        'section'    => 'background_image',
                        'type'       => 'radio',
                        'choices'    => array(
-                               'fixed'      => __('Fixed'),
                                'scroll'     => __('Scroll'),
+                               'fixed'      => __('Fixed'),
                        ),
                ) );
 
@@ -978,7 +1100,6 @@ final class WP_Customize_Manager {
 
                $locations      = get_registered_nav_menus();
                $menus          = wp_get_nav_menus();
-               $menu_locations = get_nav_menu_locations();
                $num_locations  = count( array_keys( $locations ) );
 
                $this->add_section( 'nav', array(
@@ -1084,7 +1205,7 @@ final class WP_Customize_Manager {
 
                return $color;
        }
-};
+}
 
 /**
  * Sanitizes a hex color.