Issues (4967)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/wp-includes/class-wp-customize-control.php (16 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
	 * Customizer manager.
41
	 *
42
	 * @since 3.4.0
43
	 * @access public
44
	 * @var WP_Customize_Manager
45
	 */
46
	public $manager;
47
48
	/**
49
	 * Control ID.
50
	 *
51
	 * @since 3.4.0
52
	 * @access public
53
	 * @var string
54
	 */
55
	public $id;
56
57
	/**
58
	 * All settings tied to the control.
59
	 *
60
	 * @since 3.4.0
61
	 * @access public
62
	 * @var array
63
	 */
64
	public $settings;
65
66
	/**
67
	 * The primary setting for the control (if there is one).
68
	 *
69
	 * @since 3.4.0
70
	 * @access public
71
	 * @var string
72
	 */
73
	public $setting = 'default';
74
75
	/**
76
	 * Capability required to use this control.
77
	 *
78
	 * Normally this is empty and the capability is derived from the capabilities
79
	 * of the associated `$settings`.
80
	 *
81
	 * @since 4.5.0
82
	 * @access public
83
	 * @var string
84
	 */
85
	public $capability;
86
87
	/**
88
	 * Order priority to load the control in Customizer.
89
	 *
90
	 * @since 3.4.0
91
	 * @access public
92
	 * @var int
93
	 */
94
	public $priority = 10;
95
96
	/**
97
	 * Section the control belongs to.
98
	 *
99
	 * @since 3.4.0
100
	 * @access public
101
	 * @var string
102
	 */
103
	public $section = '';
104
105
	/**
106
	 * Label for the control.
107
	 *
108
	 * @since 3.4.0
109
	 * @access public
110
	 * @var string
111
	 */
112
	public $label = '';
113
114
	/**
115
	 * Description for the control.
116
	 *
117
	 * @since 4.0.0
118
	 * @access public
119
	 * @var string
120
	 */
121
	public $description = '';
122
123
	/**
124
	 * List of choices for 'radio' or 'select' type controls, where values are the keys, and labels are the values.
125
	 *
126
	 * @since 3.4.0
127
	 * @access public
128
	 * @var array
129
	 */
130
	public $choices = array();
131
132
	/**
133
	 * List of custom input attributes for control output, where attribute names are the keys and values are the values.
134
	 *
135
	 * Not used for 'checkbox', 'radio', 'select', 'textarea', or 'dropdown-pages' control types.
136
	 *
137
	 * @since 4.0.0
138
	 * @access public
139
	 * @var array
140
	 */
141
	public $input_attrs = array();
142
143
	/**
144
	 * Show UI for adding new content, currently only used for the dropdown-pages control.
145
	 *
146
	 * @since 4.7.0
147
	 * @access public
148
	 * @var bool
149
	 */
150
	public $allow_addition = false;
151
152
	/**
153
	 * @deprecated It is better to just call the json() method
154
	 * @since 3.4.0
155
	 * @access public
156
	 * @var array
157
	 */
158
	public $json = array();
159
160
	/**
161
	 * Control's Type.
162
	 *
163
	 * @since 3.4.0
164
	 * @access public
165
	 * @var string
166
	 */
167
	public $type = 'text';
168
169
	/**
170
	 * Callback.
171
	 *
172
	 * @since 4.0.0
173
	 * @access public
174
	 *
175
	 * @see WP_Customize_Control::active()
176
	 *
177
	 * @var callable Callback is called with one argument, the instance of
178
	 *               WP_Customize_Control, and returns bool to indicate whether
179
	 *               the control is active (such as it relates to the URL
180
	 *               currently being previewed).
181
	 */
182
	public $active_callback = '';
183
184
	/**
185
	 * Constructor.
186
	 *
187
	 * Supplied `$args` override class property defaults.
188
	 *
189
	 * If `$args['settings']` is not defined, use the $id as the setting ID.
190
	 *
191
	 * @since 3.4.0
192
	 *
193
	 * @param WP_Customize_Manager $manager Customizer bootstrap instance.
194
	 * @param string               $id      Control ID.
195
	 * @param array                $args    {
196
	 *     Optional. Arguments to override class property defaults.
197
	 *
198
	 *     @type int                  $instance_number Order in which this instance was created in relation
199
	 *                                                 to other instances.
200
	 *     @type WP_Customize_Manager $manager         Customizer bootstrap instance.
201
	 *     @type string               $id              Control ID.
202
	 *     @type array                $settings        All settings tied to the control. If undefined, `$id` will
203
	 *                                                 be used.
204
	 *     @type string               $setting         The primary setting for the control (if there is one).
205
	 *                                                 Default 'default'.
206
	 *     @type int                  $priority        Order priority to load the control. Default 10.
207
	 *     @type string               $section         Section the control belongs to. Default empty.
208
	 *     @type string               $label           Label for the control. Default empty.
209
	 *     @type string               $description     Description for the control. Default empty.
210
	 *     @type array                $choices         List of choices for 'radio' or 'select' type controls, where
211
	 *                                                 values are the keys, and labels are the values.
212
	 *                                                 Default empty array.
213
	 *     @type array                $input_attrs     List of custom input attributes for control output, where
214
	 *                                                 attribute names are the keys and values are the values. Not
215
	 *                                                 used for 'checkbox', 'radio', 'select', 'textarea', or
216
	 *                                                 'dropdown-pages' control types. Default empty array.
217
	 *     @type array                $json            Deprecated. Use WP_Customize_Control::json() instead.
218
	 *     @type string               $type            Control type. Core controls include 'text', 'checkbox',
219
	 *                                                 'textarea', 'radio', 'select', and 'dropdown-pages'. Additional
220
	 *                                                 input types such as 'email', 'url', 'number', 'hidden', and
221
	 *                                                 'date' are supported implicitly. Default 'text'.
222
	 * }
223
	 */
224
	public function __construct( $manager, $id, $args = array() ) {
225
		$keys = array_keys( get_object_vars( $this ) );
226
		foreach ( $keys as $key ) {
227
			if ( isset( $args[ $key ] ) ) {
228
				$this->$key = $args[ $key ];
229
			}
230
		}
231
232
		$this->manager = $manager;
233
		$this->id = $id;
234
		if ( empty( $this->active_callback ) ) {
235
			$this->active_callback = array( $this, 'active_callback' );
236
		}
237
		self::$instance_count += 1;
238
		$this->instance_number = self::$instance_count;
239
240
		// Process settings.
241
		if ( ! isset( $this->settings ) ) {
242
			$this->settings = $id;
0 ignored issues
show
Documentation Bug introduced by
It seems like $id of type string is incompatible with the declared type array of property $settings.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
243
		}
244
245
		$settings = array();
246
		if ( is_array( $this->settings ) ) {
247
			foreach ( $this->settings as $key => $setting ) {
248
				$settings[ $key ] = $this->manager->get_setting( $setting );
249
			}
250
		} else if ( is_string( $this->settings ) ) {
251
			$this->setting = $this->manager->get_setting( $this->settings );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->manager->get_setting($this->settings) can also be of type object<WP_Customize_Setting>. However, the property $setting is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
252
			$settings['default'] = $this->setting;
253
		}
254
		$this->settings = $settings;
255
	}
256
257
	/**
258
	 * Enqueue control related scripts/styles.
259
	 *
260
	 * @since 3.4.0
261
	 */
262
	public function enqueue() {}
263
264
	/**
265
	 * Check whether control is active to current Customizer preview.
266
	 *
267
	 * @since 4.0.0
268
	 *
269
	 * @return bool Whether the control is active to the current preview.
270
	 */
271
	final public function active() {
272
		$control = $this;
273
		$active = call_user_func( $this->active_callback, $this );
274
275
		/**
276
		 * Filters response of WP_Customize_Control::active().
277
		 *
278
		 * @since 4.0.0
279
		 *
280
		 * @param bool                 $active  Whether the Customizer control is active.
281
		 * @param WP_Customize_Control $control WP_Customize_Control instance.
282
		 */
283
		$active = apply_filters( 'customize_control_active', $active, $control );
284
285
		return $active;
286
	}
287
288
	/**
289
	 * Default callback used when invoking WP_Customize_Control::active().
290
	 *
291
	 * Subclasses can override this with their specific logic, or they may
292
	 * provide an 'active_callback' argument to the constructor.
293
	 *
294
	 * @since 4.0.0
295
	 *
296
	 * @return true Always true.
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
297
	 */
298
	public function active_callback() {
299
		return true;
300
	}
301
302
	/**
303
	 * Fetch a setting's value.
304
	 * Grabs the main setting by default.
305
	 *
306
	 * @since 3.4.0
307
	 *
308
	 * @param string $setting_key
309
	 * @return mixed The requested setting's value, if the setting exists.
310
	 */
311
	final public function value( $setting_key = 'default' ) {
312
		if ( isset( $this->settings[ $setting_key ] ) ) {
313
			return $this->settings[ $setting_key ]->value();
314
		}
315
	}
316
317
	/**
318
	 * Refresh the parameters passed to the JavaScript via JSON.
319
	 *
320
	 * @since 3.4.0
321
	 */
322
	public function to_json() {
323
		$this->json['settings'] = array();
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
324
		foreach ( $this->settings as $key => $setting ) {
325
			$this->json['settings'][ $key ] = $setting->id;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
326
		}
327
328
		$this->json['type'] = $this->type;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
329
		$this->json['priority'] = $this->priority;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
330
		$this->json['active'] = $this->active();
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
331
		$this->json['section'] = $this->section;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
332
		$this->json['content'] = $this->get_content();
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
333
		$this->json['label'] = $this->label;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
334
		$this->json['description'] = $this->description;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
335
		$this->json['instanceNumber'] = $this->instance_number;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
336
337
		if ( 'dropdown-pages' === $this->type ) {
338
			$this->json['allow_addition'] = $this->allow_addition;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
339
		}
340
	}
341
342
	/**
343
	 * Get the data to export to the client via JSON.
344
	 *
345
	 * @since 4.1.0
346
	 *
347
	 * @return array Array of parameters passed to the JavaScript.
348
	 */
349
	public function json() {
350
		$this->to_json();
351
		return $this->json;
0 ignored issues
show
Deprecated Code introduced by
The property WP_Customize_Control::$json has been deprecated with message: It is better to just call the json() method

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
352
	}
353
354
	/**
355
	 * Checks if the user can use this control.
356
	 *
357
	 * Returns false if the user cannot manipulate one of the associated settings,
358
	 * or if one of the associated settings does not exist. Also returns false if
359
	 * the associated section does not exist or if its capability check returns
360
	 * false.
361
	 *
362
	 * @since 3.4.0
363
	 *
364
	 * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true.
365
	 */
366
	final public function check_capabilities() {
367
		if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) {
368
			return false;
369
		}
370
371
		foreach ( $this->settings as $setting ) {
372
			if ( ! $setting || ! $setting->check_capabilities() ) {
373
				return false;
374
			}
375
		}
376
377
		$section = $this->manager->get_section( $this->section );
378
		if ( isset( $section ) && ! $section->check_capabilities() ) {
0 ignored issues
show
This if statement, and the following return statement can be replaced with return !(isset($section)...>check_capabilities());.
Loading history...
379
			return false;
380
		}
381
382
		return true;
383
	}
