Программное создание фильтров в Drupal 7 для форматирования текста

NovaInfo 9
Опубликовано
Раздел: Технические науки
Просмотров за месяц: 2
CC BY-NC

Аннотация

В статье рассказывается о программном создании фильтров для форматирования текста на примере модуля Emoticon. Данный модуль позволяет добавлять в содержимое сайта изображения в виде смайликов. Реализован фильтр, который заменяет акронимы смайликов на соответствующие изображения.

Ключевые слова

DRUPAL 7, ФИЛЬТРЫ, HOOK_FILTER_INFO, СМАЙЛИКИ

Текст научной работы

В этой статье я расскажу, как с нуля создать свой модуль, позволяющий добавлять смайлики в содежимое сайта. На базе этого модуля будет показано как программно создать фильтр для форматирования текста. Пользователи смогут вводить акронимы смайликов, которые при сохранении ноды (содержимого) будут заменены соответствующими изображениями смайликов. Это может быть полезным на вашем сайте. Недавно социальная сеть vk.com также внедрила возможность добавления смайликов в сообщения.

Содержание файла emoticon.info:

name = Emoticondescription = Позволяет использовать на сайте смайлики.package = Novainfocore = 7.xconfigure = admin/config/content/emoticonfiles[] = emoticon.inc

Добавляем ссылку на страницу настройки в списке управления модулями. Также дополнительно указываем системе использовать файл emoticon.inc. В этом файле будет находиться класс по работе с нашим модулем. Подробности ниже.

Формирование пункта меню и вкладок

В файл emoticon.module добавим функцию emoticon_menu для перехвата hook_menu:

/** * hook_menu(). * Определяет пункты меню и вызовы страниц. */function emoticon_menu()  {  $menu['admin/config/content/emoticon'] = array(    'title'  => 'Смайлики',    'description' => 'Позволяет использовать на сайте смайлики.',    'type' => MENU_NORMAL_ITEM,    'page callback'  => 'drupal_get_form',    'page arguments' => array('emoticon_packages_settings'),    'access arguments' => array('administer emoticon'),  );  $menu['admin/config/content/emoticon/packages'] = array(    'title'  => 'Смайлики',    'description' => 'Позволяет использовать на сайте смайлики.',    'type' => MENU_DEFAULT_LOCAL_TASK,    'weight' => 0,  );  $menu['admin/config/content/emoticon/import'] = array(    'title'  => 'Импорт',    'description' => 'Позволяет импортировать пакеты смайликов на сайт.',    'type' => MENU_LOCAL_TASK,    'page callback'  => 'drupal_get_form',    'page arguments' => array('emoticon_import_settings'),    'access arguments' => array('administer emoticon'),    'weight' => 1,  );  return $menu;}

Первый элемент отвечает за формирование пункта меню по адресу admin/config/content/emoticon. Оставшие два элемента указывают на создание на этой странице вкладок. Одна из них будет отображаться по-умолчанию, поэтому использует параметры страницы, на которой она находится. Для обоих вкладок указываем, что будем использовать Form API. С помощью его будем формировать содержимое вкладок. Тут же указываем имена функций, из которых будут передавать параметры наших будущих форм.

Добавление для модуля параметров настройки

Добавляем функцию для формирования формы выбора пакетов смайликов:

/** * Страница управления модулем */function emoticon_packages_settings($form_state) {  $emoticon = new emoticon();  $packages = $emoticon->get();  if ($packages) {    $form['emoticon_package'] = array(      '#type' => 'radios',      '#title' => t('Список пакетов:'),      '#default_value' => variable_get('emoticon_package'),      '#options' => $packages,      '#description' => t('Выберите пакет смайликов, используемый по-умолчанию.'),      '#required' => TRUE,    );    } else {    $form['emoticon_enable'] = array(      '#markup' => t('Отсутствуют пакеты смайликов.'),          );  }  return system_settings_form($form);}

