I’m developing a plugin that adds a tab to the media uploader to add external videos to the media library via oembed. Everything works as expected but I need to switch to the library tab after adding a new external video via the new tab. This is part of the code I’m using:
wp.media.controller.Custom = wp.media.controller.State.extend({
initialize: function(){
this.props = new Backbone.Model({ custom_data: '' });
this.props.on( 'change:custom_data', this.refresh, this );
},
refresh: function() {
this.frame.toolbar.get().refresh();
},
customAction: function(){
wp.media.post( 'add-oembed', {
url: this.props.get('custom_data'),
post_id: wp.media.view.settings.post.id
});
this.frame.content.mode('browse');
}
});
The line this.frame.content.mode('browse')
is supposed to make the switch to the library tab, but I’m getting an error message that says:
TypeError: this.collection is undefined
Any ideas?
1 Answer
After struggling around for days through the poorly documented media modal source code and using code from the gist (thanks, Fabien), I came up with a solution:
JS:
wp.media.controller.Custom = wp.media.controller.State.extend({
initialize: function(){
this.props = new Backbone.Model({ custom_data: '' });
this.props.on( 'change:custom_data', this.refresh, this );
},
refresh: function() {
this.frame.toolbar.get().refresh();
},
// called when the toolbar button is clicked
customAction: function( controller ){
// call the PHP function that inserts an oembed attachment to the database via AJAX
wp.media.post( 'add-oembed', {
url: this.props.get( 'custom_data' ),
post_id: wp.media.view.settings.post.id
}).done( function( resp ) {
// create an attachment model using the data from the AJAX response
var attachment = wp.media.model.Attachment.create( resp );
var edit = controller.state( 'insert' );
// add the attachment to the library model
edit.get( 'library' ).add( attachment );
});
}
});
wp.media.view.Toolbar.Custom = wp.media.view.Toolbar.extend({
initialize: function() {
_.defaults( this.options, {
event: 'custom_event',
close: false,
items: {
custom_event: {
text: wp.media.view.l10n.customButton,
style: 'primary',
priority: 80,
requires: false,
click: this.customAction
}
}
});
wp.media.view.Toolbar.prototype.initialize.apply( this, arguments );
},
refresh: function() {
var custom_data = this.controller.state().props.get('custom_data');
this.get('custom_event').model.set( 'disabled', ! custom_data );
wp.media.view.Toolbar.prototype.refresh.apply( this, arguments );
},
// triggered when the button is clicked
customAction: function(){
this.controller.state().customAction( this.controller );
// switch to the library view
this.controller.setState( 'insert' );
}
});
PHP:
add_action('wp_ajax_add-oembed', 'custom_add_oembed');
function custom_add_oembed() {
$url = $_POST['url'];
$post_ID = intval($_POST['post_id']);
if (!current_user_can( 'edit_post', $post_ID ) ) {
wp_send_json_error();
}
$oembed = new WP_oEmbed();
$provider = $oembed->discover($url);
if($provider === false && substr($url, 0, 5) === 'https') {
$url = str_replace('https', 'http', $url);
$provider = $oembed->discover($url);
}
if($provider === false) {
wp_send_json_error();
}
$response = $oembed->fetch($provider, $url);
if( $response === false) {
wp_send_json_error();
}
$my_post = array(
'post_parent' => $post_ID,
'post_title' => $response->title,
'post_content' => '',
'post_status' => 'inherit',
'post_author' => get_current_user_id(),
'post_type' => 'attachment',
'guid' => $url,
'post_mime_type'=> 'oembed/' . $response->provider_name
);
$attachment_id = wp_insert_post( $my_post );
if( ! is_int($attachment_id) ) {
wp_send_json_error();
}
if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) {
wp_send_json_error();
}
wp_send_json_success( $attachment );
}