384
385
	/**
386
	 * Get the control's content for insertion into the Customizer pane.
387
	 *
388
	 * @since 4.1.0
389
	 *
390
	 * @return string Contents of the control.
391
	 */
392
	final public function get_content() {
393
		ob_start();
394
		$this->maybe_render();
395
		return trim( ob_get_clean() );
396
	}
397
398
	/**
399
	 * Check capabilities and render the control.
400
	 *
401
	 * @since 3.4.0
402
	 * @uses WP_Customize_Control::render()
403
	 */
404
	final public function maybe_render() {
405
		if ( ! $this->check_capabilities() )
406
			return;
407
408
		/**
409
		 * Fires just before the current Customizer control is rendered.
410
		 *
411
		 * @since 3.4.0
412
		 *
413
		 * @param WP_Customize_Control $this WP_Customize_Control instance.
414
		 */
415
		do_action( 'customize_render_control', $this );
416
417
		/**
418
		 * Fires just before a specific Customizer control is rendered.
419
		 *
420
		 * The dynamic portion of the hook name, `$this->id`, refers to
421
		 * the control ID.
422
		 *
423
		 * @since 3.4.0
424
		 *
425
		 * @param WP_Customize_Control $this WP_Customize_Control instance.
426
		 */
427
		do_action( "customize_render_control_{$this->id}", $this );
428
429
		$this->render();
430
	}
