Использование ПО с открытым исходным кодом для создания Web-сайта для совместной работы: Часть 5. Начало работы с Drupal

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

Элистер Льюис-Боуэн, старший инженер-программист, IBM

Элистер Льюис-БоуэнЭлистер Льюис-Боуэн (Alister Lewis-Bowen) работает старшим инженером-программистом в IBM Internet Technology Group. Он занимается Интернет и web-технологиями как сотрудник IBM UK с 1993. Элистер был переведен в США для работы над Web-сайтами спортивных событий, спонсируемых IBM, а затем как старший Web-мастер ibm.com. В настоящее время он помогает создавать семантические Web-прототипы.



Стефен Эванчик, инженер-программист, IBM

Стефен ЭванчикСтефен Эванчик (Stephen Evanchik) работает инженером-программистом в IBM Internet Technology Group. Он принимает участие во многих проектах с открытыми исходными кодами, самым известным из которых является его IBM TrackPoint-драйвер в ядре Linux. Стефен в настоящее время работает с появляющимися семантическими Web-технологиями.



Луис Вайцман, старший инженер-программист, IBM

Луис ВайцманЛуис Вайцман (Louis Weitzman) работает старшим инженером-программистом в IBM Internet Technology Group. В течение 30 лет он работал на стыке дизайна и вычислений. Помогал разрабатывать XML, фрагментированную систему управления содержимым, используемую для ibm.com, а в настоящее время участвует в обеспечении процесса проектирования новых проектов.



25.12.2006

Введение

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

Система управления содержимым Drupal сохраняет свое содержимое в базе данных. В самой базе данных содержимое хранится в виде узлов (nodes) и других объектов высокого уровня, таких как пользователи и комментарии. Существует много различных, предопределенных типов узлов, включая тексты (stories), блоги (blogs) и голосования (polls).

Drupal формирует страницу, содержащую один или несколько фрагментов информации в форме узлов, блоков и других элементов. Каждая страница обычно состоит из центрального столбца содержимого с левой и правой боковыми панелями (side-bars), а также имеет верхнюю панель, или заголовок (header), и нижнюю панель, или сноску (footer). За исключением центрального столбца остальные области являются необязательными.

Центральный столбец используется для отображения основного содержимого сайта, а необязательные области предназначены для дополнительного содержимого. Для заполнения необязательных областей небольшими фрагментами информации Drupal использует блоки. Необязательные области обычно содержат навигационные ссылки (например, наиболее популярные узлы) и другое сокращенное содержимое. Аналогично любому содержимому, блоки могут быть зависимыми от роли пользователя, обеспечивая, таким образом, специализированный вид информации.

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

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

Система меню управляет навигацией по Web-сайту и является полностью настраиваемой через пользовательский интерфейс. В отличие от этого ловушка menu управляет формированием URL, преобразованием URL и тем, какую функцию будет вызывать конкретный URL. Новички в Drupal часто путаются из-за названия этой функции, поскольку оно не относится к меню. Поэтому помните о возможных недоразумениях при работе с "menus" в Drupal.

Отделение содержимого от представления осуществляется системой, которая формирует темы страниц на основе шаблонов. Большая часть содержимого легко может быть структурирована и оформлена путем определения шаблонов (или tpl), файлов и функций темы.

Узлы могут быть организованы в категории или таксономии . Примером иерархического содержимого внутри таксономии являются форумы.

Обращение к любому содержимому производится через систему полномочий для управления доступом и изменения содержимого Web-сайта.

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

Узлы

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

Страницы (Pages)
Простые узлы для отображения содержимого (используя PHP, содержимое можно обновлять динамически; любая часть содержимого может быть динамической при использовании PHP).
Запись в блоге (Blog entry)
Узел для обслуживания Web-журнала.
Форумы (Forums)
Набор узлов и их комментариев (эти узлы группируются путем назначения элемента таксономии).
Текст (Story)
Стандартные страницы, срок действия которых истекает после определенной даты (они аналогичны нормальным страницам, но могут быть оформлены по-другому).
Комментарий (Comment)
Специальный тип содержимого, который позволяет пользователям делать комментарии к содержимому, определяемому другими узлами (комментарии не являются типом узла и хранятся в отдельной таблице базы данных).

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

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

Таксономия

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

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

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

Комментарии

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


Блоки

Блоки представляют собой маленькие, самодостаточные элементы информации, обычно отображаемые в навигационной области или в боковых панелях, но которые также могут быть размещены в любой области страницы. Они предоставляют маленькие виды информации, встроенные в представление других узлов. Модули предоставляют базовые блоки, используемые для отображения их содержимого. Администраторы могут создать новые блоки на основе существующих, а также написать PHP-код для прямого запроса и визуализации содержимого внутри блока.

