Ромка!eu

  • Отдых
  • Работа
Главная — Блоги — Ромка's blog

Это старая (Drupal 6) версия сайта romka.eu. Она больше не обновляется, комментирование материалов отключено. Обновленная версия сайта доступна по адресу http://romka.eu.

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

Ромка — Сб, 09/05/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 — отвечает за регистрацию (объявление) нового поля.
    <?php
    function cck_field_test_field_info() {
      return array(
        
    'test_text' => array(
          
    'label' => t('Test text group'),
          
    'description' => t('Test text CCK field'),
        ),
      );
    }
    ?>

    Этот хук должен возвращать ассоциативный массив, ключами которого являются системные имена создаваемых полей (эти имена должны состоять только из латинских букв, цифр и знаков подчеркивания), элементами этого массива должны быть вложенные массивы, содержащие параметры создаваемого поля. В приведенном примере я создаю одно поле с системным именем test_text.
  • hook_field — отвечает за реализацию поведения поля. Пример описываемый в этой статье очень прост, по этому это хук в нем не используется, но в более сложных случаях здесь могут быть описаны функции валидаторы, сабмиттеры и другие.
  • хук hook_field_settings определяет глобальные настройки для всех полей этого типа. Эти настройки будут выводиться в филдсете Global settings при создании и редактировании поля. Хук должен возвращать ассоциативный массив, содержащий форму в формате Forms API Друпала. Кроме того, в нашем случае здесь определяется колонка в базе данных, в которой будут храниться данные, введенные через созданное поле. Зачастую для хранения данных может быть недостаточно одной колонки, в таких случаях необходимо воспользоваться хуком hook_field.
    <?php
    function cck_field_test_field_settings($op, $field) {
      switch (
    $op) {
        case 
    'database columns':
            
    // поля в бд, которые необходимы для хранения данных из создаваемого оля
              
    return array('test_field_data' => array('type' => 'varchar', 'length' => 64, 'not null' => FALSE, 'sortable' => TRUE));  
        case 
    'form':
            
    // форма глобальных настроек поля
            
    $form = array();
            
    $form['test_num_setting'] = array(
              
    '#type' => 'textfield',
              
    '#title' => t('Test num setting'),
              
    '#default_value' => $field['test_num_setting'] === '' ? 123 : (int) $field['test_num_setting'],
              
    '#size' => 60,
              
    '#maxlength' => 128,
            );
            return 
    $form;    
            break;
        case 
    'validate':
            if(!
    is_numeric($field["test_num_setting"])) {
                
    form_set_error("test_num_setting", t('Test num setting mast be numeric'));
            }
            break;
        case 
    'save':
            return array(
    'test_num_setting');
            break;
        case 
    'views data':
          
    $allowed_values = content_allowed_values($field);
          break;
      }
    }
    ?>

Хуки widget

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

  • В hook_widget_info определяется новый виджет и привязывается к существующему филду.
    <?php
    function cck_field_test_widget_info() {
      return array(
        
    'text_test_field' => array(
          
    'label' => 'Test Text Field',
          
    'field types' => array('test_text'),
          
    'multiple values' => CONTENT_HANDLE_CORE,
          
    'callbacks' => array(
            
    'default value' => CONTENT_CALLBACK_DEFAULT,
            ),
        ),
      );
    }
    ?>

    Этот хук, так же как и хук 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), то есть форма, через которую пользователь будет добавлять контент.
    <?php
    function cck_field_test_elements() {
        
    $elements = array(
        
    'text_test_field' => array(
          
    '#input' => TRUE,
          
    '#columns' => array('test_field_data'),
          
    '#process' => array('text_test_field_process'),
          
    '#delta' => 0,
          ),
         );
        return 
    $elements;
    }
    ?>
  • Хук hook_widget_settings создает форму, через которую будут задаваться локальные настройки для виджета. Возвращаемый результат аналогичен результату, который возвращается хуком hook_field_settings.

Хуки formatter

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

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

<?php
function cck_field_test_field_formatter_info() {
  return array(
      
'default' => array(
      
'label' => t('Test default formatter'),
      
'field types' => array('test_text'),
      
'multiple values' => CONTENT_HANDLE_CORE,
    ),
      
'advanced' => array(
      
'label' => t('Test advanced formatter'),
      
'field types' => array('test_text'),
      
'multiple values' => CONTENT_HANDLE_CORE,
    ),
  );
}
?>

Таким образом, функции темизщации для этих форматтеров могут выглядеть так:
<?php
function theme_cck_field_test_formatter_default($element) {
  return 
'Text of test field >>>'. check_plain($element['#item']['test_field_data']) .' <<<< ';
}

function 
theme_cck_field_test_formatter_advanced($element) {
  return 
'Text of test field. Advanced formatter >>>'. check_plain($element['#item']['test_field_data']) .' <<<< ';
}
?>

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

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

dckyiv09-Drupal Module Development from Mitas on Vimeo.

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

  • CCK
  • dckyiev09
  • Drupal
  • доклад
  • Работа
  • Ромка's blog

как раз собирался разобраться

Anonymous (не проверено) → Пнд, 09/07/2009 - 18:54

как раз собирался разобраться в этой теме
* подписался на блог

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

Bogdan (не проверено) → Чт, 09/17/2009 - 10:33

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

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

Anonymous (не проверено) → Вс, 11/22/2009 - 05:35

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

Моё скромное мнение

Lolli (не проверено) → Втр, 03/30/2010 - 13:35

Классно пишете. Регулярно, с удовольствием читаю Ваши материалы.

