You are here

page_title.module in Page Title 5.2

Enhanced control over the page title (in the head tag).

This module gives you control over the page title. It gives you the chance to provide patterns for how the title should be structured, and on node pages, gives you the chance to specify the page title rather than defaulting to the node title.

File

page_title.module
View source
<?php

/**
 * @file
 * Enhanced control over the page title (in the head tag).
 *
 * This module gives you control over the page title. It gives you the chance
 * to provide patterns for how the title should be structured, and on node
 * pages, gives you the chance to specify the page title rather than defaulting
 * to the node title.
 */

/**
 * Implementation of hook_help().
 */
function page_title_help($section) {
  $output = NULL;
  switch ($section) {
    case 'admin/content/page_title':
      $output = '<p>' . t('Page Title provides control over the &lt;title> element on a page using token patterns and an optional textfield to override the title of the item (be it a node, term, user or other). The Token Scope column lets you know which tokens are available for this field (Global is always available). Please click on the <strong><em>more help&hellip;</em></strong> link below if you need further assistance.') . '</p>';
      break;
    case 'admin/help#page_title':
      $output = '<p>' . t('Drupal\'s default page title follows one of two patterns:') . '</p>';
      $items = array(
        t('<strong>Default Page</strong>: <samp><em>page title</em> | <em>site name</em></samp>'),
        t('<strong>Default Frontpage</strong>: <samp><em>site name</em> | <em>site slogan</em></samp>'),
      );
      $output .= theme('item_list', $items, NULL, 'ol');
      $output .= '<p>' . t('The <strong>Page Title</strong> module lets you change these defaults in two ways. First, you can adjust the patterns below using the placeholders given. This will change the way the default page titles are created. Second, on enabled forms (curently node, term & user editing forms) you have the option of specifying a title that is different to the title of the item. This field only appears if the <em>Show Field</em> box is checked for the item. If a value is provided it will be used to generate the <samp>[page-title]</samp> placeholder however if it is left blank the <samp>[page-title]</samp> token will inherit the item\'s own title.') . '</p>';
      $output .= '<p>' . t('The <samp>[page-title]</samp> token will default to the value returned from <samp>drupal_get_title</samp> if there is no value specified or no available page title field.') . '</p>';
      $output .= '<p>' . t('Certain types of page title pattern have access to special tokens which others do not, depending on their <em>scope</em>. All patterns have access to the <strong>Global</strong> scope. Content type patterns have access to the <strong>Node</strong> tokens, vocabulary patterns have access to the <strong>Taxonomy</strong> tokens and finally the user patterns have access to the <strong>User</strong> tokens.') . '</p>';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_perm().
 */
function page_title_perm() {
  return array(
    'set page title',
    'administer page titles',
  );
}

/**
 * Implementation of hook_menu().
 */
function page_title_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/content/page_title',
      'title' => t('Page titles'),
      'description' => t('Enhanced control over the page titles (in the &lt;head&gt; tag).'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'page_title_admin_settings',
      ),
      'access' => user_access('administer page titles'),
    );
  }
  else {
    if (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'page_title') {
      require_once 'page_title.admin.inc';
    }
  }
  return $items;
}

/**
 * Implementation of hook_node_type().
 *
 * Updates settings after a node type change.
 */
function page_title_node_type($op, $info) {
  if ($op == 'update' && !empty($info->old_type) and $info->type != $info->old_type) {

    // Load the old node type settings.
    $temp = variable_get('page_title_type_' . $info->old_type, '');

    // If the settings aren't empty, then save them into the new type
    if (!empty($temp)) {
      variable_set('page_title_type_' . $info->type, $temp);
    }

    // Delete the old setting
    variable_del('page_title_type_' . $info - old_type);

    // Essentially, do the same as above but with the _showfield suffix for the node type
    $temp = variable_get('page_title_type_' . $info->old_type . '_showfield', 0);
    if ($temp) {
      variable_set('page_title_type_' . $info->type . '_showfield', $temp);
    }
    variable_del('page_title_type_' . $info - old_type . '_showfield');
  }
}

/**
 * Implementation of hook_form_alter().
 */