На фазе конфигурирования, изображенной на рисунке 1, вы можете:

  • Разрешить или запретить зарегистрированные блоки.
  • Отсортировать отображение информации путем присвоения веса (от -10 до 10, элементы с меньшим числом отображаются выше в группе).
  • Разместить блоки в левой или правой боковой панели, в заголовке, в сноске или в области содержимого.
Рисунок 1. Указание различных блоков, определенных для нашего вымышленного Web-сайта
Рисунок 1. Указание различных блоков, определенных для нашего вымышленного Web-сайта

Модули

Модули являются основным механизмом расширения Drupal. Они реализуют четко определенный интерфейс, позволяющий новым модулям взаимодействовать с системой и системе взаимодействовать с модулем. Drupal вызывает функции в этих интерфейсных ловушках. Ловушки Drupal сгруппированы в три категории; они используются в модулях, которые:

Аутентификация
Обеспечивают дополнительные механизмы аутентификации пользователя
Ядро
Должны реагировать и взаимодействовать с кодом ядра Drupal
Узел
Обеспечивают новый тип узла в системе

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

После создания модуля вы должны разрешить этот модуль и назначить полномочия различным ролям, которые определены. На рисунке 2 показана часть административного экрана, на которой разрешается модуль (administer > modules). Здесь мы разрешили модули announcement и comment. Интерфейс администратора использует флажки для разрешения или запрещения индивидуальных модулей, таких как наш специализированный модуль announcement и предоставляемый системой модуль comment.

Рисунок 2. Разрешение модулей
Рисунок 2. Разрешение модулей

Ловушки

Для программного определения модуля вы должны создать специфические функции, которые соответствуют синтаксису предопределенных функций. Эти ловушки позволяют системе вызывать соответствующую PHP-функцию при просмотре страницы или сохранении информации в базе данных. Каждая ловушка имеет определенный набор параметров и определенный тип возвращаемого значения. Синтаксис ловушки должен следовать правилу: перед определенными интерфейсами указывается имя модуля. Например, ловушка для удаления узла типа announcement имеет синтаксис announcement_delete(...). Эта ловушка позволяет вашему специализированному модулю удалять из базы данных всю информацию, которую создал ваш модуль и которая должна быть удалена при удалении данного узла.

Еще один пример для просмотра узла того же типа, announcement_view(...), будет позволять модулю фильтровать содержимое на основе полномочий текущего пользователя. Примером отображения содержимого на странице является функция announcement_block(...). Она разрешает модулю возвращать небольшой контейнер оформленного согласно теме содержимого, используемого как блок на любой web-странице.

Ниже кратко описаны некоторые основные ловушки для обращения к узлу, взаимодействия с базой данных и организации тем. Более подробная информация будет приведена в следующей статье, где мы рассмотрим наш специализированный модуль announcement.

Ловушки доступа к узлу

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

<module_name>_perm
Ловушка perm определяет типы прав доступа, которые могут быть присвоены каждому пользователю. Модуль узла определяет несколько стандартных типов.
Листинг 1. Реализация ловушки perm из модуля узла
function node_perm() {
   return array('administer nodes', 'access content', 'view revisions', 
      'revert revisions');
}

Модуль узла различает узлы для администрирования, доступа к содержимому, просмотра и возврата редакций модуля. Эти строки используются при назначении привилегий различным пользовательским ролям (см. рисунок 4). Используйте существующие типы, если это возможно. Но вы всегда можете создать свои собственные типы, если семантика вашего модуля другая. Например, если модуль announcement должен отличать операцию create от операции edit, вы можете предоставить ловушку со значениями create announcement и edit announcement в массиве.

Функция Drupal user_access() облегчает проверку полномочий текущего пользователя относительно этих типов строк. Функция user_access('access content') возвращает значение TRUE, если текущий пользователь имеет права "access content" (то есть, пользователь может просматривать общее содержимое на Web-сайте). Вы обнаружите, что эта функция обычно используется в ловушке меню модуля, но вы можете свободно использовать ее везде, где вам необходимо определить полномочия пользователя перед выполнением действия.

<module_name>_access
Ловушка access обеспечивает способность ограничивать доступ к конкретным операциям с содержимым. В качестве параметров передаются операция с узлом (просмотр, создание, обновление, удаление и т.д.) и узел, для того чтобы определить полномочия. Возвращая значение Boolean, вы можете разрешить или запретить определенные операции с узлом. Например, вы можете проверить, является ли текущий пользователь автором узла, для определения возможности выполнения текущей операции. Для этого вы можете использовать следующий код, приведенный в листинге 2.
Листинг 2. Пример реализации ловушки access
function <module_name>_access($op, $node) {
   if ($op == 'update' ||  $op == 'delete') {
      if ($user->uid == $node->uid or user_access('edit <module_name>')) {
         return true;
      }
      else {
         return false;
      }
   }
}

