消える飛行機雲 僕たちは見送った 眩しくて逃げた いつだって弱くて あの日から変わらず いつまでも変わらずに いられなかったこと 悔しくて指を離す あの鳥は まだ うまく飛べないけど いつかは 風を切って知る 届かない場所が まだ遠くにある 願いだけ秘めて 見つめてる 子供たちは 夏の線路 歩く 吹く風に素足をさらして 遠くには幼かった日びを 両手には 飛び立つ希望を 消える飛行機雲 追いかけて 追いかけて この丘を越えた あの日から変わらず いつまでも 真っ直ぐに 僕たちはあるように わたつみのような 強さを守れるよ きっと ���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC ‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!class-wp-customize-nav-menu-auto-add-control.php000064400000002142152254253720015732 0ustar00 <# var elementId = _.uniqueId( 'customize-nav-menu-auto-add-control-' ); #> id_data['base'] ) { throw new Exception( 'Expected custom_css id_base.' ); } if ( 1 !== count( $this->id_data['keys'] ) || empty( $this->id_data['keys'][0] ) ) { throw new Exception( 'Expected single stylesheet key.' ); } $this->stylesheet = $this->id_data['keys'][0]; } /** * Add filter to preview post value. * * @since 4.7.9 * * @return bool False when preview short-circuits due no change needing to be previewed. */ public function preview() { if ( $this->is_previewed ) { return false; } $this->is_previewed = true; add_filter( 'wp_get_custom_css', array( $this, 'filter_previewed_wp_get_custom_css' ), 9, 2 ); return true; } /** * Filters `wp_get_custom_css` for applying the customized value. * * This is used in the preview when `wp_get_custom_css()` is called for rendering the styles. * * @since 4.7.0 * * @see wp_get_custom_css() * * @param string $css Original CSS. * @param string $stylesheet Current stylesheet. * @return string CSS. */ public function filter_previewed_wp_get_custom_css( $css, $stylesheet ) { if ( $stylesheet === $this->stylesheet ) { $customized_value = $this->post_value( null ); if ( ! is_null( $customized_value ) ) { $css = $customized_value; } } return $css; } /** * Fetch the value of the setting. Will return the previewed value when `preview()` is called. * * @since 4.7.0 * * @see WP_Customize_Setting::value() * * @return string */ public function value() { if ( $this->is_previewed ) { $post_value = $this->post_value( null ); if ( null !== $post_value ) { return $post_value; } } $id_base = $this->id_data['base']; $value = ''; $post = wp_get_custom_css_post( $this->stylesheet ); if ( $post ) { $value = $post->post_content; } if ( empty( $value ) ) { $value = $this->default; } /** This filter is documented in wp-includes/class-wp-customize-setting.php */ $value = apply_filters( "customize_value_{$id_base}", $value, $this ); return $value; } /** * Validate a received value for being valid CSS. * * Checks for imbalanced braces, brackets, and comments. * Notifications are rendered when the customizer state is saved. * * @since 4.7.0 * @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor. * @since 5.9.0 Renamed `$css` to `$value` for PHP 8 named parameter support. * @since 7.0.0 Only restricts contents which risk prematurely closing the STYLE element, * either through a STYLE end tag or a prefix of one which might become a * full end tag when combined with the contents of other styles. * * @see WP_REST_Global_Styles_Controller::validate_custom_css() * * @param string $value CSS to validate. * @return true|WP_Error True if the input was validated, otherwise WP_Error. */ public function validate( $value ) { // Restores the more descriptive, specific name for use within this method. $css = $value; $validity = new WP_Error(); $length = strlen( $css ); for ( $at = strcspn( $css, '<' ); $at < $length; $at += strcspn( $css, '<', ++$at ) ) { $remaining_strlen = $length - $at; /** * Custom CSS text is expected to render inside an HTML STYLE element. * A STYLE closing tag must not appear within the CSS text because it * would close the element prematurely. * * The text must also *not* end with a partial closing tag (e.g., `<`, * `` tag. * * Example: * * $style_a = 'p { font-weight: bold; add( 'illegal_markup', sprintf( /* translators: %s is the CSS that was provided. */ __( 'The CSS must not end in "%s".' ), esc_html( substr( $css, $at ) ) ) ); break; } if ( 1 === strspn( $css, " \t\f\r\n/>", $at + 7, 1 ) ) { $validity->add( 'illegal_markup', sprintf( /* translators: %s is the CSS that was provided. */ __( 'The CSS must not contain "%s".' ), esc_html( substr( $css, $at, 8 ) ) ) ); break; } } } if ( ! $validity->has_errors() ) { $validity = parent::validate( $css ); } return $validity; } /** * Store the CSS setting value in the custom_css custom post type for the stylesheet. * * @since 4.7.0 * @since 5.9.0 Renamed `$css` to `$value` for PHP 8 named parameter support. * * @param string $value CSS to update. * @return int|false The post ID or false if the value could not be saved. */ public function update( $value ) { // Restores the more descriptive, specific name for use within this method. $css = $value; if ( empty( $css ) ) { $css = ''; } $r = wp_update_custom_css_post( $css, array( 'stylesheet' => $this->stylesheet, ) ); if ( is_wp_error( $r ) ) { return false; } $post_id = $r->ID; // Cache post ID in theme mod for performance to avoid additional DB query. if ( $this->manager->get_stylesheet() === $this->stylesheet ) { set_theme_mod( 'custom_css_post_id', $post_id ); } return $post_id; } } class-wp-widget-area-customize-control.php000064400000003267152254253720014712 0ustar00json[ $key ] = $this->$key; } } /** * Renders the control's content. * * @since 3.9.0 */ public function render_content() { $id = 'reorder-widgets-desc-' . str_replace( array( '[', ']' ), array( '-', '' ), $this->id ); ?>

statuses = array( '' => __( 'Default' ) ); parent::__construct( $manager, $id, $args ); } /** * Enqueue scripts/styles for the color picker. * * @since 3.4.0 */ public function enqueue() { wp_enqueue_script( 'wp-color-picker' ); wp_enqueue_style( 'wp-color-picker' ); } /** * Refresh the parameters passed to the JavaScript via JSON. * * @since 3.4.0 * @uses WP_Customize_Control::to_json() */ public function to_json() { parent::to_json(); $this->json['statuses'] = $this->statuses; $this->json['defaultValue'] = $this->setting->default; $this->json['mode'] = $this->mode; } /** * Don't render the control content from PHP, as it's rendered via JS on load. * * @since 3.4.0 */ public function render_content() {} /** * Render a JS template for the content of the color picker control. * * @since 4.1.0 */ public function content_template() { ?> <# var defaultValue = '#RRGGBB', defaultValueAttr = '', inputId = _.uniqueId( 'customize-color-control-input-' ), isHueSlider = data.mode === 'hue'; if ( data.defaultValue && _.isString( data.defaultValue ) && ! isHueSlider ) { if ( '#' !== data.defaultValue.substring( 0, 1 ) ) { defaultValue = '#' + data.defaultValue; } else { defaultValue = data.defaultValue; } defaultValueAttr = ' data-default-color=' + defaultValue; // Quotes added automatically. } #> <# if ( data.label ) { #> {{{ data.label }}} <# } #> <# if ( data.description ) { #> {{{ data.description }}} <# } #>
<# if ( isHueSlider ) { #> <# } else { #> <# } #>
max_year; $data['minYear'] = (int) $this->min_year; $data['allowPastDate'] = (bool) $this->allow_past_date; $data['twelveHourFormat'] = (bool) $this->twelve_hour_format; $data['includeTime'] = (bool) $this->include_time; return $data; } /** * Renders a JS template for the content of date time control. * * @since 4.9.0 */ public function content_template() { $data = array_merge( $this->json(), $this->get_month_choices() ); $timezone_info = $this->get_timezone_info(); $date_format = get_option( 'date_format' ); $date_format = preg_replace( '/(? <# _.defaults( data, ); #> <# var idPrefix = _.uniqueId( 'el' ) + '-'; #> <# if ( data.label ) { #> {{ data.label }} <# } #>
<# if ( data.description ) { #> {{ data.description }} <# } #>
<# if ( data.includeTime ) { #>
<# var maxHour = data.twelveHourFormat ? 12 : 23; #> <# var minHour = data.twelveHourFormat ? 1 : 0; #> : <# if ( data.twelveHourFormat ) { #> <# } #>

<# } #>
get_month_abbrev( $wp_locale->get_month( $i ) ); /* translators: 1: Month number (01, 02, etc.), 2: Month abbreviation. */ $months[ $i ]['text'] = sprintf( __( '%1$s-%2$s' ), $i, $month_text ); $months[ $i ]['value'] = $i; } return array( 'month_choices' => $months, ); } /** * Get timezone info. * * @since 4.9.0 * * @return array { * Timezone info. All properties are optional. * * @type string $abbr Timezone abbreviation. Examples: PST or CEST. * @type string $description Human-readable timezone description as HTML. * } */ public function get_timezone_info() { $tz_string = get_option( 'timezone_string' ); $timezone_info = array(); if ( $tz_string ) { try { $tz = new DateTimeZone( $tz_string ); } catch ( Exception $e ) { $tz = ''; } if ( $tz ) { $now = new DateTime( 'now', $tz ); $formatted_gmt_offset = $this->format_gmt_offset( $tz->getOffset( $now ) / HOUR_IN_SECONDS ); $tz_name = str_replace( '_', ' ', $tz->getName() ); $timezone_info['abbr'] = $now->format( 'T' ); $timezone_info['description'] = sprintf( /* translators: 1: Timezone name, 2: Timezone abbreviation, 3: UTC abbreviation and offset, 4: UTC offset. */ __( 'Your timezone is set to %1$s (%2$s), currently %3$s (Coordinated Universal Time %4$s).' ), $tz_name, '' . $timezone_info['abbr'] . '', 'UTC' . $formatted_gmt_offset, $formatted_gmt_offset ); } else { $timezone_info['description'] = ''; } } else { $formatted_gmt_offset = $this->format_gmt_offset( (int) get_option( 'gmt_offset', 0 ) ); $timezone_info['description'] = sprintf( /* translators: 1: UTC abbreviation and offset, 2: UTC offset. */ __( 'Your timezone is set to %1$s (Coordinated Universal Time %2$s).' ), 'UTC' . $formatted_gmt_offset, $formatted_gmt_offset ); } return $timezone_info; } /** * Format GMT Offset. * * @since 4.9.0 * * @see wp_timezone_choice() * * @param float $offset Offset in hours. * @return string Formatted offset. */ public function format_gmt_offset( $offset ) { if ( 0 <= $offset ) { $formatted_offset = '+' . (string) $offset; } else { $formatted_offset = (string) $offset; } $formatted_offset = str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), $formatted_offset ); return $formatted_offset; } } class-wp-customize-filter-setting.php000064400000001335152254253720013775 0ustar00editor_settings = wp_enqueue_code_editor( array_merge( array( 'type' => $this->code_type, 'codemirror' => array( 'indentUnit' => 2, 'tabSize' => 2, ), ), $this->editor_settings ) ); } /** * Refresh the parameters passed to the JavaScript via JSON. * * @since 4.9.0 * * @see WP_Customize_Control::json() * * @return array Array of parameters passed to the JavaScript. */ public function json() { $json = parent::json(); $json['editor_settings'] = $this->editor_settings; $json['input_attrs'] = $this->input_attrs; return $json; } /** * Don't render the control content from PHP, as it's rendered via JS on load. * * @since 4.9.0 */ public function render_content() {} /** * Render a JS template for control display. * * @since 4.9.0 */ public function content_template() { ?> <# var elementIdPrefix = 'el' + String( Math.random() ); #> <# if ( data.label ) { #> <# } #> <# if ( data.description ) { #> {{{ data.description }}} <# } #>
__( 'Header Image' ), 'settings' => array( 'default' => 'header_image', 'data' => 'header_image_data', ), 'section' => 'header_image', 'removed' => 'remove-header', 'get_url' => 'get_header_image', ) ); } /** * Enqueues control related scripts/styles. * * @since 3.9.0 */ public function enqueue() { wp_enqueue_media(); wp_enqueue_script( 'customize-views' ); $this->prepare_control(); wp_localize_script( 'customize-views', '_wpCustomizeHeader', array( 'data' => array( 'width' => absint( get_theme_support( 'custom-header', 'width' ) ), 'height' => absint( get_theme_support( 'custom-header', 'height' ) ), 'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ), 'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ), 'currentImgSrc' => $this->get_current_image_src(), ), 'nonces' => array( 'add' => wp_create_nonce( 'header-add' ), 'remove' => wp_create_nonce( 'header-remove' ), ), 'uploads' => $this->uploaded_headers, 'defaults' => $this->default_headers, ) ); parent::enqueue(); } /** * Prepares the control. * * @since 3.9.0 * * @global Custom_Image_Header $custom_image_header */ public function prepare_control() { global $custom_image_header; if ( empty( $custom_image_header ) ) { return; } add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_header_image_template' ) ); // Process default headers and uploaded headers. $custom_image_header->process_default_headers(); $this->default_headers = $custom_image_header->get_default_header_images(); $this->uploaded_headers = $custom_image_header->get_uploaded_header_images(); } /** * Prints header image template. * * @since 3.9.0 */ public function print_header_image_template() { ?> value(); if ( isset( $this->get_url ) ) { $src = call_user_func( $this->get_url, $src ); return $src; } } /** * Renders the control's content. * * @since 3.9.0 */ public function render_content() { $visibility = $this->get_current_image_src() ? '' : ' style="display:none" '; $width = absint( get_theme_support( 'custom-header', 'width' ) ); $height = absint( get_theme_support( 'custom-header', 'height' ) ); ?>
' . $this->label . ''; } ?>

%s × %s', $width, $height ) ); } elseif ( $width ) { printf( /* translators: %s: Header width in pixels. */ __( 'Click “Add Image” to upload an image file from your computer. Your theme works best with an image with a header width of %s pixels — you’ll be able to crop your image once you upload it for a perfect fit.' ), sprintf( '%s', $width ) ); } else { printf( /* translators: %s: Header height in pixels. */ __( 'Click “Add Image” to upload an image file from your computer. Your theme works best with an image with a header height of %s pixels — you’ll be able to crop your image once you upload it for a perfect fit.' ), sprintf( '%s', $height ) ); } ?>

id ); return $exported; } } class-wp-customize-image-control.php000064400000002273152254253720013577 0ustar00 <# if ( data.label ) { #> {{ data.label }} <# } #> <# if ( data.attachment && data.attachment.id ) { #>
<# if ( data.attachment.sizes ) { #>
{{
								data.attachment.alt ?
									wp.i18n.sprintf(
										<?php
										/* translators: %s: The selected image alt text. */
										echo wp_json_encode( __( 'App icon preview: Current image: %s' ) )
										?>
										,
										data.attachment.alt
									) :
									wp.i18n.sprintf(
										<?php
										/* translators: %s: The selected image filename. */
										echo wp_json_encode( __( 'App icon preview: The current image has no alternative text. The file name is: %s' ) );
										?>
										,
										data.attachment.filename
									)
							}}
{{
										data.attachment.alt ?
											wp.i18n.sprintf(
												<?php
												/* translators: %s: The selected image alt text. */
												echo wp_json_encode( __( 'Browser icon preview: Current image: %s' ) );
												?>
												,
												data.attachment.alt
											) :
											wp.i18n.sprintf(
												<?php
												/* translators: %s: The selected image filename. */
												echo wp_json_encode( __( 'Browser icon preview: The current image has no alternative text. The file name is: %s' ) );
												?>
												,
												data.attachment.filename
											)
									}}
