WordPress 4.3
[autoinstalls/wordpress.git] / wp-includes / class-wp-customize-section.php
1 <?php
2 /**
3  * WordPress Customize Section classes
4  *
5  * @package WordPress
6  * @subpackage Customize
7  * @since 3.4.0
8  */
9
10 /**
11  * Customize Section class.
12  *
13  * A UI container for controls, managed by the WP_Customize_Manager class.
14  *
15  * @since 3.4.0
16  *
17  * @see WP_Customize_Manager
18  */
19 class WP_Customize_Section {
20
21         /**
22          * Incremented with each new class instantiation, then stored in $instance_number.
23          *
24          * Used when sorting two instances whose priorities are equal.
25          *
26          * @since 4.1.0
27          *
28          * @static
29          * @access protected
30          * @var int
31          */
32         protected static $instance_count = 0;
33
34         /**
35          * Order in which this instance was created in relation to other instances.
36          *
37          * @since 4.1.0
38          * @access public
39          * @var int
40          */
41         public $instance_number;
42
43         /**
44          * WP_Customize_Manager instance.
45          *
46          * @since 3.4.0
47          * @access public
48          * @var WP_Customize_Manager
49          */
50         public $manager;
51
52         /**
53          * Unique identifier.
54          *
55          * @since 3.4.0
56          * @access public
57          * @var string
58          */
59         public $id;
60
61         /**
62          * Priority of the section which informs load order of sections.
63          *
64          * @since 3.4.0
65          * @access public
66          * @var integer
67          */
68         public $priority = 160;
69
70         /**
71          * Panel in which to show the section, making it a sub-section.
72          *
73          * @since 4.0.0
74          * @access public
75          * @var string
76          */
77         public $panel = '';
78
79         /**
80          * Capability required for the section.
81          *
82          * @since 3.4.0
83          * @access public
84          * @var string
85          */
86         public $capability = 'edit_theme_options';
87
88         /**
89          * Theme feature support for the section.
90          *
91          * @since 3.4.0
92          * @access public
93          * @var string|array
94          */
95         public $theme_supports = '';
96
97         /**
98          * Title of the section to show in UI.
99          *
100          * @since 3.4.0
101          * @access public
102          * @var string
103          */
104         public $title = '';
105
106         /**
107          * Description to show in the UI.
108          *
109          * @since 3.4.0
110          * @access public
111          * @var string
112          */
113         public $description = '';
114
115         /**
116          * Customizer controls for this section.
117          *
118          * @since 3.4.0
119          * @access public
120          * @var array
121          */
122         public $controls;
123
124         /**
125          * Type of this section.
126          *
127          * @since 4.1.0
128          * @access public
129          * @var string
130          */
131         public $type = 'default';
132
133         /**
134          * Active callback.
135          *
136          * @since 4.1.0
137          * @access public
138          *
139          * @see WP_Customize_Section::active()
140          *
141          * @var callable Callback is called with one argument, the instance of
142          *               {@see WP_Customize_Section}, and returns bool to indicate
143          *               whether the section is active (such as it relates to the URL
144          *               currently being previewed).
145          */
146         public $active_callback = '';
147
148         /**
149          * Constructor.
150          *
151          * Any supplied $args override class property defaults.
152          *
153          * @since 3.4.0
154          *
155          * @param WP_Customize_Manager $manager Customizer bootstrap instance.
156          * @param string               $id      An specific ID of the section.
157          * @param array                $args    Section arguments.
158          */
159         public function __construct( $manager, $id, $args = array() ) {
160                 $keys = array_keys( get_object_vars( $this ) );
161                 foreach ( $keys as $key ) {
162                         if ( isset( $args[ $key ] ) ) {
163                                 $this->$key = $args[ $key ];
164                         }
165                 }
166
167                 $this->manager = $manager;
168                 $this->id = $id;
169                 if ( empty( $this->active_callback ) ) {
170                         $this->active_callback = array( $this, 'active_callback' );
171                 }
172                 self::$instance_count += 1;
173                 $this->instance_number = self::$instance_count;
174
175                 $this->controls = array(); // Users cannot customize the $controls array.
176         }
177
178         /**
179          * Check whether section is active to current Customizer preview.
180          *
181          * @since 4.1.0
182          * @access public
183          *
184          * @return bool Whether the section is active to the current preview.
185          */
186         final public function active() {
187                 $section = $this;
188                 $active = call_user_func( $this->active_callback, $this );
189
190                 /**
191                  * Filter response of {@see WP_Customize_Section::active()}.
192                  *
193                  * @since 4.1.0
194                  *
195                  * @param bool                 $active  Whether the Customizer section is active.
196                  * @param WP_Customize_Section $section {@see WP_Customize_Section} instance.
197                  */
198                 $active = apply_filters( 'customize_section_active', $active, $section );
199
200                 return $active;
201         }
202
203         /**
204          * Default callback used when invoking {@see WP_Customize_Section::active()}.
205          *
206          * Subclasses can override this with their specific logic, or they may provide
207          * an 'active_callback' argument to the constructor.
208          *
209          * @since 4.1.0
210          * @access public
211          *
212          * @return true Always true.
213          */
214         public function active_callback() {
215                 return true;
216         }
217
218         /**
219          * Gather the parameters passed to client JavaScript via JSON.
220          *
221          * @since 4.1.0
222          *
223          * @return array The array to be exported to the client as JSON.
224          */
225         public function json() {
226                 $array = wp_array_slice_assoc( (array) $this, array( 'id', 'description', 'priority', 'panel', 'type' ) );
227                 $array['title'] = html_entity_decode( $this->title, ENT_QUOTES, get_bloginfo( 'charset' ) );
228                 $array['content'] = $this->get_content();
229                 $array['active'] = $this->active();
230                 $array['instanceNumber'] = $this->instance_number;
231
232                 if ( $this->panel ) {
233                         /* translators: &#9656; is the unicode right-pointing triangle, and %s is the section title in the Customizer */
234                         $array['customizeAction'] = sprintf( __( 'Customizing &#9656; %s' ), esc_html( $this->manager->get_panel( $this->panel )->title ) );
235                 } else {
236                         $array['customizeAction'] = __( 'Customizing' );
237                 }
238
239                 return $array;
240         }
241
242         /**
243          * Checks required user capabilities and whether the theme has the
244          * feature support required by the section.
245          *
246          * @since 3.4.0
247          *
248          * @return bool False if theme doesn't support the section or user doesn't have the capability.
249          */
250         final public function check_capabilities() {
251                 if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) ) {
252                         return false;
253                 }
254
255                 if ( $this->theme_supports && ! call_user_func_array( 'current_theme_supports', (array) $this->theme_supports ) ) {
256                         return false;
257                 }
258
259                 return true;
260         }
261
262         /**
263          * Get the section's content for insertion into the Customizer pane.
264          *
265          * @since 4.1.0
266          *
267          * @return string Contents of the section.
268          */
269         final public function get_content() {
270                 ob_start();
271                 $this->maybe_render();
272                 return trim( ob_get_clean() );
273         }
274
275         /**
276          * Check capabilities and render the section.
277          *
278          * @since 3.4.0
279          */
280         final public function maybe_render() {
281                 if ( ! $this->check_capabilities() ) {
282                         return;
283                 }
284
285                 /**
286                  * Fires before rendering a Customizer section.
287                  *
288                  * @since 3.4.0
289                  *
290                  * @param WP_Customize_Section $this WP_Customize_Section instance.
291                  */
292                 do_action( 'customize_render_section', $this );
293                 /**
294                  * Fires before rendering a specific Customizer section.
295                  *
296                  * The dynamic portion of the hook name, `$this->id`, refers to the ID
297                  * of the specific Customizer section to be rendered.
298                  *
299                  * @since 3.4.0
300                  */
301                 do_action( "customize_render_section_{$this->id}" );
302
303                 $this->render();
304         }
305
306         /**
307          * Render the section UI in a subclass.
308          *
309          * Sections are now rendered in JS by default, see {@see WP_Customize_Section::print_template()}.
310          *
311          * @since 3.4.0
312          */
313         protected function render() {}
314
315         /**
316          * Render the section's JS template.
317          *
318          * This function is only run for section types that have been registered with
319          * WP_Customize_Manager::register_section_type().
320          *
321          * @since 4.3.0
322          * @access public
323          *
324          * @see WP_Customize_Manager::render_template()
325          */
326         public function print_template() {
327         ?>
328                 <script type="text/html" id="tmpl-customize-section-<?php echo $this->type; ?>">
329                         <?php $this->render_template(); ?>
330                 </script>
331         <?php
332         }
333
334         /**
335          * An Underscore (JS) template for rendering this section.
336          *
337          * Class variables for this section class are available in the `data` JS object;
338          * export custom variables by overriding WP_Customize_Section::json().
339          *
340          * @since 4.3.0
341          * @access protected
342          *
343          * @see WP_Customize_Section::print_template()
344          */
345         protected function render_template() {
346                 ?>
347                 <li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}">
348                         <h3 class="accordion-section-title" tabindex="0">
349                                 {{ data.title }}
350                                 <span class="screen-reader-text"><?php _e( 'Press return or enter to open' ); ?></span>
351                         </h3>
352                         <ul class="accordion-section-content">
353                                 <li class="customize-section-description-container">
354                                         <div class="customize-section-title">
355                                                 <button class="customize-section-back" tabindex="-1">
356                                                         <span class="screen-reader-text"><?php _e( 'Back' ); ?></span>
357                                                 </button>
358                                                 <h3>
359                                                         <span class="customize-action">
360                                                                 {{{ data.customizeAction }}}
361                                                         </span>
362                                                         {{ data.title }}
363                                                 </h3>
364                                         </div>
365                                         <# if ( data.description ) { #>
366                                                 <div class="description customize-section-description">
367                                                         {{{ data.description }}}
368                                                 </div>
369                                         <# } #>
370                                 </li>
371                         </ul>
372                 </li>
373                 <?php
374         }
375 }
376
377 /**
378  * Customize Themes Section class.
379  *
380  * A UI container for theme controls, which behaves like a backwards Panel.
381  *
382  * @since 4.2.0
383  *
384  * @see WP_Customize_Section
385  */
386 class WP_Customize_Themes_Section extends WP_Customize_Section {
387
388         /**
389          * Customize section type.
390          *
391          * @since 4.2.0
392          * @access public
393          * @var string
394          */
395         public $type = 'themes';
396
397         /**
398          * Render the themes section, which behaves like a panel.
399          *
400          * @since 4.2.0
401          * @access protected
402          */
403         protected function render() {
404                 $classes = 'accordion-section control-section control-section-' . $this->type;
405                 ?>
406                 <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
407                         <h3 class="accordion-section-title">
408                                 <?php
409                                 if ( $this->manager->is_theme_active() ) {
410                                         echo '<span class="customize-action">' . __( 'Active theme' ) . '</span> ' . $this->title;
411                                 } else {
412                                         echo '<span class="customize-action">' . __( 'Previewing theme' ) . '</span> ' . $this->title;
413                                 }
414                                 ?>
415
416                                 <button type="button" class="button change-theme" tabindex="0"><?php _ex( 'Change', 'theme' ); ?></button>
417                         </h3>
418                         <div class="customize-themes-panel control-panel-content themes-php">
419                                 <h3 class="accordion-section-title customize-section-title">
420                                         <span class="customize-action"><?php _e( 'Customizing' ); ?></span>
421                                         <?php _e( 'Themes' ); ?>
422                                         <span class="title-count theme-count"><?php echo count( $this->controls ) + 1 /* Active theme */; ?></span>
423                                 </h3>
424                                 <h3 class="accordion-section-title customize-section-title">
425                                         <?php
426                                         if ( $this->manager->is_theme_active() ) {
427                                                 echo '<span class="customize-action">' . __( 'Active theme' ) . '</span> ' . $this->title;
428                                         } else {
429                                                 echo '<span class="customize-action">' . __( 'Previewing theme' ) . '</span> ' . $this->title;
430                                         }
431                                         ?>
432                                         <button type="button" class="button customize-theme"><?php _e( 'Customize' ); ?></button>
433                                 </h3>
434
435                                 <div class="theme-overlay" tabindex="0" role="dialog" aria-label="<?php esc_attr_e( 'Theme Details' ); ?>"></div>
436
437                                 <div id="customize-container"></div>
438                                 <?php if ( count( $this->controls ) > 4 ) : ?>
439                                         <p><label for="themes-filter">
440                                                 <span class="screen-reader-text"><?php _e( 'Search installed themes...' ); ?></span>
441                                                 <input type="text" id="themes-filter" placeholder="<?php esc_attr_e( 'Search installed themes...' ); ?>" />
442                                         </label></p>
443                                 <?php endif; ?>
444                                 <div class="theme-browser rendered">
445                                         <ul class="themes accordion-section-content">
446                                         </ul>
447                                 </div>
448                         </div>
449                 </li>
450 <?php }
451 }
452
453 /**
454  * Customizer section representing widget area (sidebar).
455  *
456  * @since 4.1.0
457  *
458  * @see WP_Customize_Section
459  */
460 class WP_Customize_Sidebar_Section extends WP_Customize_Section {
461
462         /**
463          * Type of this section.
464          *
465          * @since 4.1.0
466          * @access public
467          * @var string
468          */
469         public $type = 'sidebar';
470
471         /**
472          * Unique identifier.
473          *
474          * @since 4.1.0
475          * @access public
476          * @var string
477          */
478         public $sidebar_id;
479
480         /**
481          * Gather the parameters passed to client JavaScript via JSON.
482          *
483          * @since 4.1.0
484          *
485          * @return array The array to be exported to the client as JSON.
486          */
487         public function json() {
488                 $json = parent::json();
489                 $json['sidebarId'] = $this->sidebar_id;
490                 return $json;
491         }
492
493         /**
494          * Whether the current sidebar is rendered on the page.
495          *
496          * @since 4.1.0
497          * @access public
498          *
499          * @return bool Whether sidebar is rendered.
500          */
501         public function active_callback() {
502                 return $this->manager->widgets->is_sidebar_rendered( $this->sidebar_id );
503         }
504 }
505
506 /**
507  * Customize Menu Section Class
508  *
509  * Custom section only needed in JS.
510  *
511  * @since 4.3.0
512  *
513  * @see WP_Customize_Section
514  */
515 class WP_Customize_Nav_Menu_Section extends WP_Customize_Section {
516
517         /**
518          * Control type.
519          *
520          * @since 4.3.0
521          * @access public
522          * @var string
523          */
524         public $type = 'nav_menu';
525
526         /**
527          * Get section parameters for JS.
528          *
529          * @since 4.3.0
530          * @access public
531          * @return array Exported parameters.
532          */
533         public function json() {
534                 $exported = parent::json();
535                 $exported['menu_id'] = intval( preg_replace( '/^nav_menu\[(\d+)\]/', '$1', $this->id ) );
536
537                 return $exported;
538         }
539 }
540
541 /**
542  * Customize Menu Section Class
543  *
544  * Implements the new-menu-ui toggle button instead of a regular section.
545  *
546  * @since 4.3.0
547  *
548  * @see WP_Customize_Section
549  */
550 class WP_Customize_New_Menu_Section extends WP_Customize_Section {
551
552         /**
553          * Control type.
554          *
555          * @since 4.3.0
556          * @access public
557          * @var string
558          */
559         public $type = 'new_menu';
560
561         /**
562          * Render the section, and the controls that have been added to it.
563          *
564          * @since 4.3.0
565          * @access protected
566          */
567         protected function render() {
568                 ?>
569                 <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="accordion-section-new-menu">
570                         <button type="button" class="button-secondary add-new-menu-item add-menu-toggle" aria-expanded="false">
571                                 <?php echo esc_html( $this->title ); ?>
572                         </button>
573                         <ul class="new-menu-section-content"></ul>
574                 </li>
575                 <?php
576         }
577 }