WordPress 4.1.1
[autoinstalls/wordpress.git] / wp-includes / class-wp-customize-control.php
1 <?php
2 /**
3  * Customize Control Class
4  *
5  * @package WordPress
6  * @subpackage Customize
7  * @since 3.4.0
8  */
9 class WP_Customize_Control {
10
11         /**
12          * Incremented with each new class instantiation, then stored in $instance_number.
13          *
14          * Used when sorting two instances whose priorities are equal.
15          *
16          * @since 4.1.0
17          * @access protected
18          * @var int
19          */
20         protected static $instance_count = 0;
21
22         /**
23          * Order in which this instance was created in relation to other instances.
24          *
25          * @since 4.1.0
26          * @access public
27          * @var int
28          */
29         public $instance_number;
30
31         /**
32          * @access public
33          * @var WP_Customize_Manager
34          */
35         public $manager;
36
37         /**
38          * @access public
39          * @var string
40          */
41         public $id;
42
43         /**
44          * All settings tied to the control.
45          *
46          * @access public
47          * @var array
48          */
49         public $settings;
50
51         /**
52          * The primary setting for the control (if there is one).
53          *
54          * @access public
55          * @var string
56          */
57         public $setting = 'default';
58
59         /**
60          * @access public
61          * @var int
62          */
63         public $priority = 10;
64
65         /**
66          * @access public
67          * @var string
68          */
69         public $section = '';
70
71         /**
72          * @access public
73          * @var string
74          */
75         public $label = '';
76
77         /**
78          * @access public
79          * @var string
80          */
81         public $description = '';
82
83         /**
84          * @todo: Remove choices
85          *
86          * @access public
87          * @var array
88          */
89         public $choices = array();
90
91         /**
92          * @access public
93          * @var array
94          */
95         public $input_attrs = array();
96
97         /**
98          * @deprecated It is better to just call the json() method
99          * @access public
100          * @var array
101          */
102         public $json = array();
103
104         /**
105          * @access public
106          * @var string
107          */
108         public $type = 'text';
109
110         /**
111          * Callback.
112          *
113          * @since 4.0.0
114          * @access public
115          *
116          * @see WP_Customize_Control::active()
117          *
118          * @var callable Callback is called with one argument, the instance of
119          *               WP_Customize_Control, and returns bool to indicate whether
120          *               the control is active (such as it relates to the URL
121          *               currently being previewed).
122          */
123         public $active_callback = '';
124
125         /**
126          * Constructor.
127          *
128          * Supplied $args override class property defaults.
129          *
130          * If $args['settings'] is not defined, use the $id as the setting ID.
131          *
132          * @since 3.4.0
133          *
134          * @param WP_Customize_Manager $manager
135          * @param string $id
136          * @param array $args
137          */
138         public function __construct( $manager, $id, $args = array() ) {
139                 $keys = array_keys( get_object_vars( $this ) );
140                 foreach ( $keys as $key ) {
141                         if ( isset( $args[ $key ] ) ) {
142                                 $this->$key = $args[ $key ];
143                         }
144                 }
145
146                 $this->manager = $manager;
147                 $this->id = $id;
148                 if ( empty( $this->active_callback ) ) {
149                         $this->active_callback = array( $this, 'active_callback' );
150                 }
151                 self::$instance_count += 1;
152                 $this->instance_number = self::$instance_count;
153
154                 // Process settings.
155                 if ( empty( $this->settings ) ) {
156                         $this->settings = $id;
157                 }
158
159                 $settings = array();
160                 if ( is_array( $this->settings ) ) {
161                         foreach ( $this->settings as $key => $setting ) {
162                                 $settings[ $key ] = $this->manager->get_setting( $setting );
163                         }
164                 } else {
165                         $this->setting = $this->manager->get_setting( $this->settings );
166                         $settings['default'] = $this->setting;
167                 }
168                 $this->settings = $settings;
169         }
170
171         /**
172          * Enqueue control related scripts/styles.
173          *
174          * @since 3.4.0
175          */
176         public function enqueue() {}
177
178         /**
179          * Check whether control is active to current Customizer preview.
180          *
181          * @since 4.0.0
182          * @access public
183          *
184          * @return bool Whether the control is active to the current preview.
185          */
186         public final function active() {
187                 $control = $this;
188                 $active = call_user_func( $this->active_callback, $this );
189
190                 /**
191                  * Filter response of WP_Customize_Control::active().
192                  *
193                  * @since 4.0.0
194                  *
195                  * @param bool                 $active  Whether the Customizer control is active.
196                  * @param WP_Customize_Control $control WP_Customize_Control instance.
197                  */
198                 $active = apply_filters( 'customize_control_active', $active, $control );
199
200                 return $active;
201         }
202
203         /**
204          * Default callback used when invoking WP_Customize_Control::active().
205          *
206          * Subclasses can override this with their specific logic, or they may
207          * provide an 'active_callback' argument to the constructor.
208          *
209          * @since 4.0.0
210          * @access public
211          *
212          * @return bool Always true.
213          */
214         public function active_callback() {
215                 return true;
216         }
217
218         /**
219          * Fetch a setting's value.
220          * Grabs the main setting by default.
221          *
222          * @since 3.4.0
223          *
224          * @param string $setting_key
225          * @return mixed The requested setting's value, if the setting exists.
226          */
227         public final function value( $setting_key = 'default' ) {
228                 if ( isset( $this->settings[ $setting_key ] ) ) {
229                         return $this->settings[ $setting_key ]->value();
230                 }
231         }
232
233         /**
234          * Refresh the parameters passed to the JavaScript via JSON.
235          *
236          * @since 3.4.0
237          */
238         public function to_json() {
239                 $this->json['settings'] = array();
240                 foreach ( $this->settings as $key => $setting ) {
241                         $this->json['settings'][ $key ] = $setting->id;
242                 }
243
244                 $this->json['type'] = $this->type;
245                 $this->json['priority'] = $this->priority;
246                 $this->json['active'] = $this->active();
247                 $this->json['section'] = $this->section;
248                 $this->json['content'] = $this->get_content();
249                 $this->json['label'] = $this->label;
250                 $this->json['description'] = $this->description;
251                 $this->json['instanceNumber'] = $this->instance_number;
252         }
253
254         /**
255          * Get the data to export to the client via JSON.
256          *
257          * @since 4.1.0
258          *
259          * @return array Array of parameters passed to the JavaScript.
260          */
261         public function json() {
262                 $this->to_json();
263                 return $this->json;
264         }
265
266         /**
267          * Check if the theme supports the control and check user capabilities.
268          *
269          * @since 3.4.0
270          *
271          * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true.
272          */
273         public final function check_capabilities() {
274                 foreach ( $this->settings as $setting ) {
275                         if ( ! $setting->check_capabilities() )
276                                 return false;
277                 }
278
279                 $section = $this->manager->get_section( $this->section );
280                 if ( isset( $section ) && ! $section->check_capabilities() )
281                         return false;
282
283                 return true;
284         }
285
286         /**
287          * Get the control's content for insertion into the Customizer pane.
288          *
289          * @since 4.1.0
290          *
291          * @return string Contents of the control.
292          */
293         public final function get_content() {
294                 ob_start();
295                 $this->maybe_render();
296                 $template = trim( ob_get_contents() );
297                 ob_end_clean();
298                 return $template;
299         }
300
301         /**
302          * Check capabilities and render the control.
303          *
304          * @since 3.4.0
305          * @uses WP_Customize_Control::render()
306          */
307         public final function maybe_render() {
308                 if ( ! $this->check_capabilities() )
309                         return;
310
311                 /**
312                  * Fires just before the current Customizer control is rendered.
313                  *
314                  * @since 3.4.0
315                  *
316                  * @param WP_Customize_Control $this WP_Customize_Control instance.
317                  */
318                 do_action( 'customize_render_control', $this );
319
320                 /**
321                  * Fires just before a specific Customizer control is rendered.
322                  *
323                  * The dynamic portion of the hook name, `$this->id`, refers to
324                  * the control ID.
325                  *
326                  * @since 3.4.0
327                  *
328                  * @param WP_Customize_Control $this {@see WP_Customize_Control} instance.
329                  */
330                 do_action( 'customize_render_control_' . $this->id, $this );
331
332                 $this->render();
333         }
334
335         /**
336          * Renders the control wrapper and calls $this->render_content() for the internals.
337          *
338          * @since 3.4.0
339          */
340         protected function render() {
341                 $id    = 'customize-control-' . str_replace( '[', '-', str_replace( ']', '', $this->id ) );
342                 $class = 'customize-control customize-control-' . $this->type;
343
344                 ?><li id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $class ); ?>">
345                         <?php $this->render_content(); ?>
346                 </li><?php
347         }
348
349         /**
350          * Get the data link attribute for a setting.
351          *
352          * @since 3.4.0
353          *
354          * @param string $setting_key
355          * @return string Data link parameter, if $setting_key is a valid setting, empty string otherwise.
356          */
357         public function get_link( $setting_key = 'default' ) {
358                 if ( ! isset( $this->settings[ $setting_key ] ) )
359                         return '';
360
361                 return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"';
362         }
363
364         /**
365          * Render the data link attribute for the control's input element.
366          *
367          * @since 3.4.0
368          * @uses WP_Customize_Control::get_link()
369          *
370          * @param string $setting_key
371          */
372         public function link( $setting_key = 'default' ) {
373                 echo $this->get_link( $setting_key );
374         }
375
376         /**
377          * Render the custom attributes for the control's input element.
378          *
379          * @since 4.0.0
380          * @access public
381          */
382         public function input_attrs() {
383                 foreach( $this->input_attrs as $attr => $value ) {
384                         echo $attr . '="' . esc_attr( $value ) . '" ';
385                 }
386         }
387
388         /**
389          * Render the control's content.
390          *
391          * Allows the content to be overriden without having to rewrite the wrapper in $this->render().
392          *
393          * Supports basic input types `text`, `checkbox`, `textarea`, `radio`, `select` and `dropdown-pages`.
394          * Additional input types such as `email`, `url`, `number`, `hidden` and `date` are supported implicitly.
395          *
396          * Control content can alternately be rendered in JS. See {@see WP_Customize_Control::print_template()}.
397          *
398          * @since 3.4.0
399          */
400         protected function render_content() {
401                 switch( $this->type ) {
402                         case 'checkbox':
403                                 ?>
404                                 <label>
405                                         <input type="checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?> />
406                                         <?php echo esc_html( $this->label ); ?>
407                                         <?php if ( ! empty( $this->description ) ) : ?>
408                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
409                                         <?php endif; ?>
410                                 </label>
411                                 <?php
412                                 break;
413                         case 'radio':
414                                 if ( empty( $this->choices ) )
415                                         return;
416
417                                 $name = '_customize-radio-' . $this->id;
418
419                                 if ( ! empty( $this->label ) ) : ?>
420                                         <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
421                                 <?php endif;
422                                 if ( ! empty( $this->description ) ) : ?>
423                                         <span class="description customize-control-description"><?php echo $this->description ; ?></span>
424                                 <?php endif;
425
426                                 foreach ( $this->choices as $value => $label ) :
427                                         ?>
428                                         <label>
429                                                 <input type="radio" value="<?php echo esc_attr( $value ); ?>" name="<?php echo esc_attr( $name ); ?>" <?php $this->link(); checked( $this->value(), $value ); ?> />
430                                                 <?php echo esc_html( $label ); ?><br/>
431                                         </label>
432                                         <?php
433                                 endforeach;
434                                 break;
435                         case 'select':
436                                 if ( empty( $this->choices ) )
437                                         return;
438
439                                 ?>
440                                 <label>
441                                         <?php if ( ! empty( $this->label ) ) : ?>
442                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
443                                         <?php endif;
444                                         if ( ! empty( $this->description ) ) : ?>
445                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
446                                         <?php endif; ?>
447
448                                         <select <?php $this->link(); ?>>
449                                                 <?php
450                                                 foreach ( $this->choices as $value => $label )
451                                                         echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>';
452                                                 ?>
453                                         </select>
454                                 </label>
455                                 <?php
456                                 break;
457                         case 'textarea':
458                                 ?>
459                                 <label>
460                                         <?php if ( ! empty( $this->label ) ) : ?>
461                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
462                                         <?php endif;
463                                         if ( ! empty( $this->description ) ) : ?>
464                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
465                                         <?php endif; ?>
466                                         <textarea rows="5" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
467                                 </label>
468                                 <?php
469                                 break;
470                         case 'dropdown-pages':
471                                 $dropdown = wp_dropdown_pages(
472                                         array(
473                                                 'name'              => '_customize-dropdown-pages-' . $this->id,
474                                                 'echo'              => 0,
475                                                 'show_option_none'  => __( '&mdash; Select &mdash;' ),
476                                                 'option_none_value' => '0',
477                                                 'selected'          => $this->value(),
478                                         )
479                                 );
480
481                                 // Hackily add in the data link parameter.
482                                 $dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown );
483
484                                 printf(
485                                         '<label class="customize-control-select"><span class="customize-control-title">%s</span> %s</label>',
486                                         $this->label,
487                                         $dropdown
488                                 );
489                                 break;
490                         default:
491                                 ?>
492                                 <label>
493                                         <?php if ( ! empty( $this->label ) ) : ?>
494                                                 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
495                                         <?php endif;
496                                         if ( ! empty( $this->description ) ) : ?>
497                                                 <span class="description customize-control-description"><?php echo $this->description; ?></span>
498                                         <?php endif; ?>
499                                         <input type="<?php echo esc_attr( $this->type ); ?>" <?php $this->input_attrs(); ?> value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); ?> />
500                                 </label>
501                                 <?php
502                                 break;
503                 }
504         }
505
506         /**
507          * Render the control's JS template.
508          *
509          * This function is only run for control types that have been registered with
510          * {@see WP_Customize_Manager::register_control_type()}.
511          *
512          * In the future, this will also print the template for the control's container
513          * element and be override-able.
514          *
515          * @since 4.1.0
516          */
517         final public function print_template() {
518                 ?>
519                 <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
520                         <?php $this->content_template(); ?>
521                 </script>
522                 <?php
523         }
524
525         /**
526          * An Underscore (JS) template for this control's content (but not its container).
527          *
528          * Class variables for this control class are available in the `data` JS object;
529          * export custom variables by overriding {@see WP_Customize_Control::to_json()}.
530          *
531          * @see WP_Customize_Control::print_template()
532          *
533          * @since 4.1.0
534          */
535         protected function content_template() {}
536
537 }
538
539 /**
540  * Customize Color Control Class
541  *
542  * @package WordPress
543  * @subpackage Customize
544  * @since 3.4.0
545  */
546 class WP_Customize_Color_Control extends WP_Customize_Control {
547         /**
548          * @access public
549          * @var string
550          */
551         public $type = 'color';
552
553         /**
554          * @access public
555          * @var array
556          */
557         public $statuses;
558
559         /**
560          * Constructor.
561          *
562          * @since 3.4.0
563          * @uses WP_Customize_Control::__construct()
564          *
565          * @param WP_Customize_Manager $manager
566          * @param string $id
567          * @param array $args
568          */
569         public function __construct( $manager, $id, $args = array() ) {
570                 $this->statuses = array( '' => __('Default') );
571                 parent::__construct( $manager, $id, $args );
572         }
573
574         /**
575          * Enqueue scripts/styles for the color picker.
576          *
577          * @since 3.4.0
578          */
579         public function enqueue() {
580                 wp_enqueue_script( 'wp-color-picker' );
581                 wp_enqueue_style( 'wp-color-picker' );
582         }
583
584         /**
585          * Refresh the parameters passed to the JavaScript via JSON.
586          *
587          * @since 3.4.0
588          * @uses WP_Customize_Control::to_json()
589          */
590         public function to_json() {
591                 parent::to_json();
592                 $this->json['statuses'] = $this->statuses;
593                 $this->json['defaultValue'] = $this->setting->default;
594         }
595
596         /**
597          * Don't render the control content from PHP, as it's rendered via JS on load.
598          *
599          * @since 3.4.0
600          */
601         public function render_content() {}
602
603         /**
604          * Render a JS template for the content of the color picker control.
605          *
606          * @since 4.1.0
607          */
608         public function content_template() {
609                 ?>
610                 <# var defaultValue = '';
611                 if ( data.defaultValue ) {
612                         if ( '#' !== data.defaultValue.substring( 0, 1 ) ) {
613                                 defaultValue = '#' + data.defaultValue;
614                         } else {
615                                 defaultValue = data.defaultValue;
616                         }
617                         defaultValue = ' data-default-color=' + defaultValue; // Quotes added automatically.
618                 } #>
619                 <label>
620                         <# if ( data.label ) { #>
621                                 <span class="customize-control-title">{{{ data.label }}}</span>
622                         <# } #>
623                         <# if ( data.description ) { #>
624                                 <span class="description customize-control-description">{{{ data.description }}}</span>
625                         <# } #>
626                         <div class="customize-control-content">
627                                 <input class="color-picker-hex" type="text" maxlength="7" placeholder="<?php esc_attr_e( 'Hex Value' ); ?>" {{ defaultValue }} />
628                         </div>
629                 </label>
630                 <?php
631         }
632 }
633
634 /**
635  * Customize Upload Control Class
636  *
637  * @package WordPress
638  * @subpackage Customize
639  * @since 3.4.0
640  */
641 class WP_Customize_Upload_Control extends WP_Customize_Control {
642         public $type          = 'upload';
643         public $mime_type     = '';
644         public $button_labels = array();
645         public $removed = ''; // unused
646         public $context; // unused
647         public $extensions = array(); // unused
648
649         /**
650          * Constructor.
651          *
652          * @since 4.1.0
653          *
654          * @param WP_Customize_Manager $manager {@see WP_Customize_Manager} instance.
655          */
656         public function __construct( $manager, $id, $args = array() ) {
657                 parent::__construct( $manager, $id, $args );
658
659                 $this->button_labels = array(
660                         'select'       => __( 'Select File' ),
661                         'change'       => __( 'Change File' ),
662                         'default'      => __( 'Default' ),
663                         'remove'       => __( 'Remove' ),
664                         'placeholder'  => __( 'No file selected' ),
665                         'frame_title'  => __( 'Select File' ),
666                         'frame_button' => __( 'Choose File' ),
667                 );
668         }
669
670         /**
671          * Enqueue control related scripts/styles.
672          *
673          * @since 3.4.0
674          */
675         public function enqueue() {
676                 wp_enqueue_media();
677         }
678
679         /**
680          * Refresh the parameters passed to the JavaScript via JSON.
681          *
682          * @since 3.4.0
683          * @uses WP_Customize_Control::to_json()
684          */
685         public function to_json() {
686                 parent::to_json();
687                 $this->json['mime_type'] = $this->mime_type;
688                 $this->json['button_labels'] = $this->button_labels;
689
690                 $value = $this->value();
691
692                 if ( is_object( $this->setting ) ) {
693                         if ( $this->setting->default ) {
694                                 // Fake an attachment model - needs all fields used by template.
695                                 $type = in_array( substr( $this->setting->default, -3 ), array( 'jpg', 'png', 'gif', 'bmp' ) ) ? 'image' : 'document';
696                                 $default_attachment = array(
697                                         'id' => 1,
698                                         'url' => $this->setting->default,
699                                         'type' => $type,
700                                         'icon' => wp_mime_type_icon( $type ),
701                                         'title' => basename( $this->setting->default ),
702                                 );
703
704                                 if ( 'image' === $type ) {
705                                         $default_attachment['sizes'] = array(
706                                                 'full' => array( 'url' => $this->setting->default ),
707                                         );
708                                 }
709
710                                 $this->json['defaultAttachment'] = $default_attachment;
711                         }
712
713                         if ( $value && $this->setting->default && $value === $this->setting->default ) {
714                                 // Set the default as the attachment.
715                                 $this->json['attachment'] = $this->json['defaultAttachment'];
716                         } elseif ( $value ) {
717                                 // Get the attachment model for the existing file.
718                                 $attachment_id = attachment_url_to_postid( $value );
719                                 if ( $attachment_id ) {
720                                         $this->json['attachment'] = wp_prepare_attachment_for_js( $attachment_id );
721                                 }
722                         }
723                 }
724         }
725
726         /**
727          * Don't render any content for this control from PHP.
728          *
729          * @see WP_Customize_Upload_Control::content_template()
730          * @since 3.4.0
731          */
732         public function render_content() {}
733
734         /**
735          * Render a JS template for the content of the upload control.
736          *
737          * @since 4.1.0
738          */
739         public function content_template() {
740                 ?>
741                 <label for="{{ data.settings['default'] }}-button">
742                         <# if ( data.label ) { #>
743                                 <span class="customize-control-title">{{ data.label }}</span>
744                         <# } #>
745                         <# if ( data.description ) { #>
746                                 <span class="description customize-control-description">{{{ data.description }}}</span>
747                         <# } #>
748                 </label>
749
750                 <# if ( data.attachment && data.attachment.id ) { #>
751                         <div class="current">
752                                 <div class="container">
753                                         <div class="attachment-media-view attachment-media-view-{{ data.attachment.type }} {{ data.attachment.orientation }}">
754                                                 <div class="thumbnail thumbnail-{{ data.attachment.type }}">
755                                                         <# if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.medium ) { #>
756                                                                 <img class="attachment-thumb" src="{{ data.attachment.sizes.medium.url }}" draggable="false" />
757                                                         <# } else if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.full ) { #>
758                                                                 <img class="attachment-thumb" src="{{ data.attachment.sizes.full.url }}" draggable="false" />
759                                                         <# } else if ( 'audio' === data.attachment.type ) { #>
760                                                                 <img class="attachment-thumb type-icon" src="{{ data.attachment.icon }}" class="icon" draggable="false" />
761                                                                 <p class="attachment-meta attachment-meta-title">&#8220;{{ data.attachment.title }}&#8221;</p>
762                                                                 <# if ( data.attachment.album || data.attachment.meta.album ) { #>
763                                                                 <p class="attachment-meta"><em>{{ data.attachment.album || data.attachment.meta.album }}</em></p>
764                                                                 <# } #>
765                                                                 <# if ( data.attachment.artist || data.attachment.meta.artist ) { #>
766                                                                 <p class="attachment-meta">{{ data.attachment.artist || data.attachment.meta.artist }}</p>
767                                                                 <# } #>
768                                                         <# } else { #>
769                                                                 <img class="attachment-thumb type-icon" src="{{ data.attachment.icon }}" class="icon" draggable="false" />
770                                                                 <p class="attachment-title">{{ data.attachment.title }}</p>
771                                                         <# } #>
772                                                 </div>
773                                         </div>
774                                 </div>
775                         </div>
776                         <div class="actions">
777                                 <button type="button" class="button remove-button"><?php echo $this->button_labels['remove']; ?></button>
778                                 <button type="button" class="button upload-button" id="{{ data.settings['default'] }}-button"><?php echo $this->button_labels['change']; ?></button>
779                                 <div style="clear:both"></div>
780                         </div>
781                 <# } else { #>
782                         <div class="current">
783                                 <div class="container">
784                                         <div class="placeholder">
785                                                 <div class="inner">
786                                                         <span>
787                                                                 <?php echo $this->button_labels['placeholder']; ?>
788                                                         </span>
789                                                 </div>
790                                         </div>
791                                 </div>
792                         </div>
793                         <div class="actions">
794                                 <# if ( data.defaultAttachment ) { #>
795                                         <button type="button" class="button default-button"><?php echo $this->button_labels['default']; ?></button>
796                                 <# } #>
797                                 <button type="button" class="button upload-button" id="{{ data.settings['default'] }}-button"><?php echo $this->button_labels['select']; ?></button>
798                                 <div style="clear:both"></div>
799                         </div>
800                 <# } #>
801                 <?php
802         }
803 }
804
805 /**
806  * Customize Image Control Class
807  *
808  * @package WordPress
809  * @subpackage Customize
810  * @since 3.4.0
811  */
812 class WP_Customize_Image_Control extends WP_Customize_Upload_Control {
813         public $type = 'image';
814         public $mime_type = 'image';
815
816         /**
817          * Constructor.
818          *
819          * @since 3.4.0
820          * @uses WP_Customize_Upload_Control::__construct()
821          *
822          * @param WP_Customize_Manager $manager
823          * @param string $id
824          * @param array  $args
825          */
826         public function __construct( $manager, $id, $args = array() ) {
827                 parent::__construct( $manager, $id, $args );
828
829                 $this->button_labels = array(
830                         'select'       => __( 'Select Image' ),
831                         'change'       => __( 'Change Image' ),
832                         'remove'       => __( 'Remove' ),
833                         'default'      => __( 'Default' ),
834                         'placeholder'  => __( 'No image selected' ),
835                         'frame_title'  => __( 'Select Image' ),
836                         'frame_button' => __( 'Choose Image' ),
837                 );
838         }
839
840         /**
841          * @since 3.4.2
842          * @deprecated 4.1.0
843          */
844         public function prepare_control() {}
845
846         /**
847          * @since 3.4.0
848          * @deprecated 4.1.0
849          *
850          * @param string $id
851          * @param string $label
852          * @param mixed $callback
853          */
854         public function add_tab( $id, $label, $callback ) {}
855
856         /**
857          * @since 3.4.0
858          * @deprecated 4.1.0
859          *
860          * @param string $id
861          */
862         public function remove_tab( $id ) {}
863
864         /**
865          * @since 3.4.0
866          * @deprecated 4.1.0
867          *
868          * @param string $url
869          * @param string $thumbnail_url
870          */
871         public function print_tab_image( $url, $thumbnail_url = null ) {}
872 }
873
874 /**
875  * Customize Background Image Control Class
876  *
877  * @package WordPress
878  * @subpackage Customize
879  * @since 3.4.0
880  */
881 class WP_Customize_Background_Image_Control extends WP_Customize_Image_Control {
882         public $type = 'background';
883
884         /**
885          * Constructor.
886          *
887          * @since 3.4.0
888          * @uses WP_Customize_Image_Control::__construct()
889          *
890          * @param WP_Customize_Manager $manager
891          */
892         public function __construct( $manager ) {
893                 parent::__construct( $manager, 'background_image', array(
894                         'label'    => __( 'Background Image' ),
895                         'section'  => 'background_image',
896                 ) );
897         }
898
899         /**
900          * Enqueue control related scripts/styles.
901          *
902          * @since 4.1.0
903          */
904         public function enqueue() {
905                 parent::enqueue();
906
907                 wp_localize_script( 'customize-controls', '_wpCustomizeBackground', array(
908                         'nonces' => array(
909                                 'add' => wp_create_nonce( 'background-add' ),
910                         ),
911                 ) );
912         }
913 }
914
915 class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
916         public $type = 'header';
917         public $uploaded_headers;
918         public $default_headers;
919
920         /**
921          * @param WP_Customize_Manager $manager
922          */
923         public function __construct( $manager ) {
924                 parent::__construct( $manager, 'header_image', array(
925                         'label'    => __( 'Header Image' ),
926                         'settings' => array(
927                                 'default' => 'header_image',
928                                 'data'    => 'header_image_data',
929                         ),
930                         'section'  => 'header_image',
931                         'removed'  => 'remove-header',
932                         'get_url'  => 'get_header_image',
933                 ) );
934
935         }
936
937         public function to_json() {
938                 parent::to_json();
939         }
940
941         public function enqueue() {
942                 wp_enqueue_media();
943                 wp_enqueue_script( 'customize-views' );
944
945                 $this->prepare_control();
946
947                 wp_localize_script( 'customize-views', '_wpCustomizeHeader', array(
948                         'data' => array(
949                                 'width' => absint( get_theme_support( 'custom-header', 'width' ) ),
950                                 'height' => absint( get_theme_support( 'custom-header', 'height' ) ),
951                                 'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ),
952                                 'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ),
953                                 'currentImgSrc' => $this->get_current_image_src(),
954                         ),
955                         'nonces' => array(
956                                 'add' => wp_create_nonce( 'header-add' ),
957                                 'remove' => wp_create_nonce( 'header-remove' ),
958                         ),
959                         'uploads' => $this->uploaded_headers,
960                         'defaults' => $this->default_headers
961                 ) );
962
963                 parent::enqueue();
964         }
965
966         public function prepare_control() {
967                 global $custom_image_header;
968                 if ( empty( $custom_image_header ) ) {
969                         return;
970                 }
971
972                 // Process default headers and uploaded headers.
973                 $custom_image_header->process_default_headers();
974                 $this->default_headers = $custom_image_header->get_default_header_images();
975                 $this->uploaded_headers = $custom_image_header->get_uploaded_header_images();
976         }
977
978         function print_header_image_template() {
979                 ?>
980                 <script type="text/template" id="tmpl-header-choice">
981                         <# if (data.random) { #>
982                                         <button type="button" class="button display-options random">
983                                                 <span class="dashicons dashicons-randomize dice"></span>
984                                                 <# if ( data.type === 'uploaded' ) { #>
985                                                         <?php _e( 'Randomize uploaded headers' ); ?>
986                                                 <# } else if ( data.type === 'default' ) { #>
987                                                         <?php _e( 'Randomize suggested headers' ); ?>
988                                                 <# } #>
989                                         </button>
990
991                         <# } else { #>
992
993                         <# if (data.type === 'uploaded') { #>
994                                 <div class="dashicons dashicons-no close"></div>
995                         <# } #>
996
997                         <button type="button" class="choice thumbnail"
998                                 data-customize-image-value="{{{data.header.url}}}"
999                                 data-customize-header-image-data="{{JSON.stringify(data.header)}}">
1000                                 <span class="screen-reader-text"><?php _e( 'Set image' ); ?></span>
1001                                 <img src="{{{data.header.thumbnail_url}}}" alt="{{{data.header.alt_text || data.header.description}}}">
1002                         </button>
1003
1004                         <# } #>
1005                 </script>
1006
1007                 <script type="text/template" id="tmpl-header-current">
1008                         <# if (data.choice) { #>
1009                                 <# if (data.random) { #>
1010
1011                         <div class="placeholder">
1012                                 <div class="inner">
1013                                         <span><span class="dashicons dashicons-randomize dice"></span>
1014                                         <# if ( data.type === 'uploaded' ) { #>
1015                                                 <?php _e( 'Randomizing uploaded headers' ); ?>
1016                                         <# } else if ( data.type === 'default' ) { #>
1017                                                 <?php _e( 'Randomizing suggested headers' ); ?>
1018                                         <# } #>
1019                                         </span>
1020                                 </div>
1021                         </div>
1022
1023                                 <# } else { #>
1024
1025                         <img src="{{{data.header.thumbnail_url}}}" alt="{{{data.header.alt_text || data.header.description}}}" tabindex="0"/>
1026
1027                                 <# } #>
1028                         <# } else { #>
1029
1030                         <div class="placeholder">
1031                                 <div class="inner">
1032                                         <span>
1033                                                 <?php _e( 'No image set' ); ?>
1034                                         </span>
1035                                 </div>
1036                         </div>
1037
1038                         <# } #>
1039                 </script>
1040                 <?php
1041         }
1042
1043         public function get_current_image_src() {
1044                 $src = $this->value();
1045                 if ( isset( $this->get_url ) ) {
1046                         $src = call_user_func( $this->get_url, $src );
1047                         return $src;
1048                 }
1049                 return null;
1050         }
1051
1052         public function render_content() {
1053                 $this->print_header_image_template();
1054                 $visibility = $this->get_current_image_src() ? '' : ' style="display:none" ';
1055                 $width = absint( get_theme_support( 'custom-header', 'width' ) );
1056                 $height = absint( get_theme_support( 'custom-header', 'height' ) );
1057                 ?>
1058
1059
1060                 <div class="customize-control-content">
1061                         <p class="customizer-section-intro">
1062                                 <?php
1063                                 if ( $width && $height ) {
1064                                         printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header size of <strong>%s &times; %s</strong> pixels.' ), $width, $height );
1065                                 } elseif ( $width ) {
1066                                         printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header width of <strong>%s</strong> pixels.' ), $width );
1067                                 } else {
1068                                         printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header height of <strong>%s</strong> pixels.' ), $height );
1069                                 }
1070                                 ?>
1071                         </p>
1072                         <div class="current">
1073                                 <span class="customize-control-title">
1074                                         <?php _e( 'Current header' ); ?>
1075                                 </span>
1076                                 <div class="container">
1077                                 </div>
1078                         </div>
1079                         <div class="actions">
1080                                 <?php /* translators: Hide as in hide header image via the Customizer */ ?>
1081                                 <button type="button"<?php echo $visibility ?> class="button remove"><?php _ex( 'Hide image', 'custom header' ); ?></button>
1082                                 <?php /* translators: New as in add new header image via the Customizer */ ?>
1083                                 <button type="button" class="button new"><?php _ex( 'Add new image', 'header image' ); ?></button>
1084                                 <div style="clear:both"></div>
1085                         </div>
1086                         <div class="choices">
1087                                 <span class="customize-control-title header-previously-uploaded">
1088                                         <?php _ex( 'Previously uploaded', 'custom headers' ); ?>
1089                                 </span>
1090                                 <div class="uploaded">
1091                                         <div class="list">
1092                                         </div>
1093                                 </div>
1094                                 <span class="customize-control-title header-default">
1095                                         <?php _ex( 'Suggested', 'custom headers' ); ?>
1096                                 </span>
1097                                 <div class="default">
1098                                         <div class="list">
1099                                         </div>
1100                                 </div>
1101                         </div>
1102                 </div>
1103                 <?php
1104         }
1105 }
1106
1107 /**
1108  * Widget Area Customize Control Class
1109  *
1110  * @since 3.9.0
1111  */
1112 class WP_Widget_Area_Customize_Control extends WP_Customize_Control {
1113         public $type = 'sidebar_widgets';
1114         public $sidebar_id;
1115
1116         public function to_json() {
1117                 parent::to_json();
1118                 $exported_properties = array( 'sidebar_id' );
1119                 foreach ( $exported_properties as $key ) {
1120                         $this->json[ $key ] = $this->$key;
1121                 }
1122         }
1123
1124         public function render_content() {
1125                 ?>
1126                 <span class="button-secondary add-new-widget" tabindex="0">
1127                         <?php _e( 'Add a Widget' ); ?>
1128                 </span>
1129
1130                 <span class="reorder-toggle" tabindex="0">
1131                         <span class="reorder"><?php _ex( 'Reorder', 'Reorder widgets in Customizer' ); ?></span>
1132                         <span class="reorder-done"><?php _ex( 'Done', 'Cancel reordering widgets in Customizer'  ); ?></span>
1133                 </span>
1134                 <?php
1135         }
1136
1137 }
1138
1139 /**
1140  * Widget Form Customize Control Class
1141  *
1142  * @since 3.9.0
1143  */
1144 class WP_Widget_Form_Customize_Control extends WP_Customize_Control {
1145         public $type = 'widget_form';
1146         public $widget_id;
1147         public $widget_id_base;
1148         public $sidebar_id;
1149         public $is_new = false;
1150         public $width;
1151         public $height;
1152         public $is_wide = false;
1153
1154         public function to_json() {
1155                 parent::to_json();
1156                 $exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide' );
1157                 foreach ( $exported_properties as $key ) {
1158                         $this->json[ $key ] = $this->$key;
1159                 }
1160         }
1161
1162         public function render_content() {
1163                 global $wp_registered_widgets;
1164                 require_once ABSPATH . '/wp-admin/includes/widgets.php';
1165
1166                 $widget = $wp_registered_widgets[ $this->widget_id ];
1167                 if ( ! isset( $widget['params'][0] ) ) {
1168                         $widget['params'][0] = array();
1169                 }
1170
1171                 $args = array(
1172                         'widget_id' => $widget['id'],
1173                         'widget_name' => $widget['name'],
1174                 );
1175
1176                 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) );
1177                 echo $this->manager->widgets->get_widget_control( $args );
1178         }
1179
1180         /**
1181          * Whether the current widget is rendered on the page.
1182          *
1183          * @since 4.0.0
1184          * @access public
1185          *
1186          * @return bool Whether the widget is rendered.
1187          */
1188         function active_callback() {
1189                 return $this->manager->widgets->is_widget_rendered( $this->widget_id );
1190         }
1191 }
1192