You are here

function token_tokens in Token 7

Same name and namespace in other branches
  1. 8 token.tokens.inc \token_tokens()

Implements hook_tokens().

File

./token.tokens.inc, line 367
Token callbacks for the token module.

Code

function token_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();
  $url_options = array(
    'absolute' => TRUE,
  );
  if (isset($options['language'])) {
    $url_options['language'] = $options['language'];
    $language_code = $options['language']->language;
  }
  else {
    $language_code = NULL;
  }
  $sanitize = !empty($options['sanitize']);

  // Date tokens.
  if ($type == 'date') {
    $date = !empty($data['date']) ? $data['date'] : REQUEST_TIME;

    // @todo Remove when http://drupal.org/node/1173706 is fixed.
    $date_format_types = system_get_date_types();
    foreach ($tokens as $name => $original) {
      if (isset($date_format_types[$name]) && _token_module('date', $name) == 'token') {
        $replacements[$original] = format_date($date, $name, '', NULL, $language_code);
      }
    }
  }

  // Current date tokens.
  // @todo Remove when http://drupal.org/node/943028 is fixed.
  if ($type == 'current-date') {
    $replacements += token_generate('date', $tokens, array(
      'date' => REQUEST_TIME,
    ), $options);
  }

  // Comment tokens.
  if ($type == 'comment' && !empty($data['comment'])) {
    $comment = $data['comment'];

    // Chained token relationships.
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, entity_uri('comment', $comment), $options);
    }
  }

  // Node tokens.
  if ($type == 'node' && !empty($data['node'])) {
    $node = $data['node'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'source':
          if (!empty($node->tnid) && ($source_node = node_load($node->tnid))) {
            $title = $source_node->title;
            $replacements[$original] = $sanitize ? filter_xss($title) : $title;
          }
          break;
        case 'log':
          $replacements[$original] = $sanitize ? filter_xss($node->log) : $node->log;
          break;
        case 'content-type':
          $type_name = node_type_get_name($node);
          $replacements[$original] = $sanitize ? check_plain($type_name) : $type_name;
          break;
      }
    }

    // Chained token relationships.
    if (!empty($node->tnid) && ($source_tokens = token_find_with_prefix($tokens, 'source')) && ($source_node = node_load($node->tnid))) {
      $replacements += token_generate('node', $source_tokens, array(
        'node' => $source_node,
      ), $options);
    }
    if (($node_type_tokens = token_find_with_prefix($tokens, 'content-type')) && ($node_type = node_type_load($node->type))) {
      $replacements += token_generate('content-type', $node_type_tokens, array(
        'node_type' => $node_type,
      ), $options);
    }
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, entity_uri('node', $node), $options);
    }
  }

  // Content type tokens.
  if ($type == 'content-type' && !empty($data['node_type'])) {
    $node_type = $data['node_type'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'name':
          $replacements[$original] = $sanitize ? check_plain($node_type->name) : $node_type->name;
          break;
        case 'machine-name':

          // This is a machine name so does not ever need to be sanitized.
          $replacements[$original] = $node_type->type;
          break;
        case 'description':
          $replacements[$original] = $sanitize ? filter_xss($node_type->description) : $node_type->description;
          break;
        case 'node-count':
          $query = db_select('node');
          $query
            ->condition('type', $node_type->type);
          $query
            ->addTag('node_type_node_count');
          $count = $query
            ->countQuery()
            ->execute()
            ->fetchField();
          $replacements[$original] = (int) $count;
          break;
        case 'edit-url':
          $replacements[$original] = url("admin/structure/types/manage/{$node_type->type}", $url_options);
          break;
      }
    }
  }

  // Taxonomy term tokens.
  if ($type == 'term' && !empty($data['term'])) {
    $term = $data['term'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'edit-url':
          $replacements[$original] = url("taxonomy/term/{$term->tid}/edit", $url_options);
          break;
        case 'parents':
          if ($parents = token_taxonomy_term_load_all_parents($term->tid)) {
            $replacements[$original] = token_render_array($parents, $options);
          }
          break;
        case 'root':
          $parents = taxonomy_get_parents_all($term->tid);
          $root_term = end($parents);
          if ($root_term->tid != $term->tid) {
            $replacements[$original] = $sanitize ? check_plain($root_term->name) : $root_term->name;
          }
          break;
      }
    }

    // Chained token relationships.
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, entity_uri('taxonomy_term', $term), $options);
    }

    // [term:parents:*] chained tokens.
    if ($parents_tokens = token_find_with_prefix($tokens, 'parents')) {
      if ($parents = token_taxonomy_term_load_all_parents($term->tid)) {
        $replacements += token_generate('array', $parents_tokens, array(
          'array' => $parents,
        ), $options);
      }
    }
    if ($root_tokens = token_find_with_prefix($tokens, 'root')) {
      $parents = taxonomy_get_parents_all($term->tid);
      $root_term = end($parents);
      if ($root_term->tid != $term->tid) {
        $replacements += token_generate('term', $root_tokens, array(
          'term' => $root_term,
        ), $options);
      }
    }
  }

  // Vocabulary tokens.
  if ($type == 'vocabulary' && !empty($data['vocabulary'])) {
    $vocabulary = $data['vocabulary'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'machine-name':

          // This is a machine name so does not ever need to be sanitized.
          $replacements[$original] = $vocabulary->machine_name;
          break;
        case 'edit-url':
          $replacements[$original] = url("admin/structure/taxonomy/{$vocabulary->machine_name}/edit", $url_options);
          break;
      }
    }
  }

  // File tokens.
  if ($type == 'file' && !empty($data['file'])) {
    $file = $data['file'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'basename':
          $basename = pathinfo($file->uri, PATHINFO_BASENAME);
          $replacements[$original] = $sanitize ? check_plain($basename) : $basename;
          break;
        case 'extension':
          $extension = pathinfo($file->uri, PATHINFO_EXTENSION);
          $replacements[$original] = $sanitize ? check_plain($extension) : $extension;
          break;
        case 'size-raw':
          $replacements[$original] = (int) $file->filesize;
          break;
      }
    }
  }

  // User tokens.
  if ($type == 'user' && !empty($data['user'])) {
    $account = $data['user'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'picture':
          if (variable_get('user_pictures', 0)) {
            $replacements[$original] = theme('user_picture', array(
              'account' => $account,
            ));
          }
          break;
        case 'roles':

          // The roles array may be set from checkbox values so ensure it always
          // has 'proper' data with the role names.
          $roles = array_intersect_key(user_roles(), $account->roles);
          $replacements[$original] = token_render_array($roles, $options);
          break;
      }
    }

    // Chained token relationships.
    if (variable_get('user_pictures', 0) && !empty($account->picture) && ($picture_tokens = token_find_with_prefix($tokens, 'picture'))) {

      // @todo Remove when core bug http://drupal.org/node/978028 is fixed.
      $account->picture->description = '';
      $replacements += token_generate('file', $picture_tokens, array(
        'file' => $account->picture,
      ), $options);
    }
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, entity_uri('user', $account), $options);
    }
    if ($role_tokens = token_find_with_prefix($tokens, 'roles')) {

      // The roles array may be set from checkbox values so ensure it always
      // has 'proper' data with the role names.
      $roles = array_intersect_key(user_roles(), $account->roles);
      $replacements += token_generate('array', $role_tokens, array(
        'array' => $roles,
      ), $options);
    }
  }

  // Current user tokens.
  if ($type == 'current-user') {
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'ip-address':
          $ip = ip_address();
          $replacements[$original] = $sanitize ? check_plain($ip) : $ip;
          break;
      }
    }
  }

  // Menu link tokens.
  if ($type == 'menu-link' && !empty($data['menu-link'])) {
    $link = (array) $data['menu-link'];
    if (!isset($link['title'])) {

      // Re-load the link if it was not loaded via token_menu_link_load().
      $link = token_menu_link_load($link['mlid']);
    }
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'mlid':
          $replacements[$original] = $link['mlid'];
          break;
        case 'title':
          $replacements[$original] = $sanitize ? check_plain($link['title']) : $link['title'];
          break;
        case 'url':
          $replacements[$original] = url($link['href'], $url_options);
          break;
        case 'parent':
          if (!empty($link['plid']) && ($parent = token_menu_link_load($link['plid']))) {
            $replacements[$original] = $sanitize ? check_plain($parent['title']) : $parent['title'];
          }
          break;
        case 'parents':
          if ($parents = token_menu_link_load_all_parents($link['mlid'])) {
            $replacements[$original] = token_render_array($parents, $options);
          }
          break;
        case 'root':
          if (!empty($link['p1']) && $link['p1'] != $link['mlid'] && ($root = token_menu_link_load($link['p1']))) {
            $replacements[$original] = $sanitize ? check_plain($root['title']) : $root['title'];
          }
          break;
      }
    }

    // Chained token relationships.
    if (!empty($link['plid']) && ($source_tokens = token_find_with_prefix($tokens, 'parent')) && ($parent = token_menu_link_load($link['plid']))) {
      $replacements += token_generate('menu-link', $source_tokens, array(
        'menu-link' => $parent,
      ), $options);
    }

    // [menu-link:parents:*] chained tokens.
    if ($parents_tokens = token_find_with_prefix($tokens, 'parents')) {
      if ($parents = token_menu_link_load_all_parents($link['mlid'])) {
        $replacements += token_generate('array', $parents_tokens, array(
          'array' => $parents,
        ), $options);
      }
    }
    if (!empty($link['p1']) && $link['p1'] != $link['mlid'] && ($root_tokens = token_find_with_prefix($tokens, 'root')) && ($root = token_menu_link_load($link['p1']))) {
      $replacements += token_generate('menu-link', $root_tokens, array(
        'menu-link' => $root,
      ), $options);
    }
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, array(
        'path' => $link['href'],
      ), $options);
    }
  }

  // Current page tokens.
  if ($type == 'current-page') {
    $current_path = current_path();
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'title':
          $title = drupal_get_title();
          $replacements[$original] = $sanitize ? $title : decode_entities($title);
          break;
        case 'url':
          $replacements[$original] = url($current_path, $url_options);
          break;
        case 'page-number':
          if ($page = filter_input(INPUT_GET, 'page')) {

            // @see PagerDefault::execute()
            $pager_page_array = explode(',', $page);
            $page = $pager_page_array[0];
          }
          $replacements[$original] = (int) $page + 1;
          break;
      }
    }

    // @deprecated
    // [current-page:arg] dynamic tokens.
    if ($arg_tokens = token_find_with_prefix($tokens, 'arg')) {
      foreach ($arg_tokens as $name => $original) {
        if (is_numeric($name) && ($arg = arg($name)) && isset($arg)) {
          $replacements[$original] = $sanitize ? check_plain($arg) : $arg;
        }
      }
    }

    // [current-page:query] dynamic tokens.
    if ($query_tokens = token_find_with_prefix($tokens, 'query')) {
      foreach ($query_tokens as $name => $original) {

        // @todo Should this use filter_input()?
        if (isset($_GET[$name])) {
          $replacements[$original] = $sanitize ? check_plain($_GET[$name]) : $_GET[$name];
        }
      }
    }

    // Chained token relationships.
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
      $replacements += token_generate('url', $url_tokens, array(
        'path' => $current_path,
      ), $options);
    }
  }

  // URL tokens.
  if ($type == 'url' && !empty($data['path'])) {
    $path = $data['path'];
    if (isset($data['options'])) {

      // Merge in the URL options if available.
      $url_options = $data['options'] + $url_options;
    }
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'path':
          $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path;
          $replacements[$original] = $sanitize ? check_plain($value) : $value;
          break;
        case 'alias':

          // @deprecated
          $alias = drupal_get_path_alias($path, $language_code);
          $replacements[$original] = $sanitize ? check_plain($alias) : $alias;
          break;
        case 'absolute':
          $replacements[$original] = url($path, $url_options);
          break;
        case 'relative':
          $replacements[$original] = url($path, array(
            'absolute' => FALSE,
          ) + $url_options);
          break;
        case 'brief':
          $replacements[$original] = preg_replace(array(
            '!^https?://!',
            '!/$!',
          ), '', url($path, $url_options));
          break;
        case 'unaliased':
          $replacements[$original] = url($path, array(
            'alias' => TRUE,
          ) + $url_options);
          break;
        case 'args':
          $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path;
          $replacements[$original] = token_render_array(arg(NULL, $value), $options);
          break;
      }
    }

    // [url:arg:*] chained tokens.
    if ($arg_tokens = token_find_with_prefix($tokens, 'args')) {
      $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path;
      $replacements += token_generate('array', $arg_tokens, array(
        'array' => arg(NULL, $value),
      ), $options);
    }

    // [url:unaliased:*] chained tokens.
    if ($unaliased_tokens = token_find_with_prefix($tokens, 'unaliased')) {
      $unaliased_token_data['path'] = $path;
      $unaliased_token_data['options'] = isset($data['options']) ? $data['options'] : array();
      $unaliased_token_data['options']['alias'] = TRUE;
      $replacements += token_generate('url', $unaliased_tokens, $unaliased_token_data, $options);
    }
  }

  // Entity tokens.
  if (!empty($data[$type]) && ($entity_type = token_get_entity_mapping('token', $type))) {
    $entity = $data[$type];

    // Sometimes taxonomy terms are not properly loaded.
    // @see http://drupal.org/node/870528
    if ($entity_type == 'taxonomy_term' && !isset($entity->vocabulary_machine_name)) {
      $entity->vocabulary_machine_name = db_query("SELECT machine_name FROM {taxonomy_vocabulary} WHERE vid = :vid", array(
        ':vid' => $entity->vid,
      ))
        ->fetchField();
    }
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'url':
          if (_token_module($type, 'url') == 'token' && ($uri = entity_uri($entity_type, $entity))) {
            $replacements[$original] = url($uri['path'], $uri['options']);
          }
          break;
        case 'original':
          if (_token_module($type, 'original') == 'token' && !empty($entity->original)) {
            $label = entity_label($entity_type, $entity->original);
            $replacements[$original] = $sanitize ? check_plain($label) : $label;
          }
          break;
      }
    }

    // [entity:url:*] chained tokens.
    if (($url_tokens = token_find_with_prefix($tokens, 'url')) && _token_module($type, 'url') == 'token') {
      $replacements += token_generate('url', $url_tokens, entity_uri($entity_type, $entity), $options);
    }

    // [entity:original:*] chained tokens.
    if (($original_tokens = token_find_with_prefix($tokens, 'original')) && _token_module($type, 'original') == 'token' && !empty($entity->original)) {
      $replacements += token_generate($type, $original_tokens, array(
        $type => $entity->original,
      ), $options);
    }

    // Pass through to an generic 'entity' token type generation.
    $entity_data = array(
      'entity_type' => $entity_type,
      'entity' => $entity,
      'token_type' => $type,
    );

    // @todo Investigate passing through more data like everything from entity_extract_ids().
    $replacements += token_generate('entity', $tokens, $entity_data, $options);
  }

  // Array tokens.
  if ($type == 'array' && !empty($data['array']) && is_array($data['array'])) {
    $array = $data['array'];
    $sort = isset($options['array sort']) ? $options['array sort'] : TRUE;
    $keys = element_children($array, $sort);
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'first':
          $value = $array[$keys[0]];
          $value = is_array($value) ? render($value) : (string) $value;
          $replacements[$original] = $sanitize ? check_plain($value) : $value;
          break;
        case 'last':
          $value = $array[$keys[count($keys) - 1]];
          $value = is_array($value) ? render($value) : (string) $value;
          $replacements[$original] = $sanitize ? check_plain($value) : $value;
          break;
        case 'count':
          $replacements[$original] = count($keys);
          break;
        case 'keys':
          $replacements[$original] = token_render_array($keys, $options);
          break;
        case 'reversed':
          $reversed = array_reverse($array, TRUE);
          $replacements[$original] = token_render_array($reversed, $options);
          break;
        case 'join':
          $replacements[$original] = token_render_array($array, array(
            'join' => '',
          ) + $options);
          break;
      }
    }

    // [array:value:*] dynamic tokens.
    if ($value_tokens = token_find_with_prefix($tokens, 'value')) {
      foreach ($value_tokens as $key => $original) {
        if (array_key_exists($key, $array) && in_array($key, $keys)) {
          $replacements[$original] = token_render_array_value($array[$key], $options);
        }
      }
    }

    // [array:join:*] dynamic tokens.
    if ($join_tokens = token_find_with_prefix($tokens, 'join')) {
      foreach ($join_tokens as $join => $original) {
        $replacements[$original] = token_render_array($array, array(
          'join' => $join,
        ) + $options);
      }
    }

    // [array:keys:*] chained tokens.
    if ($key_tokens = token_find_with_prefix($tokens, 'keys')) {
      $replacements += token_generate('array', $key_tokens, array(
        'array' => $keys,
      ), $options);
    }

    // [array:reversed:*] chained tokens.
    if ($reversed_tokens = token_find_with_prefix($tokens, 'reversed')) {
      $replacements += token_generate('array', $reversed_tokens, array(
        'array' => array_reverse($array, TRUE),
      ), array(
        'array sort' => FALSE,
      ) + $options);
    }

    // @todo Handle if the array values are not strings and could be chained.
  }

  // Random tokens.
  if ($type == 'random') {
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'number':
          $replacements[$original] = mt_rand();
          break;
      }
    }

    // [custom:hash:*] dynamic token.
    if ($hash_tokens = token_find_with_prefix($tokens, 'hash')) {
      $algos = hash_algos();
      foreach ($hash_tokens as $name => $original) {
        if (in_array($name, $algos)) {
          $replacements[$original] = hash($name, drupal_random_bytes(55));
        }
      }
    }
  }

  // If $type is a token type, $data[$type] is empty but $data[$entity_type] is
  // not, re-run token replacements.
  if (empty($data[$type]) && ($entity_type = token_get_entity_mapping('token', $type)) && $entity_type != $type && !empty($data[$entity_type]) && empty($options['recursive'])) {
    $data[$type] = $data[$entity_type];
    $options['recursive'] = TRUE;
    $replacements += module_invoke_all('tokens', $type, $tokens, $data, $options);
  }

  // If the token type specifics a 'needs-data' value, and the value is not
  // present in $data, then throw an error.
  if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) {

    // Only check when tests are running.
    $type_info = token_get_info($type);
    if (!empty($type_info['needs-data']) && !isset($data[$type_info['needs-data']])) {
      trigger_error(t('Attempting to perform token replacement for token type %type without required data', array(
        '%type' => $type,
      )), E_USER_WARNING);
    }
  }
  return $replacements;
}