function page_title_form_alter($form_id, &$form) {

  // If we dont have permission to set the title then we need to abort this alter now!
  if (!user_access('set page title')) {
    return;
  }

  // Check we're editing a node and also check that the node type's 'show field' is enabled
  if ($form['#id'] == 'node-form') {
    $key = 'page_title_type_' . $form['type']['#value'] . '_showfield';
    if (variable_get($key, 0)) {
      $form['page_title'] = array(
        '#type' => 'textfield',
        '#title' => t('Page title'),
        '#description' => t('Provide a description of this node to appear in the &lt;title&gt; tag which search engines can use in search result listings (optional). It is generally accepted this field should be less than 70 characters.'),
        '#default_value' => $form['#node']->page_title,
        '#size' => 60,
        '#maxlength' => 255,
        '#weight' => -4,
      );
    }
  }
  elseif ($form_id == 'taxonomy_form_term') {
    $key = 'page_title_vocab_' . $form['vid']['#value'] . '_showfield';
    if (variable_get($key, 0)) {
      $form['page_title'] = array(
        '#type' => 'textfield',
        '#title' => t('Page title'),
        '#description' => t('Provide a description of this term to appear in the &lt;title&gt; tag which search engines can use in search result listings (optional). It is generally accepted this field should be less than 70 characters.'),
        '#default_value' => page_title_load_title($form['tid']['#value'], 'term'),
        '#size' => 60,
        '#maxlength' => 255,
        '#weight' => -1,
      );
    }
  }
  elseif ($form_id == 'forum_form_forum' || $form_id == 'forum_form_container') {
    $key = 'page_title_vocab_' . $form['vid']['#value'] . '_showfield';
    if (variable_get($key, 0)) {
      $form['page_title'] = array(
        '#type' => 'textfield',
        '#title' => t('Page title'),
        '#description' => t('Provide a description of this forum to appear in the &lt;title&gt; tag which search engines can use in search result listings (optional). It is generally accepted this field should be less than 70 characters.'),
        '#default_value' => page_title_load_title($form['tid']['#value'], 'term'),
        '#size' => 60,
        '#maxlength' => 255,
        '#weight' => -20,
      );
    }
  }
  elseif ($form_id == 'user_profile_form') {
    if (variable_get('page_title_user_showfield', 0)) {
      $form['account']['page_title'] = array(
        '#type' => 'textfield',
        '#title' => t('Page title'),
        '#description' => t('Provide a description of this user to appear in the &lt;title&gt; tag which search engines can use in search result listings (optional). It is generally accepted this field should be less than 70 characters.'),
        '#default_value' => page_title_load_title($form['_account']['#value']->uid, 'user'),
        '#size' => 60,
        '#maxlength' => 255,
        '#weight' => 20,
      );
    }
  }
  elseif ($form_id == 'node_type_form') {
    $form['page_title'] = array(
      '#type' => 'fieldset',
      '#title' => t('Page Title Settings'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#tree' => TRUE,
    );
    $form['page_title']['show_field'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Page Title Field'),
      '#description' => t('If checked, the <em>Page Title</em> field will appear on the node edit form for those who have permission to set the title.'),
      '#options' => array(
        'show_field' => t('Show field'),
      ),
      '#default_value' => variable_get('page_title_type_' . $form['#node_type']->type . '_showfield', 0) ? array(
        'show_field',
      ) : array(),
    );
    $form['page_title']['pattern'] = array(
      '#type' => 'textfield',
      '#title' => t('Page Title Pattern'),
      '#default_value' => variable_get('page_title_type_' . $form['#node_type']->type, ''),
      '#description' => t('Enter the <em>Page Title</em> pattern you want to use for this node type. For more information, please use the !link settings page', array(
        '!link' => l('Page Title', 'admin/content/page_title'),
      )),
    );
    $form['#submit']['page_title_node_type_form_submit'] = array();
  }
  elseif ($form_id == 'forum_admin_settings') {
    $form['page_title_forum_root_title'] = array(
      '#type' => 'textfield',
      '#title' => t('Page title'),
      '#description' => t('Provide a description of this forum overview page to appear in the &lt;title&gt; tag which search engines can use in search result listings (optional). It is generally accepted this field should be less than 70 characters.'),
      '#default_value' => variable_get('page_title_forum_root_title', ''),
      '#size' => 60,
      '#maxlength' => 255,
      '#weight' => -1,
    );
  }
}

/**
 * Submit handler for the page title element added to the node_type_form in the implementation of hook_form_alter() above.
 */
function page_title_node_type_form_submit($form_id, $form_values) {
  $show_field = $form_values['page_title']['show_field']['show_field'] ? 1 : 0;
  variable_set('page_title_type_' . $form_values['type'] . '_showfield', $show_field);
  variable_set('page_title_type_' . $form_values['type'], $form_values['page_title']['pattern']);

  // For some reason the node module adds the fieldset as a separate entry in the variables table... we dont want this!
  variable_del('page_title_' . $form_values['type']);
}

/**
 * Implementation of hook_nodeapi().
 */
function page_title_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'update':
      if (user_access('set page title')) {
        db_query('DELETE FROM {page_title} WHERE type = "node" AND id = %d', $node->nid);
      }

    // fallthrough to insert intentional!
    case 'insert':
      if (isset($node->page_title) && drupal_strlen(trim($node->page_title)) > 0 && user_access('set page title')) {
        db_query('INSERT INTO {page_title} VALUES ("node", %d, "%s")', $node->nid, $node->page_title);
      }
      break;
    case 'delete':
      db_query('DELETE FROM {page_title} WHERE type = "node" AND id = %d', $node->nid);
      break;
    case 'load':
      return array(
        'page_title' => page_title_load_title($node->nid, 'node'),
      );
  }
}