Пример ловушки access разрешает выполнение операций update или delete, если пользователь, инициировавший запрос, является владельцем содержимого, или если ему были явно назначены права для редактирования содержимого этого типа.

Ловушки представления узла

<module_name>_form
Ловушка form определяет виджеты ввода информации, такие как текстовые поля, флажки и т.д., используемые при добавлении или редактировании узла для этого модуля. Примеры данной функции приведены в документации по соответствующей версии.

Реализация интерфейса form была изменена между выходами версий Drupal 4.6 и 4.7.

<module_name>_validate
Ловушка validate используется модулями для гарантирования корректности данных перед помещением их на Web-сайт.
<module_name>_submit
Ловушка submit используется модулями для изменения данных в узле перед помещением их на Web-сайт после успешного завершения ловушки validate.
<module_name>_view
Ловушка view обеспечивает для модуля механизм определения представления узла этого типа. Он сначала подготавливает узел, применяя фильтры посредством использования другой ловушки, затем генерирует HTML посредством процесса тематического оформления (theming).
<module_name>_menu
Ловушка menu позволяет модулю определить пути URL, которые он хочет обрабатывать. Возвращаемое значение представляет собой массив элементов. Каждый элемент является ассоциативным массивом, который определяет уникальный URL. Существуют различные варианты для возвращаемых значений, от нормальных элементов в дереве путей до элементов callback, которые регистрируют функцию, вызываемую для определенного пути.

Пример функции ловушки menu показан в листинге 3.

Листинг 3. Пример реализации ловушки menu
function <module_name>_menu() {
  $items = array();
  $items[] = array('path'     => '<module_name>', 
                   'title'    => t('Module Name'),
                   'access'   => user_access('access content'),
                   'type'     => MENU_SUGGESTED_ITEM,
                   'callback' => '<module_name>_page');
  return $items;
}

Этот пример указывает Drupal распознавать URL /<module_name>, использовать его в списке меню по умолчанию, проверить, что только роли с полномочиями "access content" могут обращаться по этому URL, и использовать функцию <module_name>_page при обнаружении этого URL в браузере.

<module_name>_nodeapi
Ловушка nodeapi является полезной функцией, если вам нужно взаимодействовать с другими модулями в системе. Например, если разрешен модуль comment, функция comment_nodeapi() могла бы быть вызвана для расширения объекта узла данными, относящимися к любому комментарию, связанному с узлом. Ловушка nodeapi может также использоваться для других событий, включая просмотр, доступ к базе данных, поиск, проверка корректности и т.д.

Ловушки базы данных узла

Таблицы node и node_revisions в базе данных содержат основную часть информации, хранящейся в системе, такую как заголовок, краткий обзор, тело, автор и время создания. Система позволяет сохранять много редакций узла без снижения производительности или масштабируемости. При написании модуля нового узла обычно в базу данных добавляется одна или несколько новых таблиц. Ловушки базы данных позволяют модулю создавать, изменять и удалять данные в таблицах при создании или изменении в системе содержимого нового узла.

Drupal имеет уровень абстракции базы данных, который содержит несколько функций, которые связывают высокоуровневый Drupal API базы данных с низкоуровневым PHP API базы данных модуля для MySQL или PostgreSQL. Реализация API абстракции базы данных позволяет достичь совместимости с различными базами данных.

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

<module_name>_load
Ловушка load позволяет модулю загружать любую дополнительную информацию для узла этого типа из дополнительных таблиц базы данных. Возвращаемое значение представляет собой объект, содержащий добавляемые дополнительные свойства. Drupal автоматически присоединяет их к загружаемому узлу. Например, код может выглядеть так, как показано в листинге 4.
Листинг 4. Пример реализации ловушки load
function <module_name>_load($node) { 
 $additions = db_fetch_object(db_query('SELECT * FROM {<module_name>} WHERE nid = %s', 
                                      $node->nid));
 return $additions; 
}

Затем $additions автоматически соединяется системой с результатами загрузки узла.

<module_name>_insert
Ловушка insert указывает модулю добавить данные в базу данных для аргумента node. Обычно это вызов функции уровня абстракции базы данных (например, db_query) для вставки данных об узле в таблицы, определенные для этого модуля. Стандартные данные (такие как тело, время создания и т.д.), хранящиеся в таблице базы данных node, записываются в базу данных автоматически.
<module_name>_update
Ловушка update обеспечивает для нашего модуля механизм обновления данных существующего узла в базе данных. Ловушка update также является самым вероятным местом реализации кода, необходимого для поддержки редакций узла для вашего модуля.
<module_name>_delete
Ловушка delete позволяет модулю выполнить дополнительное действие при удалении узла из базы данных. В это время могут быть очищены любые специфичные для модуля таблицы.

