Быстрая форма настроек с Variable API

Аватар пользователя kalabro

Код, набросанный на скорую руку в файле custom_misc.module, становится настоящим модулем, когда у него появляются настройки и страница редактирования этих настроек. Это делает модуль удобным для вашего клиента и пригодным для повторного использования на других проектах.
Сегодня я расскажу, как быстро добавить к модулю отличную форму настроек с помощью Variable API (variable).

Например, мы пишем модуль «Информация о компании», который будет централизованно хранить телефоны, факсы, адрес, часы работы подпись в письмах и другую информацию. Все эти данные можно будет отредактировать из админки без специальных знаний Drupal/PHP.
Пример выбран больше для удобства демонстрации, но практической ценности не теряет. Такой модуль поможет владельцу сайта быстро и самостоятельно поменять контактные телефоны одновременно в шапке, футере, на странице контактов и в подписях к письмам.

Назовём наш модуль "custom_company_info" и первым делом определим права на редактирование информации о компании в файле custom_company_info.module:

/**
* Implements hook_permission().
*/
function custom_company_info_permission() {
  return array(
    'administer custom company info' => array(
      'title' => t('Administer Company Information'),
      'description' => t('Allows to edit general company information like phones or address.'),
    ),
  );
}

Теперь опишем нужные нам настройки с помощью хука Variable API hook_variable_info() в файле custom_company_info.variable.inc:

/**
* Implements hook_variable_info().
*/
function custom_company_info_variable_info($options) {
  $variables['custom_company_info:address'] = array(
    'title' => t('Address', array(), $options),
    'access' => 'administer custom company info',
    'type' => 'text',
  );
  $variables['custom_company_info:phone'] = array(
    'title' => t('Phone number', array(), $options),
    'access' => 'administer custom company info',
    'type' => 'string',
  );
  return $variables;
}

В данном случае мы описали переменные 'custom_company_info:address' и 'custom_company_info:phone', которые могут быть отредактированы только при наличии права 'administer custom company info'.
Теперь включим модуль Variable Admin и перейдём на страницу admin/config/system/variable/module (Administration » Configuration » System » Variables):

Быстрая форма настроек с Variable API: Рисунок 1

Мы видим сгруппированные по модулям переменные с предпросмотром их значений. При переходе по ссылке «Edit module variables» мы попадём на готовую форму редактирования настроек модуля:

Быстрая форма настроек с Variable API: Рисунок 2

Вместо того, чтобы постоянно отсылать пользователя на страницу модуля Variable Admin, мы можем этот административный модуль вообще выключить и использовать готовую форму на своей собственной странице настроек.
Модуль Variable API позволяет строить формы настроек программно с помощью кода:

drupal_get_form('variable_module_form', 'mymodule');

Воспользуемся этой возможностью и напишем простой hook_menu:

/**
* Implements hook_menu().
*/
function custom_company_info_menu() {
  return array(
    'admin/config/system/company-info' => array(
      'title' => 'Company Information',
      'description' => 'Phones, Fax, Address, Email Signature and other site infomation.',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('variable_module_form', 'custom_company_info'),
      'access arguments' => array('administer custom company info'),
    )
  );
}

Обратите внимание на page callback/page arguments.

Теперь наша форма будет жить в разделе меню Administration » Configuration » System » Company Information.
Остаётся только прописать в info-файле пару строк и с формой настроек покончено:

dependencies[] = variable
configure = admin/config/system/company-info

Такая форма — идеальное решение для прототипирования новых модулей и внутренних разработок (custom modules).

Кроме удобной формы мы получаем:

  • Глобальные токены [variable:custom_company_info:address], [variable:custom_company_info:phone].
  • Автоматическое удаление переменных при удалении вашего модуля.
  • Удобные функции вроде variable_get_value()/variable_format_value().
  • API для работы с переменными других модулей (hook_variable_type_info_alter, hook_variable_group_info_alter, hook_variable_info_alter и др.)
  • Поддержка Features.
  • Поддержка многоязычности/многодоменности.

Последнее достигается при использовании дополнительных модулей i18n_variable/domain_variable.

Пример поддержки мультидоменности:
Быстрая форма настроек с Variable API: Рисунок 3

Давайте рассмотрим подробнее, какие ещё параметры можно указывать в hook_variable_info():

  • type — тип переменной. От типа зависит элемент формы, который будет использоваться, валидация введённых данных, форматирование.
    Вот некоторые поддерживаемые типы перемененных:
    • string — текстовая строка
    • text — многострочный текст без поддержки тегов
    • text_format — текст с поддержкой форматирования
    • array/properties/multiple — составные переменные
    • number — число
    • boolean — флажок Да/Нет
    • enable — переключатель (radio)
    • select/select_number — список
    • mail_text — специальная составная переменная Заголовок + Текст
    • mail_address
    • url
    • country
    • weekday
    • time_interval и др.
  • default — значение по умолчанию
  • required — обязательная переменная
  • options — варианты значений списков или флажков
  • localize — переводимая переменная
  • multidomain — мультидоменная переменная
  • token — генерировать глобальный токен из переменной
  • group — название группы переменных (предварительно надо зарегистрировать в hook_variable_group_info()).
  • access — право, необходимое для редактирования переменной

Пример использования типов array и text_format:

$variables['custom_company_info:phones'] = array(
    'title' => t('Phone number', array(), $options),
    'group' => 'custom_company_info',
    'access' => 'administer custom company info',
    'type' => 'array',
    'token' => TRUE,
    'multiple' => array(t('Main number'), t('Secondary number')),
  );
$variables['custom_company_info:mail_signature'] = array(
    'title' => t('Email signature', array(), $options),
    'group' => 'custom_company_info',
    'access' => 'administer custom company info',
    'type' => 'text_format',
    'token' => TRUE,
    'default' => "--\r\n[site:name]\r\n[site:url]\r\n[variable:custom_company_info:phones]\r\n",
  );

Быстрая форма настроек с Variable API: Рисунок 4

Модуль Variable API стабилен, имеет более 100 000 установок на момент написания статьи и встаёт в один ряд с Ctools и Entity API по полезности при разработке модулей для Drupal 7.

P.S.: В Drupal 8 настройки модулей похожим образом описываются в *.schema.yml/*.settings.yml и модули вроде Configuration translation уже строят формы на основе этих файлов.

Пожертвования идут непосредственно автору статьи (по умолчанию 200 руб): 

Комментарии

Аватар пользователя kalabro

Update: автор модуля

Update: автор модуля анонсировал Variable Devel, который позволяет быстро ориентироваться в зарегистрированных типах переменных и даже генерирует рутинный код для этих типов. Подробнее: Drupal Tools: Variable Files & Devel

Аватар пользователя Dark

Спасибо за статью!

Спасибо за статью!
А как сделать так, чтобы переменная по-умолчанию была переводимой. 'localize' => TRUE стоит, но если в админке не включить переводимость для переменной, то не работает.

Аватар пользователя Dark

Еще обнаружил такую проблему,

Еще обнаружил такую проблему, если переменную все-таки сделать переводимой из админки, а затем выдать права на редактирование этой формы, т.е. 'administer custom company info'. Пользователь во всех языковых формах будет видеть тексты на языке по-умолчанию.
Чтобы он мог нормально редактировать и переводить переменные, ему нужно дать права 'administer site configuration' — в модуле i18n_variable именно это право дает доступ на страницу admin/config/regional/i18n/variable. Как это побороть? Хардкодить i18n_variable модуль?