Shiba

Adventures in WordPress

  • Home
  • Dog
  • Art
  • Contact
  • WordPress Articles
    • WP Plugins
    • WP Programming
    • WP Admin Panels
    • WP Theme Design
    • WP How-To
    • WP Theme Images
You are here: Home / WordPress Programming / How to Expand the WordPress Media Manager Interface

How to Expand the WordPress Media Manager Interface

by ShibaShake 7 Comments

This is an advanced tutorial on how to expand the WordPress media manager interface with new options. In particular, I want to expand the drop-down menu in the media manager menu so that I can do searches based on posts, pages, and custom post types, as well as include their thumbnails into my galleries.

Other media manager tutorials include –

  • How to Add the WordPress 3.5 Media Manager Interface – Basic tutorial on how to add the media manager interface into our plugin or theme.
  • How to Add the WordPress 3.5 Media Manager Interface – Part 2 – More advanced tutorial on how to create our own media manager object, and how to customize its various parameters.
  • How to Add the Media Manager Menu to the Theme Preview Interface – More advanced tutorial on how to add the media manager menu into the WordPress theme customizer interface.

1. Send New Options to Media Manager Interface

Currently, the media manager only allows searches to be performed on images. There are two options in the drop-down menu – Images and Uploaded to this post.

Screenshot of the Create Gallery screen in the media manager interface.
Currently, we can only search based on images while in the create and edit gallery screens.

The first thing that I want to do, is determine which post types I want to add to the search drop-down menu. As a start, I want to be able to search for posts, pages, galleries, and shiba_links, where gallery and shiba_link are custom post types. Therefore, I define and send those entries over to the media manager javascript object by using the media_view_settings filter.

	add_filter( 'media_view_settings', 'my_media_view_settings', 10, 2);

	function my_media_view_settings($settings, $post) {
		$post_types = array('post' => 'Posts', 'page' => 'Pages', 'gallery' => 'Galleries', 'shiba_link' => 'Shiba Links');
		
		// Add in post types
		foreach ($post_types as $slug => $label) {
			if ($slug == 'attachment') continue;
			$settings['postTypes'][$slug] = $label;	
		}
		return $settings;	
	}

We can later access this array in javascript using wp.media.view.settings.postTypes.

2. Add New Options into Gallery Drop-Down Menu

The entries in the search drop-down menu are controlled by the wp.media.view.AttachmentFilters.Uploaded object. More specifically, the filter attributes are defined in the createFilters function. Therefore, to expand the drop-down menu we want to override that javascript function.

	// Override relevant media manager javascript functions
	add_action( 'admin_print_footer_scripts', 'my_override_filter_object', 51);
	function my_override_filter_object() { ?>
    	<script type="text/javascript">
		// Add custom post type filters
		l10n = wp.media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
		wp.media.view.AttachmentFilters.Uploaded.prototype.createFilters = function() {
			var type = this.model.get('type'),
				types = wp.media.view.settings.mimeTypes,
				text;
			if ( types && type )
				text = types[ type ];

			filters = {
				all: {
					text:  text || l10n.allMediaItems,
					props: {
						uploadedTo: null,
						orderby: 'date',
						order:   'DESC'					},
					priority: 10
				},

				uploaded: {
					text:  l10n.uploadedToThisPost,
					props: {
						uploadedTo: wp.media.view.settings.post.id,
						orderby: 'menuOrder',
						order:   'ASC'					},
					priority: 20
				}
			};
			// Add post types only for gallery
			if (this.options.controller._state.indexOf('gallery') !== -1) {
				delete(filters.all);
				filters.image = {
					text:  'Images',
					props: {
						type:    'image',
						uploadedTo: null,
						orderby: 'date',
						order:   'DESC'					},
					priority: 10
				};
				_.each( wp.media.view.settings.postTypes || {}, function( text, key ) {
					filters[ key ] = {
						text: text,
						props: {
							type:    key,
							uploadedTo: null,
							orderby: 'date',
							order:   'DESC'						}
					};
				});
			}
			this.filters = filters;
			
		}; // End create filters
		</script>
    <?php }

Line 7 – Override createFilters function.
Lines 8 – 34 – Copied from original createFilters function.
Lines 35 – 36 – Only change the drop-down menu for the gallery screens (gallery and edit-gallery).
Lines 37 – 47 – Remove the default ‘all’ filter and replace it with an image-type filter. This is necessary because the ‘all’ filter does not contain a type, which becomes important when we start adding in more types in addition to images.
Lines 48 – 58 – Add in our post types from step 1 (wp.media.view.settings.postTypes).

Screenshot of Create Gallery media manager screen with an expanded drop-down menu.
Expanded media manager drop-down menu containing posts, pages, and custom post types.

3. Link new filters to server

Doing searches based on our new post type options, however, always comes up empty. For the right searches to get performed, we also need to link our new filter options to our server.

