Custom byline markup for Co-Authors Plus

Co-Authors Plus is a nice plugin for assigning multiple authors to posts. However, I find its template tag for displaying byline rather limiting because sometimes we want to use fancy markup for the byline (think of avatars, publish/modification dates, etc). You can use the code below as the base for your theme’s byline markup (in this example, we’re overriding twentyfourteen_posted_on()):

function twentyfourteen_posted_on() {
	if ( is_sticky() && is_home() && ! is_paged() ) {
		echo '<span class="featured-post">' . __( 'Sticky', 'twentyfourteen' ) . '</span>';
	}

	// Set up and print post meta information.
	printf( '<span class="entry-date"><a href="%1$s" rel="bookmark"><time class="entry-date" datetime="%2$s">%3$s</time></a></span>',
		esc_url( get_permalink() ),
		esc_attr( get_the_date( 'c' ) ),
		esc_html( get_the_date() )
	);

	// get the co-authors
	if ( function_exists( 'get_coauthors' ) ) {
		$authors = get_coauthors();
	}

	// Fallback to WP users
	if ( empty( $authors ) || ! is_array( $authors ) ) {
		$authors = array( get_userdata( get_the_author_meta( 'ID' ) ) );
	}

	foreach ( $authors as $author ) {
		$_args = apply_filters(
			'coauthors_posts_link',
			array( 'href' => get_author_posts_url( intval( $author->ID ), $author->user_nicename ) )
		);

		printf(
			'<span class="byline"><span class="author vcard"><a class="url fn n" href="%1$s" rel="author">%2$s</a></span></span>',
			esc_url( $_args['href'] ),
			esc_html( $author->display_name )
		);
	}
}

“So how do I display the avatars” you ask? Add the following code to your theme’s functions.php file and use it to get the avatar image instead of the default get_avatar():

/**
 * Wrapper for get_avatar
 *
 * @param mixed  $user    User object, ID or email
 * @param int    $size    Avatar size
 * @param string $default Default avatar image
 * @param string $alt     Alt text
 */
function kucrut_get_avatar( $user, $size = 33, $default = '', $alt = false ) {
	if ( is_object( $user ) && function_exists( 'coauthors_get_avatar' ) ) {
		return coauthors_get_avatar( $user, $size, $default, $alt );
	}
	else {
		return get_avatar( $user, $size, $default, $alt );
	}
}

The State of Bluetooth Headset in Linux

A few days ago, I bought a shiny Sony SBH80 bluetooth headset. This is my first bluetooth headset ever, so I thought I’d share my experience in setting it up.

Android

Yes, Android is Linux, just not the regular one ๐Ÿ™‚
I have a Nexus 5 phone and since it comes with KitKat, the headset is fully supported. Audio quality is superb (both for streaming music and making calls). The only annoyance I experienced is that the headset need to be disconnected from the phone first before connecting it with PC. When the connection with the PC is established, you can then reconnect it with the phone (yes, it supports multiple connections).

Gentoo

I’m running the unstable Gentoo Linux, so I always have the (relatively) latest packages available. I have BlueDevil 2.0_rc1 installed as part of my KDE desktop, along with BlueZ 5.18 as its dependency. BlueDevil easily established the connection with the headset but I couldn’t use it as audio output/sink.

After a quick research, I found out that BlueZ needs to have PulseAudio support to make use of the headset functionalities. I then rebuilt it (along with some multimedia packages) with PulseAudio support. After logging in back to KDE, the headset worked. All I needed to do was giving the headset the highest priority in KDE Phonon settings, so when it’s available, Phonon will use that as the output, otherwise it will revert back to the other available devices.

However, I couldn’t make the microphone work. After some digging, I found out that HSP & HFP support were removed from Bluez 5.0, so until oFono provide those profiles, there’s no way to use the microphone ๐Ÿ™

I was curious and downgraded BlueDevil, Bluez and some other packages to their previous versions that support HFP & HSP profiles. I also removed PulseAudio support from my system since it’s not required. I had to add the following lines to /etc/asound.conf to make the headset recognized by ALSA:

pcm.sbh80 {
        type plug
        slave {
                pcm {
                        type bluetooth
                        device xx:xx:xx:xx:xx:xx
                        profile "auto"
                }
        }
        hint {
                show on
                description "Sony SBH80"
        }
}

ctl.sbh80 {
        type bluetooth
}

After that, the headset worked as audio sink but the microphone was not working still. I then found out that to make use of the microphone, the audio sink service need to be disabled. Enabling only the HFP/HSP profile without A2DP profile with BlueDevil wasn’t possible, so I installed BlueMan and it worked!

However, the sound quality was terrible and often times, Phonon won’t switch to the headset when it’s availabe, and won’t revert back to the built-in sound card when it’s disconnected. Ouch!

I figured, if I added PulseAudio support, the switching should be smooth, and I did. For the most part, it worked, but there’s this delay when the system is making an event sound which was really annoying.

Finally, I reverted back to Bluez5 with PulseAudio support and ‘sacrificed’ the microphone (I don’t do audio chat that often and my built-in mic is working fine anyway). It’s not what I really wanted, but it’s the best option I got and I’m quite happy with it.

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.

GitLab @ DigitalOcean

If you’re using the GitLab image for your droplet in DigitalOcean VPS, don’t forget to update the server_name directive in the Nginx config file (should be located at /etc/nginx/sites-available/gitlab) or you’ll get weird errors.

Also, don’t forget to change the password of MySQL root user and update GitLab’s database.yml config file:)

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.

KMail vs. KPPP

If you’re using a dial-up connection via KPPP and KMail’s complaining about network connection not being detected, just fire up Akonadi Console and toggle your resources’ states from there. I’ve yet to find the solution for this but this trick should help you get your new mails.

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 );