checkbox

Anonymous (не проверено) → Пт, 04/02/2010 - 22:19

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

Обо мне

Всем привет!
Меня зовут
Роман Архаров, я профессиональный веб-разработчик, программирую на языках PHP, Python и Action-Script, в работе использую фреймворки Drupal и Django. В этом блоге я размещаю заметки и статьи, связанные с моей работой, отдыхом и другими интересными мне темами.

Похожие заметки

  • Swftools и модуль Pdf2SWfField для Друпала
  • Доклад на DrupalConfMoscow 2011
  • Тестирование модуля "Inner poll"
  • Кеширование на Drupal-сайте. Сравнение встроенного в Drupal кеша, статического файлового кеша (модуль Boost) и Varnish
  • Поездка в Киев

Популярные заметки

  • Авторизация на Drupal-сайте с помощью аккаунта ВКонтакте
  • Перетаскивание строк таблицы. Table drag and drop — плагин для jQuery
  • Темизация Drupal. Часть 3. Основы Drupal Forms API и темизация форм
  • Темизация Drupal. Часть 4. Темизация Views
  • AJAX. Обмен данными между клиентом и сервером, закачка на сервер файлов без перезагрузки страницы при помощи библиотеки jQuery.
  • Кеширование на Drupal-сайте. Сравнение встроенного в Drupal кеша, статического файлового кеша (модуль Boost) и Varnish
  • Тестирование модуля "Inner poll"
  • Несколько панорам из путешествия по Перу и Боливии
  • Arduino + bluetooth, небольшая проблема
  • Пример разработки плагина для модуля CCK

Подписка


Последние комментарии

  • drupal-admin → Кеширование на Drupal-сайте. Сравнение эффективности встроенного в Drupal кеша, статического файлового кеша (модуль Boost) и Var → Отличная статья
  • Меховщиков Руслана → Проверка имени пользователя на наличие букв из разных алфавитов → Re: Читал про это уже на
  • Вероника → Куба. Лето 2008. Часть 3 → По поводу "приветливых жителей" Тринидада
  • Sfero → Статья в PC Magazine/RE. Drupal: разработка модуля → Немного о контенте
  • RemaGe → Статья в PC Magazine/RE. Drupal: разработка модуля → -)
  • Ромка → Статья в PC Magazine/RE. Drupal: разработка модуля → Да, будет сборка, та которую
  • RemaGe → Статья в PC Magazine/RE. Drupal: разработка модуля → -)
  • anatinge → Поездка в Киев → спасибо :)
  • Ромка → Поездка в Киев → Да, в общем-то, ничего
  • GogA → Поездка в Киев → Заинтриговал, что там за

Новые заметки

  • Кеширование на Drupal-сайте. Сравнение встроенного в Drupal кеша, статического файлового кеша (модуль Boost) и Varnish
  • Любопытное поведение модуля syslog в шестом Друпале (баг?)
  • Arduino + bluetooth, небольшая проблема
  • Гугл 1 марта прекратил поддержку сервиса Google Friend Connect
  • Проба пера в HTML5 + canvas. Эффект ластика
  • Шесть рукопожатий
  • Доклад на DrupalConfMoscow 2011
  • Статусы разных сущностей в Друпале 6
  • Футер, прибитый к низу страницы
  • Путешествие по Перу и Боливии. Часть 2

Тэги

Drupal jquery Куба Лето 2007 Лето 2008 Отдых Работа Штуки-дрюки лето модуль статья цитата
еще тэги

Навигация

  • Exchange rate
  • Переход по внешней ссылке
  • Последние сообщения
  • Фотогалереи

Курсы валют

  • 100 Казахстанских тенге — 21,3687 (-0.43)
  • 10 Украинских гривен — 27,2852 (-13.04)
  • 1 Китайский юань — 10,2706 (-40.98)
  • 100 Японских иен — 53,5332 (+12.67)
  • 1 Доллар США — 65,6210 (+33)
  • 1 Евро — 69,8076 (+29.42)
  • 10000 Белорусских рублей — 36,3310 (-2.51)
  • 1 Турецкая лира — 22,9540 (+4.99)

10 случайных заметок

  • Доклад на DrupalConfMoscow 2011
  • Баг jQuery в Firefox 3 и WebKit
  • Сегодня 256 день в году — день программиста
  • Оригинальный новогодний спецэффект для сайтов
  • Несколько статей о Друпале
  • Старый смешной мультик
  • Отладка CSS. Расширения Firebug, View formatted Source и Web Developer для Firefox
  • Backup-manager — настройка резервного копирования Linux-сервера на Amazon S3 за 5 минут
  • Разработка сайта Drupal.ru
  • Зима 2010. Поездка в Тайланд, Индонезию и Сингапур. Часть 3 — Бали, Сингапур, Пхукет

Случайные фото

Я с местным рональдом
Еще горы
Оригинальная дорожная разметка в Гаване
Море
Буквы
Дерево в Прамбанане
Радуга над футбольным полем в Лужниках
В Сингапурском зоопарке. Леопардовая (бенгальская) кошка.
Закат в Гаване
Копенгаген, Кристиания, Граффити 3
Тринидадские спортсменчики
Вечерний Копенгаген
Недалеко от Красной поляны
Вид на Бангкок с верхушки отеля Байок
Тринидад. Лошадка держит домик
Норвегия, Нордсетер
  • Отдых
  • Работа

При использовании материалов с сайта, пожалуйста, ставьте ссылку на источник. E-mail для связи: mne@romka.eu.