Пример разработки плагина для модуля CCK

Submitted by Ромка on Сб, 05/09/2009 - 17:29

Ромка аватар

На прошедшем в Киеве Друпал Кемпе я делал доклад, в котором приводил пример разработки плагина для Drupal-модуля CCK. В этой заметке я приведу краткий конспект своего доклада.

Любой создаваемый средствами CMS Drupal тип контента по умолчанию состоит из двух полей — "Тема" и "Тело сообщения", а также из нескольких полей служебной информации (автор, дата публикации и т.п.). Модуль Content Construction Kit (CCK) представляет из себя графический интерфейс, позволяющий добавить к любому типу контента (в том числе и созданному сторонними модулями) любое количество дополнительных полей, например, поля для размещения картинок, аудио- и видеофайлов и т.п. Каждое из таких полей является плагином для CCK.

Далее в этом тексте пойдет речь о разработке подобного плагина. Материал ориентирован на людей, умеющих программировать на PHP, имеющих представление о модульной системе Друпала и опыт разработки модулей для него. Если вы интересуетесь основами программирования под Друпал, то прочитайте мою статью на эту тему, которая будет опубликована в ближайшем номере журанала PC Magazine/RE.

Описание CCK

При разработке плагина для CCK в первую очередь важно понимать структуру и логику работы этого модуля. Три основные сущности, которыми оперирует модуль Content — ядро CCK:

  • Field — backend, набор функций для проверки переданных пользователем данных, записи и чтения их из БД.
  • Widget — frontend для пользователя публикующего документ. То есть виджет — это элемент формы, который будет выводиться в форме добавления материала
  • Formatter — frontend для читателя, функция темизации определяющая то, как будут выводиться на экран данные, введенные через наш виджет.

Иными словами, field отвечает за хранение и обработку данных, widget отвечает за ввод данных, а formatter за вывод данных на экран.

Ниже приведены скриншоты, на которых изображена форма добавления CCK-поля и отмечены элементы, отвечающие за создание каждой из перечисленных сущностей.





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



Те кто имеет опыт работы с модулем CCK, наверняка обращали внимание на то, что formatter и widget поля можно изменить в любой момент, а вот field задается один раз при создании нового поля и изменен быть не может. Это ограничение логично, так как со сменой field поменяется стуктутра таблицы, в которой хранятся данные и невозможно будет определить то, что делать и как преобразовать данные, которые уже сохранены в базе с использованием текущего поля.

При разработке собственного плагина для CCK программист может создать функции, реализующие собственные filed, widget и formatter, а может, например, использовать существующий field, реализованный сторонним модулем, и разработать только свои widget и formatter. Примером такого симбиоза являются модули FileField и ImageField. Первый реализует функции, позволяющие закачивать файлы на сервер и хранить их, используя системные таблицы Друпала, а второй добавляет дополнительные проверки, закачиваемых файлов.

Также программисты могут использовать field и widget реализованные сторонними модулями и разработать только свой formatter.

Англоязычную документацию, описывающую API CCK, можно найти по адресу http://drupal.org/node/342987. Далее я приведу описание самых часто используемых при разработке плагинов для CCK хуков. Для примера я разработал небольшой модуль, реализующий текстовое поле. Этот модуль не имеет никакой практической пользы, так как значительно уступает по возможностям модулю Text, входящему в стандартную поставку CCK, но на его примере легко понять логику разработки плагинов для CCK.

Хуки field

  • hook_field_info — отвечает за регистрацию (объявление) нового поля.
    1. <?php
    2. function cck_field_test_field_info() {
    3. return array(
    4. 'test_text' => array(
    5. 'label' => t('Test text group'),
    6. 'description' => t('Test text CCK field'),
    7. ),
    8. );
    9. }
    10. ?>

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

  • hook_field — отвечает за реализацию поведения поля. Пример описываемый в этой статье очень прост, по этому это хук в нем не используется, но в более сложных случаях здесь могут быть описаны функции валидаторы, сабмиттеры и другие.
  • хук hook_field_settings определяет глобальные настройки для всех полей этого типа. Эти настройки будут выводиться в филдсете Global settings при создании и редактировании поля. Хук должен возвращать ассоциативный массив, содержащий форму в формате Forms API Друпала. Кроме того, в нашем случае здесь определяется колонка/колонки в базе данных, в которой будут храниться данные, введенные через созданное поле. Если вы хотите самостоятельно обрабатывать сохранение данных в поле, то вам необходимо воспользоваться хуком hook_field.
    1. function cck_field_test_field_settings($op, $field) {
    2. switch ($op) {
    3. case 'database columns':
    4. // поля в бд, которые необходимы для хранения данных из создаваемого оля
    5. return array('test_field_data' => array('type' => 'varchar', 'length' => 64, 'not null' => FALSE, 'sortable' => TRUE));
    6. case 'form':
    7. // форма глобальных настроек поля
    8. $form = array();
    9. $form['test_num_setting'] = array(
    10. '#type' => 'textfield',
    11. '#title' => t('Test num setting'),
    12. '#default_value' => $field['test_num_setting'] === '' ? 123 : (int) $field['test_num_setting'],
    13. '#size' => 60,
    14. '#maxlength' => 128,
    15. );
    16. return $form;
    17. break;
    18. case 'validate':
    19. if(!is_numeric($field["test_num_setting"])) {
    20. form_set_error("test_num_setting", t('Test num setting mast be numeric'));
    21. }
    22. break;
    23. case 'save':
    24. return array('test_num_setting');
    25. break;
    26. case 'views data':
    27. $allowed_values = content_allowed_values($field);
    28. break;
    29. }
    30. }