431
432
	/**
433
	 * Renders the control wrapper and calls $this->render_content() for the internals.
434
	 *
435
	 * @since 3.4.0
436
	 */
437
	protected function render() {
438
		$id    = 'customize-control-' . str_replace( array( '[', ']' ), array( '-', '' ), $this->id );
439
		$class = 'customize-control customize-control-' . $this->type;
440
441
		?><li id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $class ); ?>">
442
			<?php $this->render_content(); ?>
443
		</li><?php
444
	}
445
446
	/**
447
	 * Get the data link attribute for a setting.
448
	 *
449
	 * @since 3.4.0
450
	 *
451
	 * @param string $setting_key
452
	 * @return string Data link parameter, if $setting_key is a valid setting, empty string otherwise.
453
	 */
454
	public function get_link( $setting_key = 'default' ) {
455
		if ( ! isset( $this->settings[ $setting_key ] ) )
456
			return '';
457
458
		return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"';
459
	}
460
461
	/**
462
	 * Render the data link attribute for the control's input element.
463
	 *
464
	 * @since 3.4.0
465
	 * @uses WP_Customize_Control::get_link()
466
	 *
467
	 * @param string $setting_key
468
	 */
469
	public function link( $setting_key = 'default' ) {
470
		echo $this->get_link( $setting_key );
471
	}
