2

Problem:

The WordPress iPhone app (and other WordPress-related smartphone apps) do not allow for much other than the Title and Body fields (i.e. no access to custom fields).

Goal:

My current project requires that we give our mobile bloggers the option to include a subhead with their mobile (and desktop) posts.

Solution:

I'd like to use an optional delimiter in the title. Example:

Main headline | Secondary headline

Screen shot:

enter image description here

Where the | is the delimiter that separates main title:

Main headline

... from the subheadline:

Secondary headline

Code requirements:

All built-in, and plugin, code that use "title"-getting WP methods should always return the half before the delimiter (using example from above):

Main headline

In other words, by default, no title-getting functions will ever return:

| Secondary headline

My code so far:

The code immediately below is a simple starting point.

As you can see, I'm filtering the_title and removing:

| Secondary headline

/**
 * Head/deck handling.
 *
 * Unaltered title (no quotes): "Main headline | Secondary headline"
 *
 * @see http://stackoverflow.com/a/16279114/922323
 * @see http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/post-template.php#L118
 * @see https://wordpress.stackexchange.com/questions/45589/
 */

function foo_the_title($title, $id) {

    return trim(current(explode('|', $title))); // Returns: "Main headline".

}

add_filter('the_title', 'foo_the_title', 10, 2);

By doing the above, I avoid having to worry about any other functions spitting out the delimiter (and the stuff following it), right? I'm assuming all "title"-getting functions/methods will be affected by the filter the_title? Maybe I'm missing a corner case here? UPDATE: I found a corner case: wp_title() ... Makes me wonder what else is out there?

Question(s):

Heres where I'm stuck.

How can I write a custom function (or filter/other) that will return the second half of the title?

I was playing with this:

function foo_the_subheadline() {

    return apply_filters('the_title', '  My Custom Title (tm)  | after the stuff    ');

}

Obviously, that's not doing anything useful (I need the ability to manipulate the code/$title variable in foo_the_title()).

For example, what I'd really like to do is something like this (pseudo code follows, do not use in real world):

function foo_the_title($title, $id, $part = 'current') {

    return trim($part(explode('|', $title)));

}

add_filter('the_title', 'foo_the_title', 10, 3);

function foo_get_me_the_subheadline() {

    foo_the_title(pass the title here, pass the id?, 'end'); // Using variable function: http://php.net/manual/en/functions.variable-functions.php

}

Conclusion:

Well, honestly, I'm hoping ya'll can help me find a conclusion. :)


UPDATE (2013/05/14):

See my answer below.

Thoughts:

  • Could the fundamental logic be improved?
  • Are there any alternative approaches that could work better?

2 Answers 2

4
+50

I am not sure I understand your issue right, but my guess is your conundrum - how to get to the title that is unchanged by your filter, if you are filtering it everywhere?

You can use get_post_field() function to get a raw copy of it from the post object.

However instead of messing with output (and making your saved data dependent on filters being present) I would recommend to work on splitting a title when saving post - assign first part to title as usual and tuck away second part into custom field.

7
  • Thanks @rarst! +1, I'll explore your idea of using a custom field. I guess one disadvantage would the the WP app wouldn't know how to re-load the subtitle when editing a post.
    – mhulse
    May 14, 2013 at 17:31
  • Not sure if it's doable, but instead of removing the subtitle completely from the title with the filter, couldn't you have a CSS to hide the second part?
    – gdaniel
    May 14, 2013 at 19:02
  • @gdaniel That's a decent idea; I think this plugin does something similar to that. Unfortunately, for my needs, I don't think that would be optimal. I really need a clean <h1> and <h2> (i.e. one that does not have any markup in it).
    – mhulse
    May 14, 2013 at 19:40
  • @rarst I've updated my question with a possible solution that uses get_post_field().
    – mhulse
    May 14, 2013 at 20:07
  • @MickyHulse it is more in line with site's mechanics to post solutions as answers (even on own questions), please move it to one :)
    – Rarst
    May 14, 2013 at 20:12
0

Based on this awesome tip by @Rarst:

You can use get_post_field() function to get a raw copy of it from the post object.

Here's a (possible) solution I've just now slapped together:

/**
 * Head/deck handling.
 *
 * Unaltered example title (no quotes): "First half | Second half"
 *
 * @see http://stackoverflow.com/a/16279114/922323
 * @see http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/post-template.php#L118
 * @see https://wordpress.stackexchange.com/questions/45589/
 * @see https://wordpress.stackexchange.com/questions/99039/
 */

/**
 * Private helper function to return a title or deck from the title field.
 *
 * @param $title { string } The `post_title`.
 * @param $part { string } One of "current" or "end". Default: 'current'.
 * @param $delim { string } Delimiter that separates title from deck.
 * @return { string } Title before or after delimiter.
 */

function _foo_the_title_and_deck($title, $part = 'current', $delim = '|') {

    # ((if there's no delim) ? (if the deck is requested return an empty string, otherwise return the unaltered title) : return the filtered title or deck)
    return (( ! strpos($title, $delim)) ? (($part == 'end') ? '' : $title) : trim($part(explode($delim, $title))));

}

/**
 * Filter the `post_title`.
 *
 * @param $title { string } The post title.
 * @return { string } The filterd post title.
 */

function foo_the_title($title) {

    return _foo_the_title_and_deck($title);

}

# Filter `the_title`:
add_filter('the_title', 'foo_the_title', 10, 1); // Is "10" an optimal priority in this case?

# Filter `single_post_title`:
add_filter('single_post_title', 'foo_the_title', 10, 1); // IBID?

/**
 * Filter the "deck" from the `post_title`.
 *
 * @param $post_id { integer } Optional post ID. Default: FALSE.
 * @return { string } The deck from the post's title.
 */

function foo_the_deck($post_id = FALSE) {

    # Use or get the $post_id:
    $post_id = ($post_id) ? $post_id : get_the_ID();

    return _foo_the_title_and_deck(get_post_field('post_title', $post_id), 'end');

}

/**
 * Check for the existence of a deck.
 *
 * @param $post_id { integer } Optional post ID. Default: FALSE.
 * @return { boolean } TRUE if deck exists, otherwise FALSE.
 */

function foo_has_deck($post_id = FALSE) {

    if (foo_the_deck($post_id)) return TRUE;

}

Usage on template level:

<h1><?=the_title()?></h1>

<?php if (foo_has_deck()): ?>

    <h2 class="sh4"><?=foo_the_deck()?></h2>

<?php endif; ?>

It appears to work! Though, I haven't had time yet to do thorough testing.

Ideas for improvement:

  1. Convert to simple OOP "must use" plugin. See 2013/05/15 update below.
  2. Incorporate add_filters that account for other functions not affected by the_title, like wp_title(). Thanks to @DanStefancu's comment, I've covered this corner case by filtering single_post_title.
  3. Other?

2013/05/15 UPDATE

I've created a plugin for this code and put it here (I'm open to feedback). It's my first WP plugin, ever, (I know it could be considerably improved) so please be kind. :)

3
  • 1
    You should also filter single_post_title for wp_title(). May 15, 2013 at 9:37
  • Thanks Dan! I had noticed that wp_title() was not affected by the_title; I was not sure if I should filter that as well. Thanks for the tip/clarification. I'll let you know as soon as I have added that to my example code. Thanks!!! Much appreciated. :)
    – mhulse
    May 15, 2013 at 15:38
  • My answer's been updated. I've also created a repo for a more involved, yet stupidly simple, plugin version.
    – mhulse
    May 15, 2013 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.