消える飛行機雲 僕たちは見送った
眩しくて逃げた いつだって弱くて
あの日から変わらず
いつまでも変わらずに
いられなかったこと
悔しくて指を離す
あの鳥は まだ うまく飛べないけど
いつかは 風を切って知る
届かない場所が まだ遠くにある
願いだけ秘めて 見つめてる
子供たちは 夏の線路 歩く
吹く風に素足をさらして
遠くには幼かった日びを
両手には 飛び立つ希望を
消える飛行機雲
追いかけて 追いかけて
この丘を越えた
あの日から変わらず
いつまでも 真っ直ぐに
僕たちはあるように
わたつみのような
強さを守れるよ きっと
���� 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-widget-meta.php 0000644 00000007773 15225442107 0011233 0 ustar 00 'widget_meta',
'description' => __( 'Login, RSS, & WordPress.org links.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'meta', __( 'Meta' ), $widget_ops );
}
/**
* Outputs the content for the current Meta widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Meta widget instance.
*/
public function widget( $args, $instance ) {
$default_title = __( 'Meta' );
$title = ! empty( $instance['title'] ) ? $instance['title'] : $default_title;
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/** This filter is documented in wp-includes/widgets/class-wp-nav-menu-widget.php */
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : $default_title;
echo '';
}
?>
%2$s ',
esc_url( __( 'https://wordpress.org/' ) ),
__( 'WordPress.org' )
),
$instance
);
wp_meta();
?>
';
}
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Meta widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
/**
* Outputs the settings form for the Meta widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
?>
'widget_search',
'description' => __( 'A search form for your site.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'search', _x( 'Search', 'Search widget' ), $widget_ops );
}
/**
* Outputs the content for the current Search widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Search widget instance.
*/
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
// Use active theme search form if it exists.
get_search_form();
echo $args['after_widget'];
}
/**
* Outputs the settings form for the Search widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
$title = $instance['title'];
?>
'' ) );
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
}
class-wp-widget-media-gallery.php 0000644 00000016574 15225442107 0013020 0 ustar 00 __( 'Displays an image gallery.' ),
'mime_type' => 'image',
)
);
$this->l10n = array_merge(
$this->l10n,
array(
'no_media_selected' => __( 'No images selected' ),
'add_media' => _x( 'Add Images', 'label for button in the gallery widget; should not be longer than ~13 characters long' ),
'replace_media' => '',
'edit_media' => _x( 'Edit Gallery', 'label for button in the gallery widget; should not be longer than ~13 characters long' ),
)
);
}
/**
* Get schema for properties of a widget instance (item).
*
* @since 4.9.0
*
* @see WP_REST_Controller::get_item_schema()
* @see WP_REST_Controller::get_additional_fields()
* @link https://core.trac.wordpress.org/ticket/35574
*
* @return array Schema for properties.
*/
public function get_instance_schema() {
$schema = array(
'title' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'description' => __( 'Title for the widget' ),
'should_preview_update' => false,
),
'ids' => array(
'type' => 'array',
'items' => array(
'type' => 'integer',
),
'default' => array(),
'sanitize_callback' => 'wp_parse_id_list',
),
'columns' => array(
'type' => 'integer',
'default' => 3,
'minimum' => 1,
'maximum' => 9,
),
'size' => array(
'type' => 'string',
'enum' => array_merge( get_intermediate_image_sizes(), array( 'full', 'custom' ) ),
'default' => 'thumbnail',
),
'link_type' => array(
'type' => 'string',
'enum' => array( 'post', 'file', 'none' ),
'default' => 'post',
'media_prop' => 'link',
'should_preview_update' => false,
),
'orderby_random' => array(
'type' => 'boolean',
'default' => false,
'media_prop' => '_orderbyRandom',
'should_preview_update' => false,
),
);
/** This filter is documented in wp-includes/widgets/class-wp-widget-media.php */
$schema = apply_filters( "widget_{$this->id_base}_instance_schema", $schema, $this );
return $schema;
}
/**
* Render the media on the frontend.
*
* @since 4.9.0
*
* @param array $instance Widget instance props.
*/
public function render_media( $instance ) {
$instance = array_merge( wp_list_pluck( $this->get_instance_schema(), 'default' ), $instance );
$shortcode_atts = array_merge(
$instance,
array(
'link' => $instance['link_type'],
)
);
// @codeCoverageIgnoreStart
if ( $instance['orderby_random'] ) {
$shortcode_atts['orderby'] = 'rand';
}
// @codeCoverageIgnoreEnd
echo gallery_shortcode( $shortcode_atts );
}
/**
* Loads the required media files for the media manager and scripts for media widgets.
*
* @since 4.9.0
*/
public function enqueue_admin_scripts() {
parent::enqueue_admin_scripts();
$handle = 'media-gallery-widget';
wp_enqueue_script( $handle );
$exported_schema = array();
foreach ( $this->get_instance_schema() as $field => $field_schema ) {
$exported_schema[ $field ] = wp_array_slice_assoc( $field_schema, array( 'type', 'default', 'enum', 'minimum', 'format', 'media_prop', 'should_preview_update', 'items' ) );
}
wp_add_inline_script(
$handle,
sprintf(
'wp.mediaWidgets.modelConstructors[ %s ].prototype.schema = %s;',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $exported_schema, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
wp_add_inline_script(
$handle,
sprintf(
'
wp.mediaWidgets.controlConstructors[ %1$s ].prototype.mime_type = %2$s;
_.extend( wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n, %3$s );
',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->widget_options['mime_type'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
}
/**
* Render form template scripts.
*
* @since 4.9.0
*/
public function render_control_template_scripts() {
parent::render_control_template_scripts();
?>
'',
'content' => '',
);
/**
* Sets up a new Custom HTML widget instance.
*
* @since 4.8.1
*/
public function __construct() {
$widget_ops = array(
'classname' => 'widget_custom_html',
'description' => __( 'Arbitrary HTML code.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
$control_ops = array(
'width' => 400,
'height' => 350,
);
parent::__construct( 'custom_html', __( 'Custom HTML' ), $widget_ops, $control_ops );
}
/**
* Add hooks for enqueueing assets when registering all widget instances of this widget class.
*
* @since 4.9.0
*
* @param int $number Optional. The unique order number of this widget instance
* compared to other instances of the same class. Default -1.
*/
public function _register_one( $number = -1 ) {
parent::_register_one( $number );
if ( $this->registered ) {
return;
}
$this->registered = true;
/*
* Note that the widgets component in the customizer will also do
* the 'admin_print_scripts-widgets.php' action in WP_Customize_Widgets::print_scripts().
*/
add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
/*
* Note that the widgets component in the customizer will also do
* the 'admin_footer-widgets.php' action in WP_Customize_Widgets::print_footer_scripts().
*/
add_action( 'admin_footer-widgets.php', array( 'WP_Widget_Custom_HTML', 'render_control_template_scripts' ) );
// Note this action is used to ensure the help text is added to the end.
add_action( 'admin_head-widgets.php', array( 'WP_Widget_Custom_HTML', 'add_help_text' ) );
}
/**
* Filters gallery shortcode attributes.
*
* Prevents all of a site's attachments from being shown in a gallery displayed on a
* non-singular template where a $post context is not available.
*
* @since 4.9.0
*
* @param array $attrs Attributes.
* @return array Attributes.
*/
public function _filter_gallery_shortcode_attrs( $attrs ) {
if ( ! is_singular() && empty( $attrs['id'] ) && empty( $attrs['include'] ) ) {
$attrs['id'] = -1;
}
return $attrs;
}
/**
* Outputs the content for the current Custom HTML widget instance.
*
* @since 4.8.1
*
* @global WP_Post $post Global post object.
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Custom HTML widget instance.
*/
public function widget( $args, $instance ) {
global $post;
// Override global $post so filters (and shortcodes) apply in a consistent context.
$original_post = $post;
if ( is_singular() ) {
// Make sure post is always the queried object on singular queries (not from another sub-query that failed to clean up the global $post).
$post = get_queried_object();
} else {
// Nullify the $post global during widget rendering to prevent shortcodes from running with the unexpected context on archive queries.
$post = null;
}
// Prevent dumping out all attachments from the media library.
add_filter( 'shortcode_atts_gallery', array( $this, '_filter_gallery_shortcode_attrs' ) );
$instance = array_merge( $this->default_instance, $instance );
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
// Prepare instance data that looks like a normal Text widget.
$simulated_text_widget_instance = array_merge(
$instance,
array(
'text' => $instance['content'] ?? '',
'filter' => false, // Because wpautop is not applied.
'visual' => false, // Because it wasn't created in TinyMCE.
)
);
unset( $simulated_text_widget_instance['content'] ); // Was moved to 'text' prop.
/** This filter is documented in wp-includes/widgets/class-wp-widget-text.php */
$content = apply_filters( 'widget_text', $instance['content'], $simulated_text_widget_instance, $this );
/**
* Filters the content of the Custom HTML widget.
*
* @since 4.8.1
*
* @param string $content The widget content.
* @param array $instance Array of settings for the current widget.
* @param WP_Widget_Custom_HTML $widget Current Custom HTML widget instance.
*/
$content = apply_filters( 'widget_custom_html_content', $content, $instance, $this );
// Restore post global.
$post = $original_post;
remove_filter( 'shortcode_atts_gallery', array( $this, '_filter_gallery_shortcode_attrs' ) );
// Inject the Text widget's container class name alongside this widget's class name for theme styling compatibility.
$args['before_widget'] = preg_replace( '/(?<=\sclass=["\'])/', 'widget_text ', $args['before_widget'] );
echo $args['before_widget'];
if ( ! empty( $title ) ) {
echo $args['before_title'] . $title . $args['after_title'];
}
echo ''; // The textwidget class is for theme styling compatibility.
echo $content;
echo '
';
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Custom HTML widget instance.
*
* @since 4.8.1
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Settings to save or bool false to cancel saving.
*/
public function update( $new_instance, $old_instance ) {
$instance = array_merge( $this->default_instance, $old_instance );
$instance['title'] = sanitize_text_field( $new_instance['title'] );
if ( current_user_can( 'unfiltered_html' ) ) {
$instance['content'] = $new_instance['content'];
} else {
$instance['content'] = wp_kses_post( $new_instance['content'] );
}
return $instance;
}
/**
* Loads the required scripts and styles for the widget control.
*
* @since 4.9.0
*/
public function enqueue_admin_scripts() {
$settings = wp_enqueue_code_editor(
array(
'type' => 'text/html',
'codemirror' => array(
'indentUnit' => 2,
'tabSize' => 2,
),
)
);
wp_enqueue_script( 'custom-html-widgets' );
wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.idBases.push( %s );', wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) );
if ( empty( $settings ) ) {
$settings = array(
'disabled' => true,
);
}
wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.init( %s );', wp_json_encode( $settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ), 'after' );
$l10n = array(
'errorNotice' => array(
/* translators: %d: Error count. */
'singular' => _n( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 1 ),
/* translators: %d: Error count. */
'plural' => _n( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 2 ),
// @todo This is lacking, as some languages have a dedicated dual form. For proper handling of plurals in JS, see #20491.
),
);
wp_add_inline_script( 'custom-html-widgets', sprintf( 'jQuery.extend( wp.customHtmlWidgets.l10n, %s );', wp_json_encode( $l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ), 'after' );
}
/**
* Outputs the Custom HTML widget settings form.
*
* @since 4.8.1
* @since 4.9.0 The form contains only hidden sync inputs. For the control UI, see `WP_Widget_Custom_HTML::render_control_template_scripts()`.
*
* @see WP_Widget_Custom_HTML::render_control_template_scripts()
*
* @param array $instance Current instance.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, $this->default_instance );
?>
';
$content .= __( 'Use the Custom HTML widget to add arbitrary HTML code to your widget areas.' );
$content .= '
';
if ( 'false' !== wp_get_current_user()->syntax_highlighting ) {
$content .= '';
$content .= sprintf(
/* translators: 1: Link to user profile, 2: Additional link attributes, 3: Accessibility text. */
__( 'The edit field automatically highlights code syntax. You can disable this in your user profile%3$s to work in plain text mode.' ),
esc_url( get_edit_profile_url() ),
'class="external-link" target="_blank"',
sprintf(
' %s ',
/* translators: Hidden accessibility text. */
__( '(opens in a new tab)' )
)
);
$content .= '
';
$content .= '' . __( 'When using a keyboard to navigate:' ) . '
';
$content .= '';
$content .= '' . __( 'In the editing area, the Tab key enters a tab character.' ) . ' ';
$content .= '' . __( 'To move away from this area, press the Esc key followed by the Tab key.' ) . ' ';
$content .= '' . __( 'Screen reader users: when in forms mode, you may need to press the Esc key twice.' ) . ' ';
$content .= ' ';
}
$screen->add_help_tab(
array(
'id' => 'custom_html_widget',
'title' => __( 'Custom HTML Widget' ),
'content' => $content,
)
);
}
}
class-wp-widget-rss.php 0000644 00000012174 15225442107 0011103 0 ustar 00 __( 'Entries from any RSS or Atom feed.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
$control_ops = array(
'width' => 400,
'height' => 200,
);
parent::__construct( 'rss', __( 'RSS' ), $widget_ops, $control_ops );
}
/**
* Outputs the content for the current RSS widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current RSS widget instance.
*/
public function widget( $args, $instance ) {
if ( isset( $instance['error'] ) && $instance['error'] ) {
return;
}
$url = ! empty( $instance['url'] ) ? $instance['url'] : '';
while ( ! empty( $url ) && stristr( $url, 'http' ) !== $url ) {
$url = substr( $url, 1 );
}
if ( empty( $url ) ) {
return;
}
// Self-URL destruction sequence.
if ( in_array( untrailingslashit( $url ), array( site_url(), home_url() ), true ) ) {
return;
}
$rss = fetch_feed( $url );
$title = $instance['title'];
$desc = '';
$link = '';
if ( ! is_wp_error( $rss ) ) {
$desc = esc_attr( strip_tags( html_entity_decode( $rss->get_description(), ENT_QUOTES, get_option( 'blog_charset' ) ) ) );
if ( empty( $title ) ) {
$title = strip_tags( $rss->get_title() );
}
$link = strip_tags( $rss->get_permalink() );
while ( ! empty( $link ) && stristr( $link, 'http' ) !== $link ) {
$link = substr( $link, 1 );
}
}
if ( empty( $title ) ) {
$title = ! empty( $desc ) ? $desc : __( 'Unknown Feed' );
}
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
if ( $title ) {
$feed_link = '';
$feed_url = strip_tags( $url );
$feed_icon = includes_url( 'images/rss.png' );
$feed_link = sprintf(
' ',
esc_url( $feed_url ),
esc_url( $feed_icon ),
esc_attr__( 'RSS' ),
( wp_lazy_loading_enabled( 'img', 'rss_widget_feed_icon' ) ? ' loading="lazy"' : '' )
);
/**
* Filters the classic RSS widget's feed icon link.
*
* Themes can remove the icon link by using `add_filter( 'rss_widget_feed_link', '__return_empty_string' );`.
*
* @since 5.9.0
*
* @param string|false $feed_link HTML for link to RSS feed.
* @param array $instance Array of settings for the current widget.
*/
$feed_link = apply_filters( 'rss_widget_feed_link', $feed_link, $instance );
$title = $feed_link . '';
}
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/** This filter is documented in wp-includes/widgets/class-wp-nav-menu-widget.php */
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : __( 'RSS Feed' );
echo '';
}
wp_widget_rss_output( $rss, $instance );
if ( 'html5' === $format ) {
echo ' ';
}
echo $args['after_widget'];
if ( ! is_wp_error( $rss ) ) {
$rss->__destruct();
}
unset( $rss );
}
/**
* Handles updating settings for the current RSS widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$testurl = ( isset( $new_instance['url'] ) && ( ! isset( $old_instance['url'] ) || ( $new_instance['url'] !== $old_instance['url'] ) ) );
return wp_widget_rss_process( $new_instance, $testurl );
}
/**
* Outputs the settings form for the RSS widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
if ( empty( $instance ) ) {
$instance = array(
'title' => '',
'url' => '',
'items' => 10,
'error' => false,
'show_summary' => 0,
'show_author' => 0,
'show_date' => 0,
);
}
$instance['number'] = $this->number;
wp_widget_rss_form( $instance );
}
}
class-wp-widget-pages.php 0000644 00000013130 15225442107 0011364 0 ustar 00 'widget_pages',
'description' => __( 'A list of your site’s Pages.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'pages', __( 'Pages' ), $widget_ops );
}
/**
* Outputs the content for the current Pages widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Pages widget instance.
*/
public function widget( $args, $instance ) {
$default_title = __( 'Pages' );
$title = ! empty( $instance['title'] ) ? $instance['title'] : $default_title;
/**
* Filters the widget title.
*
* @since 2.6.0
*
* @param string $title The widget title. Default 'Pages'.
* @param array $instance Array of settings for the current widget.
* @param mixed $id_base The widget ID.
*/
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$sortby = empty( $instance['sortby'] ) ? 'menu_order' : $instance['sortby'];
$exclude = empty( $instance['exclude'] ) ? '' : $instance['exclude'];
if ( 'menu_order' === $sortby ) {
$sortby = 'menu_order, post_title';
}
$output = wp_list_pages(
/**
* Filters the arguments for the Pages widget.
*
* @since 2.8.0
* @since 4.9.0 Added the `$instance` parameter.
*
* @see wp_list_pages()
*
* @param array $args An array of arguments to retrieve the pages list.
* @param array $instance Array of settings for the current widget.
*/
apply_filters(
'widget_pages_args',
array(
'title_li' => '',
'echo' => 0,
'sort_column' => $sortby,
'exclude' => $exclude,
),
$instance
)
);
if ( ! empty( $output ) ) {
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/** This filter is documented in wp-includes/widgets/class-wp-nav-menu-widget.php */
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : $default_title;
echo '';
}
?>
';
}
echo $args['after_widget'];
}
}
/**
* Handles updating settings for the current Pages widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
if ( in_array( $new_instance['sortby'], array( 'post_title', 'menu_order', 'ID' ), true ) ) {
$instance['sortby'] = $new_instance['sortby'];
} else {
$instance['sortby'] = 'menu_order';
}
$instance['exclude'] = sanitize_text_field( $new_instance['exclude'] );
return $instance;
}
/**
* Outputs the settings form for the Pages widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
// Defaults.
$instance = wp_parse_args(
(array) $instance,
array(
'sortby' => 'post_title',
'title' => '',
'exclude' => '',
)
);
?>
>
>
>
__( 'Your blogroll' ),
'customize_selective_refresh' => true,
);
parent::__construct( 'links', __( 'Links' ), $widget_ops );
}
/**
* Outputs the content for the current Links widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Links widget instance.
*/
public function widget( $args, $instance ) {
$show_description = $instance['description'] ?? false;
$show_name = $instance['name'] ?? false;
$show_rating = $instance['rating'] ?? false;
$show_images = $instance['images'] ?? true;
$category = $instance['category'] ?? false;
$orderby = $instance['orderby'] ?? 'name';
$order = 'rating' === $orderby ? 'DESC' : 'ASC';
$limit = $instance['limit'] ?? -1;
$before_widget = preg_replace( '/ id="[^"]*"/', ' id="%id"', $args['before_widget'] );
$widget_links_args = array(
'title_before' => $args['before_title'],
'title_after' => $args['after_title'],
'category_before' => $before_widget,
'category_after' => $args['after_widget'],
'show_images' => $show_images,
'show_description' => $show_description,
'show_name' => $show_name,
'show_rating' => $show_rating,
'category' => $category,
'class' => 'linkcat widget',
'orderby' => $orderby,
'order' => $order,
'limit' => $limit,
);
/**
* Filters the arguments for the Links widget.
*
* @since 2.6.0
* @since 4.4.0 Added the `$instance` parameter.
*
* @see wp_list_bookmarks()
*
* @param array $widget_links_args An array of arguments to retrieve the links list.
* @param array $instance The settings for the particular instance of the widget.
*/
wp_list_bookmarks( apply_filters( 'widget_links_args', $widget_links_args, $instance ) );
}
/**
* Handles updating settings for the current Links widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$new_instance = (array) $new_instance;
$instance = array(
'images' => 0,
'name' => 0,
'description' => 0,
'rating' => 0,
);
foreach ( $instance as $field => $val ) {
if ( isset( $new_instance[ $field ] ) ) {
$instance[ $field ] = 1;
}
}
$instance['orderby'] = 'name';
if ( in_array( $new_instance['orderby'], array( 'name', 'rating', 'id', 'rand' ), true ) ) {
$instance['orderby'] = $new_instance['orderby'];
}
$instance['category'] = (int) $new_instance['category'];
$instance['limit'] = ! empty( $new_instance['limit'] ) ? (int) $new_instance['limit'] : -1;
return $instance;
}
/**
* Outputs the settings form for the Links widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
// Defaults.
$instance = wp_parse_args(
(array) $instance,
array(
'images' => true,
'name' => true,
'description' => false,
'rating' => false,
'category' => false,
'orderby' => 'name',
'limit' => -1,
)
);
$link_cats = get_terms( array( 'taxonomy' => 'link_category' ) );
$limit = (int) $instance['limit'];
if ( ! $limit ) {
$limit = -1;
}
?>
term_id ); ?>>
name ); ?>
>
>
>
>
id="get_field_id( 'images' ); ?>" name="get_field_name( 'images' ); ?>" />
id="get_field_id( 'name' ); ?>" name="get_field_name( 'name' ); ?>" />
id="get_field_id( 'description' ); ?>" name="get_field_name( 'description' ); ?>" />
id="get_field_id( 'rating' ); ?>" name="get_field_name( 'rating' ); ?>" />
'',
'replace_media' => '',
'edit_media' => '',
'media_library_state_multi' => '',
'media_library_state_single' => '',
'missing_attachment' => '',
'no_media_selected' => '',
'add_media' => '',
);
/**
* Whether or not the widget has been registered yet.
*
* @since 4.8.1
* @var bool
*/
protected $registered = false;
/**
* The default widget description.
*
* @since 6.0.0
* @var string
*/
protected static $default_description = '';
/**
* The default localized strings used by the widget.
*
* @since 6.0.0
* @var string[]
*/
protected static $l10n_defaults = array();
/**
* Constructor.
*
* @since 4.8.0
*
* @param string $id_base Base ID for the widget, lowercase and unique.
* @param string $name Name for the widget displayed on the configuration page.
* @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for
* information on accepted arguments. Default empty array.
* @param array $control_options Optional. Widget control options. See wp_register_widget_control()
* for information on accepted arguments. Default empty array.
*/
public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
$widget_opts = wp_parse_args(
$widget_options,
array(
'description' => self::get_default_description(),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
'mime_type' => '',
)
);
$control_opts = wp_parse_args( $control_options, array() );
$this->l10n = array_merge( self::get_l10n_defaults(), array_filter( $this->l10n ) );
parent::__construct(
$id_base,
$name,
$widget_opts,
$control_opts
);
}
/**
* Add hooks while registering all widget instances of this widget class.
*
* @since 4.8.0
*
* @param int $number Optional. The unique order number of this widget instance
* compared to other instances of the same class. Default -1.
*/
public function _register_one( $number = -1 ) {
parent::_register_one( $number );
if ( $this->registered ) {
return;
}
$this->registered = true;
/*
* Note that the widgets component in the customizer will also do
* the 'admin_print_scripts-widgets.php' action in WP_Customize_Widgets::print_scripts().
*/
add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
if ( $this->is_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
}
/*
* Note that the widgets component in the customizer will also do
* the 'admin_footer-widgets.php' action in WP_Customize_Widgets::print_footer_scripts().
*/
add_action( 'admin_footer-widgets.php', array( $this, 'render_control_template_scripts' ) );
add_filter( 'display_media_states', array( $this, 'display_media_state' ), 10, 2 );
}
/**
* Get schema for properties of a widget instance (item).
*
* @since 4.8.0
*
* @see WP_REST_Controller::get_item_schema()
* @see WP_REST_Controller::get_additional_fields()
* @link https://core.trac.wordpress.org/ticket/35574
*
* @return array Schema for properties.
*/
public function get_instance_schema() {
$schema = array(
'attachment_id' => array(
'type' => 'integer',
'default' => 0,
'minimum' => 0,
'description' => __( 'Attachment post ID' ),
'media_prop' => 'id',
),
'url' => array(
'type' => 'string',
'default' => '',
'format' => 'uri',
'description' => __( 'URL to the media file' ),
),
'title' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'description' => __( 'Title for the widget' ),
'should_preview_update' => false,
),
);
/**
* Filters the media widget instance schema to add additional properties.
*
* @since 4.9.0
*
* @param array $schema Instance schema.
* @param WP_Widget_Media $widget Widget object.
*/
$schema = apply_filters( "widget_{$this->id_base}_instance_schema", $schema, $this );
return $schema;
}
/**
* Determine if the supplied attachment is for a valid attachment post with the specified MIME type.
*
* @since 4.8.0
*
* @param int|WP_Post $attachment Attachment post ID or object.
* @param string $mime_type MIME type.
* @return bool Is matching MIME type.
*/
public function is_attachment_with_mime_type( $attachment, $mime_type ) {
if ( empty( $attachment ) ) {
return false;
}
$attachment = get_post( $attachment );
if ( ! $attachment ) {
return false;
}
if ( 'attachment' !== $attachment->post_type ) {
return false;
}
return wp_attachment_is( $mime_type, $attachment );
}
/**
* Sanitize a token list string, such as used in HTML rel and class attributes.
*
* @since 4.8.0
*
* @link http://w3c.github.io/html/infrastructure.html#space-separated-tokens
* @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
* @param string|array $tokens List of tokens separated by spaces, or an array of tokens.
* @return string Sanitized token string list.
*/
public function sanitize_token_list( $tokens ) {
if ( is_string( $tokens ) ) {
$tokens = preg_split( '/\s+/', trim( $tokens ) );
}
$tokens = array_map( 'sanitize_html_class', $tokens );
$tokens = array_filter( $tokens );
return implode( ' ', $tokens );
}
/**
* Displays the widget on the front-end.
*
* @since 4.8.0
*
* @see WP_Widget::widget()
*
* @param array $args Display arguments including before_title, after_title, before_widget, and after_widget.
* @param array $instance Saved setting from the database.
*/
public function widget( $args, $instance ) {
$instance = wp_parse_args( $instance, wp_list_pluck( $this->get_instance_schema(), 'default' ) );
// Short-circuit if no media is selected.
if ( ! $this->has_content( $instance ) ) {
return;
}
echo $args['before_widget'];
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
/**
* Filters the media widget instance prior to rendering the media.
*
* @since 4.8.0
*
* @param array $instance Instance data.
* @param array $args Widget args.
* @param WP_Widget_Media $widget Widget object.
*/
$instance = apply_filters( "widget_{$this->id_base}_instance", $instance, $args, $this );
$this->render_media( $instance );
echo $args['after_widget'];
}
/**
* Sanitizes the widget form values as they are saved.
*
* @since 4.8.0
* @since 5.9.0 Renamed `$instance` to `$old_instance` to match parent class
* for PHP 8 named parameter support.
*
* @see WP_Widget::update()
* @see WP_REST_Request::has_valid_params()
* @see WP_REST_Request::sanitize_params()
*
* @param array $new_instance Values just sent to be saved.
* @param array $old_instance Previously saved values from database.
* @return array Updated safe values to be saved.
*/
public function update( $new_instance, $old_instance ) {
$schema = $this->get_instance_schema();
foreach ( $schema as $field => $field_schema ) {
if ( ! array_key_exists( $field, $new_instance ) ) {
continue;
}
$value = $new_instance[ $field ];
/*
* Workaround for rest_validate_value_from_schema() due to the fact that
* rest_is_boolean( '' ) === false, while rest_is_boolean( '1' ) is true.
*/
if ( 'boolean' === $field_schema['type'] && '' === $value ) {
$value = false;
}
if ( true !== rest_validate_value_from_schema( $value, $field_schema, $field ) ) {
continue;
}
$value = rest_sanitize_value_from_schema( $value, $field_schema );
// @codeCoverageIgnoreStart
if ( is_wp_error( $value ) ) {
continue; // Handle case when rest_sanitize_value_from_schema() ever returns WP_Error as its phpdoc @return tag indicates.
}
// @codeCoverageIgnoreEnd
if ( isset( $field_schema['sanitize_callback'] ) ) {
$value = call_user_func( $field_schema['sanitize_callback'], $value );
}
if ( is_wp_error( $value ) ) {
continue;
}
$old_instance[ $field ] = $value;
}
return $old_instance;
}
/**
* Render the media on the frontend.
*
* @since 4.8.0
*
* @param array $instance Widget instance props.
*/
abstract public function render_media( $instance );
/**
* Outputs the settings update form.
*
* Note that the widget UI itself is rendered with JavaScript via `MediaWidgetControl#render()`.
*
* @since 4.8.0
*
* @see \WP_Widget_Media::render_control_template_scripts() Where the JS template is located.
*
* @param array $instance Current settings.
*/
final public function form( $instance ) {
$instance_schema = $this->get_instance_schema();
$instance = wp_array_slice_assoc(
wp_parse_args( (array) $instance, wp_list_pluck( $instance_schema, 'default' ) ),
array_keys( $instance_schema )
);
foreach ( $instance as $name => $value ) : ?>
get_settings() as $instance ) {
if ( isset( $instance['attachment_id'] ) && $instance['attachment_id'] === $post->ID ) {
++$use_count;
}
}
if ( 1 === $use_count ) {
$states[] = $this->l10n['media_library_state_single'];
} elseif ( $use_count > 0 ) {
$states[] = sprintf( translate_nooped_plural( $this->l10n['media_library_state_multi'], $use_count ), number_format_i18n( $use_count ) );
}
return $states;
}
/**
* Enqueue preview scripts.
*
* These scripts normally are enqueued just-in-time when a widget is rendered.
* In the customizer, however, widgets can be dynamically added and rendered via
* selective refresh, and so it is important to unconditionally enqueue them in
* case a widget does get added.
*
* @since 4.8.0
*/
public function enqueue_preview_scripts() {}
/**
* Loads the required scripts and styles for the widget control.
*
* @since 4.8.0
*/
public function enqueue_admin_scripts() {
wp_enqueue_media();
wp_enqueue_script( 'media-widgets' );
}
/**
* Render form template scripts.
*
* @since 4.8.0
*/
public function render_control_template_scripts() {
?>
__( 'No media selected' ),
'add_media' => _x( 'Add Media', 'label for button in the media widget' ),
'replace_media' => _x( 'Replace Media', 'label for button in the media widget; should preferably not be longer than ~13 characters long' ),
'edit_media' => _x( 'Edit Media', 'label for button in the media widget; should preferably not be longer than ~13 characters long' ),
'add_to_widget' => __( 'Add to Widget' ),
'missing_attachment' => sprintf(
/* translators: %s: URL to media library. */
__( 'That file cannot be found. Check your media library and make sure it was not deleted.' ),
esc_url( admin_url( 'upload.php' ) )
),
/* translators: %d: Widget count. */
'media_library_state_multi' => _n_noop( 'Media Widget (%d)', 'Media Widget (%d)' ),
'media_library_state_single' => __( 'Media Widget' ),
'unsupported_file_type' => __( 'Looks like this is not the correct kind of file. Please link to an appropriate file instead.' ),
);
return self::$l10n_defaults;
}
}
class-wp-widget-archives.php 0000644 00000016115 15225442107 0012077 0 ustar 00 'widget_archive',
'description' => __( 'A monthly archive of your site’s Posts.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'archives', __( 'Archives' ), $widget_ops );
}
/**
* Outputs the content for the current Archives widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Archives widget instance.
*/
public function widget( $args, $instance ) {
$default_title = __( 'Archives' );
$title = ! empty( $instance['title'] ) ? $instance['title'] : $default_title;
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$count = ! empty( $instance['count'] ) ? '1' : '0';
$dropdown = ! empty( $instance['dropdown'] ) ? '1' : '0';
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
if ( $dropdown ) {
$dropdown_id = "{$this->id_base}-dropdown-{$this->number}";
?>
'monthly',
'format' => 'option',
'show_post_count' => $count,
),
$instance
);
switch ( $dropdown_args['type'] ) {
case 'yearly':
$label = __( 'Select Year' );
break;
case 'monthly':
$label = __( 'Select Month' );
break;
case 'daily':
$label = __( 'Select Day' );
break;
case 'weekly':
$label = __( 'Select Week' );
break;
default:
$label = __( 'Select Post' );
break;
}
?>
';
}
?>
'monthly',
'show_post_count' => $count,
),
$instance
)
);
?>
';
}
}
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Archives widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget_Archives::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$new_instance = wp_parse_args(
(array) $new_instance,
array(
'title' => '',
'count' => 0,
'dropdown' => '',
)
);
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['count'] = $new_instance['count'] ? 1 : 0;
$instance['dropdown'] = $new_instance['dropdown'] ? 1 : 0;
return $instance;
}
/**
* Outputs the settings form for the Archives widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args(
(array) $instance,
array(
'title' => '',
'count' => 0,
'dropdown' => '',
)
);
?>
id="get_field_id( 'dropdown' ); ?>" name="get_field_name( 'dropdown' ); ?>" />
id="get_field_id( 'count' ); ?>" name="get_field_name( 'count' ); ?>" />
'widget_recent_comments',
'description' => __( 'Your site’s most recent comments.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'recent-comments', __( 'Recent Comments' ), $widget_ops );
$this->alt_option_name = 'widget_recent_comments';
if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
add_action( 'wp_head', array( $this, 'recent_comments_style' ) );
}
}
/**
* Outputs the default styles for the Recent Comments widget.
*
* @since 2.8.0
*/
public function recent_comments_style() {
/**
* Filters the Recent Comments default widget styles.
*
* @since 3.1.0
*
* @param bool $active Whether the widget is active. Default true.
* @param string $id_base The widget ID.
*/
if ( ! current_theme_supports( 'widgets' ) // Temp hack #14876.
|| ! apply_filters( 'show_recent_comments_widget_style', true, $this->id_base ) ) {
return;
}
echo '';
}
/**
* Outputs the content for the current Recent Comments widget instance.
*
* @since 2.8.0
* @since 5.4.0 Creates a unique HTML ID for the `` element
* if more than one instance is displayed on the page.
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Recent Comments widget instance.
*/
public function widget( $args, $instance ) {
static $first_instance = true;
if ( ! isset( $args['widget_id'] ) ) {
$args['widget_id'] = $this->id;
}
$output = '';
$default_title = __( 'Recent Comments' );
$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : $default_title;
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
if ( ! $number ) {
$number = 5;
}
$comments = get_comments(
/**
* Filters the arguments for the Recent Comments widget.
*
* @since 3.4.0
* @since 4.9.0 Added the `$instance` parameter.
*
* @see WP_Comment_Query::query() for information on accepted arguments.
*
* @param array $comment_args An array of arguments used to retrieve the recent comments.
* @param array $instance Array of settings for the current widget.
*/
apply_filters(
'widget_comments_args',
array(
'number' => $number,
'status' => 'approve',
'post_status' => 'publish',
),
$instance
)
);
$output .= $args['before_widget'];
if ( $title ) {
$output .= $args['before_title'] . $title . $args['after_title'];
}
$recent_comments_id = ( $first_instance ) ? 'recentcomments' : "recentcomments-{$this->number}";
$first_instance = false;
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/** This filter is documented in wp-includes/widgets/class-wp-nav-menu-widget.php */
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : $default_title;
$output .= '';
}
$output .= '';
if ( 'html5' === $format ) {
$output .= ' ';
}
$output .= $args['after_widget'];
echo $output;
}
/**
* Handles updating settings for the current Recent Comments widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['number'] = absint( $new_instance['number'] );
return $instance;
}
/**
* Outputs the settings form for the Recent Comments widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$title = $instance['title'] ?? '';
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
?>
__( 'Add a navigation menu to your sidebar.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'nav_menu', __( 'Navigation Menu' ), $widget_ops );
}
/**
* Outputs the content for the current Navigation Menu widget instance.
*
* @since 3.0.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Navigation Menu widget instance.
*/
public function widget( $args, $instance ) {
// Get menu.
$nav_menu = ! empty( $instance['nav_menu'] ) ? wp_get_nav_menu_object( $instance['nav_menu'] ) : false;
if ( ! $nav_menu ) {
return;
}
$default_title = __( 'Menu' );
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/**
* Filters the HTML format of widgets with navigation links.
*
* @since 5.5.0
*
* @param string $format The type of markup to use in widgets with navigation links.
* Accepts 'html5', 'xhtml'.
*/
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : $default_title;
$nav_menu_args = array(
'fallback_cb' => '',
'menu' => $nav_menu,
'container' => 'nav',
'container_aria_label' => $aria_label,
'items_wrap' => '',
);
} else {
$nav_menu_args = array(
'fallback_cb' => '',
'menu' => $nav_menu,
);
}
/**
* Filters the arguments for the Navigation Menu widget.
*
* @since 4.2.0
* @since 4.4.0 Added the `$instance` parameter.
*
* @param array $nav_menu_args {
* An array of arguments passed to wp_nav_menu() to retrieve a navigation menu.
*
* @type callable|bool $fallback_cb Callback to fire if the menu doesn't exist. Default empty.
* @type mixed $menu Menu ID, slug, or name.
* }
* @param WP_Term $nav_menu Nav menu object for the current menu.
* @param array $args Display arguments for the current widget.
* @param array $instance Array of settings for the current widget.
*/
wp_nav_menu( apply_filters( 'widget_nav_menu_args', $nav_menu_args, $nav_menu, $args, $instance ) );
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Navigation Menu widget instance.
*
* @since 3.0.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = array();
if ( ! empty( $new_instance['title'] ) ) {
$instance['title'] = sanitize_text_field( $new_instance['title'] );
}
if ( ! empty( $new_instance['nav_menu'] ) ) {
$instance['nav_menu'] = (int) $new_instance['nav_menu'];
}
return $instance;
}
/**
* Outputs the settings form for the Navigation Menu widget.
*
* @since 3.0.0
*
* @global WP_Customize_Manager $wp_customize
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
global $wp_customize;
$title = $instance['title'] ?? '';
$nav_menu = $instance['nav_menu'] ?? '';
// Get menus.
$menus = wp_get_nav_menus();
$empty_menus_style = '';
$not_empty_menus_style = '';
if ( empty( $menus ) ) {
$empty_menus_style = ' style="display:none" ';
} else {
$not_empty_menus_style = ' style="display:none" ';
}
$nav_menu_style = '';
if ( ! $nav_menu ) {
$nav_menu_style = 'display: none;';
}
// If no menus exists, direct the user to go and create some.
?>
__( 'Displays an image.' ),
'mime_type' => 'image',
)
);
$this->l10n = array_merge(
$this->l10n,
array(
'no_media_selected' => __( 'No image selected' ),
'add_media' => _x( 'Add Image', 'label for button in the image widget' ),
'replace_media' => _x( 'Replace Image', 'label for button in the image widget; should preferably not be longer than ~13 characters long' ),
'edit_media' => _x( 'Edit Image', 'label for button in the image widget; should preferably not be longer than ~13 characters long' ),
'missing_attachment' => sprintf(
/* translators: %s: URL to media library. */
__( 'That image cannot be found. Check your media library and make sure it was not deleted.' ),
esc_url( admin_url( 'upload.php' ) )
),
/* translators: %d: Widget count. */
'media_library_state_multi' => _n_noop( 'Image Widget (%d)', 'Image Widget (%d)' ),
'media_library_state_single' => __( 'Image Widget' ),
)
);
}
/**
* Get schema for properties of a widget instance (item).
*
* @since 4.8.0
*
* @see WP_REST_Controller::get_item_schema()
* @see WP_REST_Controller::get_additional_fields()
* @link https://core.trac.wordpress.org/ticket/35574
*
* @return array Schema for properties.
*/
public function get_instance_schema() {
return array_merge(
array(
'size' => array(
'type' => 'string',
'enum' => array_merge( get_intermediate_image_sizes(), array( 'full', 'custom' ) ),
'default' => 'medium',
'description' => __( 'Size' ),
),
'width' => array( // Via 'customWidth', only when size=custom; otherwise via 'width'.
'type' => 'integer',
'minimum' => 0,
'default' => 0,
'description' => __( 'Width' ),
),
'height' => array( // Via 'customHeight', only when size=custom; otherwise via 'height'.
'type' => 'integer',
'minimum' => 0,
'default' => 0,
'description' => __( 'Height' ),
),
'caption' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => 'wp_kses_post',
'description' => __( 'Caption' ),
'should_preview_update' => false,
),
'alt' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'description' => __( 'Alternative Text' ),
),
'link_type' => array(
'type' => 'string',
'enum' => array( 'none', 'file', 'post', 'custom' ),
'default' => 'custom',
'media_prop' => 'link',
'description' => __( 'Link To' ),
'should_preview_update' => true,
),
'link_url' => array(
'type' => 'string',
'default' => '',
'format' => 'uri',
'media_prop' => 'linkUrl',
'description' => __( 'URL' ),
'should_preview_update' => true,
),
'image_classes' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => array( $this, 'sanitize_token_list' ),
'media_prop' => 'extraClasses',
'description' => __( 'Image CSS Class' ),
'should_preview_update' => false,
),
'link_classes' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => array( $this, 'sanitize_token_list' ),
'media_prop' => 'linkClassName',
'should_preview_update' => false,
'description' => __( 'Link CSS Class' ),
),
'link_rel' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => array( $this, 'sanitize_token_list' ),
'media_prop' => 'linkRel',
'description' => __( 'Link Rel' ),
'should_preview_update' => false,
),
'link_target_blank' => array(
'type' => 'boolean',
'default' => false,
'media_prop' => 'linkTargetBlank',
'description' => __( 'Open link in a new tab' ),
'should_preview_update' => false,
),
'image_title' => array(
'type' => 'string',
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'media_prop' => 'title',
'description' => __( 'Image Title Attribute' ),
'should_preview_update' => false,
),
/*
* There are two additional properties exposed by the PostImage modal
* that don't seem to be relevant, as they may only be derived read-only
* values:
* - originalUrl
* - aspectRatio
* - height (redundant when size is not custom)
* - width (redundant when size is not custom)
*/
),
parent::get_instance_schema()
);
}
/**
* Render the media on the frontend.
*
* @since 4.8.0
*
* @param array $instance Widget instance props.
*/
public function render_media( $instance ) {
$instance = array_merge( wp_list_pluck( $this->get_instance_schema(), 'default' ), $instance );
$instance = wp_parse_args(
$instance,
array(
'size' => 'thumbnail',
)
);
$attachment = null;
if ( $this->is_attachment_with_mime_type( $instance['attachment_id'], $this->widget_options['mime_type'] ) ) {
$attachment = get_post( $instance['attachment_id'] );
}
if ( $attachment ) {
$caption = '';
if ( ! isset( $instance['caption'] ) ) {
$caption = $attachment->post_excerpt;
} elseif ( trim( $instance['caption'] ) ) {
$caption = $instance['caption'];
}
$image_attributes = array(
'class' => sprintf( 'image wp-image-%d %s', $attachment->ID, $instance['image_classes'] ),
'style' => 'max-width: 100%; height: auto;',
);
if ( ! empty( $instance['image_title'] ) ) {
$image_attributes['title'] = $instance['image_title'];
}
if ( $instance['alt'] ) {
$image_attributes['alt'] = $instance['alt'];
}
$size = $instance['size'];
if ( 'custom' === $size || ! in_array( $size, array_merge( get_intermediate_image_sizes(), array( 'full' ) ), true ) ) {
$size = array( $instance['width'], $instance['height'] );
$width = $instance['width'];
} else {
$caption_size = _wp_get_image_size_from_meta( $instance['size'], wp_get_attachment_metadata( $attachment->ID ) );
$width = empty( $caption_size[0] ) ? 0 : $caption_size[0];
}
$image_attributes['class'] .= sprintf( ' attachment-%1$s size-%1$s', is_array( $size ) ? implode( 'x', $size ) : $size );
$image = wp_get_attachment_image( $attachment->ID, $size, false, $image_attributes );
} else {
if ( empty( $instance['url'] ) ) {
return;
}
$instance['size'] = 'custom';
$caption = $instance['caption'];
$width = $instance['width'];
$classes = 'image ' . $instance['image_classes'];
if ( 0 === $instance['width'] ) {
$instance['width'] = '';
}
if ( 0 === $instance['height'] ) {
$instance['height'] = '';
}
$attr = array(
'class' => $classes,
'src' => $instance['url'],
'alt' => $instance['alt'],
'width' => $instance['width'],
'height' => $instance['height'],
);
$loading_optimization_attr = wp_get_loading_optimization_attributes(
'img',
$attr,
'widget_media_image'
);
$attr = array_merge( $attr, $loading_optimization_attr );
$attr = array_map( 'esc_attr', $attr );
$image = ' $value ) {
$image .= ' ' . $name . '="' . $value . '"';
}
$image .= ' />';
} // End if().
$url = '';
if ( 'file' === $instance['link_type'] ) {
$url = $attachment ? wp_get_attachment_url( $attachment->ID ) : $instance['url'];
} elseif ( $attachment && 'post' === $instance['link_type'] ) {
$url = get_attachment_link( $attachment->ID );
} elseif ( 'custom' === $instance['link_type'] && ! empty( $instance['link_url'] ) ) {
$url = $instance['link_url'];
}
if ( $url ) {
$link = sprintf( ' $width,
'caption' => $caption,
),
$image
);
}
echo $image;
}
/**
* Loads the required media files for the media manager and scripts for media widgets.
*
* @since 4.8.0
*/
public function enqueue_admin_scripts() {
parent::enqueue_admin_scripts();
$handle = 'media-image-widget';
wp_enqueue_script( $handle );
$exported_schema = array();
foreach ( $this->get_instance_schema() as $field => $field_schema ) {
$exported_schema[ $field ] = wp_array_slice_assoc( $field_schema, array( 'type', 'default', 'enum', 'minimum', 'format', 'media_prop', 'should_preview_update' ) );
}
wp_add_inline_script(
$handle,
sprintf(
'wp.mediaWidgets.modelConstructors[ %s ].prototype.schema = %s;',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $exported_schema, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
wp_add_inline_script(
$handle,
sprintf(
'
wp.mediaWidgets.controlConstructors[ %1$s ].prototype.mime_type = %2$s;
wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n = _.extend( {}, wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n, %3$s );
',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->widget_options['mime_type'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
}
/**
* Render form template scripts.
*
* @since 4.8.0
*/
public function render_control_template_scripts() {
parent::render_control_template_scripts();
?>
__( 'Displays an audio player.' ),
'mime_type' => 'audio',
)
);
$this->l10n = array_merge(
$this->l10n,
array(
'no_media_selected' => __( 'No audio selected' ),
'add_media' => _x( 'Add Audio', 'label for button in the audio widget' ),
'replace_media' => _x( 'Replace Audio', 'label for button in the audio widget; should preferably not be longer than ~13 characters long' ),
'edit_media' => _x( 'Edit Audio', 'label for button in the audio widget; should preferably not be longer than ~13 characters long' ),
'missing_attachment' => sprintf(
/* translators: %s: URL to media library. */
__( 'That audio file cannot be found. Check your media library and make sure it was not deleted.' ),
esc_url( admin_url( 'upload.php' ) )
),
/* translators: %d: Widget count. */
'media_library_state_multi' => _n_noop( 'Audio Widget (%d)', 'Audio Widget (%d)' ),
'media_library_state_single' => __( 'Audio Widget' ),
'unsupported_file_type' => __( 'Looks like this is not the correct kind of file. Please link to an audio file instead.' ),
)
);
}
/**
* Get schema for properties of a widget instance (item).
*
* @since 4.8.0
*
* @see WP_REST_Controller::get_item_schema()
* @see WP_REST_Controller::get_additional_fields()
* @link https://core.trac.wordpress.org/ticket/35574
*
* @return array Schema for properties.
*/
public function get_instance_schema() {
$schema = array(
'preload' => array(
'type' => 'string',
'enum' => array( 'none', 'auto', 'metadata' ),
'default' => 'none',
'description' => __( 'Preload' ),
),
'loop' => array(
'type' => 'boolean',
'default' => false,
'description' => __( 'Loop' ),
),
);
foreach ( wp_get_audio_extensions() as $audio_extension ) {
$schema[ $audio_extension ] = array(
'type' => 'string',
'default' => '',
'format' => 'uri',
/* translators: %s: Audio extension. */
'description' => sprintf( __( 'URL to the %s audio source file' ), $audio_extension ),
);
}
return array_merge( $schema, parent::get_instance_schema() );
}
/**
* Render the media on the frontend.
*
* @since 4.8.0
*
* @param array $instance Widget instance props.
*/
public function render_media( $instance ) {
$instance = array_merge( wp_list_pluck( $this->get_instance_schema(), 'default' ), $instance );
$attachment = null;
if ( $this->is_attachment_with_mime_type( $instance['attachment_id'], $this->widget_options['mime_type'] ) ) {
$attachment = get_post( $instance['attachment_id'] );
}
if ( $attachment ) {
$src = wp_get_attachment_url( $attachment->ID );
} else {
$src = $instance['url'];
}
echo wp_audio_shortcode(
array_merge(
$instance,
compact( 'src' )
)
);
}
/**
* Enqueue preview scripts.
*
* These scripts normally are enqueued just-in-time when an audio shortcode is used.
* In the customizer, however, widgets can be dynamically added and rendered via
* selective refresh, and so it is important to unconditionally enqueue them in
* case a widget does get added.
*
* @since 4.8.0
*/
public function enqueue_preview_scripts() {
/** This filter is documented in wp-includes/media.php */
if ( 'mediaelement' === apply_filters( 'wp_audio_shortcode_library', 'mediaelement' ) ) {
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-mediaelement' );
}
}
/**
* Loads the required media files for the media manager and scripts for media widgets.
*
* @since 4.8.0
*/
public function enqueue_admin_scripts() {
parent::enqueue_admin_scripts();
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-mediaelement' );
$handle = 'media-audio-widget';
wp_enqueue_script( $handle );
$exported_schema = array();
foreach ( $this->get_instance_schema() as $field => $field_schema ) {
$exported_schema[ $field ] = wp_array_slice_assoc( $field_schema, array( 'type', 'default', 'enum', 'minimum', 'format', 'media_prop', 'should_preview_update' ) );
}
wp_add_inline_script(
$handle,
sprintf(
'wp.mediaWidgets.modelConstructors[ %s ].prototype.schema = %s;',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $exported_schema, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
wp_add_inline_script(
$handle,
sprintf(
'
wp.mediaWidgets.controlConstructors[ %1$s ].prototype.mime_type = %2$s;
wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n = _.extend( {}, wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n, %3$s );
',
wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->widget_options['mime_type'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
wp_json_encode( $this->l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
)
);
}
/**
* Render form template scripts.
*
* @since 4.8.0
*/
public function render_control_template_scripts() {
parent::render_control_template_scripts()
?>
__( 'A cloud of your most used tags.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'tag_cloud', __( 'Tag Cloud' ), $widget_ops );
}
/**
* Outputs the content for the current Tag Cloud widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Tag Cloud widget instance.
*/
public function widget( $args, $instance ) {
$current_taxonomy = $this->_get_current_taxonomy( $instance );
if ( ! empty( $instance['title'] ) ) {
$title = $instance['title'];
} else {
if ( 'post_tag' === $current_taxonomy ) {
$title = __( 'Tags' );
} else {
$tax = get_taxonomy( $current_taxonomy );
$title = $tax->labels->name;
}
}
$default_title = $title;
$show_count = ! empty( $instance['count'] );
$tag_cloud = wp_tag_cloud(
/**
* Filters the taxonomy used in the Tag Cloud widget.
*
* @since 2.8.0
* @since 3.0.0 Added taxonomy drop-down.
* @since 4.9.0 Added the `$instance` parameter.
*
* @see wp_tag_cloud()
*
* @param array $args Args used for the tag cloud widget.
* @param array $instance Array of settings for the current widget.
*/
apply_filters(
'widget_tag_cloud_args',
array(
'taxonomy' => $current_taxonomy,
'echo' => false,
'show_count' => $show_count,
),
$instance
)
);
if ( empty( $tag_cloud ) ) {
return;
}
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml';
/** This filter is documented in wp-includes/widgets/class-wp-nav-menu-widget.php */
$format = apply_filters( 'navigation_widgets_format', $format );
if ( 'html5' === $format ) {
// The title may be filtered: Strip out HTML and make sure the aria-label is never empty.
$title = trim( strip_tags( $title ) );
$aria_label = $title ? $title : $default_title;
echo '';
}
echo '';
echo $tag_cloud;
echo "
\n";
if ( 'html5' === $format ) {
echo ' ';
}
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Tag Cloud widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Settings to save or bool false to cancel saving.
*/
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['count'] = ! empty( $new_instance['count'] ) ? 1 : 0;
$instance['taxonomy'] = stripslashes( $new_instance['taxonomy'] );
return $instance;
}
/**
* Outputs the Tag Cloud widget settings form.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$count = isset( $instance['count'] ) ? (bool) $instance['count'] : false;
?>
true ), 'object' );
$current_taxonomy = $this->_get_current_taxonomy( $instance );
switch ( count( $taxonomies ) ) {
// No tag cloud supporting taxonomies found, display error message.
case 0:
?>
$tax ) : ?>
>
labels->name ); ?>
0 ) {
?>
/>
'widget_calendar',
'description' => __( 'A calendar of your site’s posts.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'calendar', __( 'Calendar' ), $widget_ops );
}
/**
* Outputs the content for the current Calendar widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance The settings for the particular instance of the widget.
*/
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
if ( 0 === self::$instance ) {
echo '';
} else {
echo '
';
}
get_calendar();
echo '
';
echo $args['after_widget'];
++self::$instance;
}
/**
* Handles updating settings for the current Calendar widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
/**
* Outputs the settings form for the Calendar widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
?>
'widget_categories',
'description' => __( 'A list or dropdown of categories.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
parent::__construct( 'categories', __( 'Categories' ), $widget_ops );
}
/**
* Outputs the content for the current Categories widget instance.
*
* @since 2.8.0
* @since 4.2.0 Creates a unique HTML ID for the `
` element
* if more than one instance is displayed on the page.
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Categories widget instance.
*/
public function widget( $args, $instance ) {
static $first_dropdown = true;
$default_title = __( 'Categories' );
$title = ! empty( $instance['title'] ) ? $instance['title'] : $default_title;
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$count = ! empty( $instance['count'] ) ? '1' : '0';
$hierarchical = ! empty( $instance['hierarchical'] ) ? '1' : '0';
$dropdown = ! empty( $instance['dropdown'] ) ? '1' : '0';
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$cat_args = array(
'orderby' => 'name',
'show_count' => $count,
'hierarchical' => $hierarchical,
);
if ( $dropdown ) {
printf( '';
ob_start();
?>
';
}
?>
';
}
}
echo $args['after_widget'];
}
/**
* Handles updating settings for the current Categories widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings to save.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['count'] = ! empty( $new_instance['count'] ) ? 1 : 0;
$instance['hierarchical'] = ! empty( $new_instance['hierarchical'] ) ? 1 : 0;
$instance['dropdown'] = ! empty( $new_instance['dropdown'] ) ? 1 : 0;
return $instance;
}
/**
* Outputs the settings form for the Categories widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
// Defaults.
$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
$count = isset( $instance['count'] ) ? (bool) $instance['count'] : false;
$hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false;
$dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false;
?>
/>
/>
/>
'',
);
/**
* Sets up a new Block widget instance.
*
* @since 5.8.0
*/
public function __construct() {
$widget_ops = array(
'classname' => 'widget_block',
'description' => __( 'A widget containing a block.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
$control_ops = array(
'width' => 400,
'height' => 350,
);
parent::__construct( 'block', __( 'Block' ), $widget_ops, $control_ops );
add_filter( 'is_wide_widget_in_customizer', array( $this, 'set_is_wide_widget_in_customizer' ), 10, 2 );
}
/**
* Outputs the content for the current Block widget instance.
*
* @since 5.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Block widget instance.
*/
public function widget( $args, $instance ) {
$instance = wp_parse_args( $instance, $this->default_instance );
echo str_replace(
'widget_block',
$this->get_dynamic_classname( $instance['content'] ),
$args['before_widget']
);
/**
* Filters the content of the Block widget before output.
*
* @since 5.8.0
*
* @param string $content The widget content.
* @param array $instance Array of settings for the current widget.
* @param WP_Widget_Block $widget Current Block widget instance.
*/
echo apply_filters(
'widget_block_content',
$instance['content'],
$instance,
$this
);
echo $args['after_widget'];
}
/**
* Calculates the classname to use in the block widget's container HTML.
*
* Usually this is set to `$this->widget_options['classname']` by
* dynamic_sidebar(). In this case, however, we want to set the classname
* dynamically depending on the block contained by this block widget.
*
* If a block widget contains a block that has an equivalent legacy widget,
* we display that legacy widget's class name. This helps with theme
* backwards compatibility.
*
* @since 5.8.0
*
* @param string $content The HTML content of the current block widget.
* @return string The classname to use in the block widget's container HTML.
*/
private function get_dynamic_classname( $content ) {
$blocks = parse_blocks( $content );
$block_name = isset( $blocks[0] ) ? $blocks[0]['blockName'] : null;
switch ( $block_name ) {
case 'core/paragraph':
$classname = 'widget_block widget_text';
break;
case 'core/calendar':
$classname = 'widget_block widget_calendar';
break;
case 'core/search':
$classname = 'widget_block widget_search';
break;
case 'core/html':
$classname = 'widget_block widget_custom_html';
break;
case 'core/archives':
$classname = 'widget_block widget_archive';
break;
case 'core/latest-posts':
$classname = 'widget_block widget_recent_entries';
break;
case 'core/latest-comments':
$classname = 'widget_block widget_recent_comments';
break;
case 'core/tag-cloud':
$classname = 'widget_block widget_tag_cloud';
break;
case 'core/categories':
$classname = 'widget_block widget_categories';
break;
case 'core/audio':
$classname = 'widget_block widget_media_audio';
break;
case 'core/video':
$classname = 'widget_block widget_media_video';
break;
case 'core/image':
$classname = 'widget_block widget_media_image';
break;
case 'core/gallery':
$classname = 'widget_block widget_media_gallery';
break;
case 'core/rss':
$classname = 'widget_block widget_rss';
break;
default:
$classname = 'widget_block';
}
/**
* The classname used in the block widget's container HTML.
*
* This can be set according to the name of the block contained by the block widget.
*
* @since 5.8.0
*
* @param string $classname The classname to be used in the block widget's container HTML,
* e.g. 'widget_block widget_text'.
* @param string $block_name The name of the block contained by the block widget,
* e.g. 'core/paragraph'.
*/
return apply_filters( 'widget_block_dynamic_classname', $classname, $block_name );
}
/**
* Handles updating settings for the current Block widget instance.
*
* @since 5.8.0
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Settings to save or bool false to cancel saving.
*/
public function update( $new_instance, $old_instance ) {
$instance = array_merge( $this->default_instance, $old_instance );
if ( current_user_can( 'unfiltered_html' ) ) {
$instance['content'] = $new_instance['content'];
} else {
$instance['content'] = wp_kses_post( $new_instance['content'] );
}
return $instance;
}
/**
* Outputs the Block widget settings form.
*
* @since 5.8.0
*
* @see WP_Widget_Custom_HTML::render_control_template_scripts()
*
* @param array $instance Current instance.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, $this->default_instance );
?>
'widget_text',
'description' => __( 'Arbitrary text.' ),
'customize_selective_refresh' => true,
'show_instance_in_rest' => true,
);
$control_ops = array(
'width' => 400,
'height' => 350,
);
parent::__construct( 'text', __( 'Text' ), $widget_ops, $control_ops );
}
/**
* Adds hooks for enqueueing assets when registering all widget instances of this widget class.
*
* @param int $number Optional. The unique order number of this widget instance
* compared to other instances of the same class. Default -1.
*/
public function _register_one( $number = -1 ) {
parent::_register_one( $number );
if ( $this->registered ) {
return;
}
$this->registered = true;
if ( $this->is_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
}
/*
* Note that the widgets component in the customizer will also do
* the 'admin_print_scripts-widgets.php' action in WP_Customize_Widgets::print_scripts().
*/
add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
/*
* Note that the widgets component in the customizer will also do
* the 'admin_footer-widgets.php' action in WP_Customize_Widgets::print_footer_scripts().
*/
add_action( 'admin_footer-widgets.php', array( 'WP_Widget_Text', 'render_control_template_scripts' ) );
}
/**
* Determines whether a given instance is legacy and should bypass using TinyMCE.
*
* @since 4.8.1
*
* @param array $instance {
* Instance data.
*
* @type string $text Content.
* @type bool|string $filter Whether autop or content filters should apply.
* @type bool $legacy Whether widget is in legacy mode.
* }
* @return bool Whether Text widget instance contains legacy data.
*/
public function is_legacy_instance( $instance ) {
// Legacy mode when not in visual mode.
if ( isset( $instance['visual'] ) ) {
return ! $instance['visual'];
}
// Or, the widget has been added/updated in 4.8.0 then filter prop is 'content' and it is no longer legacy.
if ( isset( $instance['filter'] ) && 'content' === $instance['filter'] ) {
return false;
}
// If the text is empty, then nothing is preventing migration to TinyMCE.
if ( empty( $instance['text'] ) ) {
return false;
}
$wpautop = ! empty( $instance['filter'] );
$has_line_breaks = ( str_contains( trim( $instance['text'] ), "\n" ) );
// If auto-paragraphs are not enabled and there are line breaks, then ensure legacy mode.
if ( ! $wpautop && $has_line_breaks ) {
return true;
}
// If an HTML comment is present, assume legacy mode.
if ( str_contains( $instance['text'], '