??????????????
Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 173

Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 174

Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 175

Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 176

Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 177

Warning: Cannot modify header information - headers already sent by (output started at /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php:4) in /home/mybf1/public_html/class.bf1.my/wp-includes/js/dist/index.php on line 178
class-wp-nav-menu-widget.php000064400000015055151230676600012027 0ustar00 __( '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 * * @param array $instance Current settings. * @global WP_Customize_Manager $wp_customize */ public function form( $instance ) { global $wp_customize; $title = isset( $instance['title'] ) ? $instance['title'] : ''; $nav_menu = isset( $instance['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. ?> '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}"; ?> '; } ?> '; } } 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_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 `

/>
/>
/>

'', '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' => isset( $instance['content'] ) ? $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 ); // Adds 'noopener' relationship, without duplicating values, to all HTML A elements that have a target. $content = wp_targeted_link_rel( $content ); /** * 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 ) ) ); if ( empty( $settings ) ) { $settings = array( 'disabled' => true, ); } wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.init( %s );', wp_json_encode( $settings ) ), '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 ) ), '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 .= ''; } $screen->add_help_tab( array( 'id' => 'custom_html_widget', 'title' => __( 'Custom HTML Widget' ), 'content' => $content, ) ); } } class-wp-widget-links.php000064400000016175151230676600011425 0ustar00 __( '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 = isset( $instance['description'] ) ? $instance['description'] : false; $show_name = isset( $instance['name'] ) ? $instance['name'] : false; $show_rating = isset( $instance['rating'] ) ? $instance['rating'] : false; $show_images = isset( $instance['images'] ) ? $instance['images'] : true; $category = isset( $instance['category'] ) ? $instance['category'] : false; $orderby = isset( $instance['orderby'] ) ? $instance['orderby'] : 'name'; $order = 'rating' === $orderby ? 'DESC' : 'ASC'; $limit = isset( $instance['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; } ?>

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' ); ?>" />

__( '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 ), wp_json_encode( $exported_schema ) ) ); 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 ), wp_json_encode( $this->widget_options['mime_type'] ), wp_json_encode( $this->l10n ) ) ); } /** * Render form template scripts. * * @since 4.8.0 */ public function render_control_template_scripts() { parent::render_control_template_scripts() ?> __( '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 ), wp_json_encode( $exported_schema ) ) ); 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 ), wp_json_encode( $this->widget_options['mime_type'] ), wp_json_encode( $this->l10n ) ) ); } /** * Render form template scripts. * * @since 4.9.0 */ public function render_control_template_scripts() { parent::render_control_template_scripts(); ?> __( '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 ), wp_json_encode( $exported_schema ) ) ); 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 ), wp_json_encode( $this->widget_options['mime_type'] ), wp_json_encode( $this->l10n ) ) ); } /** * Render form template scripts. * * @since 4.8.0 */ public function render_control_template_scripts() { parent::render_control_template_scripts(); ?> __( 'Displays a video from the media library or from YouTube, Vimeo, or another provider.' ), 'mime_type' => 'video', ) ); $this->l10n = array_merge( $this->l10n, array( 'no_media_selected' => __( 'No video selected' ), 'add_media' => _x( 'Add Video', 'label for button in the video widget' ), 'replace_media' => _x( 'Replace Video', 'label for button in the video widget; should preferably not be longer than ~13 characters long' ), 'edit_media' => _x( 'Edit Video', 'label for button in the video widget; should preferably not be longer than ~13 characters long' ), 'missing_attachment' => sprintf( /* translators: %s: URL to media library. */ __( 'That video 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( 'Video Widget (%d)', 'Video Widget (%d)' ), 'media_library_state_single' => __( 'Video Widget' ), /* translators: %s: A list of valid video file extensions. */ 'unsupported_file_type' => sprintf( __( 'Sorry, the video at the supplied URL cannot be loaded. Please check that the URL is for a supported video file (%s) or stream (e.g. YouTube and Vimeo).' ), '.' . implode( ', .', wp_get_video_extensions() ) . '' ), ) ); } /** * 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' => 'metadata', 'description' => __( 'Preload' ), 'should_preview_update' => false, ), 'loop' => array( 'type' => 'boolean', 'default' => false, 'description' => __( 'Loop' ), 'should_preview_update' => false, ), 'content' => array( 'type' => 'string', 'default' => '', 'sanitize_callback' => 'wp_kses_post', 'description' => __( 'Tracks (subtitles, captions, descriptions, chapters, or metadata)' ), 'should_preview_update' => false, ), ); foreach ( wp_get_video_extensions() as $video_extension ) { $schema[ $video_extension ] = array( 'type' => 'string', 'default' => '', 'format' => 'uri', /* translators: %s: Video extension. */ 'description' => sprintf( __( 'URL to the %s video source file' ), $video_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'] ); } $src = $instance['url']; if ( $attachment ) { $src = wp_get_attachment_url( $attachment->ID ); } if ( empty( $src ) ) { return; } $youtube_pattern = '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#'; $vimeo_pattern = '#^https?://(.+\.)?vimeo\.com/.*#'; if ( $attachment || preg_match( $youtube_pattern, $src ) || preg_match( $vimeo_pattern, $src ) ) { add_filter( 'wp_video_shortcode', array( $this, 'inject_video_max_width_style' ) ); echo wp_video_shortcode( array_merge( $instance, compact( 'src' ) ), $instance['content'] ); remove_filter( 'wp_video_shortcode', array( $this, 'inject_video_max_width_style' ) ); } else { echo $this->inject_video_max_width_style( wp_oembed_get( $src ) ); } } /** * Inject max-width and remove height for videos too constrained to fit inside sidebars on frontend. * * @since 4.8.0 * * @param string $html Video shortcode HTML output. * @return string HTML Output. */ public function inject_video_max_width_style( $html ) { $html = preg_replace( '/\sheight="\d+"/', '', $html ); $html = preg_replace( '/\swidth="\d+"/', '', $html ); $html = preg_replace( '/(?<=width:)\s*\d+px(?=;?)/', '100%', $html ); return $html; } /** * Enqueue preview scripts. * * These scripts normally are enqueued just-in-time when a video 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_video_shortcode_library', 'mediaelement' ) ) { wp_enqueue_style( 'wp-mediaelement' ); wp_enqueue_script( 'mediaelement-vimeo' ); wp_enqueue_script( 'wp-mediaelement' ); } } /** * Loads the required scripts and styles for the widget control. * * @since 4.8.0 */ public function enqueue_admin_scripts() { parent::enqueue_admin_scripts(); $handle = 'media-video-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 ), wp_json_encode( $exported_schema ) ) ); 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 ), wp_json_encode( $this->widget_options['mime_type'] ), wp_json_encode( $this->l10n ) ) ); } /** * Render form template scripts. * * @since 4.8.0 */ public function render_control_template_scripts() { parent::render_control_template_scripts() ?> '', '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-meta.php000064400000007773151230676600011237 0ustar00 '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 '