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, before returning the updated $available_variations for 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.

static_front_page_setting

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(
   array(
      'post_type' => 'my_custom_post_type',
      'paged' => $paged
   )
);

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

// 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

Using WordPress Media Uploader (wp.media)

I am writing this post as of WordPress 4.0, so this has nothing to with the ‘thickbox’ implementation in older versions of WordPress. It has been a long while since the new media library was implementated, but it has not been widely documented.

Tom McFarlin has written quite a comprehensive series titled Getting Started with the WordPress Media Uploader. However, his code had only covered usage of it in a edit/add post setting.

When using wp.media, there are a few things that we are interested. The first one is how to define the media frame. Tom has defined it this way:

file_frame = wp.media.frames.file_frame = wp.media({
    frame: 'post',
    state: 'insert',
    multiple: false
 });

Note that frame: 'post' defines that our frame will be similar to the one we see when we add media in the tinymce editor. There are cases when we are using the media frame apart from the Post setting (e.g. in theme options or a plugin settings page), we need to define it as frame: select' , and state: 'insert' has to be removed.

Also, there are more arguments that the wp.media object can take. Doing a console.log on file_frame after defining it might be useful if you want to dig deeper. But the below is what I’ve used in most cases:

file_frame = wp.media.frames.file_frame = wp.media({
   className: 'media-frame foundation-image-frame',
   frame: 'select'
   multiple: false,
   title: 'Select Media',
   library: { 
      type: 'image' // limits the frame to show only images
   },
   button: { 
      text : 'Select'
   }
});

The second thing that we are interested in is how to capture the event when we have selected the image(s) and clicked on the Select button.

Tom has defined it for a Post Setting this way:

file_frame.on( 'insert', function() {
   // Do things on insert event
});

As expected, this will only work for frame: 'post' . For frame: 'select', we will have to do this:

file_frame.on( 'select', function() {
   // Do things on select event
});

Alright, hope this is useful!

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', 'my_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(  
        array(  
            'title' => 'Prettify',  
            'block' => 'pre',  
            'classes' => 'prettyprint',
            'styles' => array(
                'display' => 'block',
                'background' => '#eee',
                'white-space' => 'pre-wrap',
                'padding' => '10px'
            )    
        ),
        array(  
            'title' => 'AnotherOne',  
            'inline' => 'span',  
            'classes' => 'class-a class-b etc'
        ),
        array(  
            '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(  
    array( 
        'title' => 'Category 1',
        'items' => array(
            array(  
                'title' => 'Item 1',  
                'block' => 'div',  
                'classes' => 'class-a'
            ),
            array(  
                'title' => 'Item 1',  
                'block' => 'div',  
                'classes' => 'class-b'
            )
        )
    ),
    array( 
        'title' => 'Category 2',
        'items' => array(
            array(  
                'title' => 'Item 3',  
                'block' => 'div',  
                'classes' => 'class-c'
            ),
            array(  
                '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!

Update:

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.

Responsive / Adaptive CSS

Neat way to load required css based on device screen width, instead of using media queries or loading all css:

Nathan Smith shows how at adapt.960.gs.

Using a proxy file to load content from external url

/* proxy.php */
<?php echo file_get_contents($_GET['url']);?>

then, assuming that you place proxy.php in the same directory of the html page:

$("#content").load('proxy.php?url=http://example.com');

© 2016 Bucket Press

Top