Дизайн URL

Drupal использует систему меню для определения навигации по Web-сайту. При создании специализированных модулей вы можете указать, как ваш модуль должен обслуживать содержимое, основываясь на URL. При получении запроса страницы система находит наилучшее совпадение, основанное на иерархической структуре путей. Если путь зарегистрирован, она использует определенную функцию как обратный вызов для формирования представляемого содержимого. Любой фрагмент пути можно использовать для выбора того, как представлять содержимое. Например, для пути /announcement/15/edit, будет представлена страница редактирования узла с id = 15, в отличие от пути /announcement/15/view, для которого будет отображаться только содержимое узла. Функции обратного вызова определяются в ловушке <module_name>_menu.

Drupal имеет также механизм для определения использования интерфейса с закладками. Эти закладки определяются в системе меню как "local tasks" (локальные задачи). При определении локальных задач вы можете назначить одну в качестве задачи по умолчанию. Локальная задача по умолчанию является первой задачей, представляемой пользователю, когда он просматривает фрагмент содержимого. Мы рекомендуем всегда назначать локальную задачу по умолчанию при использовании этой функциональной возможности.

<module_name>_menu возвращает массив спецификаций меню. Фрагмент кода в листинге 5, повторенный снова, показывает одну такую спецификацию для определения простого обратного вызова для типичного специализированного модуля.

Листинг 5. Один элемент из фрагмента кода ловушки menu
$items[] = array('path'     => '<module_name>', 
		         'title'    => t('Module Name'),
                 'access'   => user_access('access content'),
                 'type'     => MENU_SUGGESTED_ITEM,
                 'callback' => '<module_name>_page');

В спецификации к атрибутам относятся:

Path (путь)
Когда он совпадает с URL запроса, этот элемент используется.
Title (заголовок)
Заголовок элемента меню.
Access (доступ)
Значение этого атрибута определяет, может ли текущий пользователь обращаться к содержимому, указанному данным элементом.
Type (тип)
Тип спецификации меню.
Callback (функция обратного вызова)
Функция, вызываемая для формирования отображаемого содержимого при использовании этого элемента.

Существует несколько различных типов спецификаций меню:

MENU_NORMAL_ITEM
Используемый по умолчанию тип для элементов меню. Они показываются в дереве меню.
MENU_ITEM_GROUPING
Группирование элементов, которое просто перечисляет субстраницы для посещения.
MENU_CALLBACK
Регистрирует функцию, которая вызывается для генерирования содержимого, представляемого при доступе к URL.
MENU_SUGGESTED_ITEM
Предлагаемые элементы из модулей могут быть разрешены администратором.
MENU_LOCAL_TASK
Эти страницы визуализируются в виде закладок. Возможны и другие типы визуализации.
MENU_DEFAULT_LOCAL_TASK
Каждый набор локальных задач должен также предоставлять задачу по умолчанию, которая при нажатии ссылается на тот же путь, что и ее предок.

Пользователи

Еще одним объектом высокого уровня в системе является объект user, который позволяет настроить учетные записи для различных пользователей, приходящих на сайт. Как администратор вы можете создать различные роли для различных прав доступа к содержимому. Пользователи затем могут быть отнесены к одной или нескольким ролям. Обратите внимание на то, что только первый пользователь, учетная запись которого создана при конфигурировании вашей установки Drupal, имеет полномочия менять любые настройки в системе.

Администратор может назначать пользователей любым ролям, как определено в разделе управления доступом административного интерфейса Drupal. На рисунке 3 показаны роли, созданные для нашего вымышленного Web-сайта. В дополнение к стандартным ролям мы добавили роли для администраторов, пользователей, оперативного персонала и руководителей рабочих групп.

Рисунок 3. Определение ролей для указания уровня доступа пользователей к содержимому
Рисунок 3. Определение ролей для указания уровня доступа пользователей к содержимому

На рисунке 4 показан экран администратора для назначения ролей правам доступа внутри модуля. Интерфейс администратора использует флажки для разрешения или запрета прав доступа к связанным с модулями действиям для конкретных ролей. Роли перечисляются вверху таблицы, тогда как права, сгруппированные по модулю, отображаются в первом столбце. Права доступа являются строками, указанными в ловушке <module_name>_perm. Классификация пользователей по ролям может разделить ответственность задач для различных классов пользователей.

Рисунок 4. Интерфейс администратора для разрешения или запрета прав доступа
Рисунок 4. Интерфейс администратора для разрешения или запрета прав доступа

