Settings Page Meta Boxes

For a while now I’ve been slowly ripping off functionalities from KC Settings to make it more modular. Today, I’m releasing a helper plugin for you theme/plugin developers out there. This plugin should speed up your development time when creating a settings page for your plugin/theme.

I’m not sure if I’ll be releasing this plugin on WPORG. For now, you can clone/download it from GitHub.

WordPress Plugins Localization

A few days ago, I created an Indonesian translation for the Stream plugin. It’s been a while since I used POEdit to create/update translations, so this post will serve as a reminder for me. πŸ™‚

Before creating the translation for the Stream plugin, I needed to make some changes to the translatable strings so that translators can freely place the tokens. As we all know, each language has its own style, structure, and whatnot, so forcing the order of words in a sentence is a bad idea.

Stream already has some translation when I made those changes, so I needed to provide a quick guide for the translators on how they can update their translations, in this particular case, using POEdit.

Plugin Developers

As plugin developers, you need to read the excellent Language Packs 101 – Prepwork article by Otto, and that’s it. You don’t even need to provide the .po file, but providing the .pot file is a must!

Translators

If this is your first time creating the translation:

  1. Fire up POEdit
  2. Click File Β» New Catalog From POT file
  3. Select the .pot file provided by the plugin
  4. Fill Up the Translation Properties then click OK
  5. Save the file with this format: <plugin-slug>-<language-code>.po, eg: stream-id_ID.po
  6. Translate away and save the file.

If you already have the translation and want to update it:

  1. Fire up POEdit
  2. Open the current .po file
  3. Click Catalog Β» Update from POT file
  4. Select the .pot file provided by the plugin
  5. Translate away and save the file.

Widget Attributes

A while ago, I wrote about how you can add custom classes to your widgets. I’ve also created a plugin that’s available in WPORG but haven’t been updated in a while.

I’m announcing a new plugin, Widget Attributes, that you can use to add custom attributes to your widgets. Currently, it only supports the ID and classes and maybe will support adding custom attributes in the future. For now, you can download it from here. I’m submitting this plugin to WPORG and will retire the old one (I don’t like the name) and will update this post once it’s approved.

Update
The plugin is now live!

WP-CLI on Gentoo

I recently encountered this error when running wp search-replace:

PHP Fatal error:  Call to undefined function cliline() in …/wp-cli/vendor/wp-cli/php-cli-tools/lib/cli/Table.php on line 107

The FAQ says that you will need to install the php-process package, but there’s no such package nor USE flag in Gentoo. After some digging, I found out that the sysvipc and sharedmem are the USE flags that need to be added.

Add HTML Tags in Post and Widget Titles

In a recent project, I needed to use <span /> tags to add some styles (just color, actually) to post and widget titles. By default β€” and there’s no hook to disable this β€” WordPress strips any HTML tags found in post and widget titles. Here’s my solution to this problem. Please keep in mind that I only needed to add <span /> tags, so if you need to add more tags, you should modify the code to fit your needs πŸ™‚

