-
-
Save AndryWJ/dacc667af2d53c23136f2a9cebaa69b0 to your computer and use it in GitHub Desktop.
custom widgets media file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint consistent-this: [ "error", "control" ] */ | |
/** | |
* Continued from PHP Instructions on renaming / cloning image class. | |
* @link https://gist.github.com/StuffieStephie/4f654058545d693787a36e76d3521b1e | |
* | |
* Step 1: | |
* Assign previewTemplate variable to the script template ID defined in the | |
* PHP file sans 'tmpl-' (Step 6 of PHP instructions) | |
* Name here `custom-media-widget-image-preview` | |
* --------------------------------------------------------------------- | |
* Step 2: | |
* Similar to Step 1 -- assign fieldsTemplate variable to the script template ID | |
* defined in the PHP file sans 'tmpl-' (Step 5 of PHP instructions) | |
* Name here `custom-media-widget-image-fields` | |
* --------------------------------------------------------------------- | |
* Step 3: | |
* Rename Exports. (Name here: `logo`) | |
*/ | |
(function( component, $ ) { | |
'use strict'; | |
console.log('This means that the custom image widget JS file has been loaded.'); | |
var ImageWidgetModel, ImageWidgetControl; | |
/** | |
* Image widget model. | |
* | |
* See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports. | |
* | |
* @class ImageWidgetModel | |
* @constructor | |
*/ | |
ImageWidgetModel = component.MediaWidgetModel.extend({}); | |
/** | |
* Image widget control. | |
* | |
* See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports. | |
* | |
* @class ImageWidgetModel | |
* @constructor | |
*/ | |
ImageWidgetControl = component.MediaWidgetControl.extend({ | |
/** | |
* Initialize. | |
* | |
* @param {Object} options - Options. | |
* @param {Backbone.Model} options.model - Model. | |
* @param {jQuery} options.el - Control field container element. | |
* @param {jQuery} options.syncContainer - Container element where fields are synced for the server. | |
* @returns {void} | |
*/ | |
initialize: function initialize( options ) { | |
var control = this; | |
Backbone.View.prototype.initialize.call( control, options ); | |
if ( ! ( control.model instanceof component.MediaWidgetModel ) ) { | |
throw new Error( 'Missing options.model' ); | |
} | |
if ( ! options.el ) { | |
throw new Error( 'Missing options.el' ); | |
} | |
if ( ! options.syncContainer ) { | |
throw new Error( 'Missing options.syncContainer' ); | |
} | |
control.syncContainer = options.syncContainer; | |
control.$el.addClass( 'media-widget-control' ); | |
// Allow methods to be passed in with control context preserved. | |
_.bindAll( control, 'syncModelToInputs', 'render', 'updateSelectedAttachment', 'renderPreview' ); | |
if ( ! control.id_base ) { | |
_.find( component.controlConstructors, function( Constructor, idBase ) { | |
if ( control instanceof Constructor ) { | |
control.id_base = idBase; | |
return true; | |
} | |
return false; | |
}); | |
if ( ! control.id_base ) { | |
throw new Error( 'Missing id_base.' ); | |
} | |
} | |
// Track attributes needed to renderPreview in it's own model. | |
control.previewTemplateProps = new Backbone.Model( control.mapModelToPreviewTemplateProps() ); | |
// Re-render the preview when the attachment changes. | |
control.selectedAttachment = new wp.media.model.Attachment(); | |
control.renderPreview = _.debounce( control.renderPreview ); | |
control.listenTo( control.previewTemplateProps, 'change', control.renderPreview ); | |
// Make sure a copy of the selected attachment is always fetched. | |
control.model.on( 'change:attachment_id', control.updateSelectedAttachment ); | |
control.model.on( 'change:url', control.updateSelectedAttachment ); | |
control.updateSelectedAttachment(); | |
/* | |
* Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state. | |
* In the future, when widgets are JS-driven, the underlying widget instance data should be exposed as a model | |
* from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>. | |
*/ | |
control.listenTo( control.model, 'change', control.syncModelToInputs ); | |
control.listenTo( control.model, 'change', control.syncModelToPreviewProps ); | |
control.listenTo( control.model, 'change', control.render ); | |
// Update the title. | |
control.$el.on( 'input change', '.title', function updateTitle() { | |
control.model.set({ | |
title: $.trim( $( this ).val() ) | |
}); | |
}); | |
control.$el.on( 'input change', '.text_field', function updateText_field() { | |
var id = $(this).attr('id'); | |
var name_field = id.split('_').slice(1).join('_'); | |
var sets = {}; | |
sets[name_field] = $.trim( $( this ).val() ); | |
control.model.set(sets); | |
}); | |
// Update link_url attribute. | |
control.$el.on( 'input change', '.link', function updateLinkUrl() { | |
var linkUrl = $.trim( $( this ).val() ), linkType = 'custom'; | |
if ( control.selectedAttachment.get( 'linkUrl' ) === linkUrl || control.selectedAttachment.get( 'link' ) === linkUrl ) { | |
linkType = 'post'; | |
} else if ( control.selectedAttachment.get( 'url' ) === linkUrl ) { | |
linkType = 'file'; | |
} | |
control.model.set( { | |
link_url: linkUrl, | |
link_type: linkType | |
}); | |
// Update display settings for the next time the user opens to select from the media library. | |
control.displaySettings.set( { | |
link: linkType, | |
linkUrl: linkUrl | |
}); | |
}); | |
/* | |
* Copy current display settings from the widget model to serve as basis | |
* of customized display settings for the current media frame session. | |
* Changes to display settings will be synced into this model, and | |
* when a new selection is made, the settings from this will be synced | |
* into that AttachmentDisplay's model to persist the setting changes. | |
*/ | |
control.displaySettings = new Backbone.Model( _.pick( | |
control.mapModelToMediaFrameProps( | |
_.extend( control.model.defaults(), control.model.toJSON() ) | |
), | |
_.keys( wp.media.view.settings.defaultProps ) | |
) ); | |
}, | |
/** | |
* Render preview. | |
* | |
* @returns {void} | |
*/ | |
renderPreview: function renderPreview() { | |
var control = this, previewContainer, previewTemplate, fieldsContainer, fieldsTemplate, linkInput; | |
if ( ! control.model.get( 'attachment_id' ) && ! control.model.get( 'url' ) ) { | |
return; | |
} | |
previewContainer = control.$el.find( '.media-widget-preview' ); | |
/*-------------------------------------------------------------- | |
# Step 1: | |
* Assign previewTemplate variable to the script template ID defined in the | |
* PHP file sans 'tmpl-' (Step 6 of PHP instructions) | |
* Name here `custom-media-widget-image-preview` | |
--------------------------------------------------------------*/ | |
previewTemplate = wp.template( 'custom-media-widget-image-preview' ); | |
previewContainer.html( previewTemplate( control.previewTemplateProps.toJSON() ) ); | |
linkInput = control.$el.find( '.link_url' ); | |
if ( ! linkInput.is( document.activeElement ) ) { | |
fieldsContainer = control.$el.find( '.media-widget-fields' ); | |
/*-------------------------------------------------------------- | |
# Step 2: | |
* Similar to Step 1 -- assign fieldsTemplate variable to the script template ID | |
* defined in the PHP file sans 'tmpl-' (Step 5 of PHP instructions) | |
* Name here `custom-media-widget-image-fields` | |
--------------------------------------------------------------*/ | |
// fieldsTemplate = wp.template( 'custom-media-widget-image-fields' ); | |
// fieldsContainer.html( fieldsTemplate( control.previewTemplateProps.toJSON() ) ); | |
} | |
}, | |
/** | |
* Open the media image-edit frame to modify the selected item. | |
* | |
* @returns {void} | |
*/ | |
editMedia: function editMedia() { | |
var control = this, mediaFrame, updateCallback, defaultSync, metadata; | |
metadata = control.mapModelToMediaFrameProps( control.model.toJSON() ); | |
// Needed or else none will not be selected if linkUrl is not also empty. | |
if ( 'none' === metadata.link ) { | |
metadata.linkUrl = ''; | |
} | |
// Set up the media frame. | |
mediaFrame = wp.media({ | |
frame: 'image', | |
state: 'image-details', | |
metadata: metadata | |
}); | |
mediaFrame.$el.addClass( 'media-widget' ); | |
updateCallback = function() { | |
var mediaProps, linkType; | |
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview. | |
mediaProps = mediaFrame.state().attributes.image.toJSON(); | |
linkType = mediaProps.link; | |
mediaProps.link = mediaProps.linkUrl; | |
control.selectedAttachment.set( mediaProps ); | |
control.displaySettings.set( 'link', linkType ); | |
control.model.set( _.extend( | |
control.mapMediaToModelProps( mediaProps ), | |
{ error: false } | |
) ); | |
}; | |
mediaFrame.state( 'image-details' ).on( 'update', updateCallback ); | |
mediaFrame.state( 'replace-image' ).on( 'replace', updateCallback ); | |
// Disable syncing of attachment changes back to server. See <https://core.trac.wordpress.org/ticket/40403>. | |
defaultSync = wp.media.model.Attachment.prototype.sync; | |
wp.media.model.Attachment.prototype.sync = function rejectedSync() { | |
return $.Deferred().rejectWith( this ).promise(); | |
}; | |
mediaFrame.on( 'close', function onClose() { | |
mediaFrame.detach(); | |
wp.media.model.Attachment.prototype.sync = defaultSync; | |
}); | |
mediaFrame.open(); | |
}, | |
/** | |
* Get props which are merged on top of the model when an embed is chosen (as opposed to an attachment). | |
* | |
* @returns {Object} Reset/override props. | |
*/ | |
getEmbedResetProps: function getEmbedResetProps() { | |
return _.extend( | |
component.MediaWidgetControl.prototype.getEmbedResetProps.call( this ), | |
{ | |
size: 'full', | |
width: 0, | |
height: 0 | |
} | |
); | |
}, | |
/** | |
* Get the instance props from the media selection frame. | |
* | |
* Prevent the image_title attribute from being initially set when adding an image from the media library. | |
* | |
* @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame. | |
* @returns {Object} Props. | |
*/ | |
getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) { | |
var control = this; | |
return _.omit( | |
component.MediaWidgetControl.prototype.getModelPropsFromMediaFrame.call( control, mediaFrame ), | |
'image_title' | |
); | |
}, | |
/** | |
* Map model props to preview template props. | |
* | |
* @returns {Object} Preview template props. | |
*/ | |
mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() { | |
var control = this, previewTemplateProps, url; | |
url = control.model.get( 'url' ); | |
previewTemplateProps = component.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call( control ); | |
previewTemplateProps.currentFilename = url ? url.replace( /\?.*$/, '' ).replace( /^.+\//, '' ) : ''; | |
previewTemplateProps.link_url = control.model.get( 'link_url' ); | |
return previewTemplateProps; | |
} | |
}); | |
// Exports. | |
/*-------------------------------------------------------------- | |
# Step 3: | |
* Rename Exports. Name here `logo` | |
--------------------------------------------------------------*/ | |
component.controlConstructors.logo = ImageWidgetControl; | |
component.modelConstructors.logo = ImageWidgetModel; | |
})( wp.mediaWidgets, jQuery ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Widgets; | |
use WP_Widget_Media; | |
use WP_Widget; | |
/** | |
* Widget API: WP_Widget_Media_Image class | |
* | |
* @package WordPress | |
* @subpackage Widgets | |
* @since 4.8.0 | |
*/ | |
/** | |
* Core class that implements an image widget. | |
* | |
* @since 4.8.0 | |
* | |
* @see WP_Widget | |
*/ | |
class WP_Widget_Media_Logo extends WP_Widget { | |
/** | |
* Constructor. | |
* | |
* @since 4.8.0 | |
*/ | |
public $l10n = array( | |
'add_to_widget' => '', | |
'replace_media' => '', | |
'edit_media' => '', | |
'media_library_state_multi' => '', | |
'media_library_state_single' => '', | |
'missing_attachment' => '', | |
'no_media_selected' => '', | |
'add_media' => '', | |
); | |
protected $registered = false; | |
public function __construct() { | |
parent::__construct( 'logo', __( 'Logo' ), array( | |
'description' => __( 'Displays an logo.' ), | |
'mime_type' => 'image', | |
)); | |
$this->l10n = array_merge( $this->l10n, array( | |
'no_media_selected' => __( 'No image selected' ), | |
'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( | |
__( 'We can’t find that image. Check your <a href="%s">media library</a> and make sure it wasn’t deleted.' ), | |
esc_url( admin_url( 'upload.php' ) ) | |
), | |
'media_library_state_multi' => _n_noop( 'Image Widget (%d)', 'Image Widget (%d)' ), | |
'media_library_state_single' => __( 'Image Widget' ), | |
) ); | |
$l10n_defaults = array( | |
'no_media_selected' => __( 'No media selected' ), | |
'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 */ | |
__( 'We can’t find that file. Check your <a href="%s">media library</a> and make sure it wasn’t 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 isn’t the correct kind of file. Please link to an appropriate file instead.' ), | |
); | |
$this->l10n = array_merge( $l10n_defaults, array_filter( $this->l10n ) ); | |
} | |
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 ); | |
} | |
/** | |
* Render the media on the frontend. | |
* | |
* @since 4.8.0 | |
* | |
* @param array $instance Widget instance props. | |
* @return void | |
*/ | |
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 = $attachment->post_excerpt; | |
if ( $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'] ); | |
} | |
$image_attributes['class'] .= sprintf( ' attachment-%1$s size-%1$s', is_array( $size ) ? join( 'x', $size ) : $size ); | |
$image = wp_get_attachment_image( $attachment->ID, $size, false, $image_attributes ); | |
$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]; | |
} 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'] = ''; | |
} | |
$image = sprintf( '<img class="%1$s" src="%2$s" alt="%3$s" width="%4$s" height="%5$s" />', | |
esc_attr( $classes ), | |
esc_url( $instance['url'] ), | |
esc_attr( $instance['alt'] ), | |
esc_attr( $instance['width'] ), | |
esc_attr( $instance['height'] ) | |
); | |
} // End if(). | |
$url = ''; | |
if (!empty($instance['my_link_src'])) { | |
$image = sprintf( | |
'<a href="%1$s" class="%2$s logo" rel="%3$s" style="background-image: url(%4$s)" target="%5$s" %6$s %7$s>%8$s</a>', | |
esc_url($instance['my_link_src'] ), | |
esc_attr( $instance['link_classes'] ), | |
esc_attr( $instance['link_rel'] ), | |
esc_attr( $instance['url'] ), | |
! empty( $instance['link_target_blank'] ) ? '_blank' : '', | |
! empty( $instance['title'] ) ? 'title="'.$instance['title'].'"' : '', | |
! empty( $instance['atributes'] ) ? $instance['atributes'] : '', | |
'' | |
); | |
} | |
if ( $caption ) { | |
$image = img_caption_shortcode( array( | |
'width' => $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() { | |
wp_enqueue_media(); | |
wp_enqueue_script( 'media-widgets' ); | |
$handle = 'custom-media-image-widget'; | |
$path_to_JS = '/inc/Widgets/WP_Widget_Media_Logo.js'; | |
wp_enqueue_script( $handle, // Unique ID | |
get_template_directory_uri() . $path_to_JS, //Filepath | |
array('jquery'), // Dependencies | |
'1.0.0', //Version number | |
true //load in footer | |
); | |
$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() { ?> | |
<script type="text/html" id="tmpl-widget-media-<?php echo esc_attr( $this->id_base ); ?>-control"> | |
<# var elementIdPrefix = 'el' + String( Math.random() ) + '_' #> | |
<p> | |
<label for="{{ elementIdPrefix }}title"><?php esc_html_e( 'Title:' ); ?></label> | |
<input id="{{ elementIdPrefix }}title" type="text" class="widefat title"> | |
</p> | |
<# var elementIdPrefix = 'el' + String( Math.random() ) + '_'; #> | |
<# console.log(data); #> | |
<p> | |
<label data-top='bottom' for="{{ elementIdPrefix }}my_link_src"><?php esc_html_e( 'Link:' ); ?></label> | |
<input id="{{ elementIdPrefix }}my_link_src" type="text" class="widefat text_field" value="{{ data.my_link_src }}" > | |
</p> | |
<p> | |
<label data-top='bottom' for="{{ elementIdPrefix }}atributes"><?php esc_html_e( 'Atributes:' ); ?></label> | |
<input id="{{ elementIdPrefix }}atributes" type="text" class="widefat text_field" value="{{ data.atributes }}" > | |
</p> | |
<div class="media-widget-preview <?php echo esc_attr( $this->id_base ); ?>"> | |
<div class="attachment-media-view"> | |
<div class="placeholder"><?php echo esc_html( $this->l10n['no_media_selected'] ); ?></div> | |
</div> | |
</div> | |
<p class="media-widget-buttons"> | |
<button type="button" class="button edit-media selected"> | |
<?php echo esc_html( $this->l10n['edit_media'] ); ?> | |
</button> | |
<?php if ( ! empty( $this->l10n['replace_media'] ) ) : ?> | |
<button type="button" class="button change-media select-media selected"> | |
<?php echo esc_html( $this->l10n['replace_media'] ); ?> | |
</button> | |
<?php endif; ?> | |
</p> | |
<div class="media-widget-fields"> | |
</div> | |
</script> | |
<?php | |
?> | |
<script type="text/html" id="tmpl-custom-media-widget-image-preview"> | |
<# var describedById = 'describedBy-' + String( Math.random() ); #> | |
<# if ( data.error && 'missing_attachment' === data.error ) { #> | |
<div class="notice notice-error notice-alt notice-missing-attachment"> | |
<p><?php echo $this->l10n['missing_attachment']; ?></p> | |
</div> | |
<# } else if ( data.error ) { #> | |
<div class="notice notice-error notice-alt"> | |
<p><?php _e( 'Unable to preview media due to an unknown error.' ); ?></p> | |
</div> | |
<# } else if ( data.url ) { #> | |
<img class="attachment-thumb" src="{{ data.url }}" draggable="false" alt="{{ data.alt }}" <# if ( ! data.alt && data.currentFilename ) { #> aria-describedby="{{ describedById }}" <# } #> /> | |
<# if ( ! data.alt && data.currentFilename ) { #> | |
<p class="hidden" id="{{ describedById }}"><?php | |
echo sprintf( __( 'Current image: %s' ), '{{ data.currentFilename }}' ); | |
?></p> | |
<# } #> | |
<# } #> | |
</script> | |
<?php | |
} | |
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 ); | |
} | |
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' => '', | |
'name' => 'Link', | |
'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, | |
), | |
'my_link_src' => array( | |
'type' => 'string', | |
'default' => '', | |
// 'sanitize_callback' => 'sanitize_text_field', | |
'description' => __( 'Title for the widget' ), | |
'should_preview_update' => false, | |
), | |
'atributes' => 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 $this Widget object. | |
*/ | |
// $schema = apply_filters( "widget_{$this->id_base}_instance_schema", $schema, $this ); | |
return $schema; | |
} | |
public function display_media_state( $states, $post = null ) { | |
if ( ! $post ) { | |
$post = get_post(); | |
} | |
// Count how many times this attachment is used in widgets. | |
$use_count = 0; | |
foreach ( $this->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; | |
} | |
/** | |
* Sanitizes the widget form values as they are saved. | |
* | |
* @since 4.8.0 | |
* | |
* @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 $instance Previously saved values from database. | |
* @return array Updated safe values to be saved. | |
*/ | |
public function update( $new_instance, $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; | |
} | |
$instance[ $field ] = $value; | |
} | |
return $instance; | |
} | |
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 ) : ?> | |
<input | |
type="hidden" | |
data-property="<?php echo esc_attr( $name ); ?>" | |
class="media-widget-instance-property" | |
name="<?php echo esc_attr( $this->get_field_name( $name ) ); ?>" | |
id="<?php echo esc_attr( $this->get_field_id( $name ) ); // Needed specifically by wpWidgets.appendTitle(). ?>" | |
value="<?php echo esc_attr( is_array( $value ) ? join( ',', $value ) : strval( $value ) ); ?>" | |
/> | |
<?php | |
endforeach; | |
?> | |
<?php | |
} | |
protected function has_content( $instance ) { | |
return ( $instance['attachment_id'] && 'attachment' === get_post_type( $instance['attachment_id'] ) ) || $instance['url']; | |
} | |
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']; | |
/** | |
* 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 $this Widget object. | |
*/ | |
$instance = apply_filters( "widget_{$this->id_base}_instance", $instance, $args, $this ); | |
$this->render_media( $instance ); | |
echo $args['after_widget']; | |
} | |
} |
@zahid-hossain-dev
Used by "namespace Widgets"; the connection code looks like this:
add_action( 'widgets_init', 'theme_register_widgets' );
function theme_register_widgets() {
register_widget('Widgets\WP_Widget_Media_Logo');
}
Links:
https://www.php.net/manual/en/function.call-user-func-array.php
https://www.php.net/manual/en/language.namespaces.rationale.php
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
use in function.php file by include_once. But doesn't show any "Logo" widget in widget area. And also doesn't show any error in console. If i use
If i use those code for register this widget then show error -
Fatal error: Uncaught Error: call_user_func_array(): Argument #1 ($function) must be a valid callback, function "register_custom_image_widget" not found or invalid function name.
(wp v5.7.1)