472
473
	/**
474
	 * Render the custom attributes for the control's input element.
475
	 *
476
	 * @since 4.0.0
477
	 */
478
	public function input_attrs() {
479
		foreach ( $this->input_attrs as $attr => $value ) {
480
			echo $attr . '="' . esc_attr( $value ) . '" ';
481
		}
482
	}
483
484
	/**
485
	 * Render the control's content.
486
	 *
487
	 * Allows the content to be overridden without having to rewrite the wrapper in `$this::render()`.
488
	 *
489
	 * Supports basic input types `text`, `checkbox`, `textarea`, `radio`, `select` and `dropdown-pages`.
490
	 * Additional input types such as `email`, `url`, `number`, `hidden` and `date` are supported implicitly.
491
	 *
492
	 * Control content can alternately be rendered in JS. See WP_Customize_Control::print_template().
493
	 *
494
	 * @since 3.4.0
495
	 */
496
	protected function render_content() {
497
		switch( $this->type ) {
498
			case 'checkbox':
499
				?>
500
				<label>
501
					<input type="checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?> />
502
					<?php echo esc_html( $this->label ); ?>
503
					<?php if ( ! empty( $this->description ) ) : ?>
504
						<span class="description customize-control-description"><?php echo $this->description; ?></span>
505
					<?php endif; ?>
506
				</label>
507
				<?php
508
				break;
509
			case 'radio':
510
				if ( empty( $this->choices ) )
511
					return;
512
513
				$name = '_customize-radio-' . $this->id;
514
515
				if ( ! empty( $this->label ) ) : ?>
516
					<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
517
				<?php endif;
518
				if ( ! empty( $this->description ) ) : ?>
519
					<span class="description customize-control-description"><?php echo $this->description ; ?></span>
520
				<?php endif;
521
522
				foreach ( $this->choices as $value => $label ) :
523
					?>
524
					<label>
525
						<input type="radio" value="<?php echo esc_attr( $value ); ?>" name="<?php echo esc_attr( $name ); ?>" <?php $this->link(); checked( $this->value(), $value ); ?> />
526
						<?php echo esc_html( $label ); ?><br/>
527
					</label>
528
					<?php
529
				endforeach;
530
				break;
531
			case 'select':
532
				if ( empty( $this->choices ) )
533
					return;
534
535
				?>
536
				<label>
537
					<?php if ( ! empty( $this->label ) ) : ?>
538
						<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
539
					<?php endif;
540
					if ( ! empty( $this->description ) ) : ?>
541
						<span class="description customize-control-description"><?php echo $this->description; ?></span>
542
					<?php endif; ?>
543
544
					<select <?php $this->link(); ?>>
545
						<?php
546 View Code Duplication
						foreach ( $this->choices as $value => $label )
547
							echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>';
548
						?>
549
					</select>
550
				</label>
551
				<?php
552
				break;
553 View Code Duplication
			case 'textarea':
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
					<textarea rows="5" <?php $this->input_attrs(); ?> <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
563
				</label>
564
				<?php
565
				break;
566
			case 'dropdown-pages':
567
				?>
568
				<label>
569
				<?php if ( ! empty( $this->label ) ) : ?>
570
					<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
571
				<?php endif;
572
				if ( ! empty( $this->description ) ) : ?>
573
					<span class="description customize-control-description"><?php echo $this->description; ?></span>
574
				<?php endif; ?>
575
576
				<?php
577
				$dropdown_name = '_customize-dropdown-pages-' . $this->id;
578
				$show_option_none = __( '&mdash; Select &mdash;' );
579
				$option_none_value = '0';
580
				$dropdown = wp_dropdown_pages(
581
					array(
582
						'name'              => $dropdown_name,
583
						'echo'              => 0,
584
						'show_option_none'  => $show_option_none,
585
						'option_none_value' => $option_none_value,
586
						'selected'          => $this->value(),
587
					)
588
				);
589
				if ( empty( $dropdown ) ) {
590
					$dropdown = sprintf( '<select id="%1$s" name="%1$s">', esc_attr( $dropdown_name ) );
591
					$dropdown .= sprintf( '<option value="%1$s">%2$s</option>', esc_attr( $option_none_value ), esc_html( $show_option_none ) );
592
					$dropdown .= '</select>';
593
				}
594
595
				// Hackily add in the data link parameter.
596
				$dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown );
597
598
				// Even more hacikly add auto-draft page stubs.
599
				// @todo Eventually this should be removed in favor of the pages being injected into the underlying get_pages() call. See <https://github.com/xwp/wp-customize-posts/pull/250>.
600
				$nav_menus_created_posts_setting = $this->manager->get_setting( 'nav_menus_created_posts' );
601
				if ( $nav_menus_created_posts_setting && current_user_can( 'publish_pages' ) ) {
602
					$auto_draft_page_options = '';
603
					foreach ( $nav_menus_created_posts_setting->value() as $auto_draft_page_id ) {
604
						$post = get_post( $auto_draft_page_id );
605
						if ( $post && 'page' === $post->post_type ) {
606
							$auto_draft_page_options .= sprintf( '<option value="%1$s">%2$s</option>', esc_attr( $post->ID ), esc_html( $post->post_title ) );
607
						}
608
					}
609
					if ( $auto_draft_page_options ) {
610
						$dropdown = str_replace( '</select>', $auto_draft_page_options . '</select>', $dropdown );
611
					}
612
				}
613
614
				echo $dropdown;
615
				?>
616
				</label>
617
				<?php if ( $this->allow_addition && current_user_can( 'publish_pages' ) && current_user_can( 'edit_theme_options' ) ) : // Currently tied to menus functionality. ?>
618
					<button type="button" class="button-link add-new-toggle"><?php
619
						/* translators: %s: add new page label */
620
						printf( __( '+ %s' ), get_post_type_object( 'page' )->labels->add_new_item );
621
					?></button>
622
					<div class="new-content-item">
623
						<label for="create-input-<?php echo $this->id; ?>"><span class="screen-reader-text"><?php _e( 'New page title' ); ?></span></label>
624
						<input type="text" id="create-input-<?php echo $this->id; ?>" class="create-item-input" placeholder="<?php esc_attr_e( 'New page title&hellip;' ); ?>">
625
						<button type="button" class="button add-content"><?php _e( 'Add' ); ?></button>
626
					</div>
627
				<?php endif;
628
				break;
629 View Code Duplication
			default:
630
				?>
631
				<label>
632
					<?php if ( ! empty( $this->label ) ) : ?>
633
						<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
634
					<?php endif;
635
					if ( ! empty( $this->description ) ) : ?>
636
						<span class="description customize-control-description"><?php echo $this->description; ?></span>
637
					<?php endif; ?>
638
					<input type="<?php echo esc_attr( $this->type ); ?>" <?php $this->input_attrs(); ?> value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); ?> />
