Example

Desired page title: Linux (kernel)

where kernel is the top-level taxonomy term. However, such a term might not be set on a node.

I suppose I would enter into Page Title's interface:
[title] ([term-raw])

The surrounding brackets should only show if [term-raw] is actually set (configurable brackets and quotes,etc to display?). Detection of any type of brackets (), {}, [] (escaped I suppose) would be very useful. Instead for now I am title'ing at the module level based on content type for the ones where I need this kind of functionality, which is okay but I would love to see this feature in Page Title. My module functionality only supports () for now.

function mod_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'view':
      if ($node->type == 'song') {
        if (isset($node->field_song_version[0]) && !empty($node->field_song_version[0]['value'])) {
          $node->title .= '(' . check_plain($node->field_song_version[0]['value']) . ')';
          /* Now [page-title] is this and that's how page_title module will see it if the weights are set correctly in the DB */
        }
      }
      break;

    default:
      break;
  }
}

I hope this illustrates what I mean.

Comments

nicholasThompson’s picture

Title: Conditional display of token value with surrounding characters like () » Conditional display of token value with surrounding characters / Optional Tokens
Assigned: Unassigned » nicholasThompson
Status: Active » Needs work

I quite like the idea of being able to wrap parts of the Page Title in something to make them optional (although not entirely sure how it would work... maybe use {{ }}, apply the tokens and then remove {{ and }} if they contain nothing or "whitespace"?)

Alternatively to hook_nodeapi, there is hook_page_title_pattern_alter(&$pattern, &$types) and hook_page_title_alter(&$page_title).

I'm gonna leave this open as a valid feature request though...

Andrew Udvare’s picture

Because I don't think you want to deal with weights any more than this module already does, the proper hook for me was hook_preprocess_page().

function modulename_preprocess_page(&$vars) {
  if ($vars['node']->type == 'song') {
    if (!empty($vars['node']->field_song_version[0]['value'])) {
      $page_title = check_plain('"'.$vars['node']->title.'" ('.$vars['node']->field_song_version[0]['value'].') by '.$vars['node']->field_song_artist[0]['value'].' | ');
      $page_title .= $vars['site_name']; // Can't use check_plain when site title has & in it
      $vars['head_title'] = $page_title;
    }
  }
}

Rather than do what I do (which is very specific to my site), you could just read from a settings table or set variables in the DB. And still use special symbols to mean 'optionally display token' like curly brackets {}.

heyyo’s picture

Any work on this ?

Instead of adding conditionnal brackets why there isn't just a test to check if the token is empty before displaying it ?

nicholasThompson’s picture

Version: 6.x-2.3 » 6.x-2.x-dev

Because you don't know the value of a token until it's been replaced in the content.

I'm thinking something like preg_replace_callback on all optional items first... eg:

{{([term-raw])}}

Using a regex to do a replace on each optional segment FIRST, we can deal with individual tokens; ie if we replace [.+] with nothing, we're left with an empty token to compare to what would be replaced if we run token_replace on the item.

komlenic’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev

#386014: Optional Page Title Parameters was marked as a duplicate of this, but there are some concise descriptions there that parallel the ideas here well.

tj2653’s picture

I've run into the same issue. I have a content type that uses 3 fields in the page title, along with the Site Name and Slogan. But some nodes for this content type don't have data in any of the 3 fields, so I get a very ugly page title of [node:field_lorem] [node:field_ipsum] [node:field_dolor] | MySite | My Site Slogan.

I've tried Andy's workaround, mentioned in post #2, but I'm confused if that could be used alongside the Page Title module, or if Page Title needs to be disabled for it to work.

komlenic’s picture

@tj2653 #2 may be a bit confusing because it's very custom to his site - the important bit is that you can use mymodule_preprocess_XXX to alter the page title, where XXX is the name of the template file where the template variable 'head_title' is inserted. (Which template file 'head_title' appears in may vary depending on your theme.) A solution I have employed may serve as a good example or outright solve your issue:

In my case (probably the most common scenario), I'm using single characters '|' as separators. So I have [node:field_lorem] | [node:field_ipsum] | [node:field_dolor]. I realized the issue is that if any of those are blank, I end up with:

  • A pipe character at the end or beginning of the title string
  • 2 or more pipe characters next to each other

So I wrote this function:

<?php
/**
* Strips multiple, leading, and trailing separators from page titles.
*
* @param $title string The page title.
* @param $separators array An array of page title separators. 
* @return array The page title with any multiple, leading, or trailing
*   separators removed.
*/
function mymodule_title_trim($title, $separators = array('|','-')) {
  foreach ($separators as $char) {
    $special_chars = array ('[', '\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', '{', '}');
   
    if (in_array($char, $special_chars)) {
      $escaped_char = '\\' . $char;
    }
    else {
      $escaped_char = $char;
    }
    //reduce duplicated separators to one
    $title = preg_replace('/((\s)?' . $escaped_char . '(\s)?){2,}/', ' ' . $char . ' ', trim($title));
    //eliminate any separators that occur at string beginning
    $title = preg_replace('/^' . $escaped_char . '(.*)/', '$1', trim($title));
    //eliminate any separators that occur at string end
    $title = preg_replace('/(.*)' . $escaped_char . '$/', '$1', trim($title));
  }
  return $title;
}  
?>

Note that by default the function is checking for | and - as separators. If you're using something else, adjust accordingly.

Now, in my theme, 'head_title' is inserted in html.tpl.php so all I need to do is:

<?php
/**
* Implements hook_preprocess_html().
*/
function mymodule_preprocess_html(&$vars) {
  $vars['head_title'] = mymodule_title_trim($vars['head_title']);
}
?>

Just drop both snippets above in a custom module. You may also need to do some conditions such as checking for the correct node type etc, so that this is only applied on the nodes you want.

Hope that clears it up! This is a fairly elegant workaround but it still would be nice to have logic/conditional ability within Page Title or Token.

tj2653’s picture

Hey Chris - thanks for writing that up! I did see your other post late last night, and customized it to my website (basically I just trim off any time the page title includes "[node:field_lorem] [node:field_ipsum] [node:field_dolor]", since all 3 of those will always either be all empty or all filled. Thanks for the help :)

geefin’s picture

I used a quick and dirty fix, simply dropping

$head_title = preg_replace('`\[[^\]]*\]`','',$head_title);

Into the html.tpl.php template file above the printing of the tag sorted it. This will strip out anything in between the unpopulated '[some-term]' tags.

Not an ideal solution, but a solution for now.

dkre’s picture

Great temp solution - thanks