In particular, searches performed in the media manager interface gets passed on to our server as an AJAX call – wp_ajax_query-attachments. One way to enable our expanded search options is to override this ajax function.

	add_action('wp_ajax_query-attachments', 'my_wp_ajax_query_attachments', 1);
	function my_wp_ajax_query_attachments() {
		if ( ! current_user_can( 'upload_files' ) )
			wp_send_json_error();
	
		$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
		$query = array_intersect_key( $query, array_flip( array(
			's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
			'post_parent', 'post__in', 'post__not_in',
		) ) );

		if (isset($query['post_mime_type']) && ($query['post_mime_type'] != "image")) {
			// post type
			$query['post_type'] = $query['post_mime_type'];
			$query['post_status'] = 'publish';
			unset($query['post_mime_type']);
		} else { 
			// image
			$query['post_type'] = 'attachment';
			$query['post_status'] = 'inherit';
			if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
				$query['post_status'] .= ',private';
		}
		
		$query = apply_filters( 'ajax_query_attachments_args', $query );
		$query = new WP_Query( $query );
	
		// $posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
		$posts = array_map( 'my_prepare_items_for_js'), $query->posts );
		$posts = array_filter( $posts );
	
		wp_send_json_success( $posts );
	}

Lines 3-10 – From original ajax function.
Line 12 – Check for our added post types (i.e. where post_mime_type != image).
Lines 14-16 – Set post_type and post_status appropriately for search. Unset post_mime_type since we are searching based on post types and not based on images.
Lines 18-25 – From original ajax function.
Line 26 – Perform the search using the WP_Query object.
Line 28 – The wp_prepare_attachment_for_js function only prepares attachment objects. Other object types are not processed and then simply removed by the array_filter PHP function on line 30.

To properly return our post type objects, we will need to write our own processing function (my_prepare_items_for_js) that can deal with both attachments and posts.

	function my_prepare_items_for_js($item) {
		switch($item->post_type) {
		case 'attachment':
			return wp_prepare_attachment_for_js($item);
		case 'post':
		case 'page':
		case 'gallery':
		default:
			return my_prepare_post_for_js($item);
		}
	}
	
	function my_prepare_post_for_js( $post ) {
		if ( ! $post = get_post( $post ) )
			return;
	
		$attachment_id = get_post_thumbnail_id( $post->ID );
		$attachment = get_post($attachment_id);
		$post_link = get_permalink( $post->ID );

		$type = $post->post_type; $subtype = 'none';
		if ($attachment) {
			$url = wp_get_attachment_url( $attachment->ID );
		} else { // Show default image
			$url = includes_url('images/crystal/default.png');
		}
		
		$response = array(
			'id'          => $post->ID,
			'title'       => $post->post_title, 
			'filename'    => wp_basename( $post_link ), 
			'url'         => $url,
			'link'        => $post_link,
			'alt'         => '',
			'author'      => $post->post_author,
			'description' => $post->post_content,
			'caption'     => $post->post_excerpt,
			'name'        => $post->post_name,
			'status'      => $post->post_status,
			'uploadedTo'  => $post->post_parent,
			'date'        => strtotime( $post->post_date_gmt ) * 1000,
			'modified'    => strtotime( $post->post_modified_gmt ) * 1000,
			'menuOrder'   => '', // $attachment->menu_order,
			'mime'        => '', // $attachment->post_mime_type,
			'type'        => $type,
			'subtype'     => $subtype,
			'icon'        => $url, // wp_mime_type_icon( $attachment_id ),
			'dateFormatted' => mysql2date( get_option('date_format'), $post->post_date ),
			'nonces'      => array(
				'update' => false,
				'delete' => false,
			),
			'editLink'   => false,
		);
	
		// Don't allow delete or update for posts. So don't create nonces.
		
		return apply_filters( 'wp_prepare_post_for_js', $response, $post );
	}

Once we add in our own query-attachments function, our post type searches work as they should.

Screenshot of the Create Gallery screen where we are doing a post search.
Doing a post search in the wordpress media manager interface.

4. Adding our search results to the gallery

Unfortunately, there is one more fly in the ointment. When we click on Create Gallery, only selected images get added. To include our post type objects, we will need to override the mainGalleryToolbar javascript function.

		// Add to my_override_filter_object function
		wp.media.view.MediaFrame.Post.prototype.mainGalleryToolbar = function( view ) {
			var controller = this;

			this.selectionStatusToolbar( view );

			view.set( 'gallery', {
				style:    'primary',
				text:     l10n.createNewGallery,
				priority: 60,
				requires: { selection: true },

				click: function() {
					var selection = controller.state().get('selection'),
						edit = controller.state('gallery-edit');
		//				models = selection.where({ type: 'image' });

					// Don't filter based on type
					edit.set( 'library', selection);
		/*			edit.set( 'library', new wp.media.model.Selection( selection, {
						props:    selection.props.toJSON(),
						multiple: true
					}) );
		*/					
					this.controller.setState('gallery-edit');
				}
			});
		};

