In this post, I am going to cover the Admin UI elements of the Quote of the Day code. You can read the previous post to see how I created the custom QOTD post and the tag taxonomy. In that article, I also created the form to enter quotes using the new custom fields of Quote, Person and Source.
If you were following along, you may notice a few gaps in the functionality. The big one is when you select “All Quotes” in the admin panel, which results in the default display of Title, Author, Date, etc. This is not very useful when trying to maintain the list of quotes – so next we are going to customize the display to include our new columns.
Adding and removing columns is pretty easy, we start by adding a filter to the “manage_edit-[post type]_colums” hook like so:
1 2 3 4 5 6 7 8 9 10 | add_filter('manage_edit-qotd_columns','qotd_columns'); function qotd_columns($columns){ $columns['quote'] = 'Quote'; $columns['person'] = 'Person'; $columns['source'] = 'Source'; $columns['author'] = 'Author'; $columns['quote-type'] = 'Quote Type'; unset( $columns['comments'] ); return $columns; } |
add_filter('manage_edit-qotd_columns','qotd_columns'); function qotd_columns($columns){ $columns['quote'] = 'Quote'; $columns['person'] = 'Person'; $columns['source'] = 'Source'; $columns['author'] = 'Author'; $columns['quote-type'] = 'Quote Type'; unset( $columns['comments'] ); return $columns; }
There are two things going on in that filter, first we are adding a column element (such as the first one ‘quote’) with a display value (‘Quote’ in this case) to the $columns array. There is nothing special about the association between the column identifier, such as ‘quote-type’, and the label, which is the more user friendly ‘Quote Type’. The second thing is the removal of the “Comments” column, since we aren’t going to have comments. This is done by removing the element from the columns array with the unset call. However, this is actually a bad example, since the QOTD post type doesn’t support comments (currently) so the UI automatically hides that column for you. An additional note, before you decide to remove the “Title” column, realize that it is the only way by default to have a link to edit the custom post.
You also need to populate the new columns. That is done with a hook to the ‘manage_posts_custom_column’ action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | add_action('manage_posts_custom_column', 'pop_qotd_column'); function pop_qotd_column($column){ if('quote' == $column){ $quote = esc_html( get_post_meta( get_the_ID(), 'quote', true)); echo $quote; } elseif ('person' == $column){ $person = esc_html( get_post_meta( get_the_ID(), 'person', true)); echo $person; } elseif ('source' == $column){ $source = esc_html( get_post_meta( get_the_ID(), 'source', true)); echo $source; } elseif ('author' == $column){ $author = esc_html( get_post_meta( get_the_ID(), 'author', true)); echo $author; } elseif ('quote-type' == $column){ $quote_type = wp_get_post_terms( get_the_ID(), 'qotd_type', array("fields" => "names")); echo esc_html(implode(', ', $quote_type)); } } |
add_action('manage_posts_custom_column', 'pop_qotd_column'); function pop_qotd_column($column){ if('quote' == $column){ $quote = esc_html( get_post_meta( get_the_ID(), 'quote', true)); echo $quote; } elseif ('person' == $column){ $person = esc_html( get_post_meta( get_the_ID(), 'person', true)); echo $person; } elseif ('source' == $column){ $source = esc_html( get_post_meta( get_the_ID(), 'source', true)); echo $source; } elseif ('author' == $column){ $author = esc_html( get_post_meta( get_the_ID(), 'author', true)); echo $author; } elseif ('quote-type' == $column){ $quote_type = wp_get_post_terms( get_the_ID(), 'qotd_type', array("fields" => "names")); echo esc_html(implode(', ', $quote_type)); } }
The first three columns are very straight forward, you are getting the ID for the post listed with get_the_ID()
and using the the get_post_meta()
to bring back the values for each metadata element. Displaying the quote types (which are basically tags) is handled differently. First we bring back an array of the tags using the wp_get_post_terms()
method. The parameters are the ID of the quote in question, the taxonomy we are interested in and what should be returned. In this case, we are asking for all of the names. We turn that array into a comma separated list with the handy PHP implode function, and escape any HTML characters that may have snuck in.
At this point we have the list in a presentable state, but we can improve it further. Let’s make our new columns sortable. The first step is to add the columns you want to sort.
1 2 3 4 5 6 7 8 | add_filter('manage_edit-qotd_sortable_columns','qotd_sort'); function qotd_sort($columns){ $columns['quote'] = 'quote'; $columns['person'] = 'person'; $columns['source'] = 'source'; $columns['author'] = 'author'; return $columns; } |
add_filter('manage_edit-qotd_sortable_columns','qotd_sort'); function qotd_sort($columns){ $columns['quote'] = 'quote'; $columns['person'] = 'person'; $columns['source'] = 'source'; $columns['author'] = 'author'; return $columns; }
Title and Date come with sorting, so those two do not need to be included. It is interesting that Author does not, so we are going to add it. Unfortunately, all the previous code does is construct the url “wp-admin/edit.php?post_type=qotd&orderby=quote&order=asc” for the table header row quote column. Since this is metadata, we have to tell the actual WP query how to sort.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | add_filter('request', 'qotd_orderby'); function qotd_orderby( $args ){ if(!is_admin()) return $args; if(!is_array($args)) return $args; if ( isset( $args['orderby'] ) ) { if ( 'quote' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'quote', 'orderby' => 'meta_value' ) ); } elseif ( 'person' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'person', 'orderby' => 'meta_value' ) ); } elseif ( 'source' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'source', 'orderby' => 'meta_value' ) ); } elseif ( 'author' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'author', 'orderby' => 'meta_value' ) ); } } return $args; } |
add_filter('request', 'qotd_orderby'); function qotd_orderby( $args ){ if(!is_admin()) return $args; if(!is_array($args)) return $args; if ( isset( $args['orderby'] ) ) { if ( 'quote' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'quote', 'orderby' => 'meta_value' ) ); } elseif ( 'person' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'person', 'orderby' => 'meta_value' ) ); } elseif ( 'source' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'source', 'orderby' => 'meta_value' ) ); } elseif ( 'author' == $args['orderby'] ) { $args = array_merge( $args, array( 'meta_key' => 'author', 'orderby' => 'meta_value' ) ); } } return $args; }
Here we intercept the request with a filter, and check a few basic things to see if we need to update it. If we aren’t on the Admin page or if the current arguments are not an array, we don’t need to update the query. If it passes the test, we need to tell the query which meta key to use and how to define “natural order” for the values. A quick check in the documentation provides us the two additional key-value pairs so that we identify the metadata fields and the way it should be ordered. In our case, these are all text fields, so we use the meta_value but if they needed to be ordered numerically, there is a meta_value_num option.
On reflection, I do have “post_type=qotd” in the query string so I could check for the proper post type. This could prevent conflicts if some other code used, for example, “source” as a numeric value and wanted to order it that way.
That is it – you have a list of the quotes and can sort, edit, quick-edit and trash from the “All Quotes” link. Next time we discuss this, we will add some user preferences, create a shortcode and get it on the page.


Latest posts by Larry (see all)
- Warframe Missions: Part 2 – Other Inner Planet Missions - December 22, 2015
- Review: Assassin’s Creed Black Flag - November 22, 2015
- Warframe Missions: Part 1 – the Basic Missions - November 19, 2015