Настройка внешнего вида вашего Web-сайта

Drupal отделяет содержимое от представления, используя систему поддержки тем. Вы можете оформить тему для вашего содержимого, используя в Drupal различные механизмы поддержки тем. Хотя вы можете запрограммировать тему полностью в PHP, механизм поддержки тем предоставляет интегрированную среду для разработки, что может сэкономить время. В настоящее время на сайте Drupal доступны механизмы поддержки тем PHPTemplate, XTemplate и Smarty. Мы выбрали для использования механизм PHPTemplate, поскольку он является механизмом по умолчанию и предлагает последовательное использование PHP на уровне логики, в модулях и на уровне представления.

Стандартные функции системы поддержки тем

Понимание того, как базовый код системы поддержки тем ищет соответствующий метод, является важным для разработчиков модулей. Модули должны быть написаны так, чтобы разрешить другим конструкторам системы интегрировать содержимое модуля во внешний вид и поведение их web-сайта. Drupal в настоящее время выполняет поиск трех PHP-функций, формирующих оформленное темой содержимое, в следующем порядке:

  1. <theme name>_<content name>
    Эта функция строится из названия текущей темы и названия содержимого, или типа узла, который оформляется темой. Если текущая тема называется ibc, и мы оформляем темой содержимое announcement, то функция должна иметь название ibc_announcement.
  2. <theme engine name>_<content name>
    Эта функция строится из названия текущего механизма тем и названия содержимого. Мы используем механизм PHPtemplate, поэтому названием нашей функции для содержимого announcement должно быть phptemplate_announcement.
  3. theme_<content name>
    Это последняя и самая простая функция. Если мы оформляем темой содержимое announcement, названием функции будет просто theme_announcement.

Тема определяется набором файлов в каталоге тем Drupal. Drupal поставляется с необходимыми для темы файлами, набор которых зависит от вашего механизма поддержки тем. Вы можете настроить вашу тему разными способами; мы представляем наш подход изменения представления данных для получения xHTML-структуры, стиля и схемы, которые мы хотели иметь для Web-сайта.

Файлы шаблонов

PHPTemplate позволяет вам отображать специальные файлы, называемые файлами шаблонов, на специальные функции и модули в Drupal. Файл шаблона, имя которого заканчивается на .tpl.php, использует массив данных, передаваемый ему назначенной для него функцией или модулем. Используя PHP и xHTML, этими данными можно управлять, для того чтобы представить их на Web-странице. Существуют стандартные шаблоны для имеющихся типов узлов, предоставляемые Drupal для настройки вашей темы. Файлы page.tpl.php, node.tpl.php и comment.tpl.php являются примерами стандартных шаблонов. Они расположены в каталоге theme. Страница, определенная шаблоном page, используется для отображения на ней любого узла, определенного шаблоном node.

page.tpl.php
Это, вероятно, то место, откуда вы начали бы настройку вашей собственной темы. Это шаблон, который определяет структуру всех страниц содержимого, отображаемого системой Drupal. Здесь вы можете определить ваши глобальные структурные элементы xHTML, такие как элементы head и body, включаемые файлы для стилевых таблиц, скелетные DIV-элементы, устанавливающие семантику схемы вашего содержимого, и т.д.
node.tpl.php
Этот шаблон используется для манипулирования тем, как отображаются данные узла. Если вы хотите оформить тему для узла определенного типа, нужно скопировать файл node.tpl.php и изменить иго имя на node-<type>.tpl.php, где <type> - это название типа узла. По данной методике мы изменили схему по умолчанию для содержимого форума, используя шаблон под названием node-forum.tpl.php в разделе discussions Web-сайта IBC.
comment.tpl.php
Этот файл шаблона управляет схемой одиночного комментария. Комментарии могут быть добавлены на страницы при помощи модуля Drupal Comment.

Переопределение существующих функций системы поддержки тем

Механизм PHPtemplate позволяет отображать шаблоны на функции конкретного механизма поддержки тем. Функции системы поддержки тем предоставляют стандартные методы построения Web-содержимого, используемые модулями, обеспечивающими функции ядра в Drupal, или вашими собственными модулями, расширяющими Drupal.

Одним из примеров является функция theme_links. При наличии массива анкерных (anchor) элементов xHTML (ссылок), theme_links будет возвращать строку, содержащую эти ссылки, разделенные указанным символом. Это пример очень простого функционального блока. Листинг 6 изменяет вывод таким образом, что элемент DIV с атрибутом class и значением links будет охватывать разделенный список ссылок.

Существует специальный файл (который вы можете использовать в каталоге индивидуальной темы), называемый template.php. Если этот файл существует, Drupal будет использовать его для разрешения переопределения действия по умолчанию системы поддержки тем. В файле template.php мы можем создать функцию, приведенную в листинге 6.

