ertttert
Books-CMS.clan.su

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

В Drupal поддерживается множество различных типов нод (в пользовательском интерфейсе они называются типами контента (content type)), такие как статьи и базовые страницы. Мы ограничим использование аннотаций только некоторыми типами нод. Для этого понадобится создать страницу, где можно сообщить модулю о том, какие типы контента мы хотим аннотировать. На этой странице будет представлен набор флажков — по одному для каждого существующего типа контента. Это позволит конечному пользователю указать, какие типы контента могут аннотироваться, сбросив или установив соответствующие флажки (рис. 2.1). Такая страница является административной, а это значит, что ее код необходимо загружать и синтаксически анализировать только при необходимости. Поэтому мы поместим этот код в отдельный файл, а не в annotate.module, который будет загружаться и выполняться при каждом веб-запросе. Поскольку Drupal было указано, что искать форму параметров нужно в файле annotate.admin.inc, мы создадим файл sites/all/modules/annotate/annotate.admin.inc и поместим в него следующий код:

/**
* @file
* Обратные вызовы административной страницы для модуля аннотирования.
*/

/**
* Создание формы. Настройка аннотирования.
*
* @ingroup forms
* @see system_settings_form().
*/
function annotate_admin_settings() {
// Получение массива типов нод: ключи — это внутренние имена,
// а значения — "дружественные имена". Например:
// array('page' => 'Basic Page', 'article' => 'Articles')
$types = node_type_get_types();
foreach($types as $node_type) {
$options[$node_type->type] = $node_type->name;
}
$form['annotate_node_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Users may annotate these content types'),
// Пользователи могут аннотировать эти типы контента
'#options' => $options,
'#default_value' => variable_get('annotate_node_types', array('page')),
'#description' => t('A text field will be available on these content types to make author-specific notes.'),
// Для этих типов контента будут доступны текстовые
// поля, предназначенные для авторских заметок
);
return system_settings_form($form, TRUE);
}

Формы в Drupal представляются в виде вложенной древовидной структуры — т.е. массива массивов. Эта структура описывает, каким образом механизм отображения форм Drupal должен представлять эту форму. Для наглядности лучше размещать каждый элемент массива в отдельной строке. Средства формы отмечаются знаком # и играют роль ключей массива. Вначале мы объявим, что тип элемента формы должен быть checkboxes; это означает, что на основании ассоциативного массива будет создано несколько флажков. Этот массив уже содержится в переменной $options. Содержимое переменной $options присваивается выходным данным функции node_type_get_types(), которая возвращает массив объектов. Эти выходные данные должны выглядеть примерно так:


[article] => stdClass Object (
 [type] => article
 [name] => Article
 [base] => node_content
 [description] => Use articles for time-sensitive content like news, press releases or blog posts.
 [help] =>
 [has_title] => 1
 [title_label] => Title
 [has_body] => 1
 [body_label] => Body
 [custom] => 1
 [modified] => 1
 [locked] => 0
 [orig_type] => article
)

Ключами массива объектов являются внутренние имена Drupal для типов нод, а дружественные имена (т.е., которые выводятся пользователю) содержатся в атрибуте name объекта. Согласно требованиям API-интерфейса форм Drupal, #options должно быть массивом пар ключ => значение. Это позволит циклу foreach использовать атрибут type для создания ключа и атрибут name для создания значения нового массива, который здесь называется $options. На основе значений из массива $options в нашей веб-форме Drupal сгенерирует флажки для типов нод Basic page и article, а также для всех других типов контента, доступных на сайте. Заголовок элементу формы назначается определением значения свойства #title.