<# } #>
<# if ( data.canUpload ) { #> <# } #>
<# } else { #>
<# if ( data.canUpload ) { #> <# } #>
<# if ( data.defaultAttachment ) { #> <# } #>
<# } #> <# if ( data.description ) { #> {{{ data.description }}} <# } #> json['theme'] = $this->theme; } /** * Don't render the control content from PHP, as it's rendered via JS on load. * * @since 4.2.0 */ public function render_content() {} /** * Render a JS template for theme display. * * @since 4.2.0 */ public function content_template() { /* translators: %s: Theme name. */ $details_label = sprintf( __( 'Details for theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $customize_label = sprintf( __( 'Customize theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $preview_label = sprintf( __( 'Live preview theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $install_label = sprintf( __( 'Install and preview theme: %s' ), '{{ data.theme.name }}' ); ?> <# if ( data.theme.active ) { #>
<# } else { #>
<# } #> <# if ( data.theme.screenshot && data.theme.screenshot[0] ) { #>
<# } else { #>
<# } #>
<# if ( 'installed' === data.theme.type && data.theme.hasUpdate ) { #> <# if ( data.theme.updateResponse.compatibleWP && data.theme.updateResponse.compatiblePHP ) { #>

' . __( 'Update now' ) . '' ); } ?>

<# } else { #>

<# if ( ! data.theme.updateResponse.compatibleWP && ! data.theme.updateResponse.compatiblePHP ) { #> Please update WordPress, and then learn more about updating PHP.' ), self_admin_url( 'update-core.php' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } elseif ( current_user_can( 'update_core' ) ) { printf( /* translators: %s: URL to WordPress Updates screen. */ ' ' . __( 'Please update WordPress.' ), self_admin_url( 'update-core.php' ) ); } elseif ( current_user_can( 'update_php' ) ) { printf( /* translators: %s: URL to Update PHP page. */ ' ' . __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } ?> <# } else if ( ! data.theme.updateResponse.compatibleWP ) { #> Please update WordPress.' ), self_admin_url( 'update-core.php' ) ); } ?> <# } else if ( ! data.theme.updateResponse.compatiblePHP ) { #> Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } ?> <# } #>

<# } #> <# } #> <# if ( ! data.theme.compatibleWP || ! data.theme.compatiblePHP ) { #>

<# if ( ! data.theme.compatibleWP && ! data.theme.compatiblePHP ) { #> Please update WordPress, and then learn more about updating PHP.' ), self_admin_url( 'update-core.php' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } elseif ( current_user_can( 'update_core' ) ) { printf( /* translators: %s: URL to WordPress Updates screen. */ ' ' . __( 'Please update WordPress.' ), self_admin_url( 'update-core.php' ) ); } elseif ( current_user_can( 'update_php' ) ) { printf( /* translators: %s: URL to Update PHP page. */ ' ' . __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } ?> <# } else if ( ! data.theme.compatibleWP ) { #> Please update WordPress.' ), self_admin_url( 'update-core.php' ) ); } ?> <# } else if ( ! data.theme.compatiblePHP ) { #> Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); wp_update_php_annotation( '

', '' ); } ?> <# } #>

<# } #> <# if ( data.theme.active ) { #>

{{ data.theme.name }}

'success', 'additional_classes' => array( 'notice-alt' ), ) ); ?> <# } else if ( 'installed' === data.theme.type ) { #> <# if ( data.theme.blockTheme ) { #>

{{ data.theme.name }}

<# if ( data.theme.actions.activate ) { #> <# } #>
<# if ( data.theme.actions.activate ) { #> activate this theme, and use the Site Editor to customize it.' ), '{{{ data.theme.actions.activate }}}' ); ?> <# } #> 'error', 'additional_classes' => array( 'notice-alt' ), ) ); ?> <# } else { #>

{{ data.theme.name }}

<# if ( data.theme.compatibleWP && data.theme.compatiblePHP ) { #> <# } else { #> <# } #>
'success', 'additional_classes' => array( 'notice-alt' ), ) ); ?> <# } #> <# } else { #>

{{ data.theme.name }}

<# if ( data.theme.compatibleWP && data.theme.compatiblePHP ) { #> <# } else { #> <# } #>
<# } #>
json['width'] = absint( $this->width ); $this->json['height'] = absint( $this->height ); $this->json['flex_width'] = absint( $this->flex_width ); $this->json['flex_height'] = absint( $this->flex_height ); } } class-wp-customize-nav-menu-locations-control.php000064400000005401152254253720016230 0ustar00 <# var elementId; #> __( 'Background Image' ), 'section' => 'background_image', ) ); } /** * Enqueue control related scripts/styles. * * @since 4.1.0 */ public function enqueue() { parent::enqueue(); $custom_background = get_theme_support( 'custom-background' ); wp_localize_script( 'customize-controls', '_wpCustomizeBackground', array( 'defaults' => ! empty( $custom_background[0] ) ? $custom_background[0] : array(), 'nonces' => array( 'add' => wp_create_nonce( 'background-add' ), ), ) ); } } class-wp-customize-upload-control.php000064400000002255152254253720014001 0ustar00value(); if ( $value ) { // Get the attachment model for the existing file. $attachment_id = attachment_url_to_postid( $value ); if ( $attachment_id ) { $this->json['attachment'] = wp_prepare_attachment_for_js( $attachment_id ); } } } } class-wp-customize-media-control.php000064400000022372152254253720013576 0ustar00button_labels = wp_parse_args( $this->button_labels, $this->get_default_button_labels() ); } /** * Enqueue control related scripts/styles. * * @since 3.4.0 * @since 4.2.0 Moved from WP_Customize_Upload_Control. */ public function enqueue() { wp_enqueue_media(); } /** * Refresh the parameters passed to the JavaScript via JSON. * * @since 3.4.0 * @since 4.2.0 Moved from WP_Customize_Upload_Control. * * @see WP_Customize_Control::to_json() */ public function to_json() { parent::to_json(); $this->json['label'] = html_entity_decode( $this->label, ENT_QUOTES, get_bloginfo( 'charset' ) ); $this->json['mime_type'] = $this->mime_type; $this->json['button_labels'] = $this->button_labels; $this->json['canUpload'] = current_user_can( 'upload_files' ); $value = $this->value(); if ( is_object( $this->setting ) ) { if ( $this->setting->default ) { /* * Fake an attachment model - needs all fields used by template. * Note that the default value must be a URL, NOT an attachment ID. */ $ext = wp_check_filetype( $this->setting->default )['ext']; $ext_types = wp_get_ext_types(); $type = isset( $ext_types['image'] ) && in_array( $ext, $ext_types['image'], true ) ? 'image' : 'document'; $default_attachment = array( 'id' => 1, 'url' => $this->setting->default, 'type' => $type, 'icon' => wp_mime_type_icon( $type, '.svg' ), 'title' => wp_basename( $this->setting->default ), ); if ( 'image' === $type ) { $default_attachment['sizes'] = array( 'full' => array( 'url' => $this->setting->default ), ); } $this->json['defaultAttachment'] = $default_attachment; } if ( $value && $this->setting->default && $value === $this->setting->default ) { // Set the default as the attachment. $this->json['attachment'] = $this->json['defaultAttachment']; } elseif ( $value ) { $this->json['attachment'] = wp_prepare_attachment_for_js( $value ); } } } /** * Don't render any content for this control from PHP. * * @since 3.4.0 * @since 4.2.0 Moved from WP_Customize_Upload_Control. * * @see WP_Customize_Media_Control::content_template() */ public function render_content() {} /** * Render a JS template for the content of the media control. * * @since 4.1.0 * @since 4.2.0 Moved from WP_Customize_Upload_Control. */ public function content_template() { ?> <# var descriptionId = _.uniqueId( 'customize-media-control-description-' ); var describedByAttr = data.description ? ' aria-describedby="' + descriptionId + '" ' : ''; #> <# if ( data.label ) { #> {{ data.label }} <# } #>
<# if ( data.description ) { #> {{{ data.description }}} <# } #> <# if ( data.attachment && data.attachment.id ) { #>
<# if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.medium ) { #> <# } else if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.full ) { #> <# } else if ( 'audio' === data.attachment.type ) { #> <# if ( data.attachment.image && data.attachment.image.src && data.attachment.image.src !== data.attachment.icon ) { #> <# } else { #> <# } #>

