Работа с токенами. Часть 1

Опубликовал Максим Баев, 18 апреля 2016, 09:29

Немного о токенах

Здесь будет описано несколько вариантов работы с токенами. Токены предоставляет третий по популярности модуль Token. Токены - это специальные слова обрамленные квадратными скобками ("[", "]"), которые в некоторых случаях могут заменяться на смысловые значения. Например, если установить четвертый по популярности модуль pathauto, то в админке "Home » Administration » Configuration » Search and metadata » URL aliases" (admin/config/search/path/patterns) можно будет использовать токены для генерации человекочитабельных путей (алиасов) к страницам:
URL Patterns

Чтобы получить список токенов достаточно кликнуть на ссылку Browse available tokens (Показать список доступных токенов), после чего откроется всплывающее окно.
Доступные токены
Для того, чтобы использовать в качестве пути заголовок страницы достаточно вставить токен [node:title] в поле соответствующее пути шаблону пути для вашего типа материала.

Создание своих токенов

Предположим существующие токены, по какой-либо причине, не подходят и нужно создать свой токен. Для этого необходимо создать свой модуль и реализовать два хука:

  • hook_token_info - описывает список доступных токенов
  • hook_tokens - заменяет токен на данные в момент использования

Чтобы программно найти и заменить токены на данные в тексте, достаточно использовать функцию token_replace($text), где $text - это любой текст в котором могут быть токены (так же доступны более сложные варианты использования этой функции. См. в документации).

Итак, у нас уже есть модуль example, теперь нужно реализовать хуки. Чтобы было понятно, что к чему относится, придумаем легенду. Предположим:

У нас есть сайт, который продает какой-либо функционал со своего сайта, а в качестве продуктов использует роли. Если пользователь купил продукт, то ему назначается роль. На сайте есть страница, с карточками продуктов, где пользователи должны видеть ссылки на покупку продукта, если у него нет роли связанной с этим продуктом. Иначе, он должен видеть слово "Куплено", которое означает, что этот продукт уже куплен.

Реализация hook_token_info

Этот хук "сообщает" Друпалу, о новом токене, который он может использовать. Мы назовем его check-product. Добавляем код в файл example.module:

<?php
/**
 * Implements hook_token_info().
 */
function example_token_info() {
  $tokens['user']['check-product:?'] = array(
    'name' => t('User has product'),
    'description' => t('Creates link to purchase ANY product in case if' .
      ' signed in user has no the product, show flag that the product' .
      ' is purchased otherwise.'),
  );

  return array(
    'tokens' => $tokens,
  );
}

Здесь мы добавляем знак вопроса в ключе, таким способом давая понять администратору, что вместо знака вопроса можно подставлять имя любого продукта (роли).
Проверка наличия токена

Токен появился - идем дальше. Теперь нужно добавить обработчик этого токена, иначе он так и будет показываться: [current-user:has-product:?].

Реализация hook_tokens

Теперь Drupal "знает" о новых токенах, которые он может обрабатывать. Но обработчика еще нет. Исправляем этот недочет:

<?php
/**
 * Implements hook_tokens().
 */
function example_tokens($type, $tokens, array $data = array()) {
  // Список замененных токенов на данные.
  $replacements = array();
  // Только если мы получили правильный тип данных и пользователь авторизован.
  if ($type == 'current-user' && !empty($GLOBALS['user']->uid)) {
    $products = $GLOBALS['user']->roles;

    // Шаблон указанный в токене.
    $pattern = 'check-product:';

    // Список токенов приходит как массив, где администратор
    // может проверять наличие сразу несколько продуктов,
    // указав несколько токенов: [current-user:check-product:First] [current-user:check-product:Second]
    foreach ($tokens as $name => $original) {

      // Обрабатываем токен, только если он подходит под наш шаблон.
      if (strpos($name, $pattern) !== FALSE) {
        // Получаем имя продукта(роли).
        $product = substr($name, mb_strlen($pattern));

        // Если у пользователя куплен продукт, то просто показываем Куплено (Purchased).
        if(in_array($product, $products)) {
          $replacements[$original] = t('Purchased');
        }
        // Иначе показываем ссылку на (выдуманную) страницу покупки этого продукта.
        else {
          $title_link = t('Purchase product @product', array(
            '@product' => $product
          ));
          $replacements[$original] = l($title_link, '/purchase/'.$product);
        }
      }
    }
  }

  return $replacements;
}

Результат работы токенов

Администратору сайта достаточно написать [current-user:has-product:Царь], где Role - это любая роль на сайте и пользователи будут видеть Purchase product Царь или Purchased (Куплено).

Правильность написания ролей/продуктов в данном случае мы оставляем на совести администраторов сайта.

Теперь все готово, можно насладиться результатом. Если ввести список токенов:
Enter product tokens

то можно получить
Handled tokens

Этот метод подразумевает под собой использование токенов в теле материала, но Друпал по умолчанию эти поля не обрабатывает. Чтобы это исправить можно поставить модуль Token Filter. Установка и настройка модуля Token Filter достаточно проста.

Продолжение: Работа с токенами. Часть 2

Другие посты