Листинг 6. Функция phptemplate_links из файла template.php
function phptemplate_links($links, $delimiter = ' | ') {
  if (!is_array($links)) {
    return '';
  }
  $content = '<div class="links">';
  $content .= implode($delimiter, $links);
  $content .= '</div>';
  return $content;
}

Создавая функцию phptemplate_links в файле template.php, мы указываем Drupal переопределить функцию по умолчанию theme_links. В переопределенной функции мы окружаем элементом DIV список ссылок и возвращаем полученную в результате строку.

Оформление темами новых модулей

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

Создание представления по умолчанию
Для генерирования оформленного темой вывода по умолчанию мы создали функцию в модуле. Она обрабатывает переданные в нее данные и возвращает оформленное темой содержимое в виде строки. Примером может быть оформленный темой список элементов в модуле shopping_list_items. Оформленный темой вывод является неотсортированным xHTML-списком элементов, показанным в листинге 7.

Листинг 7. Оформление темой вывода в виде неотсортированного списка элементов
function theme_shopping_list_items($list = array()) {
   $content = '<ul>';
   foreach ($list as $list_item) {
      $content .= '<li>'.$list_item.'</li>';
   }
   $content .= '</ul>';
   return $content;
}

Затем, в той части вашего модуля, где вы формируете Web-страницу, используется функция Drupal theme для вызова функции theme_shopping_list_items, возвращающей оформленный список. Последовательность выполнения приведена в листинге 8.

Листинг 8. Оформление списка элементов
$tools = array('hammer', 'drill', 'saw');
$content .= theme('shopping_list_items', $tools);

Переопределение вывода модуля при помощи темы
Как объяснялось ранее, мы можем использовать файл template.php в каталоге theme для переопределения функций theme. Исходя из приведенного выше примера, предположим, что мы хотим изменить действие по умолчанию по отображению списка элементов, сгенерированного модулем shopping_list_items, с неотсортированного xHTML-списка на xHTML- список определений, показанный в листинге 9. Мы создаем эту функцию в файле template.php или в файле модуля узла.

Листинг 9. Оформление вывода как списка определений
function phptemplate_shopping_list_items($items = array()) {
  $content = '<dl>';
  foreach ($items as $list_item) {
    $content .= '<dt>'.$list_item.'<dt>';
  }
  $content .= '</dl>';
  return $content;
}

Поскольку Drupal знает, что наша тема использует механизм PHPtemplate, он автоматически переопределит функцию theme_shopping_list_items в модуле shopping_list на новую функцию. В результате будет выводиться xHTML- список определений вашего оборудования. Выполняя еще один шаг, мы можем указать Drupal использовать файл шаблона для определения представления этого списка, определяя имя файла внутри этой переопределяющей функции, как показано в листинге 10.

Листинг 10. Функция, использующая файл шаблона для оформления темой
function phptemplate_shopping_list_items($items = array()) {
  $template_file = 'shopping_list_items';
  $content = _phptemplate_callback('shopping_list_items', 
                                   array('items' => $items), $template_file); 
  return $content;
}

Файл шаблона может содержать приведенный ниже код.

Листинг 11. Фрагмент кода из файла шаблона для представления списка элементов
<dl>
<?php foreach ($items as $list_item) : ?>
	<dl><?php print $list_item; ?></dl>
<?php endforeach; ?>
</dl>

Здесь мы используем наши знания механизма PHPtemplate. Функция _phptemplate_callback соединяет наш вызов phptemplate_shopping_list_items с файлом шаблона под названием shopping_list_items.tpl.php с переменной list_items, установленной в массив $items. Этот метод оформления содержимого является предпочтительным, поскольку он четко отделяет массив PHP-кода от xHTML.

Структура и стиль содержимого

Мы описали механизмы использования системы поддержки тем Drupal для расширения и изменения представления содержимого по умолчанию. Дополнительный аспект должен учитывать структуру содержимого, генерируемого каждым узлом, и общий стиль, применяемый к этой структуре. Использование механизма PHPtemplate позволяет Web-дизайнерам поддерживать структурированный xHTML для данных, генерируемых модулями. Этот вариант позволяет также использовать Cascading Style Sheets (CSS) для изменения представления или стиля этой структуры. Мы обнаружили, что полезно сохранять формирование данных внутри модуля (а формирование xHTML - внутри шаблонов) для отделения данных от представления.

Структура всей Web-страницы создается файлом page.tpl.php, расположенном в каталоге theme. В этом файле можно использовать xHTML для определения базовой схемы Web-страницы, в которую включается содержимое других узлов. Поскольку расположение заголовка, тела, боковых панелей и сноски на нашем Web-сайте остается неизменным, эти структуры определяются здесь.