Line 18 – Just pass through our selection instead of filtering it based on image type as is done in lines 19-22.

Now, posts, pages, and more can be added to our media manager gallery.

Screenshot of the Edit Gallery screen after we hit the Create Gallery button.
Now, posts, pages, and more can be added to our media manager gallery.

5. Customize our post type rendering

Finally, we can make our post type objects more pretty by overriding the media manager attachment template.

	// Override attachment template - i.e. how attachment objects are viewed
	// in the media manager interface
	add_action( 'admin_footer', 'my_print_media_templates', 5);
	function print_media_templates() { ?>
	<script type="text/html" id="tmpl-attachment">
		[Insert template code here]
	</script>
	<?php }

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Comments

  1. Ken William says

    October 19, 2017 at 2:13 am

    Thanks to ShibaShake for sharing it, it was really helpful to me personally. I spent nearly a day implementing this feature for my plugin and now it’s really perfect. Great!

    Reply
  2. Cyril says

    January 4, 2015 at 10:01 am

    Hi,

    Thanks for this!

    I have been implementing this but I need more features, for example, I need to display more than on thumbnail per post (we are uing acf and custom get field). We’ve been working on it but we don’t find a way to do it.

    We can pay for this modification, if you are interested in, please contact me and I will explain what I need, and you will tell me your price 🙂

    Thanks in advance,

    Cyril

    Reply
    • Cyril says

      January 16, 2015 at 2:29 am

      Hi,

      Can you help me with this as a freelance job?

      You can contact me on my e-mail address.

      Thanks in advance,

      Cyril

      Reply
      • ShibaShake says

        January 16, 2015 at 9:03 pm

        Hello Cyril, I am not doing any freelance jobs at the moment. Too much on my plate. Good luck with your project.

  3. Zain says

    July 30, 2014 at 4:07 am

    Hi Shiba,

    Great tutorial (and very cool site)!

    I’m just wondering – do you have a tutorial on how you can change the default WordPress Media Manager “Link To | Media File” location so it goes to the *large* version of the image, instead of the *original* size? A lot of site authors are now uploading very large 8MB+ images from their cameras, without realising that they’re slowing down their site. That would be really helpful!

    An nice solution for a plugin/theme would be an option to set the default size for the Media File URL, so a user could choose to always use one of the other sizes (medium/large/original/custom). Alternatively, an image size dropdown, rather than the text input field, for the user to choose the right size.

    Anyway, keep up the great work – it’s appreciated!

    Cheers,

    Zain

    Reply
  4. Rizqy says

    June 6, 2014 at 10:51 am

    Hi, thanks for this cool tutorial. I was spending 2 hours implementing this feature for my plugin and now it works perfectly. 🙂

    Reply
  5. jey says

    January 8, 2014 at 11:08 pm

    HI Its very useful, But is there any way to add a textbox or a new dropdown to the gallery page

    Reply

Recent Posts

  • Screenshot of an example article in code view of a modified Gutenberg editor.How to Harness the Power of WordPress Gutenberg Blocks and Combine It with Legacy Free-Form Text
  • Screenshot of the Success, WordPress has been installed page.Migrating Your WordPress Website to Amazon EC2 (AWS)
  • Screenshot of WinSCP for creating a SFTP configuration.How to Set-Up SFTP on Amazon EC2 (AWS)
  • WordPress Gutenberg code view screenshot of this article.How to Prevent Gutenberg Autop from Messing Up Your Code, Shortcodes, and Scripts
  • Screenshot of the Success, WordPress has been installed page.How to Create a WordPress Website on Amazon EC2 (AWS)

Recent Comments

  • Create Pop-up Windows in Your WordPress Blog with Thickbox (57)
    • Jim Camomile
      - I have used this tutorial several times and it is one of the few simple and effective ways to add popups with dynamic content, ...
  • How to Add Admin Columns in WordPress (7)
    • Andy Globe
      - Hi Friends, I am facing two problem in WordPress admin1. Load custom CSS for wp-admin on user-role base (editor) 2. ...
  • Example blog front-page using excerpts and the Shiba Theme.Optimize Your WordPress Plugins with Tags (5)
    • DF
      - thanks, i went the other way and added a filter if pages I wanted.
  • WordPress Search Widget – How to Style It (57)
    • Nelson
      - Tanks master - Fine
  • Update custom inputs with the proper data using Javascript.Expand the WordPress Quick Edit Menu (59)
    • Mike G
      - This is exactly what is happening to me. It is updating the value in the database and in the column, but I have to refresh ...

Copyright © 2022 · Genesis Skins by ShibaShake · Terms of Service · Privacy Policy ·