/**
 * Implementation of hook_taxonomy().
 */
function page_title_taxonomy($op, $type, $edit) {
  if ($type == 'vocabulary') {
    return;
  }
  switch ($op) {
    case 'update':
      if (user_access('set page title')) {
        db_query('DELETE FROM {page_title} WHERE type = "term" AND id = %d', $edit['tid']);
      }

    // Fallthrough to insert is intentional!
    case 'insert':
      if (isset($edit['page_title']) && drupal_strlen(trim($edit['page_title'])) > 0 && user_access('set page title')) {
        db_query('INSERT INTO {page_title} VALUES("term", %d, "%s")', $edit['tid'], $edit['page_title']);
      }
      break;
    case 'delete':
      db_query('DELETE FROM {page_title} WHERE type = "term" AND id = %d', $edit['tid']);
      break;
  }
}

/**
 * Implementation of hook_user().
 */
function page_title_user($op, &$edit, &$account) {
  switch ($op) {
    case 'update':
      if (user_access('set page title')) {
        db_query('DELETE FROM {page_title} WHERE type = "user" AND id = %d', $account->uid);
      }

    // Fallthrough to insert is intentional!
    case 'insert':
      if (isset($edit['page_title']) && drupal_strlen(trim($edit['page_title'])) > 0 && user_access('set page title')) {
        db_query('INSERT INTO {page_title} VALUES("user", %d, "%s")', $account->uid, $edit['page_title']);
      }
      break;
    case 'delete':
      db_query('DELETE FROM {page_title} WHERE type = "user" AND id = %d', $account->uid);
      break;
  }
}

/**
 * Simple wrapper function to get the currently set title for a page
 *
 * @return
 *   string the title for the current page
 */