Мы были внимательны и использовали корректную xHTML-разметку для наших навигационных элементов (заголовков разделов и т.д.), поэтому содержимое нашего Web-сайта представляется в приемлемом формате даже при отсутствии оформления.

Одна из переменных, представленных в этом шаблоне системой поддержки тем в Drupal, может сигнализировать, должна ли отображаться титульная страница. Используя минимум PHP, мы применили эту переменную для структурирования xHTML несколько иначе, чем для подчиненных страниц Web-сайта.

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

В следующей статье мы более подробно рассмотрим технические приемы, использованные нами для структурирования и оформления нашего Web-сайта на Drupal.

Мы ссылались на стилевые таблицы для экрана и печати в заголовке Web-страницы, как определено в файле page.tpl.php. Для категоризации и управления стилем мы решили разбить CSS-оформление на отдельные файлы и включить их в файл стилевой таблицы основного экрана. Основные стили общих xHTML-элементов содержались в одной стилевой таблице CSS, схема в другой, а изменения стиля в разделах Web-сайта размещались в своих собственных файлах. Как и в ситуации с файлами шаблонов, все файлы стилевых таблиц располагались в каталоге theme.


Последовательность построения узла

В данном разделе мы рассмотрим, как Drupal строит узел. Полезно понимать последовательность, в которой Drupal собирает информацию для определенного узла, как ядро взаимодействует с модулем и как этот модуль визуализируется перед представлением на Web-странице. Подразумевается, что это обзор, поэтому некоторый уровень детализации останется за рамками рассмотрения в данном разделе. На рисунке 5 показана блок-схема последовательности построения узла.

Рисунок 5. Итоговая блок-схема последовательности построения узла для операции View
Рисунок 5. Итоговая блок-схема последовательности построения узла для операции View

Более крупная версия данного рисунка

Путь в URL-запросе структурирован так, что за /node/, или типом узла, следует id узла, а затем операция узла. Если путь равен /node/15/edit, это указывает Drupal, что должна быть отображена форма редактирования для узла 15. Единственным исключением в этой структуре является случай, когда URL-путь равен /node/add или /node/add/<node_type>, а Drupal знает, что надо применить операцию Add.

В данном разделе вы узнаете о четырех следующих операциях:

View (просмотр)
Операция по умолчанию, которая формирует страницу только для просмотра.
Add (добавление)
Операция, представляющая форму для добавления нового узла.
Edit (редактирование)
Операция, представляющая форму для редактирования существующего узла.
Delete (удаление)
Операция, которая удаляет узел из системы Drupal.

Помните о том, что система меню знает о том, какую функцию вызвать, основываясь на полученном URL. Мы начнем рассмотрение последовательности построения узла с точки, где система меню вызывает функцию node_page() в node.module.

Первое, что должен сделать Drupal, - определить операцию. Если после id узла в URL операция не указана, предполагается операция по умолчанию view.

Операция View

Перед возможностью какой-либо визуализации узла создается контейнер для всех данных, связанных с этим узлом. Этот объект node заполняется данными из записи таблиц базы данных node и node_revisions, чьи значения поля первичного ключа являются такими же, как id узла в URL. К этим данным относятся тип узла, заголовок, обзор, тело, автор и время создания.

Затем к этому объекту node применяются все расширенные данные. Это осуществляется посредством двух ловушек: load и nodeapi. Ловушка nodeapi обеспечивает для любого модуля еще один способ расширения базовых операций Drupal: load, view, prepare, delete.

Поскольку node_type уже известен, Drupal использует его для определения, существует ли функция <node_type>_load(). Например, если типом узла является announcement, вызывается функция announcement_load(), где она может расширить информацию об узле по умолчанию датой публикации и истечения срока уведомления.

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

Затем Drupal сохраняет заголовок узла, который он может использовать для включения в заголовок Web-страницы позже в цикле жизни запроса.

Далее Drupal начинает процесс визуализации данных объекта node в содержимом. Действие по умолчанию - создать и сохранить оформленный вывод для тела и реферата узла. Если Drupal находит ловушку <node_type>_view(), она будет вызвана для переопределения оформления этих фрагментов содержимого. Например, если типом узла является announcement, то функция announcement_view() может возвратить оформленный фрагмент содержимого для дат публикации и истечения срока уведомления в дополнение к содержимому тела и обзора.

Как и для раздела load данной последовательности, Drupal теперь ищет любые ловушки nodeapi во всех доступных модулях. Вызов этой функции содержит аргумент, означающий, что Drupal оформляет данные объекта node и разрешает любому модулю изменять или расширять содержимое в оформленном фрагменте body. Затем оно сохраняется в объекте node.

