Retrieving taxonomy terms belonging to a set of posts

This issue comes up often, where I need to show a list of all terms belonging to a set of posts being queried. One useful case would be to allow the user to filter the queried posts by clicking on a ‘term’ from the generated list of terms.

Let’s say we are on a taxonomy-term archive page, and we want to show a list of all the terms belonging to the queried set of posts. This is what we can do:

// getting the posts we want based on the taxonomy of current query, returning an array of post IDs
$someposts = get_posts(
        'post_type' => 'custom_post_type',
        'posts_per_page' => -1,
        'fields' => 'ids', // return an array of ids
        'tax_query' => array(
                'taxonomy' => get_query_var('taxonomy'),
                'field' => 'slug',
                'terms' => $term_slug = get_queried_object()->slug,

And to get all the taxonomy terms belonging to the retrieved posts above:

$somepoststerms = get_terms(
        'taxonomy' => 'custom_tax',
        'object_ids' = $someposts;

Caldera Forms – Setting up Conditional Logic based on a post’s taxonomy term

I was trying to set up the following using Caldera Forms’ Conditional Group. This log is based on Caldera Forms 1.7.2.

In my form, I needed a Select field X that was auto populated with a list of every post of a custom post type. This can be easily achieved by selecting ‘Auto Populate’ and choosing ‘Post Type’ when setting up the field using Caldera Forms’ UI. More details can be found under the section ‘Auto-populating Caldera Forms Select Field Options’ in the documentation.

When a user selects an option in field X, I needed another field Y to be hidden or shown based on field X selected option’s taxonomy term (i.e. the selected post’s taxonomy term); if it belonged to taxonomy term Z, then field Y should be hidden.

Caldera Forms’ conditional logic doesn’t provide such logic out of the box – there was no method to check a taxonomy term against the selected option.

To work around, I had to include the taxonomy term slug as part of the value of each option (in field X), with which I can then make use as a condition to check against when setting up the conditional group. However, the ‘Auto Populate’ method mentioned above does not allow us to set the taxonomy term slug as part of each option’s value.

Caldera has a caldera_forms_render_get_field filter that allows us to customise auto populated fields. So we’ll code this:

add_filter( 'caldera_forms_render_get_field', function( $field )  {
    if ( 'field_X_slug' == $field[ 'slug' ]  ) {
        $args = array(
            'post_type' => 'custom-post-type',
            'order' => 'ASC',
            'orderby' => 'title',
            'posts_per_page' => -1,

        $myposts = get_posts( $args );

        if ( ! empty( $myposts ) ) {
            foreach( $myposts as $post ) {
                $post_terms = get_the_terms( $post->ID , 'custom-taxonomy' );
                $field_value = array();
                foreach ( $post_terms as $post_term ) {
                    $field_value[] = $post_term->slug;
                $field_value[] = $post->post_name;
                $field[ 'config' ][ 'option' ][ $post->ID ] = array(
                    'value' => '_' . implode( "_", $field_value ),
                    'label' => wp_strip_all_tags( $post->post_title, true )
    return $field;

This results in field X’s options having values that look something like ‘_tax-term-Z_tax-term-AZ_post-slug’.

Having the above, we can then set up a conditional group by setting up a conditional line that hides field Y if field X CONTAINS _tax-term-Z_.

Changing ‘Stock Availability’ Text for Product Variations

This documents one method to change the ‘Stock Availability’ text for Woocommerce Product Variations.

My requirement was that when a Product Variation was selected by the user on the frontend, in the following instances I wanted to show the corresponding availability text:

  • Available: ‘[number] units available for your purchase.’ instead of the default ‘Available’.
  • Out Of Stock: ‘Oops, we have no stock left.’ instead of the default ‘Out of stock’.

In order to do this, we need to override the template found in the plugin directory woocommerce/single-product/add-to-cart/variable.php. This is where the ‘Add to Cart’ code for the Variable Product’s page is found.

In this template, you’ll find the following:

<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $available_variations ) ) ?>">

json_encode( $available_variations ) provides the data which is used for updating (via javascript) the corresponding information such as minimum quantity, stock availability on the product page whenever the user selects a product variation on the dropdown select.

The variable $available_variations is an array passed into the page from a WooCommerce function woocommerce_variable_add_to_cart found in includes/wc-template-functions.php. Note that this variable is derived from $product->get_available_variations(), and it returns values (such as min and max quantity, stock availability) for all available Variations found under a Variable Product.

Therefore, we need to update the availability_html value to reflect what we want for each variation, and then output the updated $available_variations that will be parsed by json_encode().

So in the variable.php template, I added the following code before the <form> element:

foreach( $available_variations as $i => $variation ) {
    //check if variation has stock or not 
    if ( $variation['is_in_stock'] ) {
        // Get max qty that user can purchase
        $max_qty = $variation['max_qty'];

        // Prepare availability html for stock available instance
        $availability_html = '<p class="stock in-stock">' . $max_qty . ' units available for your purchase.' . '</p>';
    } else {
        // Prepare availability html for out of stock instance
        $availability_html = '<p class="stock out-of-stock">Oops, we have no stock left.</p>';
    $available_variations[$i]['availability_html'] = $availability_html;

And the json_encode found at the form’s data-product_variations attribute will create the updated data.

That’s it.

Querying Custom Post Types with Page Navigation on Front Page

I was experimenting with displaying custom post types on the front page of a wordpress site using various methods.

I had first tried using get_posts(), but it couldn’t deal with pagination.

The next alternative was to use WP_Query(). At first I had tried to implement this in the home.php template, but next_posts_link() returned an error 404. It had teh same result when I tried in on front-page.php.

My last try was to implement this as a page template, and in the “Reading Settings” of the WordPress admin, selected to display a static page that used the page template.


This made a difference, and it worked. So I’ve come to the conclusion that when implementing a solution to display custom post types with pagination on a website’s home page, using WP_Query() through a page template is the optimal way to do so.

Here’s the final code:

//get the correct paged figure on a static page - see related note (a)
if ( get_query_var('paged') ) {
   $paged = get_query_var('paged');
elseif ( get_query_var('page') ) {
   $paged = get_query_var('page');
else {
   $paged = 1;

// Query Custom Post Type posts. WP_query instead of get_posts for pagination purposes
$custom_posts = new WP_Query(
      'post_type' => 'my_custom_post_type',
      'paged' => $paged

// Start the loop
if ( $custom_posts->have_posts() ) :
   while ( $custom_posts->have_posts() ) :
      get_template_part( 'content-archive', get_post_type() );

// next_posts_link() usage with max_num_pages - see related note (b)
next_posts_link( 'Older Entries', $custom_posts->max_num_pages );
previous_posts_link( 'Newer Entries' );

Related notes:
(a) https://codex.wordpress.org/Pagination
(b) https://codex.wordpress.org/Function_Reference/next_posts_link

Adding Custom Styles Dropdown in WordPress TinyMCE Editor

I have been trying out a WordPress plugin called WP Code Prettify to make code snippets on this website look more presentable. Previously, I was simply using <pre> or <code> tags without any styling and it was difficult to read.

Well, WP Code Prettify will automatically style all <pre> or <code> tags specified with the prettyprint CSS class.

Everything’s pretty cool except that I had to manually type in class="prettyprint" in the WordPress text editor, which is going to be somewhat of a hassle in the long run.

Prior to WordPress 3.9, there was a ‘Formats’ dropdown, in which we could add custom styles which the user could then simply select to apply specific CSS classes to elements.

But in 3.9’s TinyMCE 4.0, the Formats dropdown is hidden by default. So the first thing I had to do was to reactivate it. This Formats dropdown “button” in TinyMCE is called styleselect. In functions.php in the theme, enable styleselect like this:

// Callback function to insert 'styleselect' into the $buttons array
function custom_mce_buttons_2( $buttons ) {
    array_unshift( $buttons, 'styleselect' );
    return $buttons;
// Register the callback to the appropriate filter
add_filter('mce_buttons_2', 'custom_mce_buttons_2');

Note that ‘_2’ in the mce_buttons_2 filter refers to the second row of the TinyMCE buttons. I could use mce_buttons_3 which would add it to an empty third row but it wouldn’t look as good, sitting there all alone – wasting space as well.

Now I can go on to add custom styles to this Formats dropdown, which will allow me to simply select it from the list and apply it to <pre> elements:

// Callback function to filter the MCE settings
function custom_mce_before_init_insert_formats( $init_array ) {  
    // Define the style_formats array
    $style_formats = array(  
            'title' => 'Prettify',  
            'block' => 'pre',  
            'classes' => 'prettyprint',
            'styles' => array(
                'display' => 'block',
                'background' => '#eee',
                'white-space' => 'pre-wrap',
                'padding' => '10px'
            'title' => 'AnotherOne',  
            'inline' => 'span',  
            'classes' => 'class-a class-b etc'
            'title' => 'AnotherTwo',  
            'selector' => 'p',  
            'classes' => 'class-d'
    // Insert the array, JSON ENCODED, into 'style_formats'
    $init_array['style_formats'] = json_encode( $style_formats );  
    return $init_array;  

// Attach callback to 'tiny_mce_before_init' 
add_filter( 'tiny_mce_before_init', 'custom_mce_before_init_insert_formats' );

The above code will add 3 new style formats titled Prettify, AnotherOne and AnotherTwo to the Formats dropdown.

Selecting Prettify will apply the prettyprint class to an element. Since the block argument was specified as pre, it creates a new <pre> element with the style applied, and will replace the existing block element selected.

When AnotherOne is selected: since the inline argument was specified, it creates a new inline <span> element with the specified classes applied, and will wrap whatever is selected in the editor, not replacing any tags.

When AnotherTwo is selected: since the selector argument was specified, it limits the specified format to a specific HTML tag (in this case, the <p>), and will apply the specified classes to an existing tag instead of creating one.

You can refer to the WP Codex for the full Style Format Arguments specified for $style_formats. Just an additional note regarding ‘styles’ argument – this is used for rendering the style of the element when shown in the editor. I could have added this in editor-style.css instead.

To go further, if I have many other format items to add to the dropdown, I could even categorise multiple format items by creating a nested dropdown by specifying $style_formats like this, :

// Creating nested format/style items with it's own settings
$style_formats = array(  
        'title' => 'Category 1',
        'items' => array(
                'title' => 'Item 1',  
                'block' => 'div',  
                'classes' => 'class-a'
                'title' => 'Item 1',  
                'block' => 'div',  
                'classes' => 'class-b'
        'title' => 'Category 2',
        'items' => array(
                'title' => 'Item 3',  
                'block' => 'div',  
                'classes' => 'class-c'
                'title' => 'Item 4',  
                'block' => 'div',  
                'classes' => 'class-d'

So that’s all, and not too difficult to implement. In my opinion, it is important to consider how you would want your user to use the style formats that you add to the Formats dropdown. So specifying the correct values to the inline | block | selector and wrapper arguments is crucial. For example, if wrapper is set to true for a format, and the user keeps on applying it to a block element without first clearing the formatting, we will end up creating nested block elements unknowingly.

Formats Dropdown

An example of a TinyMCE Formats nested dropdown button

Now, I hope the code snippets are easier to read than before!

Next and previous post link in same custom taxonomy

Until now, if you use next_post_link(‘%link’, ‘%title’, true) or previous_post_link(‘%link’, ‘%title’, true) to get the adjacent post for a custom post type which has a taxonomy assigned to it, it doesn’t work as intended. This is because these two functions are based on get_adjacent_post() which is hardcoded to look to the taxonomy ‘category’. So hard luck if you need them to work for your custom taxonomy.

There is a plugin that helps solve this issue: http://wordpress.org/extend/plugins/previous-and-next-post-in-same-taxonomy (update: this plugin is no longer available).  And work is ongoing to resolve this, which you might want to have a read: http://core.trac.wordpress.org/ticket/17807 .

However, if you have customised the order of your custom post type posts, the above plugin is not going to work, because the above mentioned functions are hardcoded to get next and previous posts based on their post dates.

So if you need to get next and previous post links in the same custom taxonomy, with a custom posts order, you might want to try these few lines of codes in your single.php template:

// get_posts in same custom taxonomy
$postlist_args = array(
   'posts_per_page'  => -1,
   'orderby'         => 'menu_order title',
   'order'           => 'ASC',
   'post_type'       => 'your_custom_post_type',
   'your_custom_taxonomy' => 'your_custom_taxonomy_term'
$postlist = get_posts( $postlist_args );

// get ids of posts retrieved from get_posts
$ids = array();
foreach ($postlist as $thepost) {
   $ids[] = $thepost->ID;

// get and echo previous and next post in the same taxonomy        
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
if ( !empty($previd) ) {
   echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
if ( !empty($nextid) ) {
   echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';

Hope this helps!


The above issues to get adjacent posts based on taxonomy has been fixed according to http://core.trac.wordpress.org/ticket/17807 , but this is still limited to getting posts sorted by post date only. However, this is being resolved here: https://core.trac.wordpress.org/ticket/26937 .

You can now add a $taxonomy argument to each of the adjacent post functions. Previously, related functions took an array of category (IDs) to search. These can now be taxonomy term IDs and each function now has $taxonomy = ‘category’ as an optional argument.

Related functions affected: get_previous_post(), get_next_post(), get_adjacent_post(), get_adjacent_post_rel_link(), adjacent_posts_rel_link(), next_post_rel_link(), prev_post_rel_link(), get_boundary_post(), get_previous_post_link(), previous_post_link(), get_next_post_link(), next_post_link(), get_adjacent_post_link(), adjacent_post_link().

get_header_image() returns null

While working on a theme in wordpress 3.4.2, I realised that wordpress function get_header_image() returns null in a ‘mu-plugins’ plugin even though in the theme’s functions.php file I’ve set a ‘default-image’ like this:

add_theme_support( 'custom-header', array(
    'default-image' => get_template_directory_uri() . '/subdir/default-header-image.jpg'

In the theme template file header.php, I’ve called get_header_image(), and it returns the default image properly on the front-end.

It seems the ‘default-image’ defined in functions.php add_theme_support is not ‘saved’ into the database upon theme activation. And most probably because functions.php is loaded after mu-plugins, and therefore in the plugin it’s not possible to use get_header_image() to get the  ‘default-image’ defined in ‘add_theme_support’.

Well, now the question is whether wordpress should save the ‘default-image’ to database upon theme activation? Comments anyone?

WordPress Tinymce Dialogs

If you are trying to implement tinymce for your theme options page or plugins and the Insert/edit link doesn’t pop up the dialog after the button is clicked, try this:

add_action( 'admin_print_footer_scripts', 'wp_tiny_mce_preload_dialogs', 30 );
add_action( 'tiny_mce_preload_dialogs', 'wp_link_dialog', 30 );

This worked for me as of version 3.1.3.

Converting HTML entities to characters

I was trying to use WordPress post titles as email subject headers in such a way:

$subject = get_the_title();
wp_mail( $to, $subject, $message);

However this became a problem when the post title included smart quotes, em-dash, ellipsis and the likes of them. My email subject ended up looking like this:

Hey &#8211; This is my Post&#8217;s Title

where it should have been:

Hey - This is my Post's Title

Well, I solved this by using the php function html_entity_decode before sending the $subject to wp_mail():

$subject = html_entity_decode( get_the_title(), ENT_QUOTES, 'UTF-8' )

ENT_QUOTES denotes converting both double and single quotes. The last parameter defines the character set – it is set as UTF-8 since smart quotes and em-dashes are part of the UTF-8 set.

Extend WordPress Login Expiration

The default login session cookie is 48 hours. Although it’s usually enough for most users, it can be frustratingly short for developers and administrators. Here’s something useful for those who do not want the hassle of logging in now and then. Add this to your theme’s functions.php , or create a php file and load it in the Must Use Plugins folder:

add_filter( 'auth_cookie_expiration', 'new_login_session_period' );
function new_login_session_period( $expirein ) {
    return 31556926; // this equals to 1 year in seconds

But I guess you’ll also have to make sure that your browser settings does not expire your cookies within 1 year (or any figure that you’ve specified) for the above to work.

© 2021 Bucket Press