: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Retrieves a customize section.
* @param string $id Section ID.
* @return WP_Customize_Section|void The section, if set.
public function get_section( $id ) {
if ( isset( $this->sections[ $id ] ) ) {
return $this->sections[ $id ];
* Removes a customize section.
* Note that removing the section doesn't destroy the WP_Customize_Section instance or remove its filters.
* @param string $id Section ID.
public function remove_section( $id ) {
unset( $this->sections[ $id ] );
* Registers a customize section type.
* Registered types are eligible to be rendered via JS and created dynamically.
* @see WP_Customize_Section
* @param string $section Name of a custom section which is a subclass of WP_Customize_Section.
public function register_section_type( $section ) {
$this->registered_section_types[] = $section;
* Renders JS templates for all registered section types.
public function render_section_templates() {
foreach ( $this->registered_section_types as $section_type ) {
$section = new $section_type( $this, 'temp', array() );
$section->print_template();
* Adds a customize control.
* @since 4.5.0 Return added WP_Customize_Control instance.
* @see WP_Customize_Control::__construct()
* @param WP_Customize_Control|string $id Customize Control object, or ID.
* @param array $args Optional. Array of properties for the new Control object.
* See WP_Customize_Control::__construct() for information
* on accepted arguments. Default empty array.
* @return WP_Customize_Control The instance of the control that was added.
public function add_control( $id, $args = array() ) {
if ( $id instanceof WP_Customize_Control ) {
$control = new WP_Customize_Control( $this, $id, $args );
$this->controls[ $control->id ] = $control;
* Retrieves a customize control.
* @param string $id ID of the control.
* @return WP_Customize_Control|void The control object, if set.
public function get_control( $id ) {
if ( isset( $this->controls[ $id ] ) ) {
return $this->controls[ $id ];
* Removes a customize control.
* Note that removing the control doesn't destroy the WP_Customize_Control instance or remove its filters.
* @param string $id ID of the control.
public function remove_control( $id ) {
unset( $this->controls[ $id ] );
* Registers a customize control type.
* Registered types are eligible to be rendered via JS and created dynamically.
* @param string $control Name of a custom control which is a subclass of
public function register_control_type( $control ) {
$this->registered_control_types[] = $control;
* Renders JS templates for all registered control types.
public function render_control_templates() {
if ( $this->branching() ) {
/* translators: %s: User who is customizing the changeset in customizer. */
'locked' => __( '%s is already customizing this changeset. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ),
/* translators: %s: User who is customizing the changeset in customizer. */
'locked_allow_override' => __( '%s is already customizing this changeset. Do you want to take over?' ),
/* translators: %s: User who is customizing the changeset in customizer. */
'locked' => __( '%s is already customizing this site. Please wait until they are done to try customizing. Your latest changes have been autosaved.' ),
/* translators: %s: User who is customizing the changeset in customizer. */
'locked_allow_override' => __( '%s is already customizing this site. Do you want to take over?' ),
foreach ( $this->registered_control_types as $control_type ) {
$control = new $control_type(
$control->print_template();
<script type="text/html" id="tmpl-customize-control-default-content">
var inputId = _.uniqueId( 'customize-control-default-input-' );
var descriptionId = _.uniqueId( 'customize-control-default-description-' );
var describedByAttr = data.description ? ' aria-describedby="' + descriptionId + '" ' : '';
<# switch ( data.type ) {
<span class="customize-inside-control-row">
data-customize-setting-key-link="default"
<label for="{{ inputId }}">
<# if ( data.description ) { #>
<span id="{{ descriptionId }}" class="description customize-control-description">{{{ data.description }}}</span>
<# if ( data.label ) { #>
<label for="{{ inputId }}" class="customize-control-title">
<# if ( data.description ) { #>
<span id="{{ descriptionId }}" class="description customize-control-description">{{{ data.description }}}</span>
<# _.each( data.choices, function( val, key ) { #>
<span class="customize-inside-control-row">
if ( _.isObject( val ) ) {
id="{{ inputId + '-' + value }}"
data-customize-setting-key-link="default"
<label for="{{ inputId + '-' + value }}">{{ text }}</label>
<# if ( data.label ) { #>
<label for="{{ inputId }}" class="customize-control-title">
<# if ( data.description ) { #>
<span id="{{ descriptionId }}" class="description customize-control-description">{{{ data.description }}}</span>
'data-customize-setting-key-link': 'default'
if ( 'textarea' === data.type ) {
} else if ( 'button' === data.type ) {
inputAttrs['class'] = 'button button-secondary';
inputAttrs.type = 'button';
inputAttrs.type = data.type;
if ( data.description ) {
inputAttrs['aria-describedby'] = descriptionId;
_.extend( inputAttrs, data.input_attrs );
<# if ( 'button' === data.type ) { #>
<# _.each( _.extend( inputAttrs ), function( value, key ) { #>
{{{ key }}}="{{ value }}"
>{{ inputAttrs.value }}</button>
<# } else if ( 'textarea' === data.type ) { #>
<# _.each( _.extend( inputAttrs ), function( value, key ) { #>
{{{ key }}}="{{ value }}"
>{{ inputAttrs.value }}</textarea>
<# } else if ( 'select' === data.type ) { #>
<# delete inputAttrs.type; #>
<# _.each( _.extend( inputAttrs ), function( value, key ) { #>
{{{ key }}}="{{ value }}"
<# _.each( data.choices, function( val, key ) { #>
if ( _.isObject( val ) ) {
<option value="{{ value }}">{{ text }}</option>
<# _.each( _.extend( inputAttrs ), function( value, key ) { #>
{{{ key }}}="{{ value }}"
<script type="text/html" id="tmpl-customize-notification">
<li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.containerClasses || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
<div class="notification-message">{{{ data.message || data.code }}}</div>
<# if ( data.dismissible ) { #>
<button type="button" class="notice-dismiss"><span class="screen-reader-text">
/* translators: Hidden accessibility text. */
<script type="text/html" id="tmpl-customize-changeset-locked-notification">
<li class="notice notice-{{ data.type || 'info' }} {{ data.containerClasses || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
<div class="notification-message customize-changeset-locked-message">
<img class="customize-changeset-locked-avatar" src="{{ data.lockUser.avatar }}" alt="{{ data.lockUser.name }}" />
<p class="currently-editing">
<# if ( data.message ) { #>
<# } else if ( data.allowOverride ) { #>
echo esc_html( sprintf( $l10n['locked_allow_override'], '{{ data.lockUser.name }}' ) );
echo esc_html( sprintf( $l10n['locked'], '{{ data.lockUser.name }}' ) );
<p class="notice notice-error notice-alt" hidden></p>
<p class="action-buttons">
<# if ( data.returnUrl !== data.previewUrl ) { #>
<a class="button customize-notice-go-back-button" href="{{ data.returnUrl }}"><?php _e( 'Go back' ); ?></a>
<a class="button customize-notice-preview-button" href="{{ data.frontendPreviewUrl }}"><?php _e( 'Preview' ); ?></a>
<# if ( data.allowOverride ) { #>
<button class="button button-primary wp-tab-last customize-notice-take-over-button"><?php _e( 'Take over' ); ?></button>
<script type="text/html" id="tmpl-customize-code-editor-lint-error-notification">
<li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.containerClasses || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
<div class="notification-message">{{{ data.message || data.code }}}</div>
<# var elementId = 'el-' + String( Math.random() ); #>
<input id="{{ elementId }}" type="checkbox">
<label for="{{ elementId }}"><?php _e( 'Update anyway, even though it might break your site?' ); ?></label>
/* The following template is obsolete in core but retained for plugins. */
<script type="text/html" id="tmpl-customize-control-notifications">
<# _.each( data.notifications, function( notification ) { #>
<li class="notice notice-{{ notification.type || 'info' }} {{ data.altNotice ? 'notice-alt' : '' }}" data-code="{{ notification.code }}" data-type="{{ notification.type }}">{{{ notification.message || notification.code }}}</li>
<script type="text/html" id="tmpl-customize-preview-link-control" >
<# var elementPrefix = _.uniqueId( 'el' ) + '-' #>
<p class="customize-control-title">
<?php esc_html_e( 'Share Preview Link' ); ?>
<p class="description customize-control-description"><?php esc_html_e( 'See how changes would look live on your website, and share the preview with people who can\'t access the Customizer.' ); ?></p>
<div class="customize-control-notifications-container"></div>
<div class="preview-link-wrapper">
<label for="{{ elementPrefix }}customize-preview-link-input" class="screen-reader-text">
/* translators: Hidden accessibility text. */
esc_html_e( 'Preview Link' );
<span class="preview-control-element" data-component="url"></span>
<span class="screen-reader-text">
/* translators: Hidden accessibility text. */
_e( '(opens in a new tab)' );
<input id="{{ elementPrefix }}customize-preview-link-input" readonly tabindex="-1" class="preview-control-element" data-component="input">
<button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button>
<script type="text/html" id="tmpl-customize-selected-changeset-status-control">
<# var inputId = _.uniqueId( 'customize-selected-changeset-status-control-input-' ); #>
<# var descriptionId = _.uniqueId( 'customize-selected-changeset-status-control-description-' ); #>
<# if ( data.label ) { #>
<label for="{{ inputId }}" class="customize-control-title">{{ data.label }}</label>
<# if ( data.description ) { #>
<span id="{{ descriptionId }}" class="description customize-control-description">{{{ data.description }}}</span>
<# _.each( data.choices, function( choice ) { #>
<# var choiceId = inputId + '-' + choice.status; #>
<span class="customize-inside-control-row">
<input id="{{ choiceId }}" type="radio" value="{{ choice.status }}" name="{{ inputId }}" data-customize-setting-key-link="default">
<label for="{{ choiceId }}">{{ choice.label }}</label>
* Helper function to compare two objects by priority, ensuring sort stability via instance_number.
* @deprecated 4.7.0 Use wp_list_sort()
* @param WP_Customize_Panel|WP_Customize_Section|WP_Customize_Control $a Object A.
* @param WP_Customize_Panel|WP_Customize_Section|WP_Customize_Control $b Object B.
protected function _cmp_priority( $a, $b ) {
_deprecated_function( __METHOD__, '4.7.0', 'wp_list_sort' );
if ( $a->priority === $b->priority ) {
return $a->instance_number - $b->instance_number;
return $a->priority - $b->priority;
* Prepares panels, sections, and controls.
* For each, check if required related components exist,
* whether the user has the necessary capabilities,
public function prepare_controls() {
$this->controls = wp_list_sort(
'instance_number' => 'ASC',
foreach ( $this->controls as $id => $control ) {
if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) {
$this->sections[ $control->section ]->controls[] = $control;
$controls[ $id ] = $control;
$this->controls = $controls;
$this->sections = wp_list_sort(
'instance_number' => 'ASC',
foreach ( $this->sections as $section ) {
if ( ! $section->check_capabilities() ) {
$section->controls = wp_list_sort(
'instance_number' => 'ASC',
if ( ! $section->panel ) {
$sections[ $section->id ] = $section;
// This section belongs to a panel.
if ( isset( $this->panels [ $section->panel ] ) ) {
$this->panels[ $section->panel ]->sections[ $section->id ] = $section;
$this->sections = $sections;
$this->panels = wp_list_sort(