First, add the span tags to the desired post and widget titles, replacing the < and > characters with hashes ( # ):

Add fake span tags to post and widget titles

Now, let’s create a tiny mu-plugin to handle our HTML tags. We’ll be using four filter hooks for this:

  • the_title, triggered in post titles
  • the_title_rss, triggered in post titles for feeds
  • wp_title, triggered in HTML document title, and
  • widget_title, triggered in β€” well, you guessed it right β€” widget titles

The plugin:

/*
Plugin Name: Enable HTML tags in post and widget titles
Author: Dzikri Aziz
Author URI: https://dz.aziz.im/
Version: 0.1
License: GPL v2
*/


function kc_convert_title_html_tags( $string ) {
  global $wp_current_filter;
  $filter = end($wp_current_filter);
  $search = array('#span#', '#/span#');
  $replace = ( in_array($filter, array('wp_title', 'the_title_rss')) || ($filter == 'the_title' && (is_admin() || in_array('wp_head', $wp_current_filter))) ) ? '' : array('<span>', '</span>');
  $string = str_replace( $search, $replace, $string );

  return $string;
}

add_filter( 'the_title', 'kc_convert_title_html_tags' );
add_filter( 'the_title_rss', 'kc_convert_title_html_tags' );
add_filter( 'wp_title', 'kc_convert_title_html_tags' );
add_filter( 'widget_title', 'kc_convert_title_html_tags' );

Take a closer look to the replacement string. We need to strip our fake HTML tags from the post titles when:

  • kc_convert_title_html_tags() is called by wp_title or the_title_rss hook
  • the_title filter hook is triggered from within wp_head action hook (eg. the post title is used by the title attribute of feed links
  • we’re viewing a post table in admin area.

However, when we’re inside the <body />, they need to be converted to the real tags.

That’s it! πŸ™‚

wp_list_pages() for Custom Post Types

wp_list_pages() is a handy little function for displaying a list of hierarchical post type, and it works with custom post types too. Unfortunately, when used for a custom post type, the list items don’t have the necessary CSS classes for current page item/ancestors. Here’s a quick fix for this particular problem.

/**
 * Filter the list of CSS classes
 *
 * @param array   $css_class    An array of CSS classes to be applied
 *                              to each list item.
 * @param WP_Post $page         Page data object.
 * @param int     $depth        Depth of page, used for padding.
 * @param array   $args         An array of arguments.
 */
function kucrut_page_css_class( $css_class, $page, $depth, $args ) {
  if ( empty( $args['post_type'] ) || ! is_singular( $args['post_type'] ) ) {
    return $css_class;
  }

  $_current_page = get_queried_object();

  if ( in_array( $page->ID, $_current_page->ancestors ) ) {
    $css_class[] = 'current_page_ancestor';
  }

  if ( $page->ID === $_current_page->ID ) {
    $css_class[] = 'current_page_item';
  } elseif ( $_current_page && $page->ID === $_current_page->post_parent ) {
    $css_class[] = 'current_page_parent';
  }

  return $css_class;
}
add_filter( 'page_css_class', 'kucrut_page_css_class', 10, 4 );

Using Built-in Post Finder in Plugins

I was making some improvements to the KC Posts widget module in my KC Essentials plugin, and I wanted to make it easy for the users to find post IDs they want to include/exclude from the query. As you may already know, in the Media admin page, we can ‘attach’ an attachment to a post. It uses a neat jQuery UI dialog box to find posts. Here’s how I use it in KC Essentials.

First add we need to add the dialog box and the required JS to the admin page, in my case, it’s widgets.php.

add_action( 'load-widgets.php', 'my_widgets_admin_actions' );
function my_widgets_admin_actions() {
  # Enqueue scripts
  wp_enqueue_script( 'my-widgets-admin-scripts', plugins_url('myscript.js', __FILE__), array('media', 'wp-ajax-response'), '0.1', true );

  # Add the finder dialog box
  add_action( 'admin_footer', 'find_posts_div', 99 );
}

Next, create myscript.js file inside the plugin directory and add these lines:

jQuery(document).ready(function($) {
  // Find posts
  var $findBox = $('#find-posts'),
      $found   = $('#find-posts-response'),
      $findBoxSubmit = $('#find-posts-submit');

  // Open
  $('input.kc-find-post').live('dblclick', function() {
    $findBox.data('kcTarget', $(this));
    findPosts.open();
  });

  // Insert
  $findBoxSubmit.click(function(e) {
    e.preventDefault();

    // Be nice!
    if ( !$findBox.data('kcTarget') )
      return;

    var $selected = $found.find('input:checked');
    if ( !$selected.length )
      return false;

    var $target = $findBox.data('kcTarget'),
        current = $target.val(),
        current = current === '' ? [] : current.split(','),
        newID   = $selected.val();

    if ( $.inArray(newID, current) < 0 ) {
      current.push(newID);
      $target.val( current.join(',') );
    }
  });

  // Double click on the radios
  $('input[name="found_post_id"]', $findBox).live('dblclick', function() {
    $findBoxSubmit.trigger('click');
  });

  // Close
  $( '#find-posts-close' ).click(function() {
    $findBox.removeData('kcTarget');
  });
});

A quick explanation:
When the user double-clicks the input.kc-find-post field, the finder dialog box will popup. Clicking the Select button will send the selected post’s ID to the input field. This can also be done by double-clicking one of the radio inputs at the left side of each found posts.

Need a demo? Just install KC Essentials πŸ™‚

jQuery in Widgets Admin Page

Here’s a quick tip. If you built a custom widget for your themes/plugins and you need jQuery for the configuration form, you’ll need to call it when the ajax process is done, that is when a widget was just dropped to a sidebar/widget area, or the user just saved the configuration.

jQuery(document).ready(function($) {
  $('.widgets-sortables').ajaxSuccess(function() {
    // do your thing
  });
});

Hacking Term List Table

Term list table, unlike post list table, is not very customizable. What I needed was to display the thumbnail/icon of each term, to make it easier for the content editors to distinguish one term from another.

I consider this as a hack, not because we’re going to edit a core file (never ever do that, please!), but because we’re (ab)using a filter hook to display the thumbnail, which should normally be done through an action hook. Unfortunately, if we take a look at wp-admin/includes/class-wp-terms-list-table.php file, there’s only one action hook in there, which can’t help us. However, there’s a filter hook that can be useful for our situation: "{$taxonomy}_row_actions", normally used to customize the action links that show up when we hover over a term row.

Before we begin, We need to decide how we attach an image to a term. There are many plugins out there that can help us with this, but in this guide we’ll be using my own plugin, KC Settings. By the way, if the plugin of your choice doesn’t use termmeta table to store terms metadata, I strongly suggest you to look for another plugin πŸ™‚

Let’s get started with creating a mu-plugin file, or editing a our theme’s function.php file (not recommended). We’ll be using the category taxonomy throughout this guide, but you can off course use other taxonomies.

First we’ll add an entry for KC Settings, (please refer to the sample files included in the plugin to learn about the setting array), or you can also use the Builder if you like.

function my_category_metadata( $groups ) {
  $groups[] = array(
    'category' => array(
      array(
        'id'        => 'category-meta',
        'title'     => 'Metadata',
        'fields'    => array(
          array(
            'id'    => 'icon',
            'title' => 'Icon',
            'type'  => 'file'
          )
        )
      )
    )
  );

  return $groups;
}
add_filter( 'kc_term_settings', 'my_category_metadata' );

Now we can attach an image when creating/editing a term:

Attach/set term icon

To get the data, we can use get_term_meta(). For example, assuming the category ID is 20:

print_r( get_metadata('term', 20, 'icon', true) );

…which outputs:

Array
(
  [selected] => Array
    (
      [0] => 38
    )
  [files] => Array
    (
      [0] => 38
    )
)

Next, we’ll display each term’s icon on the term list table:

function my_category_column_hack( $actions, $term ) {
  if ( $icon = get_metadata('term', $term->term_id, 'icon', true) ) {
    if ( isset($icon['selected'][0]) && $img = wp_get_attachment_image( $icon['selected'][0]) )
      echo '<a href="'.get_edit_post_link($icon['selected'][0]).'" class="term-icon">'.$img.'</a>';
  }

  return $actions;
}
add_filter( 'category_row_actions', 'my_category_column_hack', 10, 2 );

We’re basically done, and the term table should now display the icons of each term. However, we need to add some CSS to make it look a little bit sexier and to match the Media screen.

<?php
function my_admin_inline_styles() {
  $screen = get_current_screen();
  if ( $screen->base == 'edit-tags' ) { ?>
<style>.term-icon {float:left;width:40px;height:40px;overflow:hidden;margin-right:10px} .term-icon img {max-width:100%;height:auto}</style>
  <?php }
}
add_action( 'admin_print_styles', 'my_admin_inline_styles', 99 );

Add Panel to Debug Bar

We all have WP_DEBUG enabled and use Debug Bar when developing WordPress plugins and themes, right? Here’s how I added my own panel.

Debug Bar Panel

class myDebugPanel {
  function title() {
    return 'My Debug';
  }

  function prerender() {}

  function is_visible() {
    return true;
  }

  function render() {
    echo '<pre>Panel content....</pre>';
  }
}

The class should be easy to understand, and don’t remove the prerender() method, it’s needed by Debug Bar when adding our panel.

Next, we’ll inject our new panel into Debug Bar panels collection, and we’re done.

function my_debug_panel_insert( $panels ) {
  $panels[] = new myDebugPanel;
  return $panels;
}
add_filter( 'debug_bar_panels', 'my_debug_panel_insert' );