639
				</label>
640
				<?php
641
				break;
642
		}
643
	}
644
645
	/**
646
	 * Render the control's JS template.
647
	 *
648
	 * This function is only run for control types that have been registered with
649
	 * WP_Customize_Manager::register_control_type().
650
	 *
651
	 * In the future, this will also print the template for the control's container
652
	 * element and be override-able.
653
	 *
654
	 * @since 4.1.0
655
	 */
656
	final public function print_template() {
657
		?>
658
		<script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
659
			<?php $this->content_template(); ?>
660
		</script>
661
		<?php
662
	}
663
664
	/**
665
	 * An Underscore (JS) template for this control's content (but not its container).
666
	 *
667
	 * Class variables for this control class are available in the `data` JS object;
668
	 * export custom variables by overriding WP_Customize_Control::to_json().
669
	 *
670
	 * @see WP_Customize_Control::print_template()
671
	 *
672
	 * @since 4.1.0
673
	 */
674
	protected function content_template() {}
675
676
}
677
678
/**
679
 * WP_Customize_Color_Control class.
680
 */
681
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-color-control.php' );
682
683
/**
684
 * WP_Customize_Media_Control class.
685
 */
686
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-media-control.php' );
687
688
/**
689
 * WP_Customize_Upload_Control class.
690
 */