Хуки widget

Хуки для создания собственного виджета имеют похожие на хуки field имена и логику использования.

  • В hook_widget_info определяется новый виджет и привязывается к существующему филду.
    1. function cck_field_test_widget_info() {
    2. return array(
    3. 'text_test_field' => array(
    4. 'label' => 'Test Text Field',
    5. 'field types' => array('test_text'),
    6. 'multiple values' => CONTENT_HANDLE_CORE,
    7. 'callbacks' => array(
    8. 'default value' => CONTENT_CALLBACK_DEFAULT,
    9. ),
    10. ),
    11. );
    12. }

    Этот хук, так же как и хук hook_field_info, должен возвращать ассоциативный массив. Ключами массива должны быть системные имена, а значениями — вложенные массивы с параметрами. Одним из важных параметров является "field types", в котором определяется field, к которому привязан создаваемый widget, в нашем случае виджет text_test_field привязывается к филду test_text.

  • Hook_widget отвечает за поведение виджета.
  • Самый важный и интересный хук — hook_elements. Все перечисленные выше хуки входят в API модуля CCK, а этот хук входит в Forms API Друпала. В нем определяется функция (в нашем примере text_test_field_process), которая будет отвечать за то как будет выглядеть создаваемый виджет (в нашем случае text_test_field), то есть форма, через которую пользователь будет добавлять контент.
    1. function cck_field_test_elements() {
    2. $elements = array(
    3. 'text_test_field' => array(
    4. '#input' => TRUE,
    5. '#columns' => array('test_field_data'),
    6. '#process' => array('text_test_field_process'),
    7. '#delta' => 0,
    8. ),
    9. );
    10. return $elements;
    11. }
  • Хук hook_widget_settings создает форму, через которую будут задаваться локальные настройки для виджета. Возвращаемый результат аналогичен результату, который возвращается хуком hook_field_settings.

Хуки formatter

Разработка форматтеров — это самая простая часть при создании плагина для CCK. Чтобы определить свои форматтеры нужно зарегистрировать их через хук hook_formatter_info, после этого для каждого форматтера нужно определить свою функцию темизации. Функции темизации для форматтера должны иметь имена вида theme_названиемодуля_formatter_имяформаттера, кроме того, они, как и любые другие функции темизации, должны быть зарегистрированы через hook_theme модуля.

В нашем примере определяется два форматтера с именами default и advanced:

  1. function cck_field_test_field_formatter_info() {
  2. return array(
  3. 'default' => array(
  4. 'label' => t('Test default formatter'),
  5. 'field types' => array('test_text'),
  6. 'multiple values' => CONTENT_HANDLE_CORE,
  7. ),
  8. 'advanced' => array(
  9. 'label' => t('Test advanced formatter'),
  10. 'field types' => array('test_text'),
  11. 'multiple values' => CONTENT_HANDLE_CORE,
  12. ),
  13. );
  14. }

Таким образом, функции темизщации для этих форматтеров могут выглядеть так:

  1. function theme_cck_field_test_formatter_default($element) {
  2. return 'Text of test field >>>'. check_plain($element['#item']['test_field_data']) .' <<<< ';
  3. }
  4.  
  5. function theme_cck_field_test_formatter_advanced($element) {
  6. return 'Text of test field. Advanced formatter >>>'. check_plain($element['#item']['test_field_data']) .' <<<< ';
  7. }

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

upd. А вот и видео с доклада:

dckyiv09-Drupal Module Development from Mitas on Vimeo.

Александром Митасовым и видео-партнером DrupalCamp Kyiv 2009 «Николаевским курьером»

ВложениеРазмер
Package icon cck_field_test.zip4 KB

6 Comments

Отличный материал для начала

Отличный материал для начала программирования модулей для cck. Если бы расширить материал, то цены бы ему не было.

понравился момент во время

понравился момент во время доклада
"позволяет загружать файлы.... ухты ничего себе" ))))))

checkbox

А если есть необходимость создать такое же поле, только вместо текста нужно использовать checkbox, есть ли какие-либо серьезные отличия?