function page_title_get_title() {

  // If we're looking at a node or a comment on a node, get the node object from the menu system.
  if (arg(0) == 'node' && is_numeric(arg(1)) || arg(0) == 'comment' && arg(1) == 'reply' && is_numeric(arg(2)) && module_exists('comment')) {
    $nid = arg(0) == 'node' ? arg(1) : arg(2);
    $node = node_load($nid);

    // If the node has a custom page title and the node type is configured to have a custom page title (ie, it's not a leftover from a previous setting), then use it.
    if (!empty($node->page_title) && variable_get('page_title_type_' . $node->type . '_showfield', 0)) {
      $title = $node->page_title;
    }
  }
  elseif (arg(0) == 'user' && is_numeric(arg(1))) {
    if (variable_get('page_title_user_showfield', 0) && ($user_title = page_title_load_title(arg(1), 'user'))) {
      $title = $user_title;
    }
  }
  elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2)) && module_exists('taxonomy')) {
    $term = taxonomy_get_term(arg(2));
    if (variable_get('page_title_vocab_' . $term->vid . '_showfield', 0) && ($term_title = page_title_load_title($term->tid, 'term'))) {
      $title = $term_title;
    }
  }
  elseif (arg(0) == 'forum' && module_exists('forum')) {

    // If there is a number then its a container or forum
    if (is_numeric(arg(1))) {
      $term = taxonomy_get_term(arg(1));
      if (variable_get('page_title_vocab_' . $term->vid . '_showfield', 0) && ($term_title = page_title_load_title($term->tid, 'term'))) {
        $title = $term_title;
      }
    }
    else {
      $title = variable_get('page_title_forum_root_title', '');
    }
  }

  // If nothing above set a title, give the legacy function a chance to act
  if (empty($title)) {
    $title = page_title_set_title();
  }

  // If we still have no title, fall back to the title provided by Drupal Core
  if (empty($title)) {
    $title = drupal_get_title();
  }

  // Give other modules the oppertunity to use hook_page_title_alter() to modify the title.
  foreach (module_implements('page_title_alter') as $module) {
    $function = $module . '_page_title_alter';
    call_user_func_array($function, array(
      &$title,
    ));
  }

  // Return the title in a safe form (allow no tags (such as emphasised or strong tags) and entity encode)
  return filter_xss($title, array());
}

/**
 * Gets the page title for a type & id.
 *
 * @param $id
 *   int The objects id.
 * @param $type
 *   string What is the scope (usually 'node', 'term' or 'user').
 *
 * @return
 *   string the page title for the given type & id.
 */
function page_title_load_title($id, $type) {
  return db_result(db_query('SELECT page_title FROM {page_title} WHERE type = "%s" AND id = %d', $type, $id));
}

/**
 * Wrapper for old function...
 * NOTE: This has been depricated in favor of page_title_load_title().
 */
function page_title_node_get_title($nid) {
  return page_title_load_title($nid, 'node');
}

/**
 * Legacy page title setting function...
 * NOTE: This has been depreicated in favour of hook_page_title_alter().
 */
function page_title_set_title($title = NULL) {
  static $stored_title;
  if (isset($title)) {
    $stored_title = $title;
  }
  return $stored_title;
}

/**
 * Determines what title should be sent to the page template.
 *
 * Call this function from the page hook of function _phptemplate_variables in
 * template.php.
 *
 * @return
 *   string The page's title.
 */