Добавляем радиокнопки для выбора пакета смайликов, который нужно использовать по-умолчанию. Для этого получаем из базы данных список всех установленных пакетов. Об этом расскажу позже. Если мы не получили список пакетов или он оказался пустым, то выводим сообщение. В этом случае на странице импорта пакетов смайликов нужно выполнить импорт. К статье я прикрепил один такой пакет, основанный на смайликах Колобки. Его нужно будет поместить в директорию emoticon публичного подкаталога сайта. Обычно это директория sites / default / files. Подробности на странице управления файловой системы Drupal.

Стандартная функция system_settings_form добавляет к форме кнопки управления, а также добавляет страницу для обработки результатов. Результат заполнения формы сохраняется в таблице variables базы данных. С помощью стандартной функции variable_get можно получить значение из этой таблицы. Соответственно функция variable_set позволяет записать в неё значение. Этот способ является в Drupal самым простым методом сохранять данные в базе данных. Эту таблицу можно использовать не только для хранения значений форм настроек, но и для другой информации, которая может быть использована в модуле. Запомните этот способ для использования в ваших модулях.

Добавляем функцию для формирования формы импорта пакетов смайликов:

/** * Страница импорта * */function emoticon_import_settings($form_state) {  $emoticon = new emoticon();  $packages = $emoticon->set();  if ($packages) {    $form['emoticon_import'] = array(      '#type' => 'radios',      '#title' => t('Список пакетов:'),      '#default_value' => variable_get('emoticon_import'),      '#options' => $packages,      '#description' => t('Выберите пакет смайликов для установки.'),      '#required' => TRUE,    );    $form['submit'] = array(      '#type' => 'submit',      '#value' => t('Выполнить'),    );  } else {    $form['emoticon_enable'] = array(      '#markup' => t('Отсутствуют пакеты смайликов.'),          );  }  return $form;}

Также добавляем радиокнопки выбора пакетов смайликов, но уже тех, которые ещё не импортированы. В этой форме мы уже не можем использовать стандартную функцию для обработки результатов. Для этого добавлем ещё одну функцию:

function emoticon_import_settings_submit($form, &$form_state) {  $emoticon = new emoticon();  $emoticon->import($form_state['values']['emoticon_import']);}

К имени функции должно быть добавлено слово submit. Таким образом Drupal понимает, что новая функция отвечает за обработку результатов заполнения формы. Результаты формы передаются через массив $form_state['values']. Его значения можно посмотреть через средства отладки. Для этого нужно скачать и установить модуль devel. Послу установки данного модуля мы можем использовать его функции для вывода значений указанных переменных. Например:

dsm($form_state['values']);

В дальнейшем я буду часто ссылаться на этот метод для отладки модуля. О других полезных функциях этого модуля можно почитать в документации. Вообще рекомендую постоянно обращаться за информацией к официальной документации Drupal. Там вы сможете получить достаточно много полезной информации об используемых функциях и хуках.

Права доступа

Следующий хук позволяет нам определить собственные права доступа для настройки нашего модуля:

/** * hook_permission(). */function emoticon_permission() {  return array(    'administer emoticon' => array(      'title' => t('Настройка смайлов'),      'description' => t('Изменение настроек модуля Смайлы.'),    ),  );}

Определяем название и описание для разрешения роли на настройку модуля. Это право доступа мы использовали выше для пункта меню и его вкладок.

Страница помощи

Добавим для нашего модуля для вкладки импорта информацию об установке пакетов смайликов. Для этого в файл emoticon.module добавим функцию:

/** * hook_help(). */function emoticon_help($path, $arg)  {  switch ($path)  {    case 'admin/config/content/emoticon/import':      $output  = '<p>' . t('Для загрузки пакетов смайликов нужно добавить эти пакеты в директорию !dir', array(        '!dir' => l(t('Emoticon'), file_create_url('public://emoticon'))      )) .'</p>';      return $output;      break;  }}

Теперь на странице импорта пакетов смайликов будет отображаться полезная информация.

Создание фильтра

