Wordpress 4.6
[autoinstalls/wordpress.git] / wp-includes / class-wp-customize-control.php
1 <?php
2 /**
3  * WordPress Customize Control classes
4  *
5  * @package WordPress
6  * @subpackage Customize
7  * @since 3.4.0
8  */
9
10 /**
11  * Customize Control class.
12  *
13  * @since 3.4.0
14  */
15 class WP_Customize_Control {
16
17         /**
18          * Incremented with each new class instantiation, then stored in $instance_number.
19          *
20          * Used when sorting two instances whose priorities are equal.
21          *
22          * @since 4.1.0
23          *
24          * @static
25          * @access protected
26          * @var int
27          */
28         protected static $instance_count = 0;
29
30         /**
31          * Order in which this instance was created in relation to other instances.
32          *
33          * @since 4.1.0
34          * @access public
35          * @var int
36          */
37         public $instance_number;
38
39         /**
40          * @access public
41          * @var WP_Customize_Manager
42          */
43         public $manager;
44
45         /**
46          * @access public
47          * @var string
48          */
49         public $id;
50
51         /**
52          * All settings tied to the control.
53          *
54          * @access public
55          * @var array
56          */
57         public $settings;
58
59         /**
60          * The primary setting for the control (if there is one).
61          *
62          * @access public
63          * @var string
64          */
65         public $setting = 'default';
66
67         /**
68          * Capability required to use this control.
69          *
70          * Normally this is empty and the capability is derived from the capabilities
71          * of the associated `$settings`.
72          *
73          * @since 4.5.0
74          * @access public
75          * @var string
76          */
77         public $capability;
78
79         /**
80          * @access public
81          * @var int
82          */
83         public $priority = 10;
84
85         /**
86          * @access public
87          * @var string
88          */
89         public $section = '';
90
91         /**
92          * @access public
93          * @var string
94          */
95         public $label = '';
96
97         /**
98          * @access public
99          * @var string
100          */
101         public $description = '';
102
103         /**
104          * @todo: Remove choices
105          *
106          * @access public
107          * @var array
108          */
109         public $choices = array();
110
111         /**
112          * @access public
113          * @var array
114          */
115         public $input_attrs = array();
116
117         /**
118          * @deprecated It is better to just call the json() method
119          * @access public
120          * @var array
121          */
122         public $json = array();
123
124         /**
125          * @access public
126          * @var string
127          */
128         public $type = 'text';
129
130         /**
131          * Callback.
132          *
133          * @since 4.0.0
134          * @access public
135          *
136          * @see WP_Customize_Control::active()
137          *
138          * @var callable Callback is called with one argument, the instance of
139          *               WP_Customize_Control, and returns bool to indicate whether
140          *               the control is active (such as it relates to the URL
141          *               currently being previewed).
142          */
143         public $active_callback = '';
144
145         /**
146          * Constructor.
147          *
148          * Supplied `$args` override class property defaults.
149          *
150          * If `$args['settings']` is not defined, use the $id as the setting ID.
151          *
152          * @since 3.4.0
153          *
154          * @param WP_Customize_Manager $manager Customizer bootstrap instance.
155          * @param string               $id      Control ID.
156          * @param array                $args    {
157          *     Optional. Arguments to override class property defaults.
158          *
159          *     @type int                  $instance_number Order in which this instance was created in relation
160          *                                                 to other instances.
161          *     @type WP_Customize_Manager $manager         Customizer bootstrap instance.
162          *     @type string               $id              Control ID.
163          *     @type array                $settings        All settings tied to the control. If undefined, `$id` will
164          *                                                 be used.
165          *     @type string               $setting         The primary setting for the control (if there is one).
166          *                                                 Default 'default'.
167          *     @type int                  $priority        Order priority to load the control. Default 10.
168          *     @type string               $section         Section the control belongs to. Default empty.
169          *     @type string               $label           Label for the control. Default empty.
170          *     @type string               $description     Description for the control. Default empty.
171          *     @type array                $choices         List of choices for 'radio' or 'select' type controls, where
172          *                                                 values are the keys, and labels are the values.
173          *                                                 Default empty array.
174          *     @type array                $input_attrs     List of custom input attributes for control output, where
175          *                                                 attribute names are the keys and values are the values. Not
176          *                                                 used for 'checkbox', 'radio', 'select', 'textarea', or
177          *                                                 'dropdown-pages' control types. Default empty array.
178          *     @type array                $json            Deprecated. Use WP_Customize_Control::json() instead.
179          *     @type string               $type            Control type. Core controls include 'text', 'checkbox',
180          *                                                 'textarea', 'radio', 'select', and 'dropdown-pages'. Additional
181          *                                                 input types such as 'email', 'url', 'number', 'hidden', and
182          *                                                 'date' are supported implicitly. Default 'text'.
183          * }
184          */
185         public function __construct( $manager, $id, $args = array() ) {
186                 $keys = array_keys( get_object_vars( $this ) );
187                 foreach ( $keys as $key ) {
188                         if ( isset( $args[ $key ] ) ) {
189                                 $this->$key = $args[ $key ];
190                         }
191                 }
192
193                 $this->manager = $manager;
194                 $this->id = $id;
195                 if ( empty( $this->active_callback ) ) {
196                         $this->active_callback = array( $this, 'active_callback' );
197                 }
198                 self::$instance_count += 1;
199                 $this->instance_number = self::$instance_count;
200
201                 // Process settings.
202                 if ( ! isset( $this->settings ) ) {
203                         $this->settings = $id;
204                 }
205
206                 $settings = array();
207                 if ( is_array( $this->settings ) ) {
208                         foreach ( $this->settings as $key => $setting ) {
209                                 $settings[ $key ] = $this->manager->get_setting( $setting );
210                         }
211                 } else if ( is_string( $this->settings ) ) {
212                         $this->setting = $this->manager->get_setting( $this->settings );
213                         $settings['default'] = $this->setting;
214                 }
215                 $this->settings = $settings;
216         }
217
218         /**
219          * Enqueue control related scripts/styles.
220          *
221          * @since 3.4.0
222          */
223         public function enqueue() {}
224
225         /**
226          * Check whether control is active to current Customizer preview.
227          *
228          * @since 4.0.0
229          * @access public
230          *
231          * @return bool Whether the control is active to the current preview.
232          */
233         final public function active() {
234                 $control = $this;
235                 $active = call_user_func( $this->active_callback, $this );
236
237                 /**
238                  * Filters response of WP_Customize_Control::active().
239                  *
240                  * @since 4.0.0
241                  *
242                  * @param bool                 $active  Whether the Customizer control is active.
243                  * @param WP_Customize_Control $control WP_Customize_Control instance.
244                  */
245                 $active = apply_filters( 'customize_control_active', $active, $control );
246
247                 return $active;
248         }
249
250         /**
251          * Default callback used when invoking WP_Customize_Control::active().
252          *
253          * Subclasses can override this with their specific logic, or they may
254          * provide an 'active_callback' argument to the constructor.
255          *
256          * @since 4.0.0
257          * @access public
258          *
259          * @return true Always true.
260          */
261         public function active_callback() {
262                 return true;
263         }
264
265         /**
266          * Fetch a setting's value.
267          * Grabs the main setting by default.
268          *
269          * @since 3.4.0
270          *
271          * @param string $setting_key
272          * @return mixed The requested setting's value, if the setting exists.
273          */
274         final public function value( $setting_key = 'default' ) {
275                 if ( isset( $this->settings[ $setting_key ] ) ) {
276                         return $this->settings[ $setting_key ]->value();
277                 }
278         }
279
280         /**
281          * Refresh the parameters passed to the JavaScript via JSON.
282          *
283          * @since 3.4.0
284          */
285         public function to_json() {
286                 $this->json['settings'] = array();
287                 foreach ( $this->settings as $key => $setting ) {
288                         $this->json['settings'][ $key ] = $setting->id;
289                 }
290
291                 $this->json['type'] = $this->type;
292                 $this->json['priority'] = $this->priority;
293                 $this->json['active'] = $this->active();
294                 $this->json['section'] = $this->section;
295                 $this->json['content'] = $this->get_content();
296                 $this->json['label'] = $this->label;
297                 $this->json['description'] = $this->description;
298                 $this->json['instanceNumber'] = $this->instance_number;
299         }
300
301         /**
302          * Get the data to export to the client via JSON.
303          *
304          * @since 4.1.0
305          *
306          * @return array Array of parameters passed to the JavaScript.
307          */
308         public function json() {
309                 $this->to_json();
310                 return $this->json;
311         }
312
313         /**
314          * Checks if the user can use this control.
315          *
316          * Returns false if the user cannot manipulate one of the associated settings,
317          * or if one of the associated settings does not exist. Also returns false if
318          * the associated section does not exist or if its capability check returns
319          * false.
320          *
321          * @since 3.4.0
322          *
323          * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true.
324          */
325         final public function check_capabilities() {
326                 if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) {
327                         return false;
328                 }
329
330                 foreach ( $this->settings as $setting ) {
331                         if ( ! $setting || ! $setting->check_capabilities() ) {
332                                 return false;
333                         }
334                 }
335
336                 $section = $this->manager->get_section( $this->section );
337                 if ( isset( $section ) && ! $section->check_capabilities() ) {
338                         return false;
339                 }
340
341                 return true;
342         }
343
344         /**
345          * Get the control's content for insertion into the Customizer pane.
346          *
347          * @since 4.1.0
348          *
349          * @return string Contents of the control.
350          */
351         final public function get_content() {
352                 ob_start();
353                 $this->maybe_render();
354                 return trim( ob_get_clean() );
355         }
356
357         /**
358          * Check capabilities and render the control.
359          *
360          * @since 3.4.0
361          * @uses WP_Customize_Control::render()
362          */
363         final public function maybe_render() {
364                 if ( ! $this->check_capabilities() )
365                         return;
366
367                 /**
368                  * Fires just before the current Customizer control is rendered.
369                  *
370                  * @since 3.4.0
371                  *
372                  * @param WP_Customize_Control $this WP_Customize_Control instance.
373                  */
374                 do_action( 'customize_render_control', $this );
375
376                 /**
377                  * Fires just before a specific Customizer control is rendered.
378                  *
379                  * The dynamic portion of the hook name, `$this->id`, refers to
380                  * the control ID.
381                  *
382                  * @since 3.4.0
383                  *
384                  * @param WP_Customize_Control $this WP_Customize_Control instance.
385                  */
386                 do_action( 'customize_render_control_' . $this->id, $this );
387
388                 $this->render();
389         }
390
391         /**
392          * Renders the control wrapper and calls $this->render_content() for the internals.
393          *
394          * @since 3.4.0
395          */
396         protected function render() {
397                 $id    = 'customize-control-' . str_replace( array( '[', ']' ), array( '-', '' ), $this->id );
398                 $class = 'customize-control customize-control-' . $this->type;
399
400                 ?><li id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $class ); ?>">
401                         <?php $this->render_content(); ?>
402                 </li><?php
403         }
404
405         /**
406          * Get the data link attribute for a setting.
407          *
408          * @since 3.4.0
409          *
410          * @param string $setting_key
411          * @return string Data link parameter, if $setting_key is a valid setting, empty string otherwise.
412          */
413         public function get_link( $setting_key = 'default' ) {
414                 if ( ! isset( $this->settings[ $setting_key ] ) )
415                         return '';
416
417                 return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"';
418         }
419
420         /**
421          * Render the data link attribute for the control's input element.
422          *
423          * @since 3.4.0
424          * @uses WP_Customize_Control::get_link()
425          *
426          * @param string $setting_key
427          */
428         public function link( $setting_key = 'default' ) {
429                 echo $this->get_link( $setting_key );
430         }
431
432         /**
433          * Render the custom attributes for the control's input element.
434          *
435          * @since 4.0.0
436          * @access public
437          */
438         public function input_attrs() {
439                 foreach ( $this->input_attrs as $attr => $value ) {
440                         echo $attr . '="' . esc_attr( $value ) . '" ';
441                 }
442         }
443
444         /**
445          * Render the control's content.
446          *
447          * Allows the content to be overriden without having to rewrite the wrapper in `$this::render()`.
448          *
449          * Supports basic input types `text`, `checkbox`, `textarea`, `radio`, `select` and `dropdown-pages`.
450          * Additional input types such as `email`, `url`, `number`, `hidden` and `date` are supported implicitly.
451          *
452          * Control content can alternately be rendered in JS. See WP_Customize_Control::print_template().
453          *
454          * @since 3.4.0
455          */
456         protected function render_content() {
457                 switch( $this->type ) {
458                         case 'checkbox':
459                                 ?>
460                                 <label>
461                                         <input type="checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?> />
462                                         <?php echo esc_html( $this->label ); ?>
463                                         <?php if ( ! empty( $this->description ) ) : ?>
464                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
465                                         <?php endif; ?>
466                                 </label>
467                                 <?php
468                                 break;
469                         case 'radio':
470                                 if ( empty( $this->choices ) )
471                                         return;
472
473                                 $name = '_customize-radio-' . $this->id;
474
475                                 if ( ! empty( $this->label ) ) : ?>
476                                         <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
477                                 <?php endif;
478                                 if ( ! empty( $this->description ) ) : ?>
479                                         <span class="description customize-control-description"><?php echo $this->description ; ?></span>
480                                 <?php endif;
481
482                                 foreach ( $this->choices as $value => $label ) :
483                                         ?>
484                                         <label>
485                                                 <input type="radio" value="<?php echo esc_attr( $value ); ?>" name="<?php echo esc_attr( $name ); ?>" <?php $this->link(); checked( $this->value(), $value ); ?> />
486                                                 <?php echo esc_html( $label ); ?><br/>
487                                         </label>
488                                         <?php
489                                 endforeach;
490                                 break;
491                         case 'select':
492                                 if ( empty( $this->choices ) )
493                                         return;
494
495                                 ?>
496                                 <label>
497                                         <?php if ( ! empty( $this->label ) ) : ?>
498                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
499                                         <?php endif;
500                                         if ( ! empty( $this->description ) ) : ?>
501                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
502                                         <?php endif; ?>
503
504                                         <select <?php $this->link(); ?>>
505                                                 <?php
506                                                 foreach ( $this->choices as $value => $label )
507                                                         echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>';
508                                                 ?>
509                                         </select>
510                                 </label>
511                                 <?php
512                                 break;
513                         case 'textarea':
514                                 ?>
515                                 <label>
516                                         <?php if ( ! empty( $this->label ) ) : ?>
517                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
518                                         <?php endif;
519                                         if ( ! empty( $this->description ) ) : ?>
520                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
521                                         <?php endif; ?>
522                                         <textarea rows="5" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
523                                 </label>
524                                 <?php
525                                 break;
526                         case 'dropdown-pages':
527                                 ?>
528                                 <label>
529                                 <?php if ( ! empty( $this->label ) ) : ?>
530                                         <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
531                                 <?php endif;
532                                 if ( ! empty( $this->description ) ) : ?>
533                                         <span class="description customize-control-description"><?php echo $this->description; ?></span>
534                                 <?php endif; ?>
535
536                                 <?php $dropdown = wp_dropdown_pages(
537                                         array(
538                                                 'name'              => '_customize-dropdown-pages-' . $this->id,
539                                                 'echo'              => 0,
540                                                 'show_option_none'  => __( '&mdash; Select &mdash;' ),
541                                                 'option_none_value' => '0',
542                                                 'selected'          => $this->value(),
543                                         )
544                                 );
545
546                                 // Hackily add in the data link parameter.
547                                 $dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown );
548                                 echo $dropdown;
549                                 ?>
550                                 </label>
551                                 <?php
552                                 break;
553                         default:
554                                 ?>
555                                 <label>
556                                         <?php if ( ! empty( $this->label ) ) : ?>
557                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
558                                         <?php endif;
559                                         if ( ! empty( $this->description ) ) : ?>
560                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
561                                         <?php endif; ?>
562                                         <input type="<?php echo esc_attr( $this->type ); ?>" <?php $this->input_attrs(); ?> value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); ?> />
563                                 </label>
564                                 <?php
565                                 break;
566                 }
567         }
568
569         /**
570          * Render the control's JS template.
571          *
572          * This function is only run for control types that have been registered with
573          * WP_Customize_Manager::register_control_type().
574          *
575          * In the future, this will also print the template for the control's container
576          * element and be override-able.
577          *
578          * @since 4.1.0
579          */
580         final public function print_template() {
581                 ?>
582                 <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
583                         <?php $this->content_template(); ?>
584                 </script>
585                 <?php
586         }
587
588         /**
589          * An Underscore (JS) template for this control's content (but not its container).
590          *
591          * Class variables for this control class are available in the `data` JS object;
592          * export custom variables by overriding WP_Customize_Control::to_json().
593          *
594          * @see WP_Customize_Control::print_template()
595          *
596          * @since 4.1.0
597          */
598         protected function content_template() {}
599
600 }
601
602 /** WP_Customize_Color_Control class */
603 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-color-control.php' );
604
605 /** WP_Customize_Media_Control class */
606 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-media-control.php' );
607
608 /** WP_Customize_Upload_Control class */
609 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-upload-control.php' );
610
611 /** WP_Customize_Image_Control class */
612 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-image-control.php' );
613
614 /** WP_Customize_Background_Image_Control class */
615 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-background-image-control.php' );
616
617 /** WP_Customize_Cropped_Image_Control class */
618 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-cropped-image-control.php' );
619
620 /** WP_Customize_Site_Icon_Control class */
621 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-site-icon-control.php' );
622
623 /** WP_Customize_Header_Image_Control class */
624 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-control.php' );
625
626 /** WP_Customize_Theme_Control class */
627 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-theme-control.php' );
628
629 /** WP_Widget_Area_Customize_Control class */
630 require_once( ABSPATH . WPINC . '/customize/class-wp-widget-area-customize-control.php' );
631
632 /** WP_Widget_Form_Customize_Control class */
633 require_once( ABSPATH . WPINC . '/customize/class-wp-widget-form-customize-control.php' );
634
635 /** WP_Customize_Nav_Menu_Control class */
636 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-control.php' );
637
638 /** WP_Customize_Nav_Menu_Item_Control class */
639 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-control.php' );
640
641 /** WP_Customize_Nav_Menu_Location_Control class */
642 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-location-control.php' );
643
644 /** WP_Customize_Nav_Menu_Name_Control class */
645 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' );
646
647 /** WP_Customize_Nav_Menu_Auto_Add_Control class */
648 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' );
649
650 /** WP_Customize_New_Menu_Control class */
651 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' );