: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// Ignore the rest of the match object.
shortcode = shortcode.shortcode;
if ( _.isUndefined( shortcode.get('id') ) && ! _.isUndefined( defaultPostId ) ) {
shortcode.set( 'id', defaultPostId );
attachments = this.attachments( shortcode );
selection = new wp.media.model.Selection( attachments.models, {
props: attachments.props.toJSON(),
selection[ this.tag ] = attachments[ this.tag ];
// Fetch the query's attachments, and then break ties from the
// query to allow for sorting.
selection.more().done( function() {
// Break ties with the query.
selection.props.set({ query: false });
selection.props.unset('orderby');
// Destroy the previous gallery frame.
if ( shortcode.attrs.named.type && 'video' === shortcode.attrs.named.type ) {
state = 'video-' + this.tag + '-edit';
state = this.tag + '-edit';
// Store the current frame.
setDefaults: function( attrs ) {
// Remove default attributes from the shortcode.
_.each( this.defaults, function( value, key ) {
attrs[ key ] = self.coerce( attrs, key );
if ( value === attrs[ key ] ) {
wp.media._galleryDefaults = {
id: wp.media.view.settings.post && wp.media.view.settings.post.id,
orderby : 'menu_order ID'
if ( wp.media.view.settings.galleryDefaults ) {
wp.media.galleryDefaults = _.extend( {}, wp.media._galleryDefaults, wp.media.view.settings.galleryDefaults );
wp.media.galleryDefaults = wp.media._galleryDefaults;
wp.media.gallery = new wp.media.collection({
editTitle : wp.media.view.l10n.editGalleryTitle,
defaults : wp.media.galleryDefaults,
setDefaults: function( attrs ) {
var self = this, changed = ! _.isEqual( wp.media.galleryDefaults, wp.media._galleryDefaults );
_.each( this.defaults, function( value, key ) {
attrs[ key ] = self.coerce( attrs, key );
if ( value === attrs[ key ] && ( ! changed || value === wp.media._galleryDefaults[ key ] ) ) {
* @namespace wp.media.featuredImage
wp.media.featuredImage = {
* Get the featured image post ID
* @return {wp.media.view.settings.post.featuredImageId|number}
return wp.media.view.settings.post.featuredImageId;
* Sets the featured image ID property and sets the HTML in the post meta box to the new featured image.
* @param {number} id The post ID of the featured image, or -1 to unset it.
var settings = wp.media.view.settings;
settings.post.featuredImageId = id;
wp.media.post( 'get-post-thumbnail-html', {
post_id: settings.post.id,
thumbnail_id: settings.post.featuredImageId,
_wpnonce: settings.post.nonce
}).done( function( html ) {
window.alert( wp.i18n.__( 'Could not set that as the thumbnail image. Try a different attachment.' ) );
$( '.inside', '#postimagediv' ).html( html );
* Remove the featured image id, save the post thumbnail data and
* set the HTML in the post meta box to no featured image.
wp.media.featuredImage.set( -1 );
* The Featured Image workflow
* @this wp.media.featuredImage
* @return {wp.media.view.MediaFrame.Select} A media workflow.
wp.media.frame = this._frame;
states: [ new wp.media.controller.FeaturedImage() , new wp.media.controller.EditImage() ]
this._frame.on( 'toolbar:create:featured-image', function( toolbar ) {
* @this wp.media.view.MediaFrame.Select
this.createSelectToolbar( toolbar, {
text: wp.media.view.l10n.setFeaturedImage
this._frame.on( 'content:render:edit-image', function() {
var selection = this.state('featured-image').get('selection'),
view = new wp.media.view.EditImage( { model: selection.single(), controller: this } ).render();
this.content.set( view );
// After bringing in the frame, load the actual editor via an Ajax call.
this._frame.state('featured-image').on( 'select', this.select );
* 'select' callback for Featured Image workflow, triggered when
* the 'Set Featured Image' button is clicked in the media modal.
* @this wp.media.controller.FeaturedImage
var selection = this.get('selection').single();
if ( ! wp.media.view.settings.post.featuredImageId ) {
wp.media.featuredImage.set( selection ? selection.id : -1 );
* Open the content media manager to the 'featured image' tab when
* the post thumbnail is clicked.
* Update the featured image id when the 'remove' link is clicked.
$('#postimagediv').on( 'click', '#set-post-thumbnail', function( event ) {
// Stop propagation to prevent thickbox from activating.
wp.media.featuredImage.frame().open();
}).on( 'click', '#remove-post-thumbnail', function() {
wp.media.featuredImage.remove();
$( wp.media.featuredImage.init );
/** @namespace wp.media.editor */
* Send content to the editor
* @param {string} html Content to send to the editor
insert: function( html ) {
var editor, wpActiveEditor,
hasTinymce = ! _.isUndefined( window.tinymce ),
hasQuicktags = ! _.isUndefined( window.QTags );
if ( this.activeEditor ) {
wpActiveEditor = window.wpActiveEditor = this.activeEditor;
wpActiveEditor = window.wpActiveEditor;
* Delegate to the global `send_to_editor` if it exists.
* This attempts to play nice with any themes/plugins
* that have overridden the insert functionality.
if ( window.send_to_editor ) {
return window.send_to_editor.apply( this, arguments );
if ( ! wpActiveEditor ) {
if ( hasTinymce && tinymce.activeEditor ) {
editor = tinymce.activeEditor;
wpActiveEditor = window.wpActiveEditor = editor.id;
} else if ( ! hasQuicktags ) {
} else if ( hasTinymce ) {
editor = tinymce.get( wpActiveEditor );
if ( editor && ! editor.isHidden() ) {
editor.execCommand( 'mceInsertContent', false, html );
} else if ( hasQuicktags ) {
QTags.insertContent( html );
document.getElementById( wpActiveEditor ).value += html;
// If the old thickbox remove function exists, call it in case
// a theme/plugin overloaded it.
if ( window.tb_remove ) {
try { window.tb_remove(); } catch( e ) {}
* Setup 'workflow' and add to the 'workflows' cache. 'open' can
* subsequently be called upon it.
* @param {string} id A slug used to identify the workflow.
* @param {Object} [options={}]
* @return {wp.media.view.MediaFrame.Select} A media workflow.
add: function( id, options ) {
var workflow = this.get( id );
// Only add once: if exists return existing.
workflow = workflows[ id ] = wp.media( _.defaults( options || {}, {
title: wp.media.view.l10n.addMedia,
workflow.on( 'insert', function( selection ) {
var state = workflow.state();
selection = selection || state.get('selection');
$.when.apply( $, selection.map( function( attachment ) {
var display = state.display( attachment ).toJSON();
return this.send.attachment( display, attachment.toJSON() );
}, this ) ).done( function() {
wp.media.editor.insert( _.toArray( arguments ).join('\n\n') );
workflow.state('gallery-edit').on( 'update', function( selection ) {
this.insert( wp.media.gallery.shortcode( selection ).string() );
workflow.state('playlist-edit').on( 'update', function( selection ) {
this.insert( wp.media.playlist.shortcode( selection ).string() );
workflow.state('video-playlist-edit').on( 'update', function( selection ) {
this.insert( wp.media.playlist.shortcode( selection ).string() );
workflow.state('embed').on( 'select', function() {
var state = workflow.state(),
type = state.get('type'),
embed = state.props.toJSON();
embed.url = embed.url || '';
this.send.link( embed ).done( function( resp ) {
wp.media.editor.insert( resp );
} else if ( 'image' === type ) {
if ( 'none' === embed.link ) {
} else if ( 'file' === embed.link ) {
embed.linkUrl = embed.url;
this.insert( wp.media.string.image( embed ) );
workflow.state('featured-image').on( 'select', wp.media.featuredImage.select );
workflow.setState( workflow.options.state );
* Determines the proper current workflow id
* @param {string} [id=''] A slug used to identify the workflow.
* @return {wpActiveEditor|string|tinymce.activeEditor.id}
// If an empty `id` is provided, default to `wpActiveEditor`.
id = window.wpActiveEditor;
// If that doesn't work, fall back to `tinymce.activeEditor.id`.
if ( ! id && ! _.isUndefined( window.tinymce ) && tinymce.activeEditor ) {
id = tinymce.activeEditor.id;
// Last but not least, fall back to the empty string.
* Return the workflow specified by id
* @param {string} id A slug used to identify the workflow.
* @return {wp.media.view.MediaFrame} A media workflow.
* Remove the workflow represented by id from the workflow cache
* @param {string} id A slug used to identify the workflow.
/** @namespace wp.media.editor.send */
* Called when sending an attachment to the editor
* @param {Object} props Attachment details (align, link, size, etc).
* @param {Object} attachment The attachment object, media version of Post.
attachment: function( props, attachment ) {
var caption = attachment.caption,
// If captions are disabled, clear the caption.
if ( ! wp.media.view.settings.captions ) {
delete attachment.caption;
props = wp.media.string.props( props, attachment );
post_content: attachment.description,
options.url = props.linkUrl;
if ( 'image' === attachment.type ) {
html = wp.media.string.image( props );
}, function( option, prop ) {
options[ option ] = props[ prop ];
} else if ( 'video' === attachment.type ) {
html = wp.media.string.video( props, attachment );
} else if ( 'audio' === attachment.type ) {
html = wp.media.string.audio( props, attachment );
html = wp.media.string.link( props );
options.post_title = props.title;
return wp.media.post( 'send-attachment-to-editor', {
nonce: wp.media.view.settings.nonce.sendToEditor,
post_id: wp.media.view.settings.post.id
* Called when 'Insert From URL' source is not an image. Example: YouTube url.
link: function( embed ) {
return wp.media.post( 'send-link-to-editor', {
nonce: wp.media.view.settings.nonce.sendToEditor,
link_text: embed.linkText,