Drupal нам предлагает несколько хуков для программной фильтрации содержимого сайта. Фильтры играют большую роль в форматировании текста. Фильтры не изменяют текст пользователя. Он остается таким же как был перед сохранением. Фильтры влияют на конечный результат отображения этого текста. Поэтому отображение текста в редакторе может отличаться от его вывода на странице. Нам модуль использует акронимы смайликов в качестве входных данных фильтра, а на выходе мы получаем изображения. Добавим наш фильтр. Для этого нам потребуется написать несколько функций.

Установим параметры фильтра:

/** * hook_filter_info(). */function emoticon_filter_info() {  $filters['filter_emoticon'] = array(    'title' => t('Позволяет использовать на сайте смайлики.'),    'process callback' => 'emoticon_filter_process',    'settings callback' => 'emoticon_filter_settings',    'default settings' => array(      'emoticon_package' => variable_get('emoticon_package'),    ),    'tips callback' => 'emoticon_filter_tips',    'weight' => 0,  );  return $filters;}

Укажем в параметрах фильтра три функции.

  • Первая отвечает за фильтрацию данных;
  • Вторая позволяет использовать настройки фильтра;
  • Третья указывает советы при установке и настройке фильтра.

Об этих функциях чуть позже. Также нужно указать название фильтра, а также настройки по-умолчанию. Хочу также отметить, что хуки фильтров для седьмой версии Drupal не соответствуют более ранним версиям. Учитывайте это, если захотите использовать данный материал для написания своего модуля. В целом рекомендую всегда сверять полученные знания с официальной документации на предмет соответствия.

Продолжим…

Фильтрации данных

Добавим функцию для фильтрации данных введённых пользователем:

function emoticon_filter_process($text = '', $filter, $format) {  $emoticon = new emoticon();  $values = $emoticon->getValues($filter->settings['emoticon_package']);  // dsm($values);  $acronyms = array();  $icons = array();  foreach ($values[0] as $key => $value) {    $elements = explode(",", $value);    foreach ($elements as $acronym) {      $acronyms[] = $acronym;      $icons[] = '<img src="' . $values[1][$key] . '" title="' . $acronym . '" />';    }  }  // dsm(array($acronyms, $icons));  $text = str_replace($acronyms, $icons, $text);  return $text;}

Получаем список всех акронимов смайликов и соответствующих им изображений. Затем заменяем акронимы на изображения. Всё просто!

Формирования формы настроек фильтра

Добавим функцию для формирования формы настроек нашего фильтра:

function emoticon_filter_settings($form, &$form_state, $filter, $format, $defaults, $filters) {  $emoticon = new emoticon();  $packages = $emoticon->get();  if ($packages) {    $settings['emoticon_packages'] = array(      '#type' => 'radios',      '#title' => t('Список пакетов:'),      '#default_value' => $filter->settings['emoticon_package'],      '#options' => $packages,      '#description' => t('Выберите пакет смайликов, используемый по-умолчанию.'),    );  } else {    $settings['emoticon_enable'] = array(      '#markup' => t('Отсутствуют пакеты смайликов.'),          );  }    return $settings;}

Форма похоже на рассмотренные нами ранее формы настроек на странице. Не буду на ней останавливаться.

Справочная информация о текстовом формате ввода

Добавим функцию, которая выводит справочную информацию о текстовом формате ввода:

function emoticon_filter_tips($filter, $format, $long = FALSE) {  if ($long) {    return t('Акронимы смайликов преобразуются в соответствующие изображения.');  }  else {    return t('Акронимы смайликов преобразуются в соответствующие изображения.');  }}

В нашем случае краткая и полная информация о текстовом формате ввода ничем не отличаются. Можно было составить более короткую запись функции, но для примера решил оставить. Краткую информацию можно увидеть под полем выбора формата текста при добавлении содержимого. Полная версия отображается на специальной странице.

Создание таблиц базы данных

Для хранения информации об установленных пакетах смайликов, а также об акронимах и соответствующих им изображения, создадим таблицы в базе данных. Для этого используется hook_schema. Нужно в файл emoticon.install добавить функцию:

/** * hook_schema(). * Определяет для модуля схему таблиц в базе данных. */function emoticon_schema() {  $schema['emoticon'] = array(    'description' => 'Смайлики',    'fields' => array(      'sid' => array(        'description' => 'Идентификационный номер',         'type' => 'serial',        'unsigned' => TRUE,        'not null' => TRUE,      ),      'acronyms' => array(        'description' => 'Обозначение',        'type' => 'varchar',        'not null' => TRUE,        'default' => '',        'length' => 255,      ),      'icon' => array(        'description' => 'Изображение',        'type' => 'int',        'not null' => TRUE,        'default' => 0,      ),      'package' => array(        'description' => 'Пакет смайлов',        'type' => 'int',        'not null' => TRUE,        'default' => 0,      ),    ),    'primary key' => array('sid'),  );  $schema['emoticon_package'] = array(    'description' => 'Пакеты смайлов',    'fields' => array(      'pid' => array(        'description' => 'Идентификационный номер',         'type' => 'serial',        'unsigned' => TRUE,        'not null' => TRUE,      ),      'package' => array(        'description' => 'Наименование',        'type' => 'varchar',        'not null' => TRUE,        'default' => '',        'length' => 64,      ),      'dir' => array(        'description' => 'Директория пакета',        'type' => 'varchar',        'not null' => TRUE,        'default' => '',        'length' => 255,      ),    ),    'primary key' => array('pid'),  );  return $schema;}​

Указываем два элемента массива, которые будут соответствовать двум таблицам:

  • emoticon. Будет хранить информацию об акронимах и соответствующих им изображениям, а также их связь с пакетами;
  • emoticon-package. Информация о пакетах смайликов.

Для каждого элемента задаём описание, поля и первичный ключ. Рекомендую после установки модуля посмотреть как создались таблицы в базе данных, а также информацию о полях этих таблиц.

Установка модуля

Ранее я упоминал, что пакеты смайликов для импорта должны располагать в определенной директории. Поэтому мы должны обеспечить существование этого каталога. Воспользуемся hook_install для его создания при установке модуля.

Описание функции emoticon_install:

/** * hook_install(). * Установка модуля. */function emoticon_install() {  if (!is_dir('public://emoticon')) {    mkdir('public://emoticon');  }}

Удаление модуля

После жизнедеятельности модуля мы должны почистить после него мусор. В частности, нам необходимо удалить данные из таблицы variables. Нужно использовать hook_uninstall для выполнения действий при удалении модуля из системы.

Описание функции emoticon_uninstall:

/** * hook_uninstall(). * Удаление модуля. */function emoticon_uninstall() {  db_delete('variable')    ->condition('name', 'emoticon_%', 'LIKE')    ->execute();  cache_clear_all('variables', 'cache_bootstrap');}

Работа с базой данных и файловой системой

Стандартная функция db_delete позволяет удалять записи из таблиц базы данных. Но сама по себе функция только готовит SQL-запрос в базу данных. В параметре к ней нужно передать название таблицы. За формирование условия в SQL-запрос отмечает метод condition, в который мы должны передать название поля, значение этого поля и метод. В завершении нужно выполнить метод execute для выполнения сформированного SQL-запроса.

Пример:

  /**   * Получаем список установленных пакетов.   *   * @return FALSE или Массив со списком установленных пакетов.   *   */  public function get() {    // Массив установленных пакетов.    $get = array();    // Выполняем запрос к базе данных.    $query = db_select('emoticon_package', 'p');    $query      ->fields('p', array('pid', 'package'));    $result = $query      ->execute()            ->fetchAll();    // Формируем результат.    if ($result) {      foreach ($result as $value) {        $get[$value->pid] = $value->package;      }    } else {      $get = FALSE;    }    // Возвращаем результат.    return $get;  }

В этом примере мы выполняем запрос к базе данных. Для этого мы воспользовались стандартной функцией db_select. Также как и в предыдущем примере мы передаем для неё название таблицы, устанавливаем необходимые поля с помощью метода fields и выполняет SQL-запрос. Получить все результаты нашего запроса можно с помощью метода fetchAll. Далее обрабатываем данные и возвращаем результат.

Пример:

  /**   * Получаем список значений пакета.   *   * @param $pid   *     ID. ID пакета.   *    * @return FALSE или Массив значений.   *   */  public function getValues($pid) {    // Выполняем запросы к базе данных.    $query = db_select('emoticon_package', 'p');    $query      ->fields('p', array('dir'))      ->condition('p.pid', $pid);    $dir = $query      ->execute()            ->fetchField();    $query = db_select('emoticon', 'e');    $query      ->fields('e', array('acronyms', 'icon'))      ->condition('e.package', $pid);    $result = $query      ->execute()      ->fetchAll();    // Массив списков акронимов.    $acronyms = array();    // Массив ссылок на иконку.    $icons = array();    // Заполняем массивы данными.    foreach ($result as $value) {      $acronyms[] = $value->acronyms;      $icons[] = file_create_url($dir . '/' . sprintf('%03d', $value->icon) . '.gif');    }    // Возвращаем результат.    return array($acronyms, $icons);  }

Выполняем два запроса к таблицам базы данных. Здесь мы используем новый метод fetchField, который возвращает значение только одно поля для одной записи.

Отвлечемся немного от базы данных и посмотри на стандартную функцию file_create_url. Эта замечательная функция позволяет получить полный путь к файлу, если даже относительный путь указан в виде public://. Иначе вы не сможете работать с файлами, расположенными в этой директории.

Пример:

  /**   * Получаем список не установленных пакетов.   *   * @return FALSE или Объект со списком не установленных пакетов.   *   */  public function set() {    // Массив не установленных пакетов.    $set = array();    // Получаем список установленных пакетов.    $packages = $this->get();        // В директории импорта находим пакеты.    $files = file_scan_directory('public://emoticon', '/(.*)\.info/');    // dsm($files);    // Проверяем все пакеты.    foreach ($files as $f) {      // Определяем директорию пакета.      $dir = dirname($f->uri);      // Определяем название пакета.      $package = explode("/", $dir);      $package = $package[sizeof($package) - 1];      // Название директории, в которой находится пакет, должно совпадать с именем файла {package}.info.      // Пакет не должен быть импортирован ранее.      if ($package == $f->name && (empty($packages) || !in_array($package, $packages))) {        $set[$dir] = $package;      }    }    // Возвращаем результат.    return empty($set) ? FALSE : $set;  }

В этом методе нашего класса с помощью функции file_scan_directory получаем список всех файлов, а затем обрабатываем его и возвращаем в нужном виде.

Пример:

  /**   * Создаём новый пакет.   *   * @param $package   *     Строка. Название пакета.   *   * @param $dir   *     Строка. Директория пакета.   *    * @return FALSE или ID пакета.   *   */  public function create($package, $dir) {    // Выполняем запрос к базе данных на добавление записи.    $pid = db_insert('emoticon_package')      ->fields(array(          'package' => $package,          'dir' => $dir,        ))      ->execute();    // Возвращаем результат.    return $pid;  }

Функция db_insert формирует запрос на добавление записи в таблицу.

Пример:

  /**   * Добавляем новые записи в пакет.   *   * @param $package   *     Строка. Название пакета.   *    * @param $values   *     Двухмерный массив. Акроним, ID изображения, ID пакета.   *   * @return FALSE или ID пакета.   *   */  public function append($values) {    // dsm($values);    // Выполняем запрос к базе данных на добавление записи.    $query = db_insert('emoticon')      ->fields(array('acronyms', 'icon', 'package'));    foreach ($values as $record) {      $query->values($record);    }    $query->execute();  }

С помощью метода values мы сможем добавить в наш запрос несколько полей со значениями.

Читайте также

Цитировать

Долганов, А.А. Программное создание фильтров в Drupal 7 для форматирования текста / А.А. Долганов. — Текст : электронный // NovaInfo, 2012. — № 9. — URL: https://novainfo.ru/article/1486 (дата обращения: 29.01.2022).

Поделиться