Ссылки - это еще один тип содержимого, которое может быть добавлено к объекту node. Они предлагают дополнительные оформленные Web-ссылки к содержимому узла, и Drupal позволяет любому модулю добавлять их через ловушку link.

Затем Drupal проверяет, должны ли визуализироваться комментарии для этого узла. Он использует данные всех комментариев, хранящихся в объекте node, для оформления фрагментов содержимого, требуемых до сохранения их в объекте node.

Наконец, объект node со всеми его данными и оформленным содержимым передается в систему Theming для визуализации как оформленный узел. В этот момент времени наш узел полностью построен и готов для отображения.

Операция Add

При указании Drupal в URL-пути операции добавления узла последовательность построения узла значительно отличается от операции View. Во-первых, Drupal проверяет, существует ли тип узла в URL-пути; если да, он проверяет, имеет ли пользователь, выполнивший этот запрос, полномочия для создания нового узла. Если эти условия выполняются, Drupal начинает собирать форму, требуемую для добавления узла этого типа. Если нет, отображается страница, перечисляющая доступные типы узлов.

Как и при операции View, Drupal создает объект node, который сохраняет все данные, которые могут использоваться для визуализации формы. Как часть подготовки данных для этого объекта node, Drupal вызывает ловушку <node_type>_prepare() (при ее наличии). Это дает возможность связанному модулю выполнить предобработку всех данных, требующих включения в объект node.

Для предоставления любым другим модулям способности добавлять или изменять объект node, вызываются все ловушки nodeapi с аргументом, обозначающим, что Drupal выполняет подготовку к показу формы для добавления.

Способ обработки формы в Drupal здесь не описывается, но он будет рассмотрен в следующей статье.

Теперь Drupal формирует структуру данных, которая описывает виджеты формы для данных объекта node. Перед визуализацией формы вызывается ловушка <module_name>_form_alter() для любых модулей, позволяя изменять структуру данных формы. Например, модуль taxonomy может использовать ловушку form_alter при вставке формы для выбора терминов классификации, определенных для этого типа узла.

Наконец, структура данных формы используется для визуализации получаемого узла, представляющего форму.

Операция Edit

Операция Edit аналогична операции Add, за исключением того, что в URL-пути предоставляется id узла.

При построении узла с использованием операции Edit, Drupal снова создает объект node для сохранения данных, используемых для визуализации получаемой страницы. Как описывалось для операции View, вызываются ловушки <module_name>_load и <module_name>_nodeapi для разрешения модулям добавлять или изменять данные объекта node. Естественно, если данный id узла не найден в базе данных или отсутствуют права доступа на изменение этого узла, на Web-странице отображается соответствующий ответ при помощи системы сообщений Drupal.

Если id узла найден, а доступ для редактирования разрешен, Drupal выполняет процесс, аналогичный описанному для операции Add. Однако, поскольку объект node содержит данные, связанные с этим узлом, структура данных формы представляет эти данные в виджетах формы во время их визуализации.

Операция Delete

Drupal обрабатывает операцию Delete несколько иначе по сравнению с другими операциями. Хотя процесс создает и заполняет объект node аналогично операциям View и Edit, эти данные не используются таким же способом для визуализации узла или формы для редактирования данных узла. Вместо этого проверяются права доступа на удаление узла. Drupal затем создает простую форму, которая визуализируется на Web-странице, запрашивая у пользователя подтверждение операции удаления.

Хотя данный раздел не описывает процесс представления формы в Drupal, полезно знать, что для разрешения модулям очищать любые расширенные таблицы базы данных или переменные, связанные с типом этого узла, активизируются ловушки <module_name>_delete и <module_name>_nodeapi.


Резюме

В данной статье вы познакомились с концепциями, терминологией и техническими приемами, используемыми в Drupal. Эти функциональные блоки формируют основу принципа работы Drupal. Вы узнали, что такое:

  • Узлы
  • Блоки
  • Модули и интерфейс ловушек
  • URL-дизайн и система меню
  • Пользователи и полномочия
  • Оформление внешнего вида вашего Web-сайта
  • Последовательность построения узла

Хотя это и частичное введение, данные концепции являются ключевыми для освоения внутренней работы Drupal. Как только вы изучите основы, будет легче двигаться вперед в настройке вашей среды и Web-сайта.

Следующая статья данной серии (часть 6) описывает расширение Drupal специализированным модулем создания уведомлений для нашего Web-сайта. Будет представлено более подробное описание нашего модуля, включая специфические примеры кода.

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=185504
ArticleTitle=Использование ПО с открытым исходным кодом для создания Web-сайта для совместной работы: Часть 5. Начало работы с Drupal
publish-date=12252006