function page_title_page_get_title() {
  static $title = NULL;
  if (is_null($title)) {

    // If frontpage, then use the frontpage pattern and set the title.
    if (drupal_is_front_page()) {

      // Get the frontpage pattern
      $page_title_pattern = variable_get('page_title_front', '[site-name] | [site-slogan]');

      // If the frontpage pattern is empty, fallback to the default.
      if (empty($page_title_pattern)) {
        $page_title_pattern = variable_get('page_title_default', '[page-title] | [site-slogan]');
      }

      // Append the pattern for pages with a pager on them
      $page_title_pattern .= isset($_REQUEST['page']) ? variable_get('page_title_pager_pattern', '') : '';

      // Give other modules the oppertunity to use hook_page_title_pattern_alter() to modify the title. Only need to pass the pattern, there are no tokens to alter.
      foreach (module_implements('page_title_pattern_alter') as $module) {
        $function = $module . '_page_title_pattern_alter';
        call_user_func_array($function, array(
          &$page_title_pattern,
        ));
      }

      // Apply the token patterns using the one-level replacer (frontpage is only "global" scope). Need to flush the token cache first.
      token_get_values('global', NULL, TRUE);
      $title = token_replace($page_title_pattern);
    }
    else {

      // Initialize some variables we need
      $page_title_pattern = '';
      $types = array(
        'global' => NULL,
      );

      // Determine scope
      // Node (either node or comment reply)
      if (arg(0) == 'node' && is_numeric(arg(1)) || arg(0) == 'comment' && arg(1) == 'reply' && is_numeric(arg(2)) && module_exists('comment')) {
        $nid = arg(0) == 'node' ? arg(1) : arg(2);
        $types['node'] = node_load($nid);
        $page_title_pattern = variable_get('page_title_type_' . $types['node']->type, '');
      }
      elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2)) && module_exists('taxonomy')) {
        $types['taxonomy'] = taxonomy_get_term(arg(2));
        $page_title_pattern = variable_get('page_title_vocab_' . $types['taxonomy']->vid, '');
      }
      elseif (arg(0) == 'forum' && module_exists('forum')) {
        if (is_numeric(arg(1))) {
          $types['taxonomy'] = taxonomy_get_term(arg(1));
        }
        $forum_vid = variable_get('forum_nav_vocabulary', '');
        $page_title_pattern = variable_get('page_title_vocab_' . $forum_vid, '');
      }
      elseif (arg(0) == 'user' && is_numeric(arg(1))) {
        $types['user'] = user_load(array(
          'uid' => arg(1),
        ));
        $page_title_pattern = variable_get('page_title_user', '');
      }
      elseif (arg(0) == 'blog' && is_numeric(arg(1))) {
        $types['user'] = user_load(array(
          'uid' => arg(1),
        ));
        $page_title_pattern = variable_get('page_title_blog', '');
      }

      // If pattern is emtpy (either if the type is not overridable or simply not set) fallback to the default pattern)
      if (empty($page_title_pattern)) {
        $page_title_pattern = variable_get('page_title_default', '[page-title] | [site-name]');
      }

      // Append the pattern for pages with a pager on them
      $page_title_pattern .= isset($_REQUEST['page']) ? variable_get('page_title_pager_pattern', '') : '';

      // Give other modules the oppertunity to use hook_page_title_pattern_alter() to modify the pattern and the tokens.
      $data = array(
        &$page_title_pattern,
        &$types,
      );
      foreach (module_implements('page_title_pattern_alter') as $module) {
        $function = $module . '_page_title_pattern_alter';
        call_user_func_array($function, $data);
      }

      // Apply token patterns using token_replace_multiple after flushing the token cache
      token_get_values('global', NULL, TRUE);
      $title = token_replace_multiple($page_title_pattern, $types);
    }
  }

  // Passing an empty array for the allowed tags as we dont want *any* allowed tags - although any tags should have either been removed or entity encoded by now.
  return filter_xss($title, array());
}

/**
 * Implementation of hook_token_values().
 *
 * @param
 *   string The type of token being generated
 *
 * @return
 *   array An array of Token ID and Token Value pairs
 */
function page_title_token_values($type) {
  $values = array();
  if ($type == 'global') {
    $values['page-title'] = page_title_get_title();
  }
  return $values;
}

/**
 * Implementation of hook_token_list().
 *
 * @param
 *   string Which type of token list are we generating?
 *
 * @return
 *   array Nested array of Token ID and Token Name pairs.
 */
function page_title_token_list($type = 'all') {
  $tokens = array();
  if ($type == 'global' || $type == 'all') {
    $tokens['global']['page-title'] = t("The page title.");
  }
  return $tokens;
}

/**
 * Implementation of hook_preprocess_page().
 */
function page_title_preprocess_page(&$vars) {
  $vars['head_title'] = page_title_page_get_title();
}

Functions

Namesort descending Description
page_title_form_alter Implementation of hook_form_alter().
page_title_get_title Simple wrapper function to get the currently set title for a page
page_title_help Implementation of hook_help().
page_title_load_title Gets the page title for a type & id.
page_title_menu Implementation of hook_menu().
page_title_nodeapi Implementation of hook_nodeapi().
page_title_node_get_title Wrapper for old function... NOTE: This has been depricated in favor of page_title_load_title().
page_title_node_type Implementation of hook_node_type().
page_title_node_type_form_submit Submit handler for the page title element added to the node_type_form in the implementation of hook_form_alter() above.
page_title_page_get_title Determines what title should be sent to the page template.
page_title_perm Implementation of hook_perm().
page_title_preprocess_page Implementation of hook_preprocess_page().
page_title_set_title Legacy page title setting function... NOTE: This has been depreicated in favour of hook_page_title_alter().
page_title_taxonomy Implementation of hook_taxonomy().
page_title_token_list Implementation of hook_token_list().
page_title_token_values Implementation of hook_token_values().
page_title_user Implementation of hook_user().