На заметку! Любой текст, который выводится пользователю (вроде свойств #title и #description из нашего поля формы), необходимо указывать внутри функции t() — это функция Drupal, предназначенная для облегчения перевода строк. Преобразование всего текста через эту функцию строкового перевода значительно облегчает локализацию модуля на различные языки. Для пункта меню здесь это не сделано потому, что пункты меню переводятся автоматически.

Следующая директива — #default_value — задает стандартное значение для данного элемента формы. Поскольку checkboxes является множественным элементом формы (т.е. флажков несколько), значением #default_value будет массив. Это значение #default_value стоит рассмотреть более внимательно:

variable_get('annotate_node_types', array('page'))

Drupal позволяет программистам сохранять и выбирать любые значения с помощью специальной пары функций: variable_get() и variable_set(). Значения хранятся в базе данных variables и доступны в любой момент при обработке запроса. А поскольку эти переменные выбираются из базы данных при каждом запросе, не следует хранить таким способом большие объемы данных. Обратите внимание: функции variable_get() передается (для выборки) ключ, который описывает значение, и значение по умолчанию. В рассматриваемом случае значением по умолчанию является массив с типами нод, которые допускают аннотирование. По умолчанию мы разрешим аннотирование для типов контента базовых страниц (Basic Page).

Совет. При использовании функции system_settings_form() имя элемента формы (в данном случае — annotate_node_types) должно совпадать с именем ключа, передаваемым в variable_get().

Здесь добавлено описание, которое немного поможет администратору сайта понять, что следует поместить в данное поле. О формах речь пойдет в главе 11. Теперь добавим код для обработки добавления и удаления поля аннотации в типах контента. Если администратор сайта отмечает тип контента, к этому типу контента должно быть добавлено поле для аннотации. Если администратор сайта решит убрать поле аннотации из типа контента, это поле должно быть удалено. Для определения поля и связывания его с типом контента мы используем интерфейс Field API системы Drupal. Этот API-интерфейс обрабатывает все действия, связанные с настройкой поля, включая создание таблицы в базе данных Drupal для хранения значений, отправленных авторами контента, создание элемента формы, который будет использоваться для сбора информации, вводимой автором, и связывание поля с типом контента и вывод этого поля на форме редактирования ноды при отображении ноды на странице. Программный интерфейс Field API будет рассмотрен в главе 4. Вначале понадобится создать подпрограмму проверки, которая будет вызываться при отправке формы администратором сайта. В этой подпрограмме модуль проверит, установлен или сброшен флажок для типа контента. Если он сброшен, будет выполнена проверка, что тип контента не содержит связанного с ним поля аннотации. Если содержит, это означает, что администратор сайта желает удалить такое поле из данного типа контента, и нужно удалить аннотации, которые уже занесены в базу данных. Если флажок установлен, модуль проверяет, существует ли поле в данном типе контента, и если нет, модуль добавляет такое поле к типу контента.

/**
* annotate_admin_settings_validate
*/
function annotate_admin_settings_submit($form, $form_state) {
// Цикл по всем флажкам типов контента, имеющихся на форме.
foreach ($form_state['values']['annotate_node_types'] as $key => $value) {
// Если флажок для типа контента сброшен, проверяем,
// имеется ли у данного типа контента связанное с ним поле аннотации,
// с помощью функции field_info_instance. Если имеется,
// нужно удалить поле аннотации, т.к. флажок сброшен.
if (!$value) {
 $instance = field_info_instance('node', 'annotation', $key);
 if (!empty($instance)) {
  field_delete_instance($instance);
  watchdog("Annotation", "Deleted annotation field from content type: ".$key);
 } // Конец варианта, когда аннотация существует, и ее необходимо удалить.
} else {
 // Если флажок для типа контента установлен, проверяем, связано ли с данным
 // типом контента поле. Если нет, добавим в тип контента поле аннотации.
 $instance = field_info_instance('node', 'annotation', $key);
 if (empty($instance)) {
  $instance = array(
  'field_name' => 'annotation',
  'entity_type' => 'node',
  'bundle' => $key,
  'label' => t('Annotation'),
  'widget_type' => 'text_textarea_with_summary',
  'settings' => array('display_summary' => TRUE),
  'display' => array(
  'default' => array(
  'type' => 'text_default',
),
  'teaser' => array(
  'type' => 'text_summary_or_trimmed',
  ),
 ),
);
$instance = field_create_instance($instance);
watchdog("Annotation", "Added annotation field to content type: ".$key);
} // Конец варианта, когда поля аннотации нет, и оно добавляется.
} // Конец оператора if.
} // Конец оператора foreach.
}

Теперь нужно создать файл .install для нашего модуля. Этот файл содержит одну или несколько функций, которые вызываются при инсталляции или удалении модуля. В нашем случае при инсталляции модуля должно быть создано поле аннотации, чтобы администраторы сайта могли связывать его с типами контента. При удалении модуля необходимо удалить поле аннотации из всех типов контента и удалить поле с его содержимым из базы данных Drupal. Для этого в каталоге модуля аннотирования понадобится создать новый файл по имени annotate.install. Первая вызываемая функция — hook_install(). В соответствии со стандартами именования функций хуков в Drupal мы назовем ее annotate_install(), заменив слово hook именем модуля. В функции hook_install будет выполняться проверка существования поля с помощью Field API, и если оно не существует, будет создаваться поле аннотации.

<?php
/**
* Реализация hook_install()
*/
function annotate_install() {
  // Проверка, существует ли поле аннотации.
  $field = field_info_field('annotation');
  // Если поле аннотации не существует, оно создается.
  if (empty($field)) {
    $field = array(
    'field_name' => 'annotation',
    'type' => 'text_with_summary',
    'entity_types' => array('node'),
    'translatable' => TRUE,
    );
    $field = field_create_field($field);
  }
}

После этого нужно создать функцию удаления (деинсталляции) с помощью hook_uninstall. Мы создадим функцию с именем annotate_uninstall и воспользуемся функцией отслеживания watchdog для записи сообщения администратору сайта о том, что модуль деинсталлирован. Затем применим API-функцию node_get_types() для сбора списка всех типов контента, которые имеются на сайте, с последующим просмотром этого списка типов, чтобы определить, существует ли поле аннотации для данного типа контента. Если да, оно удаляется. После этого можно удалить само поле аннотации.

/**
* Реализация hook_uninstall()
*/
function annotate_uninstall() {
    watchdog("Annotate Module", "Uninstalling module and deleting fields");
    $types = node_type_get_types();
    foreach($types as $type) {
        delete_annotation($type);
    }
    $field = field_info_field('annotation');
    if ($field) {
        field_delete_field('annotation');
    }
}
function delete_annotation($type) {
    $instance = field_info_instance('node', 'annotation', $type->type);
    if ($instance) {
        field_delete_instance($instance);
    }
}

Последним шагом процесса должно быть включение в файл .module проверки, является ли лицо, просматривающее ноду, автором этой ноды. Если это не автор, то поле аннотирования нужно скрыть. Мы применим простой подход с помощью функции hook_node_load() — хука, который вызывается при загрузке ноды. Внутри функции hook_node_load() будет выполняться проверка, является ли пользователь, просматривающий ноду, его автором. Если это не автор, аннотация скрывается с помощью функции сброса.

/**
* Реализация hook_node_load()
*/
function annotate_node_load($nodes, $types) {
 global $user;
 // Проверка, является ли лицо, просматривающее ноду, автором.
 // Если нет, аннотация скрывается.
 foreach ($nodes as $node) {
 if ($user->uid != $node->uid) {
 unset($node->annotation);
 }
 }
}

Сохраните созданные файлы (.info, .install, .admin.inc, .module) и щелкните на пункте Modules (Модули) в меню администрирования в верхней части страницы. Наш модуль должен появиться в группе Pro Drupal Development (если не появился, перепроверьте синтаксис файлов annotate.info и annotate.module; они должны находиться в каталоге >sites/all/modules/custom). Активируйте новый модуль. После активации модуля перейдите по адресу admin/config/annotate/settings should — там должна появиться форма настройки для annotate.module (рис. 2.1).

Написав лишь несколько строк кода, мы получили функциональную форму настройки для нашего модуля, которая автоматически сохраняет и запоминает параметры! Это дает некоторое представление о мощи, заложенной в Drupal. Давайте протестируем процесс. Для этого сначала разрешим аннотирование для всех типов контента. Установите все флажки на странице настройки параметров и щелкните на кнопке Save configuration (Сохранить конфигурацию). Потом создайте новую ноду базовой страницы и прокрутите ее вниз, пока не увидите поле аннотирования (рис. 2.2).

Создайте новую ноду, введя значения в поле заголовка, тела и аннотации. После этого щелкните на кнопке сохранения — результат должен быть похож на показанный на рис. 2.3.

Здесь, даже неявно, не выполнялось ни одной операции с базами данных — непонятно, где Drupal сохраняет и откуда выбирает значения для поля аннотации? Все скрытые операции по созданию таблицы для хранения значения, а также сохранение и выборку значений при сохранении и загрузке ноды выполняет интерфейс Field API. При вызове функция field_create_field() из Field API создает таблицу в базе данных Drupal с помощью стандартного соглашения об именовании field_data_<имя_поля>. В случае нашего поля аннотирования таблица называется field_data_annotations. Более подробно Field API рассматривается в главе 4.

Всего комментариев: 0
Имя *:
Email *:
Код *:


Бесплатный конструктор сайтов - uCoz