“{{ data.attachment.title }}”

<# if ( data.attachment.album || data.attachment.meta.album ) { #>

{{ data.attachment.album || data.attachment.meta.album }}

<# } #> <# if ( data.attachment.artist || data.attachment.meta.artist ) { #>

{{ data.attachment.artist || data.attachment.meta.artist }}

<# } #> <# } else if ( 'video' === data.attachment.type ) { #>
<# } else { #>

{{ data.attachment.title }}

<# } #>
<# if ( data.canUpload ) { #> <# } #>
<# } else { #>
<# if ( data.canUpload ) { #> <# } #>
<# if ( data.defaultAttachment ) { #> <# } #>
<# } #> mime_type ) ? strtok( ltrim( $this->mime_type, '/' ), '/' ) : 'default'; switch ( $mime_type ) { case 'video': return array( 'select' => __( 'Select video' ), 'change' => __( 'Change video' ), 'default' => __( 'Default' ), 'remove' => __( 'Remove' ), 'placeholder' => __( 'No video selected' ), 'frame_title' => __( 'Select video' ), 'frame_button' => __( 'Choose video' ), ); case 'audio': return array( 'select' => __( 'Select audio' ), 'change' => __( 'Change audio' ), 'default' => __( 'Default' ), 'remove' => __( 'Remove' ), 'placeholder' => __( 'No audio selected' ), 'frame_title' => __( 'Select audio' ), 'frame_button' => __( 'Choose audio' ), ); case 'image': return array( 'select' => __( 'Select image' ), 'site_icon' => __( 'Select Site Icon' ), 'change' => __( 'Change image' ), 'default' => __( 'Default' ), 'remove' => __( 'Remove' ), 'placeholder' => __( 'No image selected' ), 'frame_title' => __( 'Select image' ), 'frame_button' => __( 'Choose image' ), ); default: return array( 'select' => __( 'Select file' ), 'change' => __( 'Change file' ), 'default' => __( 'Default' ), 'remove' => __( 'Remove' ), 'placeholder' => __( 'No file selected' ), 'frame_title' => __( 'Select file' ), 'frame_button' => __( 'Choose file' ), ); } // End switch(). } } class-wp-customize-background-image-setting.php000064400000001416152254253720015707 0ustar00
  • manager->is_theme_active() ) { echo '' . __( 'Active theme' ) . ' {{ data.title }}'; } else { echo '' . __( 'Previewing theme' ) . ' {{ data.title }}'; } ?>

    • ' . __( 'Themes' ) . '' ); // Separate strings for consistency with other panels. ?> <# if ( data.description ) { #> <# } #>
      <# if ( data.description ) { #>
      {{{ data.description }}}
      <# } #>
    • sidebar_id; return $json; } /** * Whether the current sidebar is rendered on the page. * * @since 4.1.0 * * @return bool Whether sidebar is rendered. */ public function active_callback() { return $this->manager->widgets->is_sidebar_rendered( $this->sidebar_id ); } } class-wp-customize-nav-menu-setting.php000064400000045270152254253720014244 0ustar00-?\d+)\]$/'; const TAXONOMY = 'nav_menu'; const TYPE = 'nav_menu'; /** * Setting type. * * @since 4.3.0 * @var string */ public $type = self::TYPE; /** * Default setting value. * * @since 4.3.0 * @var array * * @see wp_get_nav_menu_object() */ public $default = array( 'name' => '', 'description' => '', 'parent' => 0, 'auto_add' => false, ); /** * Default transport. * * @since 4.3.0 * @var string */ public $transport = 'postMessage'; /** * The term ID represented by this setting instance. * * A negative value represents a placeholder ID for a new menu not yet saved. * * @since 4.3.0 * @var int */ public $term_id; /** * Previous (placeholder) term ID used before creating a new menu. * * This value will be exported to JS via the {@see 'customize_save_response'} filter * so that JavaScript can update the settings to refer to the newly-assigned * term ID. This value is always negative to indicate it does not refer to * a real term. * * @since 4.3.0 * @var int * * @see WP_Customize_Nav_Menu_Setting::update() * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() */ public $previous_term_id; /** * Whether or not update() was called. * * @since 4.3.0 * @var bool */ protected $is_updated = false; /** * Status for calling the update method, used in customize_save_response filter. * * See {@see 'customize_save_response'}. * * When status is inserted, the placeholder term ID is stored in `$previous_term_id`. * When status is error, the error is stored in `$update_error`. * * @since 4.3.0 * @var string updated|inserted|deleted|error * * @see WP_Customize_Nav_Menu_Setting::update() * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() */ public $update_status; /** * Any error object returned by wp_update_nav_menu_object() when setting is updated. * * @since 4.3.0 * @var WP_Error * * @see WP_Customize_Nav_Menu_Setting::update() * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() */ public $update_error; /** * Constructor. * * Any supplied $args override class property defaults. * * @since 4.3.0 * * @throws Exception If $id is not valid for this setting type. * * @param WP_Customize_Manager $manager Customizer bootstrap instance. * @param string $id A specific ID of the setting. * Can be a theme mod or option name. * @param array $args Optional. Setting arguments. */ public function __construct( WP_Customize_Manager $manager, $id, array $args = array() ) { if ( empty( $manager->nav_menus ) ) { throw new Exception( 'Expected WP_Customize_Manager::$nav_menus to be set.' ); } if ( ! preg_match( self::ID_PATTERN, $id, $matches ) ) { throw new Exception( "Illegal widget setting ID: $id" ); } $this->term_id = (int) $matches['id']; parent::__construct( $manager, $id, $args ); } /** * Get the instance data for a given widget setting. * * @since 4.3.0 * * @see wp_get_nav_menu_object() * * @return array Instance data. */ public function value() { if ( $this->is_previewed && get_current_blog_id() === $this->_previewed_blog_id ) { $undefined = new stdClass(); // Symbol. $post_value = $this->post_value( $undefined ); if ( $undefined === $post_value ) { $value = $this->_original_value; } else { $value = $post_value; } } else { $value = false; // Note that a term_id of less than one indicates a nav_menu not yet inserted. if ( $this->term_id > 0 ) { $term = wp_get_nav_menu_object( $this->term_id ); if ( $term ) { $value = wp_array_slice_assoc( (array) $term, array_keys( $this->default ) ); $nav_menu_options = (array) get_option( 'nav_menu_options', array() ); $value['auto_add'] = false; if ( isset( $nav_menu_options['auto_add'] ) && is_array( $nav_menu_options['auto_add'] ) ) { $value['auto_add'] = in_array( $term->term_id, $nav_menu_options['auto_add'], true ); } } } if ( ! is_array( $value ) ) { $value = $this->default; } } return $value; } /** * Handle previewing the setting. * * @since 4.3.0 * @since 4.4.0 Added boolean return value * * @see WP_Customize_Manager::post_value() * * @return bool False if method short-circuited due to no-op. */ public function preview() { if ( $this->is_previewed ) { return false; } $undefined = new stdClass(); $is_placeholder = ( $this->term_id < 0 ); $is_dirty = ( $undefined !== $this->post_value( $undefined ) ); if ( ! $is_placeholder && ! $is_dirty ) { return false; } $this->is_previewed = true; $this->_original_value = $this->value(); $this->_previewed_blog_id = get_current_blog_id(); add_filter( 'wp_get_nav_menus', array( $this, 'filter_wp_get_nav_menus' ), 10, 2 ); add_filter( 'wp_get_nav_menu_object', array( $this, 'filter_wp_get_nav_menu_object' ), 10, 2 ); add_filter( 'default_option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) ); add_filter( 'option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) ); return true; } /** * Filters the wp_get_nav_menus() result to ensure the inserted menu object is included, and the deleted one is removed. * * @since 4.3.0 * * @see wp_get_nav_menus() * * @param WP_Term[] $menus An array of menu objects. * @param array $args An array of arguments used to retrieve menu objects. * @return WP_Term[] Array of menu objects. */ public function filter_wp_get_nav_menus( $menus, $args ) { if ( get_current_blog_id() !== $this->_previewed_blog_id ) { return $menus; } $setting_value = $this->value(); $is_delete = ( false === $setting_value ); $index = -1; // Find the existing menu item's position in the list. foreach ( $menus as $i => $menu ) { if ( (int) $this->term_id === (int) $menu->term_id || (int) $this->previous_term_id === (int) $menu->term_id ) { $index = $i; break; } } if ( $is_delete ) { // Handle deleted menu by removing it from the list. if ( -1 !== $index ) { array_splice( $menus, $index, 1 ); } } else { // Handle menus being updated or inserted. $menu_obj = (object) array_merge( array( 'term_id' => $this->term_id, 'term_taxonomy_id' => $this->term_id, 'slug' => sanitize_title( $setting_value['name'] ), 'count' => 0, 'term_group' => 0, 'taxonomy' => self::TAXONOMY, 'filter' => 'raw', ), $setting_value ); array_splice( $menus, $index, ( -1 === $index ? 0 : 1 ), array( $menu_obj ) ); } // Make sure the menu objects get re-sorted after an update/insert. if ( ! $is_delete && ! empty( $args['orderby'] ) ) { $menus = wp_list_sort( $menus, array( $args['orderby'] => 'ASC', ) ); } // @todo Add support for $args['hide_empty'] === true. return $menus; } /** * Temporary non-closure passing of orderby value to function. * * @since 4.3.0 * @var string * * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus() * @see WP_Customize_Nav_Menu_Setting::_sort_menus_by_orderby() */ protected $_current_menus_sort_orderby; /** * Sort menu objects by the class-supplied orderby property. * * This is a workaround for a lack of closures. * * @since 4.3.0 * @deprecated 4.7.0 Use wp_list_sort() * * @param object $menu1 * @param object $menu2 * @return int * * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus() */ protected function _sort_menus_by_orderby( $menu1, $menu2 ) { _deprecated_function( __METHOD__, '4.7.0', 'wp_list_sort' ); $key = $this->_current_menus_sort_orderby; return strcmp( $menu1->$key, $menu2->$key ); } /** * Filters the wp_get_nav_menu_object() result to supply the previewed menu object. * * Requesting a nav_menu object by anything but ID is not supported. * * @since 4.3.0 * * @see wp_get_nav_menu_object() * * @param object|null $menu_obj Object returned by wp_get_nav_menu_object(). * @param string $menu_id ID of the nav_menu term. Requests by slug or name will be ignored. * @return object|null */ public function filter_wp_get_nav_menu_object( $menu_obj, $menu_id ) { $ok = ( get_current_blog_id() === $this->_previewed_blog_id && is_int( $menu_id ) && $menu_id === $this->term_id ); if ( ! $ok ) { return $menu_obj; } $setting_value = $this->value(); // Handle deleted menus. if ( false === $setting_value ) { return false; } // Handle sanitization failure by preventing short-circuiting. if ( null === $setting_value ) { return $menu_obj; } $menu_obj = (object) array_merge( array( 'term_id' => $this->term_id, 'term_taxonomy_id' => $this->term_id, 'slug' => sanitize_title( $setting_value['name'] ), 'count' => 0, 'term_group' => 0, 'taxonomy' => self::TAXONOMY, 'filter' => 'raw', ), $setting_value ); return $menu_obj; } /** * Filters the nav_menu_options option to include this menu's auto_add preference. * * @since 4.3.0 * * @param array $nav_menu_options Nav menu options including auto_add. * @return array (Maybe) modified nav menu options. */ public function filter_nav_menu_options( $nav_menu_options ) { if ( get_current_blog_id() !== $this->_previewed_blog_id ) { return $nav_menu_options; } $menu = $this->value(); $nav_menu_options = $this->filter_nav_menu_options_value( $nav_menu_options, $this->term_id, false === $menu ? false : $menu['auto_add'] ); return $nav_menu_options; } /** * Sanitize an input. * * Note that parent::sanitize() erroneously does wp_unslash() on $value, but * we remove that in this override. * * @since 4.3.0 * * @param array $value The menu value to sanitize. * @return array|false|null Null if an input isn't valid. False if it is marked for deletion. * Otherwise the sanitized value. */ public function sanitize( $value ) { // Menu is marked for deletion. if ( false === $value ) { return $value; } // Invalid. if ( ! is_array( $value ) ) { return null; } $default = array( 'name' => '', 'description' => '', 'parent' => 0, 'auto_add' => false, ); $value = array_merge( $default, $value ); $value = wp_array_slice_assoc( $value, array_keys( $default ) ); $value['name'] = trim( esc_html( $value['name'] ) ); // This sanitization code is used in wp-admin/nav-menus.php. $value['description'] = sanitize_text_field( $value['description'] ); $value['parent'] = max( 0, (int) $value['parent'] ); $value['auto_add'] = ! empty( $value['auto_add'] ); if ( '' === $value['name'] ) { $value['name'] = _x( '(unnamed)', 'Missing menu name.' ); } /** This filter is documented in wp-includes/class-wp-customize-setting.php */ return apply_filters( "customize_sanitize_{$this->id}", $value, $this ); } /** * Storage for data to be sent back to client in customize_save_response filter. * * See {@see 'customize_save_response'}. * * @since 4.3.0 * @var array * * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() */ protected $_widget_nav_menu_updates = array(); /** * Create/update the nav_menu term for this setting. * * Any created menus will have their assigned term IDs exported to the client * via the {@see 'customize_save_response'} filter. Likewise, any errors will be exported * to the client via the customize_save_response() filter. * * To delete a menu, the client can send false as the value. * * @since 4.3.0 * @since 7.0.0 Return type updated from null|void to bool for compatibility with base class. * * @see wp_update_nav_menu_object() * * @param array|false $value { * The value to update. Note that slug cannot be updated via wp_update_nav_menu_object(). * If false, then the menu will be deleted entirely. * * @type string $name The name of the menu to save. * @type string $description The term description. Default empty string. * @type int $parent The id of the parent term. Default 0. * @type bool $auto_add Whether pages will auto_add to this menu. Default false. * } * @return bool Whether updated. */ protected function update( $value ) { if ( $this->is_updated ) { return ( 'error' !== $this->update_status ); } $this->is_updated = true; $is_placeholder = ( $this->term_id < 0 ); $is_delete = ( false === $value ); add_filter( 'customize_save_response', array( $this, 'amend_customize_save_response' ) ); $auto_add = null; if ( $is_delete ) { // If the current setting term is a placeholder, a delete request is a no-op. if ( $is_placeholder ) { $this->update_status = 'deleted'; } else { $r = wp_delete_nav_menu( $this->term_id ); if ( is_wp_error( $r ) ) { $this->update_status = 'error'; $this->update_error = $r; } else { $this->update_status = 'deleted'; $auto_add = false; } } } else { // Insert or update menu. $menu_data = wp_array_slice_assoc( $value, array( 'description', 'parent' ) ); $menu_data['menu-name'] = $value['name']; $menu_id = $is_placeholder ? 0 : $this->term_id; $r = wp_update_nav_menu_object( $menu_id, wp_slash( $menu_data ) ); $original_name = $menu_data['menu-name']; $name_conflict_suffix = 1; while ( is_wp_error( $r ) && 'menu_exists' === $r->get_error_code() ) { $name_conflict_suffix += 1; /* translators: 1: Original menu name, 2: Duplicate count. */ $menu_data['menu-name'] = sprintf( __( '%1$s (%2$d)' ), $original_name, $name_conflict_suffix ); $r = wp_update_nav_menu_object( $menu_id, wp_slash( $menu_data ) ); } if ( is_wp_error( $r ) ) { $this->update_status = 'error'; $this->update_error = $r; } else { if ( $is_placeholder ) { $this->previous_term_id = $this->term_id; $this->term_id = $r; $this->update_status = 'inserted'; } else { $this->update_status = 'updated'; } $auto_add = $value['auto_add']; } } if ( null !== $auto_add ) { $nav_menu_options = $this->filter_nav_menu_options_value( (array) get_option( 'nav_menu_options', array() ), $this->term_id, $auto_add ); update_option( 'nav_menu_options', $nav_menu_options ); } if ( 'inserted' === $this->update_status ) { // Make sure that new menus assigned to nav menu locations use their new IDs. foreach ( $this->manager->settings() as $setting ) { if ( ! preg_match( '/^nav_menu_locations\[/', $setting->id ) ) { continue; } $post_value = $setting->post_value( null ); if ( ! is_null( $post_value ) && (int) $post_value === $this->previous_term_id ) { $this->manager->set_post_value( $setting->id, $this->term_id ); $setting->save(); } } // Make sure that any nav_menu widgets referencing the placeholder nav menu get updated and sent back to client. foreach ( array_keys( $this->manager->unsanitized_post_values() ) as $setting_id ) { $nav_menu_widget_setting = $this->manager->get_setting( $setting_id ); if ( ! $nav_menu_widget_setting || ! preg_match( '/^widget_nav_menu\[/', $nav_menu_widget_setting->id ) ) { continue; } $widget_instance = $nav_menu_widget_setting->post_value(); // Note that this calls WP_Customize_Widgets::sanitize_widget_instance(). if ( empty( $widget_instance['nav_menu'] ) || (int) $widget_instance['nav_menu'] !== $this->previous_term_id ) { continue; } $widget_instance['nav_menu'] = $this->term_id; $updated_widget_instance = $this->manager->widgets->sanitize_widget_js_instance( $widget_instance ); $this->manager->set_post_value( $nav_menu_widget_setting->id, $updated_widget_instance ); $nav_menu_widget_setting->save(); $this->_widget_nav_menu_updates[ $nav_menu_widget_setting->id ] = $updated_widget_instance; } } return ( 'error' !== $this->update_status ); } /** * Updates a nav_menu_options array. * * @since 4.3.0 * * @see WP_Customize_Nav_Menu_Setting::filter_nav_menu_options() * @see WP_Customize_Nav_Menu_Setting::update() * * @param array $nav_menu_options Array as returned by get_option( 'nav_menu_options' ). * @param int $menu_id The term ID for the given menu. * @param bool $auto_add Whether to auto-add or not. * @return array (Maybe) modified nav_menu_options array. */ protected function filter_nav_menu_options_value( $nav_menu_options, $menu_id, $auto_add ) { $nav_menu_options = (array) $nav_menu_options; if ( ! isset( $nav_menu_options['auto_add'] ) ) { $nav_menu_options['auto_add'] = array(); } $i = array_search( $menu_id, $nav_menu_options['auto_add'], true ); if ( $auto_add && false === $i ) { array_push( $nav_menu_options['auto_add'], $this->term_id ); } elseif ( ! $auto_add && false !== $i ) { array_splice( $nav_menu_options['auto_add'], $i, 1 ); } return $nav_menu_options; } /** * Export data for the JS client. * * @since 4.3.0 * * @see WP_Customize_Nav_Menu_Setting::update() * * @param array $data Additional information passed back to the 'saved' event on `wp.customize`. * @return array Export data. */ public function amend_customize_save_response( $data ) { if ( ! isset( $data['nav_menu_updates'] ) ) { $data['nav_menu_updates'] = array(); } if ( ! isset( $data['widget_nav_menu_updates'] ) ) { $data['widget_nav_menu_updates'] = array(); } $data['nav_menu_updates'][] = array( 'term_id' => $this->term_id, 'previous_term_id' => $this->previous_term_id, 'error' => $this->update_error ? $this->update_error->get_error_code() : null, 'status' => $this->update_status, 'saved_value' => 'deleted' === $this->update_status ? null : $this->value(), ); $data['widget_nav_menu_updates'] = array_merge( $data['widget_nav_menu_updates'], $this->_widget_nav_menu_updates ); $this->_widget_nav_menu_updates = array(); return $data; } } class-wp-customize-nav-menu-location-control.php000064400000004373152254253720016054 0ustar00json['locationId'] = $this->location_id; } /** * Render content just like a normal select control. * * @since 4.3.0 * @since 4.9.0 Added a button to create menus. */ public function render_content() { if ( empty( $this->choices ) ) { return; } $value_hidden_class = ''; $no_value_hidden_class = ''; if ( $this->value() ) { $value_hidden_class = ' hidden'; } else { $no_value_hidden_class = ' hidden'; } ?> -?\d+)\]$/'; const POST_TYPE = 'nav_menu_item'; const TYPE = 'nav_menu_item'; /** * Setting type. * * @since 4.3.0 * @var string */ public $type = self::TYPE; /** * Default setting value. * * @since 4.3.0 * @var array * * @see wp_setup_nav_menu_item() */ public $default = array( // The $menu_item_data for wp_update_nav_menu_item(). 'object_id' => 0, 'object' => '', // Taxonomy name. 'menu_item_parent' => 0, // A.K.A. menu-item-parent-id; note that post_parent is different, and not included. 'position' => 0, // A.K.A. menu_order. 'type' => 'custom', // Note that type_label is not included here. 'title' => '', 'url' => '', 'target' => '', 'attr_title' => '', 'description' => '', 'classes' => '', 'xfn' => '', 'status' => 'publish', 'nav_menu_term_id' => 0, // This will be supplied as the $menu_id arg for wp_update_nav_menu_item(). '_invalid' => false, ); /** * Default transport. * * @since 4.3.0 * @since 4.5.0 Default changed to 'refresh' * @var string */ public $transport = 'refresh'; /** * The post ID represented by this setting instance. This is the db_id. * * A negative value represents a placeholder ID for a new menu not yet saved. * * @since 4.3.0 * @var int */ public $post_id; /** * Storage of pre-setup menu item to prevent wasted calls to wp_setup_nav_menu_item(). * * @since 4.3.0 * @var array|null */ protected $value; /** * Previous (placeholder) post ID used before creating a new menu item. * * This value will be exported to JS via the customize_save_response filter * so that JavaScript can update the settings to refer to the newly-assigned * post ID. This value is always negative to indicate it does not refer to * a real post. * * @since 4.3.0 * @var int * * @see WP_Customize_Nav_Menu_Item_Setting::update() * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() */ public $previous_post_id; /** * When previewing or updating a menu item, this stores the previous nav_menu_term_id * which ensures that we can apply the proper filters. * * @since 4.3.0 * @var int */ public $original_nav_menu_term_id; /** * Whether or not update() was called. * * @since 4.3.0 * @var bool */ protected $is_updated = false; /** * Status for calling the update method, used in customize_save_response filter. * * See {@see 'customize_save_response'}. * * When status is inserted, the placeholder post ID is stored in $previous_post_id. * When status is error, the error is stored in $update_error. * * @since 4.3.0 * @var string updated|inserted|deleted|error * * @see WP_Customize_Nav_Menu_Item_Setting::update() * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() */ public $update_status; /** * Any error object returned by wp_update_nav_menu_item() when setting is updated. * * @since 4.3.0 * @var WP_Error * * @see WP_Customize_Nav_Menu_Item_Setting::update() * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() */ public $update_error; /** * Constructor. * * Any supplied $args override class property defaults. * * @since 4.3.0 * * @throws Exception If $id is not valid for this setting type. * * @param WP_Customize_Manager $manager Customizer bootstrap instance. * @param string $id A specific ID of the setting. * Can be a theme mod or option name. * @param array $args Optional. Setting arguments. */ public function __construct( WP_Customize_Manager $manager, $id, array $args = array() ) { if ( empty( $manager->nav_menus ) ) { throw new Exception( 'Expected WP_Customize_Manager::$nav_menus to be set.' ); } if ( ! preg_match( self::ID_PATTERN, $id, $matches ) ) { throw new Exception( "Illegal widget setting ID: $id" ); } $this->post_id = (int) $matches['id']; add_action( 'wp_update_nav_menu_item', array( $this, 'flush_cached_value' ), 10, 2 ); parent::__construct( $manager, $id, $args ); // Ensure that an initially-supplied value is valid. if ( isset( $this->value ) ) { $this->populate_value(); foreach ( array_diff( array_keys( $this->default ), array_keys( $this->value ) ) as $missing ) { throw new Exception( "Supplied nav_menu_item value missing property: $missing" ); } } } /** * Clear the cached value when this nav menu item is updated. * * @since 4.3.0 * * @param int $menu_id The term ID for the menu. * @param int $menu_item_id The post ID for the menu item. */ public function flush_cached_value( $menu_id, $menu_item_id ) { unset( $menu_id ); if ( $menu_item_id === $this->post_id ) { $this->value = null; } } /** * Get the instance data for a given nav_menu_item setting. * * @since 4.3.0 * * @see wp_setup_nav_menu_item() * * @return array|false Instance data array, or false if the item is marked for deletion. */ public function value() { $type_label = null; if ( $this->is_previewed && get_current_blog_id() === $this->_previewed_blog_id ) { $undefined = new stdClass(); // Symbol. $post_value = $this->post_value( $undefined ); if ( $undefined === $post_value ) { $value = $this->_original_value; } else { $value = $post_value; } } elseif ( isset( $this->value ) ) { $value = $this->value; } else { $value = false; // Note that an ID of less than one indicates a nav_menu not yet inserted. if ( $this->post_id > 0 ) { $post = get_post( $this->post_id ); if ( $post && self::POST_TYPE === $post->post_type ) { $is_title_empty = empty( $post->post_title ); $value = (array) wp_setup_nav_menu_item( $post ); if ( isset( $value['type_label'] ) ) { $type_label = $value['type_label']; } if ( $is_title_empty ) { $value['title'] = ''; } } } if ( ! is_array( $value ) ) { $value = $this->default; } // Cache the value for future calls to avoid having to re-call wp_setup_nav_menu_item(). $this->value = $value; $this->populate_value(); $value = $this->value; } // These properties are read-only and are part of the setting for use in the Customizer UI. if ( is_array( $value ) ) { $value_obj = (object) $value; $value['type_label'] = $type_label ?? $this->get_type_label( $value_obj ); $value['original_title'] = $this->get_original_title( $value_obj ); } return $value; } /** * Prepares the value for editing on the client. * * @since 6.8.3 * * @return array|false Value prepared for the client. */ public function js_value() { $value = parent::js_value(); if ( is_array( $value ) && isset( $value['original_title'] ) ) { // Decode entities for the sake of displaying the original title as a placeholder. $value['original_title'] = html_entity_decode( $value['original_title'], ENT_QUOTES, get_bloginfo( 'charset' ) ); } return $value; } /** * Get original title. * * @since 4.7.0 * * @param object $item Nav menu item. * @return string The original title, without entity decoding. */ protected function get_original_title( $item ) { $original_title = ''; if ( 'post_type' === $item->type && ! empty( $item->object_id ) ) { $original_object = get_post( $item->object_id ); if ( $original_object ) { /** This filter is documented in wp-includes/post-template.php */ $original_title = apply_filters( 'the_title', $original_object->post_title, $original_object->ID ); if ( '' === $original_title ) { /* translators: %d: ID of a post. */ $original_title = sprintf( __( '#%d (no title)' ), $original_object->ID ); } } } elseif ( 'taxonomy' === $item->type && ! empty( $item->object_id ) ) { $original_term_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' ); if ( ! is_wp_error( $original_term_title ) ) { $original_title = $original_term_title; } } elseif ( 'post_type_archive' === $item->type ) { $original_object = get_post_type_object( $item->object ); if ( $original_object ) { $original_title = $original_object->labels->archives; } } return $original_title; } /** * Get type label. * * @since 4.7.0 * * @param object $item Nav menu item. * @return string The type label. */ protected function get_type_label( $item ) { if ( 'post_type' === $item->type ) { $object = get_post_type_object( $item->object ); if ( $object ) { $type_label = $object->labels->singular_name; } else { $type_label = $item->object; } } elseif ( 'taxonomy' === $item->type ) { $object = get_taxonomy( $item->object ); if ( $object ) { $type_label = $object->labels->singular_name; } else { $type_label = $item->object; } } elseif ( 'post_type_archive' === $item->type ) { $type_label = __( 'Post Type Archive' ); } else { $type_label = __( 'Custom Link' ); } return $type_label; } /** * Ensure that the value is fully populated with the necessary properties. * * Translates some properties added by wp_setup_nav_menu_item() and removes others. * * @since 4.3.0 * * @see WP_Customize_Nav_Menu_Item_Setting::value() */ protected function populate_value() { if ( ! is_array( $this->value ) ) { return; } if ( isset( $this->value['menu_order'] ) ) { $this->value['position'] = $this->value['menu_order']; unset( $this->value['menu_order'] ); } if ( isset( $this->value['post_status'] ) ) { $this->value['status'] = $this->value['post_status']; unset( $this->value['post_status'] ); } if ( ! isset( $this->value['nav_menu_term_id'] ) && $this->post_id > 0 ) { $menus = wp_get_post_terms( $this->post_id, WP_Customize_Nav_Menu_Setting::TAXONOMY, array( 'fields' => 'ids', ) ); if ( ! empty( $menus ) ) { $this->value['nav_menu_term_id'] = array_shift( $menus ); } else { $this->value['nav_menu_term_id'] = 0; } } foreach ( array( 'object_id', 'menu_item_parent', 'nav_menu_term_id' ) as $key ) { if ( ! is_int( $this->value[ $key ] ) ) { $this->value[ $key ] = (int) $this->value[ $key ]; } } foreach ( array( 'classes', 'xfn' ) as $key ) { if ( is_array( $this->value[ $key ] ) ) { $this->value[ $key ] = implode( ' ', $this->value[ $key ] ); } } if ( ! isset( $this->value['title'] ) ) { $this->value['title'] = ''; } if ( ! isset( $this->value['_invalid'] ) ) { $this->value['_invalid'] = false; $is_known_invalid = ( ( ( 'post_type' === $this->value['type'] || 'post_type_archive' === $this->value['type'] ) && ! post_type_exists( $this->value['object'] ) ) || ( 'taxonomy' === $this->value['type'] && ! taxonomy_exists( $this->value['object'] ) ) ); if ( $is_known_invalid ) { $this->value['_invalid'] = true; } } // Remove remaining properties available on a setup nav_menu_item post object which aren't relevant to the setting value. $irrelevant_properties = array( 'ID', 'comment_count', 'comment_status', 'db_id', 'filter', 'guid', 'ping_status', 'pinged', 'post_author', 'post_content', 'post_content_filtered', 'post_date', 'post_date_gmt', 'post_excerpt', 'post_mime_type', 'post_modified', 'post_modified_gmt', 'post_name', 'post_parent', 'post_password', 'post_title', 'post_type', 'to_ping', ); foreach ( $irrelevant_properties as $property ) { unset( $this->value[ $property ] ); } } /** * Handle previewing the setting. * * @since 4.3.0 * @since 4.4.0 Added boolean return value. * * @see WP_Customize_Manager::post_value() * * @return bool False if method short-circuited due to no-op. */ public function preview() { if ( $this->is_previewed ) { return false; } $undefined = new stdClass(); $is_placeholder = ( $this->post_id < 0 ); $is_dirty = ( $undefined !== $this->post_value( $undefined ) ); if ( ! $is_placeholder && ! $is_dirty ) { return false; } $this->is_previewed = true; $this->_original_value = $this->value(); $this->original_nav_menu_term_id = $this->_original_value['nav_menu_term_id']; $this->_previewed_blog_id = get_current_blog_id(); add_filter( 'wp_get_nav_menu_items', array( $this, 'filter_wp_get_nav_menu_items' ), 10, 3 ); $sort_callback = array( __CLASS__, 'sort_wp_get_nav_menu_items' ); if ( ! has_filter( 'wp_get_nav_menu_items', $sort_callback ) ) { add_filter( 'wp_get_nav_menu_items', array( __CLASS__, 'sort_wp_get_nav_menu_items' ), 1000, 3 ); } // @todo Add get_post_metadata filters for plugins to add their data. return true; } /** * Filters the wp_get_nav_menu_items() result to supply the previewed menu items. * * @since 4.3.0 * * @see wp_get_nav_menu_items() * * @param WP_Post[] $items An array of menu item post objects. * @param WP_Term $menu The menu object. * @param array $args An array of arguments used to retrieve menu item objects. * @return WP_Post[] Array of menu item objects. */ public function filter_wp_get_nav_menu_items( $items, $menu, $args ) { $this_item = $this->value(); $current_nav_menu_term_id = null; if ( isset( $this_item['nav_menu_term_id'] ) ) { $current_nav_menu_term_id = $this_item['nav_menu_term_id']; unset( $this_item['nav_menu_term_id'] ); } $should_filter = ( $menu->term_id === $this->original_nav_menu_term_id || $menu->term_id === $current_nav_menu_term_id ); if ( ! $should_filter ) { return $items; } // Handle deleted menu item, or menu item moved to another menu. $should_remove = ( false === $this_item || ( isset( $this_item['_invalid'] ) && true === $this_item['_invalid'] ) || ( $this->original_nav_menu_term_id === $menu->term_id && $current_nav_menu_term_id !== $this->original_nav_menu_term_id ) ); if ( $should_remove ) { $filtered_items = array(); foreach ( $items as $item ) { if ( $item->db_id !== $this->post_id ) { $filtered_items[] = $item; } } return $filtered_items; } $mutated = false; $should_update = ( is_array( $this_item ) && $current_nav_menu_term_id === $menu->term_id ); if ( $should_update ) { foreach ( $items as $item ) { if ( $item->db_id === $this->post_id ) { foreach ( get_object_vars( $this->value_as_wp_post_nav_menu_item() ) as $key => $value ) { $item->$key = $value; } $mutated = true; } } // Not found so we have to append it.. if ( ! $mutated ) { $items[] = $this->value_as_wp_post_nav_menu_item(); } } return $items; } /** * Re-apply the tail logic also applied on $items by wp_get_nav_menu_items(). * * @since 4.3.0 * * @see wp_get_nav_menu_items() * * @param WP_Post[] $items An array of menu item post objects. * @param WP_Term $menu The menu object. * @param array $args An array of arguments used to retrieve menu item objects. * @return WP_Post[] Array of menu item objects. */ public static function sort_wp_get_nav_menu_items( $items, $menu, $args ) { // @todo We should probably re-apply some constraints imposed by $args. unset( $args['include'] ); // Remove invalid items only in front end. if ( ! is_admin() ) { $items = array_filter( $items, '_is_valid_nav_menu_item' ); } if ( ARRAY_A === $args['output'] ) { $items = wp_list_sort( $items, array( $args['output_key'] => 'ASC', ) ); $i = 1; foreach ( $items as $k => $item ) { $items[ $k ]->{$args['output_key']} = $i++; } } return $items; } /** * Get the value emulated into a WP_Post and set up as a nav_menu_item. * * @since 4.3.0 * * @return WP_Post With wp_setup_nav_menu_item() applied. */ public function value_as_wp_post_nav_menu_item() { $item = (object) $this->value(); unset( $item->nav_menu_term_id ); $item->post_status = $item->status; unset( $item->status ); $item->post_type = 'nav_menu_item'; $item->menu_order = $item->position; unset( $item->position ); if ( empty( $item->title ) && ! empty( $item->original_title ) ) { $item->title = $item->original_title; // This is NOT entity-decoded. It comes from self::get_original_title(). } if ( $item->title ) { $item->post_title = $item->title; } // 'classes' should be an array, as in wp_setup_nav_menu_item(). if ( isset( $item->classes ) && is_scalar( $item->classes ) ) { $item->classes = explode( ' ', $item->classes ); } $item->ID = $this->post_id; $item->db_id = $this->post_id; $post = new WP_Post( (object) $item ); if ( empty( $post->post_author ) ) { $post->post_author = get_current_user_id(); } if ( ! isset( $post->type_label ) ) { $post->type_label = $this->get_type_label( $post ); } // Ensure nav menu item URL is set according to linked object. if ( 'post_type' === $post->type && ! empty( $post->object_id ) ) { $post->url = get_permalink( $post->object_id ); } elseif ( 'taxonomy' === $post->type && ! empty( $post->object ) && ! empty( $post->object_id ) ) { $post->url = get_term_link( (int) $post->object_id, $post->object ); } elseif ( 'post_type_archive' === $post->type && ! empty( $post->object ) ) { $post->url = get_post_type_archive_link( $post->object ); } if ( is_wp_error( $post->url ) ) { $post->url = ''; } /** This filter is documented in wp-includes/nav-menu.php */ $post->attr_title = apply_filters( 'nav_menu_attr_title', $post->attr_title ); /** This filter is documented in wp-includes/nav-menu.php */ $post->description = apply_filters( 'nav_menu_description', wp_trim_words( $post->description, 200 ) ); /** This filter is documented in wp-includes/nav-menu.php */ $post = apply_filters( 'wp_setup_nav_menu_item', $post ); return $post; } /** * Sanitize an input. * * Note that parent::sanitize() erroneously does wp_unslash() on $value, but * we remove that in this override. * * @since 4.3.0 * @since 5.9.0 Renamed `$menu_item_value` to `$value` for PHP 8 named parameter support. * * @param array|false $value The menu item value to sanitize. * @return array|false|null|WP_Error Null or WP_Error if an input isn't valid. False if it is marked for deletion. * Otherwise the sanitized value. */ public function sanitize( $value ) { // Restores the more descriptive, specific name for use within this method. $menu_item_value = $value; // Menu is marked for deletion. if ( false === $menu_item_value ) { return $menu_item_value; } // Invalid. if ( ! is_array( $menu_item_value ) ) { return null; } $default = array( 'object_id' => 0, 'object' => '', 'menu_item_parent' => 0, 'position' => 0, 'type' => 'custom', 'title' => '', 'url' => '', 'target' => '', 'attr_title' => '', 'description' => '', 'classes' => '', 'xfn' => '', 'status' => 'publish', 'original_title' => '', 'nav_menu_term_id' => 0, '_invalid' => false, ); $menu_item_value = array_merge( $default, $menu_item_value ); $menu_item_value = wp_array_slice_assoc( $menu_item_value, array_keys( $default ) ); $menu_item_value['position'] = (int) $menu_item_value['position']; foreach ( array( 'object_id', 'menu_item_parent', 'nav_menu_term_id' ) as $key ) { // Note we need to allow negative-integer IDs for previewed objects not inserted yet. $menu_item_value[ $key ] = (int) $menu_item_value[ $key ]; } foreach ( array( 'type', 'object', 'target' ) as $key ) { $menu_item_value[ $key ] = sanitize_key( $menu_item_value[ $key ] ); } foreach ( array( 'xfn', 'classes' ) as $key ) { $value = $menu_item_value[ $key ]; if ( ! is_array( $value ) ) { $value = explode( ' ', $value ); } $menu_item_value[ $key ] = implode( ' ', array_map( 'sanitize_html_class', $value ) ); } // Apply the same filters as when calling wp_insert_post(). /** This filter is documented in wp-includes/post.php */ $menu_item_value['title'] = wp_unslash( apply_filters( 'title_save_pre', wp_slash( $menu_item_value['title'] ) ) ); /** This filter is documented in wp-includes/post.php */ $menu_item_value['attr_title'] = wp_unslash( apply_filters( 'excerpt_save_pre', wp_slash( $menu_item_value['attr_title'] ) ) ); /** This filter is documented in wp-includes/post.php */ $menu_item_value['description'] = wp_unslash( apply_filters( 'content_save_pre', wp_slash( $menu_item_value['description'] ) ) ); if ( '' !== $menu_item_value['url'] ) { $menu_item_value['url'] = sanitize_url( $menu_item_value['url'] ); if ( '' === $menu_item_value['url'] ) { return new WP_Error( 'invalid_url', __( 'Invalid URL.' ) ); // Fail sanitization if URL is invalid. } } if ( 'publish' !== $menu_item_value['status'] ) { $menu_item_value['status'] = 'draft'; } $menu_item_value['_invalid'] = (bool) $menu_item_value['_invalid']; /** This filter is documented in wp-includes/class-wp-customize-setting.php */ return apply_filters( "customize_sanitize_{$this->id}", $menu_item_value, $this ); } /** * Creates/updates the nav_menu_item post for this setting. * * Any created menu items will have their assigned post IDs exported to the client * via the {@see 'customize_save_response'} filter. Likewise, any errors will be * exported to the client via the customize_save_response() filter. * * To delete a menu, the client can send false as the value. * * @since 4.3.0 * @since 7.0.0 Return type updated from null|void to bool for compatibility with base class. * * @see wp_update_nav_menu_item() * * @param array|false $value The menu item array to update. If false, then the menu item will be deleted * entirely. See WP_Customize_Nav_Menu_Item_Setting::$default for what the value * should consist of. * @return bool Whether updated. */ protected function update( $value ) { if ( $this->is_updated ) { return ( 'error' !== $this->update_status ); } $this->is_updated = true; $is_placeholder = ( $this->post_id < 0 ); $is_delete = ( false === $value ); // Update the cached value. $this->value = $value; add_filter( 'customize_save_response', array( $this, 'amend_customize_save_response' ) ); if ( $is_delete ) { // If the current setting post is a placeholder, a delete request is a no-op. if ( $is_placeholder ) { $this->update_status = 'deleted'; } else { $r = wp_delete_post( $this->post_id, true ); if ( false === $r ) { $this->update_error = new WP_Error( 'delete_failure' ); $this->update_status = 'error'; } else { $this->update_status = 'deleted'; } // @todo send back the IDs for all associated nav menu items deleted, so these settings (and controls) can be removed from Customizer? } } else { // Handle saving menu items for menus that are being newly-created. if ( $value['nav_menu_term_id'] < 0 ) { $nav_menu_setting_id = sprintf( 'nav_menu[%s]', $value['nav_menu_term_id'] ); $nav_menu_setting = $this->manager->get_setting( $nav_menu_setting_id ); if ( ! $nav_menu_setting || ! ( $nav_menu_setting instanceof WP_Customize_Nav_Menu_Setting ) ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'unexpected_nav_menu_setting' ); return false; } if ( false === $nav_menu_setting->save() ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'nav_menu_setting_failure' ); return false; } if ( (int) $value['nav_menu_term_id'] !== $nav_menu_setting->previous_term_id ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'unexpected_previous_term_id' ); return false; } $value['nav_menu_term_id'] = $nav_menu_setting->term_id; } // Handle saving a nav menu item that is a child of a nav menu item being newly-created. if ( $value['menu_item_parent'] < 0 ) { $parent_nav_menu_item_setting_id = sprintf( 'nav_menu_item[%s]', $value['menu_item_parent'] ); $parent_nav_menu_item_setting = $this->manager->get_setting( $parent_nav_menu_item_setting_id ); if ( ! $parent_nav_menu_item_setting || ! ( $parent_nav_menu_item_setting instanceof WP_Customize_Nav_Menu_Item_Setting ) ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'unexpected_nav_menu_item_setting' ); return false; } if ( false === $parent_nav_menu_item_setting->save() ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'nav_menu_item_setting_failure' ); return false; } if ( (int) $value['menu_item_parent'] !== $parent_nav_menu_item_setting->previous_post_id ) { $this->update_status = 'error'; $this->update_error = new WP_Error( 'unexpected_previous_post_id' ); return false; } $value['menu_item_parent'] = $parent_nav_menu_item_setting->post_id; } // Insert or update menu. $menu_item_data = array( 'menu-item-object-id' => $value['object_id'], 'menu-item-object' => $value['object'], 'menu-item-parent-id' => $value['menu_item_parent'], 'menu-item-position' => $value['position'], 'menu-item-type' => $value['type'], 'menu-item-title' => $value['title'], 'menu-item-url' => $value['url'], 'menu-item-description' => $value['description'], 'menu-item-attr-title' => $value['attr_title'], 'menu-item-target' => $value['target'], 'menu-item-classes' => $value['classes'], 'menu-item-xfn' => $value['xfn'], 'menu-item-status' => $value['status'], ); $r = wp_update_nav_menu_item( $value['nav_menu_term_id'], $is_placeholder ? 0 : $this->post_id, wp_slash( $menu_item_data ) ); if ( is_wp_error( $r ) ) { $this->update_status = 'error'; $this->update_error = $r; } else { if ( $is_placeholder ) { $this->previous_post_id = $this->post_id; $this->post_id = $r; $this->update_status = 'inserted'; } else { $this->update_status = 'updated'; } } } return ( 'error' !== $this->update_status ); } /** * Export data for the JS client. * * @since 4.3.0 * * @see WP_Customize_Nav_Menu_Item_Setting::update() * * @param array $data Additional information passed back to the 'saved' event on `wp.customize`. * @return array Save response data. */ public function amend_customize_save_response( $data ) { if ( ! isset( $data['nav_menu_item_updates'] ) ) { $data['nav_menu_item_updates'] = array(); } $data['nav_menu_item_updates'][] = array( 'post_id' => $this->post_id, 'previous_post_id' => $this->previous_post_id, 'error' => $this->update_error ? $this->update_error->get_error_code() : null, 'status' => $this->update_status, ); return $data; } } class-wp-customize-nav-menus-panel.php000064400000006355152254253720014052 0ustar00render_screen_options( array( 'wrap' => false ) ); } /** * Returns the advanced options for the nav menus page. * * Link title attribute added as it's a relatively advanced concept for new users. * * @since 4.3.0 * @deprecated 4.5.0 Deprecated in favor of wp_nav_menu_manage_columns(). */ public function wp_nav_menu_manage_columns() { _deprecated_function( __METHOD__, '4.5.0', 'wp_nav_menu_manage_columns' ); require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; return wp_nav_menu_manage_columns(); } /** * An Underscore (JS) template for this panel's content (but not its container). * * Class variables for this panel class are available in the `data` JS object; * export custom variables by overriding WP_Customize_Panel::json(). * * @since 4.3.0 * * @see WP_Customize_Panel::print_template() */ protected function content_template() { ?>
    • {{ data.title }}' ); ?>
      <# if ( data.description ) { #>
      {{{ data.description }}}
      <# } #>
      render_screen_options(); ?>
    • manager = $manager; require_once ABSPATH . WPINC . '/customize/class-wp-customize-partial.php'; add_action( 'customize_preview_init', array( $this, 'init_preview' ) ); } /** * Retrieves the registered partials. * * @since 4.5.0 * * @return array Partials. */ public function partials() { return $this->partials; } /** * Adds a partial. * * @since 4.5.0 * * @see WP_Customize_Partial::__construct() * * @param WP_Customize_Partial|string $id Customize Partial object, or Partial ID. * @param array $args Optional. Array of properties for the new Partials object. * See WP_Customize_Partial::__construct() for information * on accepted arguments. Default empty array. * @return WP_Customize_Partial The instance of the partial that was added. */ public function add_partial( $id, $args = array() ) { if ( $id instanceof WP_Customize_Partial ) { $partial = $id; } else { $class = 'WP_Customize_Partial'; /** This filter is documented in wp-includes/customize/class-wp-customize-selective-refresh.php */ $args = apply_filters( 'customize_dynamic_partial_args', $args, $id ); /** This filter is documented in wp-includes/customize/class-wp-customize-selective-refresh.php */ $class = apply_filters( 'customize_dynamic_partial_class', $class, $id, $args ); $partial = new $class( $this, $id, $args ); } $this->partials[ $partial->id ] = $partial; return $partial; } /** * Retrieves a partial. * * @since 4.5.0 * * @param string $id Customize Partial ID. * @return WP_Customize_Partial|null The partial, if set. Otherwise null. */ public function get_partial( $id ) { if ( isset( $this->partials[ $id ] ) ) { return $this->partials[ $id ]; } else { return null; } } /** * Removes a partial. * * @since 4.5.0 * * @param string $id Customize Partial ID. */ public function remove_partial( $id ) { unset( $this->partials[ $id ] ); } /** * Initializes the Customizer preview. * * @since 4.5.0 */ public function init_preview() { add_action( 'template_redirect', array( $this, 'handle_render_partials_request' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) ); } /** * Enqueues preview scripts. * * @since 4.5.0 */ public function enqueue_preview_scripts() { wp_enqueue_script( 'customize-selective-refresh' ); add_action( 'wp_footer', array( $this, 'export_preview_data' ), 1000 ); } /** * Exports data in preview after it has finished rendering so that partials can be added at runtime. * * @since 4.5.0 */ public function export_preview_data() { $partials = array(); foreach ( $this->partials() as $partial ) { if ( $partial->check_capabilities() ) { $partials[ $partial->id ] = $partial->json(); } } $switched_locale = switch_to_user_locale( get_current_user_id() ); $l10n = array( 'shiftClickToEdit' => __( 'Shift-click to edit this element.' ), 'clickEditMenu' => __( 'Click to edit this menu.' ), 'clickEditWidget' => __( 'Click to edit this widget.' ), 'clickEditTitle' => __( 'Click to edit the site title.' ), 'clickEditMisc' => __( 'Click to edit this element.' ), /* translators: %s: document.write() */ 'badDocumentWrite' => sprintf( __( '%s is forbidden' ), 'document.write()' ), ); if ( $switched_locale ) { restore_previous_locale(); } $exports = array( 'partials' => $partials, 'renderQueryVar' => self::RENDER_QUERY_VAR, 'l10n' => $l10n, ); // Export data to JS. wp_print_inline_script_tag( sprintf( 'var _customizePartialRefreshExports = %s;', wp_json_encode( $exports, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) . "\n//# sourceURL=" . rawurlencode( __METHOD__ ) ); } /** * Registers dynamically-created partials. * * @since 4.5.0 * * @see WP_Customize_Manager::add_dynamic_settings() * * @param string[] $partial_ids Array of the partial IDs to add. * @return WP_Customize_Partial[] Array of added WP_Customize_Partial instances. */ public function add_dynamic_partials( $partial_ids ) { $new_partials = array(); foreach ( $partial_ids as $partial_id ) { // Skip partials already created. $partial = $this->get_partial( $partial_id ); if ( $partial ) { continue; } $partial_args = false; $partial_class = 'WP_Customize_Partial'; /** * Filters a dynamic partial's constructor arguments. * * For a dynamic partial to be registered, this filter must be employed * to override the default false value with an array of args to pass to * the WP_Customize_Partial constructor. * * @since 4.5.0 * * @param false|array $partial_args The arguments to the WP_Customize_Partial constructor. * @param string $partial_id ID for dynamic partial. */ $partial_args = apply_filters( 'customize_dynamic_partial_args', $partial_args, $partial_id ); if ( false === $partial_args ) { continue; } /** * Filters the class used to construct partials. * * Allow non-statically created partials to be constructed with custom WP_Customize_Partial subclass. * * @since 4.5.0 * * @param string $partial_class WP_Customize_Partial or a subclass. * @param string $partial_id ID for dynamic partial. * @param array $partial_args The arguments to the WP_Customize_Partial constructor. */ $partial_class = apply_filters( 'customize_dynamic_partial_class', $partial_class, $partial_id, $partial_args ); $partial = new $partial_class( $this, $partial_id, $partial_args ); $this->add_partial( $partial ); $new_partials[] = $partial; } return $new_partials; } /** * Checks whether the request is for rendering partials. * * Note that this will not consider whether the request is authorized or valid, * just that essentially the route is a match. * * @since 4.5.0 * * @return bool Whether the request is for rendering partials. */ public function is_render_partials_request() { return ! empty( $_POST[ self::RENDER_QUERY_VAR ] ); } /** * Handles PHP errors triggered during rendering the partials. * * These errors will be relayed back to the client in the Ajax response. * * @since 4.5.0 * * @param int $errno Error number. * @param string $errstr Error string. * @param string $errfile Error file. * @param int $errline Error line. * @return true Always true. */ public function handle_error( $errno, $errstr, $errfile = null, $errline = null ) { $this->triggered_errors[] = array( 'partial' => $this->current_partial_id, 'error_number' => $errno, 'error_string' => $errstr, 'error_file' => $errfile, 'error_line' => $errline, ); return true; } /** * Handles the Ajax request to return the rendered partials for the requested placements. * * @since 4.5.0 */ public function handle_render_partials_request() { if ( ! $this->is_render_partials_request() ) { return; } /* * Note that is_customize_preview() returning true will entail that the * user passed the 'customize' capability check and the nonce check, since * WP_Customize_Manager::setup_theme() is where the previewing flag is set. */ if ( ! is_customize_preview() ) { wp_send_json_error( 'expected_customize_preview', 403 ); } elseif ( ! isset( $_POST['partials'] ) ) { wp_send_json_error( 'missing_partials', 400 ); } // Ensure that doing selective refresh on 404 template doesn't result in fallback rendering behavior (full refreshes). status_header( 200 ); $partials = json_decode( wp_unslash( $_POST['partials'] ), true ); if ( ! is_array( $partials ) ) { wp_send_json_error( 'malformed_partials' ); } $this->add_dynamic_partials( array_keys( $partials ) ); /** * Fires immediately before partials are rendered. * * Plugins may do things like call wp_enqueue_scripts() and gather a list of the scripts * and styles which may get enqueued in the response. * * @since 4.5.0 * * @param WP_Customize_Selective_Refresh $refresh Selective refresh component. * @param array $partials Placements' context data for the partials rendered in the request. * The array is keyed by partial ID, with each item being an array of * the placements' context data. */ do_action( 'customize_render_partials_before', $this, $partials ); set_error_handler( array( $this, 'handle_error' ), error_reporting() ); $contents = array(); foreach ( $partials as $partial_id => $container_contexts ) { $this->current_partial_id = $partial_id; if ( ! is_array( $container_contexts ) ) { wp_send_json_error( 'malformed_container_contexts' ); } $partial = $this->get_partial( $partial_id ); if ( ! $partial || ! $partial->check_capabilities() ) { $contents[ $partial_id ] = null; continue; } $contents[ $partial_id ] = array(); // @todo The array should include not only the contents, but also whether the container is included? if ( empty( $container_contexts ) ) { // Since there are no container contexts, render just once. $contents[ $partial_id ][] = $partial->render( null ); } else { foreach ( $container_contexts as $container_context ) { $contents[ $partial_id ][] = $partial->render( $container_context ); } } } $this->current_partial_id = null; restore_error_handler(); /** * Fires immediately after partials are rendered. * * Plugins may do things like call wp_footer() to scrape scripts output and return them * via the {@see 'customize_render_partials_response'} filter. * * @since 4.5.0 * * @param WP_Customize_Selective_Refresh $refresh Selective refresh component. * @param array $partials Placements' context data for the partials rendered in the request. * The array is keyed by partial ID, with each item being an array of * the placements' context data. */ do_action( 'customize_render_partials_after', $this, $partials ); $response = array( 'contents' => $contents, ); if ( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) { $response['errors'] = $this->triggered_errors; } $setting_validities = $this->manager->validate_setting_values( $this->manager->unsanitized_post_values() ); $exported_setting_validities = array_map( array( $this->manager, 'prepare_setting_validity_for_js' ), $setting_validities ); $response['setting_validities'] = $exported_setting_validities; /** * Filters the response from rendering the partials. * * Plugins may use this filter to inject `$scripts` and `$styles`, which are dependencies * for the partials being rendered. The response data will be available to the client via * the `render-partials-response` JS event, so the client can then inject the scripts and * styles into the DOM if they have not already been enqueued there. * * If plugins do this, they'll need to take care for any scripts that do `document.write()` * and make sure that these are not injected, or else to override the function to no-op, * or else the page will be destroyed. * * Plugins should be aware that `$scripts` and `$styles` may eventually be included by * default in the response. * * @since 4.5.0 * * @param array $response { * Response. * * @type array $contents Associative array mapping a partial ID its corresponding array of contents * for the containers requested. * @type array $errors List of errors triggered during rendering of partials, if `WP_DEBUG_DISPLAY` * is enabled. * } * @param WP_Customize_Selective_Refresh $refresh Selective refresh component. * @param array $partials Placements' context data for the partials rendered in the request. * The array is keyed by partial ID, with each item being an array of * the placements' context data. */ $response = apply_filters( 'customize_render_partials_response', $response, $this, $partials ); wp_send_json_success( $response ); } } class-wp-customize-new-menu-control.php000064400000003256152254253720014252 0ustar00 <# if ( data.description ) { #>

      {{ data.description }}

      <# } #> $key = $args[ $key ]; } } $this->component = $component; $this->id = $id; $this->id_data['keys'] = preg_split( '/\[/', str_replace( ']', '', $this->id ) ); $this->id_data['base'] = array_shift( $this->id_data['keys'] ); if ( empty( $this->render_callback ) ) { $this->render_callback = array( $this, 'render_callback' ); } // Process settings. if ( ! isset( $this->settings ) ) { $this->settings = array( $id ); } elseif ( is_string( $this->settings ) ) { $this->settings = array( $this->settings ); } if ( empty( $this->primary_setting ) ) { $this->primary_setting = current( $this->settings ); } } /** * Retrieves parsed ID data for multidimensional setting. * * @since 4.5.0 * * @return array { * ID data for multidimensional partial. * * @type string $base ID base. * @type array $keys Keys for multidimensional array. * } */ final public function id_data() { return $this->id_data; } /** * Renders the template partial involving the associated settings. * * @since 4.5.0 * * @param array $container_context Optional. Array of context data associated with the target container (placement). * Default empty array. * @return string|array|false The rendered partial as a string, raw data array (for client-side JS template), * or false if no render applied. */ final public function render( $container_context = array() ) { $partial = $this; $rendered = false; if ( ! empty( $this->render_callback ) ) { ob_start(); $return_render = call_user_func( $this->render_callback, $this, $container_context ); $ob_render = ob_get_clean(); if ( null !== $return_render && '' !== $ob_render ) { _doing_it_wrong( __FUNCTION__, __( 'Partial render must echo the content or return the content string (or array), but not both.' ), '4.5.0' ); } /* * Note that the string return takes precedence because the $ob_render may just\ * include PHP warnings or notices. */ $rendered = $return_render ?? $ob_render; } /** * Filters partial rendering. * * @since 4.5.0 * * @param string|array|false $rendered The partial value. Default false. * @param WP_Customize_Partial $partial WP_Customize_Setting instance. * @param array $container_context Optional array of context data associated with * the target container. */ $rendered = apply_filters( 'customize_partial_render', $rendered, $partial, $container_context ); /** * Filters partial rendering for a specific partial. * * The dynamic portion of the hook name, `$partial->ID` refers to the partial ID. * * @since 4.5.0 * * @param string|array|false $rendered The partial value. Default false. * @param WP_Customize_Partial $partial WP_Customize_Setting instance. * @param array $container_context Optional array of context data associated with * the target container. */ $rendered = apply_filters( "customize_partial_render_{$partial->id}", $rendered, $partial, $container_context ); return $rendered; } /** * Default callback used when invoking WP_Customize_Control::render(). * * Note that this method may echo the partial *or* return the partial as * a string or array, but not both. Output buffering is performed when this * is called. Subclasses can override this with their specific logic, or they * may provide an 'render_callback' argument to the constructor. * * This method may return an HTML string for straight DOM injection, or it * may return an array for supporting Partial JS subclasses to render by * applying to client-side templating. * * @since 4.5.0 * * @param WP_Customize_Partial $partial Partial. * @param array $context Context. * @return string|array|false */ public function render_callback( WP_Customize_Partial $partial, $context = array() ) { unset( $partial, $context ); return false; } /** * Retrieves the data to export to the client via JSON. * * @since 4.5.0 * * @return array Array of parameters passed to the JavaScript. */ public function json() { $exports = array( 'settings' => $this->settings, 'primarySetting' => $this->primary_setting, 'selector' => $this->selector, 'type' => $this->type, 'fallbackRefresh' => $this->fallback_refresh, 'containerInclusive' => $this->container_inclusive, ); return $exports; } /** * Checks if the user can refresh this partial. * * Returns false if the user cannot manipulate one of the associated settings, * or if one of the associated settings does not exist. * * @since 4.5.0 * * @return bool False if user can't edit one of the related settings, * or if one of the associated settings does not exist. */ final public function check_capabilities() { if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) { return false; } foreach ( $this->settings as $setting_id ) { $setting = $this->component->manager->get_setting( $setting_id ); if ( ! $setting || ! $setting->check_capabilities() ) { return false; } } return true; } } class-wp-widget-form-customize-control.php000064400000005126152254253720014741 0ustar00json[ $key ] = $this->$key; } // Get the widget_control and widget_content. require_once ABSPATH . 'wp-admin/includes/widgets.php'; $widget = $wp_registered_widgets[ $this->widget_id ]; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } $args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], ); $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0], ) ); $widget_control_parts = $this->manager->widgets->get_widget_control_parts( $args ); $this->json['widget_control'] = $widget_control_parts['control']; $this->json['widget_content'] = $widget_control_parts['content']; } /** * Override render_content to be no-op since content is exported via to_json for deferred embedding. * * @since 3.9.0 */ public function render_content() {} /** * Whether the current widget is rendered on the page. * * @since 4.0.0 * * @return bool Whether the widget is rendered. */ public function active_callback() { return $this->manager->widgets->is_widget_rendered( $this->widget_id ); } } class-wp-customize-background-position-control.php000064400000005730152254253720016477 0ustar00 array( 'label' => __( 'Top Left' ), 'icon' => 'dashicons dashicons-arrow-left-alt', ), 'center top' => array( 'label' => __( 'Top' ), 'icon' => 'dashicons dashicons-arrow-up-alt', ), 'right top' => array( 'label' => __( 'Top Right' ), 'icon' => 'dashicons dashicons-arrow-right-alt', ), ), array( 'left center' => array( 'label' => __( 'Left' ), 'icon' => 'dashicons dashicons-arrow-left-alt', ), 'center center' => array( 'label' => __( 'Center' ), 'icon' => 'background-position-center-icon', ), 'right center' => array( 'label' => __( 'Right' ), 'icon' => 'dashicons dashicons-arrow-right-alt', ), ), array( 'left bottom' => array( 'label' => __( 'Bottom Left' ), 'icon' => 'dashicons dashicons-arrow-left-alt', ), 'center bottom' => array( 'label' => __( 'Bottom' ), 'icon' => 'dashicons dashicons-arrow-down-alt', ), 'right bottom' => array( 'label' => __( 'Bottom Right' ), 'icon' => 'dashicons dashicons-arrow-right-alt', ), ), ); ?> <# if ( data.label ) { #> {{{ data.label }}} <# } #> <# if ( data.description ) { #> {{{ data.description }}} <# } #>
      $input ) : ?>
      action; $exported['filter_type'] = $this->filter_type; return $exported; } /** * Renders a themes section as a JS template. * * The template is only rendered by PHP once, so all actions are prepared at once on the server side. * * @since 4.9.0 */ protected function render_template() { ?>
    • filter_bar_content_template(); ?>
      filter_drawer_content_template(); ?>

      %s', __( 'Search WordPress.org themes' ) ) ); ?>

    • <# if ( 'wporg' === data.action ) { #>
      <# } else { #>
      <# } #>
      <# if ( 'wporg' === data.action ) { #> <# } #>
      0' ); ?>
      <# if ( 'wporg' === data.action ) { #>
      $features ) : ?>
      $feature_name ) : ?>
      <# } #> setting->post_id; return $exported; } } class-wp-customize-new-menu-section.php000064400000003235152254253720014233 0ustar00
      • setting->term_id; return $exported; } } class-wp-customize-header-image-setting.php000064400000003456152254253720015026 0ustar00manager->get_setting( 'header_image' )->post_value(); } if ( is_array( $value ) && isset( $value['choice'] ) ) { $custom_image_header->set_header_image( $value['choice'] ); } else { $custom_image_header->set_header_image( $value ); } return true; } }