691
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-upload-control.php' );
692
693
/**
694
 * WP_Customize_Image_Control class.
695
 */
696
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-image-control.php' );
697
698
/**
699
 * WP_Customize_Background_Image_Control class.
700
 */
701
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-background-image-control.php' );
702
703
/**
704
 * WP_Customize_Background_Position_Control class.
705
 */
706
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-background-position-control.php' );
707
708
/**
709
 * WP_Customize_Cropped_Image_Control class.
710
 */
711
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-cropped-image-control.php' );
712
713
/**
714
 * WP_Customize_Site_Icon_Control class.
715
 */
716
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-site-icon-control.php' );
717
718
/**
719
 * WP_Customize_Header_Image_Control class.
720
 */
721
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-control.php' );
722
723
/**
724
 * WP_Customize_Theme_Control class.
725
 */
726
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-theme-control.php' );
727
728
/**
729
 * WP_Widget_Area_Customize_Control class.
730
 */
731
require_once( ABSPATH . WPINC . '/customize/class-wp-widget-area-customize-control.php' );
732
733
/**
734
 * WP_Widget_Form_Customize_Control class.
735
 */
736
require_once( ABSPATH . WPINC . '/customize/class-wp-widget-form-customize-control.php' );
737
738
/**
739
 * WP_Customize_Nav_Menu_Control class.
740
 */
741
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-control.php' );
742
743
/**
744
 * WP_Customize_Nav_Menu_Item_Control class.
745
 */
746
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-control.php' );
747
748
/**
749
 * WP_Customize_Nav_Menu_Location_Control class.
750
 */
751
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-location-control.php' );
752
753
/**
754
 * WP_Customize_Nav_Menu_Name_Control class.
755
 */
756
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' );
757
758
/**
759
 * WP_Customize_Nav_Menu_Auto_Add_Control class.
760
 */
761
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' );
762
763
/**
764
 * WP_Customize_New_Menu_Control class.
765
 */
766
require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' );
767