Друпал

Здесь собраны подшивки по Друпалу

Мультисайтинг для Друпала 6, часть 1

Итак, мультисайтинг - что это такое и зачем он нужен?

Если сказать коротко - мультисайтинг нужен как для разработчиков сайтов, так и для пользователей:
1. Для разработчиков сайтов. Мультисайтинг избавит Вас от изнурительной повторяющейся работы. Если у Вас один сайт, Вам не нужен мультисайтинг. Но если сайтов несколько - тогда без мультисайтинга Вы будете вынуждены для каждого сайта отдельно устанавливать одни и те же модули, обновлять каждый сайт по отдельности и так далее. А ведь всё это колоссальная трата времени, которой при желании легко можно избежать.
2. Для пользователей. Когда при мультисайтинге объединяются записи баз данных, серьёзно облегчается работа с посетителями сайтов, и при этом самим посетителям связки сайтов гораздо удобнее, легче и комфортнее при посещении Ваших сайтов.

Я остановлюсь именно на мультисайтинге для шестого Друпала, для чего неплохо будет обратиться к первоисточнику - то есть к документации, которая входит в базовый установочный пакет Друпала - файлу INSTALL.txt:

Один единственный раз установив Друпал, Вы можете поддерживать несколько сайтов на движке Друпала, и каждый Ваш сайт будет иметь свои собственные настройки, структуру и контент.

Конфигурация каждого Вашего сайта задаётся в подкаталогах папки sites. Каждый такой подкаталог обязательно должен иметь файл settings.php, который и определяет настройки сайтов. Самый лёгкий способ создать дополнительный сайт - это скопировать туда папку default и изменить настройки в файле settings.php так, как Вам это нужно. Имя новообразованной папки определяется адресом URL сайта. Например, настройки конфигурации сайта www.nam.by могут быть определены в файле 'sites/nam.by/settings.php' (префикс 'www.'может быть пропущен, если пользователи могут иметь доступ к Вашему сайту, как к http://nam.by/).
Ваши сайты не обязаны иметь разные домены. Вы также можете использовать поддомены и подкаталоги для новых сайтов. Например, example.com, sub.example.com, или sub.example.com/site3 - все они могут быть определены как независимые сайты на Друпале. И настройки конфигурации для этих сайтов устанавливаются в файле settings.php по следующим путям:

sites/default/settings.php
sites/example.com/settings.php
sites/sub.example.com/settings.php
sites/sub.example.com.site3/settings.php

Когда Друпал ищет настройки конфигурации сайта (к примеру www.ru.wikipedia.org/wiki ), то поиск производится по директориям в следующем порядке:

sites/www.ru.wikipedia.org.wiki/settings.php
sites/ru.wikipedia.org.wiki/settings.php
sites/wikipedia.org.wiki/settings.php
sites/www.ru.wikipedia.org/settings.php
sites/ru.wikipedia.org/settings.php
sites/wikipedia.org/settings.php
sites/default/settings.php

Это была первая вводная статья, продолжение во второй части. Если Вам что либо не понятно, оставляйте свои комментарии, я обязательно постараюсь Вам помочь.

С уважением, Ёж

Мультисайтинг для Друпала 6, часть 2

Итак, продолжаю перевод официальной документации Друпала 6.

Если Вы используете нестандартный порт, то номер порта будет рассматриваться как более глубокий поддомен. К примеру: http://www.example.com:8080/ будет загружаться из sites/8080.www.example.com/.

Каждый сайт Вашей связки может иметь свои собственные модули и темы, дополнительно к тем, которые установлены изначально в папках modules и themes. Для того, чтобы использовать дополнительные модули и темы только для какого-либо одного сайта, Вы должны добавить подкаталоги modules и themes в папке для настроек этого сайта. К примеру, если sub.example.com использует специальный модуль или тему, которые не должны быть доступны на других сайтах, они должны быть установлены в соответствующие папки:

sites/sub.example.com/:
settings.php
themes/custom_theme - в папку themes записываете тему
modules/custom_module - в папку modules записываете модуль

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

С уважением, Ёж

Друпал. Настройка темы

Эта статья посвящается настройке темы для Друпала. Статья рассказывает о некоторых полезных механизмах работы с движком PHPTemplate.

node.tpl.php - это файл шаблона для вывода Ваших нод (или документов). Этот шаблон определяет не только то, как Вы будете выводить саму ноду, но и то, как она будет отображаться в списке тизеров (анонсов). А ведь порою крайне необходимо делать это по-разному. Например, возьмите Ваши анонсы статей на главной странице. Вы пишете блог, и на главной странице анонсы постов блога - и под каждым таким анонсом надпись "Все записи блога". И эта надпись повторяется десять раз на главной странице - просто ужас, иголки встают дыбом. То же самое можно сказать о надписи "Добавить комментарий". Нелогично оставлять комментарий к статье, прочитав лишь её анонс. Информацию об авторе статьи тоже можно убрать с главной страницы - особенно это касается личных блогов - зачем на главной странице десять раз повторять одно и то же имя автора?

Для разного отображения тизеров и полных нод можно использовать логические переменные $page и $is_front. Переменная $is_front равна True(1) в том случае, если отображается главная страница сайта. Так как её использовать, чтобы создать шаблон для тизеров на главной страницы? Очень просто - открываю файл node.tpl.php в своей теме, и прописываю в самом его начале следующую строчку:

<?php if ($is_front): include "node-front.tpl.php"; return; endif; ?>

Таким образом я говорю Друпалу, что если я располагаюсь на главной странице, шаблон для отображения нод находится не в файле node.tpl.php, а в файле node-front.tpl.php. Создаю в той же директории файл с таким именем - после чего проще всего скопировать туда весь код из файла node.tpl.php, и убрать всё, что мне не нужно. Например, я убираю с главной страницы всё, что относится к переменной $submitted (имя автора и время добавления статьи), переменную $links (ссылки типа "Все записи блога" и "Добавить комментарий"), переменную $terms (список терминов таксономии) и так далее. Но позвольте, время добавления статьи неплохо было бы и оставить, убрать лучше просто имя автора. Но переменная $submitted всё равно не нужна, решаю я. Для отображения даты и времени существует такая замечательная функция PHP, как date(). Например, прописать вот такую строчку перед переменной $content (переменная для отображения основного содержимого Вашей статьи):

<?php print date("d.m.Y - H:i", $node->created) ?>

И вуаля, в диве submitted отображается теперь только дата создания документа, и никакого имени автора.

Итак, это я сделал - теперь жму на каком-нибудь термине таксономии, которые отображаются у меня теперь только на странице самой ноды - и снова вылазит та же самая проблема. Идёт перечисление всех статей, относящихся к данному термину таксономии, и снова под каждым анонсом тот же самый кошмар - ссылка "Все записи блога", "Добавить комментарий" и так далее. Ну что ж, придётся теперь воспользоваться переменной $page. Её значени равно True(1) в том случае, если Друпал отображает какую-то ноду, но никак не список нод. Итак, прописываю в начале файла node.tpl.php ещё одну строчку:

<?php if (!$page): include "node-front2.tpl.php"; return; endif; ?>

Эта строчка говорит Друпалу о том, что если Друпал отображает список анонсов нод - файл шаблона для него - не node.tpl.php, а node-front2.tpl.php (на самом деле назвать можно как угодно). И снова я всё что, мне нужно прописываю в этом новом файле шаблона. Проблема решена!

С уважением, Ёж

Drupal-темизация: Прошлое

Вашему вниманию предлагается перевод обзорной статьи Джеффа Итона (Jeff Eaton) – «Друпал, дизайнеры и будущее». Что было в прошлом, что мы имеем на данный момент, и что имеет смысл ожидать нам всем в будущем. Но сначала, естественно, было прошлое, многие из читателей тоже могут вспомнить те времена, когда для сайтов вручную оптимизировались GIF-изображения и делалась табличная HTML-вёрстка. Лично я например тогда только поступил в радио-технический колледж, и вспоминаю книгу Игоря Мархвиды «HTML, CSS и JavaScript». Вот, пример такой работы, один из сайтов самого Джеффа – до сих пор рабочий сайт между прочим.

Перейду же теперь к Друпалу. Друпал сперва имел репутацию CMS, с которой дизайнеру было работать не так уж и легко, и долгое время это было действительно заслуженно. В первую очередь, подход Друпала к генерации HTML-страницы несколько отличается от подхода, который применяется в том же WordPress или Movable Type (ещё один очень распространённый движок для блоггинга). Прежде чем запрашивать у CMS необходимые части данных и работать с ними, тема Друпала предопределяет небольшие части текста (заголовок, имя автора и так далее) и, соответственно, только предопределив их, тема готова встроить всё это в сгенерированную HTML-вёрстку. Поэтому тут нужна некоторая перемена мышления – для дизайнера и верстальщика.

И в прошлом разработка темы на Друпале превращалась из обычной HTML вёрстки в работу, требовавшую нехилые навыки работы на PHP. В то время как большие части (например, разметка элементов страницы или индивидуальных частей контента) могли изменяться в template-файлах движка темы, то изменение темизации более мелких частей (например меню навигации или фрагменты информации о данной статье) требовали от Вас пробираться в глубины API Drupal-темизации и писать код. Те, кто помнят времена функции _phptemplate_variables(), знают, о чём я говорю. В итоге изменение разметки требовало написание сторонних модулей, которые копались в коде ядра, искали места, в которых генерируется соответствующий HTML-код, и переопределяли всё это своими собственными PHP-функциями. Это всё конечно прекрасно работало, но это было настоящим адом для людей, привыкших работать на чистой HTML и CSS вёрстке.

Оригинал тут.

Но в наше время всё конечно же совсем по другому. :) Продолжение следует…

Ёж

Drupal-темизация: Настоящее

То, что есть на данный момент - это Друпал 6.x, и работа, проделанная для этой версии Друпала - это действительно серьёзный шаг на пути к удобству управлением Вашими темами.

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

example - это в данном случае название темы.

Файл example.info - это то место, в котором Вы определяете регионы для наших блоков. Регионы для блоков выделены красным на рисунке.
Там же в файле .info Вы определяете, что стили для нашей темы будут прописаны в файле style.css. После чего CSS будет запрашиваться именно из этого файла. Можно указать и какое нибудь другое имя, можно прописать несколько имён (возможно Вы видели - так делается в некоторых темах). В первую очередь это нужно для удобства самого разработчика - то есть Вы легко можете разграничить где будет прописан CSS для тех или иных элементов страницы, а не пихать это всё в один файл. И всё что нужно для этого - это просто прописать имена всех этих дополнительных .css файлов в файле .info.

Назначение файлов page.tpl.php, node.tpl.php и так далее - уже давно расписано до меня, тут содержатся шаблоны блоков, нод, общий шаблон страницы (page.tpl.php).

Также в папке с темой содержится файл logo.png - это картинка, которая используется как лого по умолчанию, скриншот темы и так далее (ну это уже лирика).

Ну и обычно в папке images внутри темы - все картинки, которые использует данная тема в процессе своей работы.

Так же легко можно создавать и подтему, на рисунке ниже:

В данном случае sub_example - это имя подтемы.

В файле sub_example.info - определяете тему родителя (define parent theme), определяете или переопределяете стили CSS родительской темы. Как видите - всё очень просто. В Друпале легко создавать чистые CSS темы, даже без необходимости изменять шаблоны - и это тоже безусловно большой плюс.

Ну и конечно файл template.php - в котором можно переопределить любую функцию темы, не относящуюся к стандартным типам (block, node, comment и т.п.).

Оригинал статьи теперь уже тут. Просто немного отошёл от первой статьи, решив более углубится в практическое, нежели в теоретическое описание.

С уважением, Ёж.

Drupal-темизация: Будущее?

Друпал седьмой ветки пока ещё находится в разработке, но уже сейчас уделяется немало внимания улучшению работы с темами оформления. Некоторые предлагают использовать сеточную систему для быстрой вёрстки - например, систему подобную фреймворку 960 Grid System - вёрстка с использованием сетки шириной в 960 пикселей. Это может существенно ускорить разработку тем.

Но это всё только предположения. Как лучше всего бороздить просторы Большого Театра пока можно только предполагать. Конечно, когда выйдет седьмой Друпал, тогда всё и увидим. Пока лишь можно перечислить, что бы хотелось увидеть в Друпале 7. Что упростит разработку тем?

1. Включить в ядро файл layout.css который будет только лишь правильно позиционировать основные элементы страницы - content, header и sidebars. Переопределять данный файл можно было бы очень легко - просто добавлением CSS-файла с таким же именем в свою тему. Для вновь прибывших это также было бы полезно - быстрее бы разобрались как файлы шаблонов работают при минималистской вёрстке.

2. Обеспечить тему оформления в ядре, которая содержала бы только .info файл. Ну и, соответственно, тот самый файл layout.css, который размечает основные регионы. Такая тема могла бы служить хорошим примером того, на основе чего и строится любая друпаловская тема. И хорошим отправным пунктом для многих.

3. Обеспечить одну или несколько тем, включённых в ядро, для создания которых было использовано только CSS и несколько картинок, вставленных с помощью стандартной HTML-разметки. Ведь если на Друпале можно будет легко создать тему, построенную с помощью чистой CSS-вёрстки, то нужно сделать так, чтоб было ещё легче.

4. Создать наглядную тему, которая использует как стандартное переопределение с помощью шаблонов tpl.php, так и jQuery - для добавления разного интересного функционала. Например, прописать какой-либо регион - который будет сворачиваться и разворачиваться с помощью jQuery, сделать например, чтобы в какой-то теме комментарии автора статьи показывались по-другому и так далее. Это будет хорошей опорой для людей - и люди быстрее будут знакомится с самыми современными и передовыми технологиями.

5. Создать тему, с помощью которой можно легко добавлять один или несколько регионов, в которых бы отображались новости - подобно тому, как это стандартно реализовано в Joomla! и некоторых продвинутых WordPress темах.

6. Расширить Readme файлы, которые подробнее разъясняли бы, что и как делается в темах. (К сожалению - многие новички рунета никогда не бывают застуканы за занятием прочтения Readme-файлов, а жаль. На Западе несколько по другому - у них там для любого новичка Readme.txt - это как святая святых).

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

Оригинал статьи всё там же :).

Спасибо за внимание.

Полуночный Ёж.

Друпал - модуль User Points

  Здесь подробнее остановлюсь на модуле User Points, и на всех возможностях, которые предоставляет данный модуль. Сам по себе модуль User Points для шестёрки служит в первую очередь как API для других модулей, которые работают с поинтами.

 Основные моменты, которые позволяет реализовывать базовый модуль User Points - это зарабатывание пользователями юзерпоинтов за следующие действия пользователей на сайте:

 - публикация ноды (за публикацию нод разного типа можно присваивать разное количество юзерпоинтов);

 - публикация комментариев;

 - модерация комментариев и так далее...

 Поинты могут вычитаться в ответ на удаление ноды или комментария. Если например автор ноды или комментария меняется - соответственно поинты передаются от старого автора новому. Сколько поинтов будет начисляться за то или иное действие - это устанавливает администратор сайта. Также администратор может отслеживать логи для каждого подобного действия. 

 Также модуль предоставляет 2 блока. Один блок показывает 5 первых пользователей, имеющих наибольшее количество юзерпоинтов. И другой блок показывает количество поинтов, которые есть у соответствующего юзера.

 Но особый интерес конечно представляют интегрированные с User Points модули. Постараюсь ниже дать краткий обзор наиболее полезных и/или интересных из них.

 Ubercart Userpoints - этот модуль интегрирует модуль User Points с Уберкартом, и позволяет юзерпоинтами оплачивать покупки, делать скидки людям, имеющим определённое количество юзерпоинов, etc. Для шестого Друпала данный модуль правда пока находится в деве, он зависит от модуля Уберкарта Conditional Actions, а не от Rules (аналог Workflow-NG для пятёрки).

 Userpoints Node Action - модуль создаёт интерфейс для админов сайта, позволяющий применять юзерпоинты пользователями для оплаты некоторых действий с нодой, например публикация ноды, расположение ноды на главной странице, прикрепление ноды вверху списка (sticky). Этот модуль также прекрасно работает с модулем Override Node Options, в совокупности с которым можно расширять список подобных действий.

 Referral - позволяет работать с реферральными ссылками.

 Userpoints Store Credit - определяет новый метод оплаты товаров магазина на Уберкарте (store credit payment method), который позволяет платить за товары сайта не фактическими деньгами. Данный модуль для шестёрки пока также находится в деве.

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

 

 Спасибо за внимание.

Drupal 6.x. Создание модуля – файл .install

Файл с расширением .install (mymodule.install, где mymodule – имя Вашего модуля) запускается в первый раз после того, как Вы включаете соответствующий модуль в админке, этот файл запускает необходимые процедуры по установке, которые могут быть необходимы Вашему модулю. В большинстве случаев для установки модуля обычно нужно создать таблицы и поля в БД, с которыми будет впоследствии оперировать данный модуль. Для файла с расширением .install не нужен какой-либо специальный синтаксис – это такой же PHP файл, как и, например, файл с расширением .module.

Файл .install нужен также для того, чтобы выполнить обновление модуля, когда подключается его новая версия.

Необходимые инструкции по установке вложены в функцию _install() (эта функция объявляется в файле .install). Функция имеет имя mymodule_install(), где mymodule - имя Вашего модуля. Этот хук вызывается Друпалом при первом включении модуля. Обычно эта функция (хук) применяется для того, чтобы создать таблицу в БД для нового модуля.

В Друпале 6.x для создания таблиц и полей в БД применяется Schema API. Schema API позволяет модулям объявлять свои таблицы БД в структурированном массиве (подобно Form API) и обеспечивает функции API для создания, удаления и изменения таблиц, столбцов, строк, ключей и индексов БД.

Я хочу разобрать пример из документации по Schema API с сайта Drupal.org.

Например, как создаётся таблица БД для самой обычной ноды (модуль Node ядра Друпала, обязательный модуль, с помощью которого добавляются и загружаются ноды). Это отрывок из файла node.install, из функции node_schema().

<?php
$schema
['node'] = array(
   
'description' => t('The base table for nodes.'), 
   
'fields' => array(    // Таблица содержит четыре поля (колонки) - <em>'nid', 'vid', 'type' и 'title'
     
'nid' => array(  <strong>// Первое поле
      
'description' => t('The primary identifier for a node.'), // Описание поля
      
'type' => 'serial', // Тип первого поля - 'serial'
      
'unsigned' => TRUE,
      
'not null' => TRUE), // Конец первого поля</strong>
     
'vid' => array(  // Второе поле
      
'description' => t('The current {node_revisions}.vid version identifier.'),// Описание поля
      
'type' => 'int', // Тип второго поля - 'int'
      
'unsigned' => TRUE,
      
'not null' => TRUE,
      
'default' => 0), // Конец второго поля
     
'type' => array(   // Третье поле
      
'description' => t('The {node_type} of this node.'), // Описание поля
      
'type' => 'varchar', // Тип третьего поля - 'varchar'
      
'length' => 32,
      
'not null' => TRUE,
      
'default' => ''), // Конец третьего поля
     
'title' => array(   // Четвёртое поле
       
'description' => t('The title of this node, always treated a non-markup plain text.'), // Описание поля
       
'type' => 'varchar', // Тип четвёртого поля - 'varchar'
       
'length' => 255,
       
'not null' => TRUE,
       
'default' => ''), // Конец четвёртого поля
     
), // Конец перечисления полей
   
'indexes' => array(  // Два индекса таблицы 'node_changed' и 'node_created'
     
'node_changed'=> array('changed'), // Поле 'changed' - для изменённых нод
     
'node_created'=> array('created'), // Поле 'created' - для созданных нод
     
),
   
'unique keys'=> array( // Вторичный ключ таблицы
    
'vid'=> array('vid') // Ключ 'vid' - поле 'vid'
     
),
   
'primary key'=> array('nid'), // Первичный ключ таблицы - поле 'nid'
   
);
?>

Как видите, таблица содержит четыре поля - для каждого поля есть тип ('type'), описание ('description'), а также другие настраиваемые параметры, пока не буду на них углубляться - сейчас важнее понять общую структуру.

Продолжение в следующих постах. Оригинал статьи.

Спасибо за внимание.

Ёж

Drupal 6.x. Создание модуля – hook_schema

Итак, для того, чтобы через Schema API организовывались поля БД для создаваемых модулей, модуль должен иметь файл .install, в котором используется хук hook_schema() (в предыдущих версиях Друпала hook_schema() объявлялся в файле .schema, но в шестёрке это уже не используется). Приведём пример, файл mymodule.install для модуля mymodule:

<?php
function mymodule_schema() {
 
$schema['mytable1'] = array(
    
// Перечисление полей таблицы mytable1
 
);
 
$schema['mytable2'] = array(
   
// Перечисление полей таблицы mytable2
 
);
  return
$schema;
}
function
mymodule_install() {
 
// Создание таблиц при инсталляции модуля
 
drupal_install_schema('mymodule');
}
function
mymodule_uninstall() {
 
// Удаление таблиц
 
drupal_uninstall_schema('mymodule');
}
?>

$schema['mytable1'] = array(
// Перечисление полей таблицы mytable1
); - в первой статье есть более подробный пример, как задаются поля и ключи в таблице - пример из первой статьи.

Для разработчиков модулей есть такой очень полезный модуль Schema Module. Несколько слов о том, зачем он нужен, впоследствии можно будет остановиться на этом модуле поподробнее:

С уважением, Ёж

SQL и Views

Один из самых используемых модулей Друпала Views стал таким популярным в первую очередь благодаря своей простоте. По сути дела те же самые SQL-запросы - но только Вам не нужно самим писать никакого кода. К тому же - построив страницу или блок с каким-либо view, Вы легко оперируете с данной страницей, как и с любой другой страницей Друпала. И ещё - модули сами сообщают обо всём Views, а Вам остаётся только выбрать нужные значения, и не нужно даже думать о том, как правильно передать ту или иную переменную.

Как например работает язык SQL? Он работает на запросах к БД. Так вот - тем кто привык и умеет писать простейшие (или даже и не простейшие, а пусть даже сложнейшие) запросы будет ещё легче задать параметры в настройках Views и получить тот же самый результат.

Возьмём к примеру простейший SQL-запрос:

SELECT title FROM node WHERE nid = 13

Всё понятно, не так ли? Выбираем поля (title) из таблицы (node), но только такие поля, для которых nid=13. Но и каждый Ваш view также строится на точно таких же SQL-запросах, только вы их задаёте в настройках создаваемого вида. Любой такой запрос можно разложить на базовые составляющие: утверждение select, условие where, условие order by. А теперь давайте ассоциируем это с тем, как такие условия задаются в вашем виде view:

SELECT [Поля]
FROM [view type and any relationships]
WHERE [Фильтры или arguments]
ORDER BY [sort criteria]

Как видите всё достаточно просто - я просто ассоциировал вкладки в настройках Вашего вида view (на картинке) с параметрами, которые передавались бы при построении аналогичного SQL-запроса.

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

Ёж.

Views - работа с аргументами

В этой статье я продолжу рассказывать о модуле Views - одном из самых замечательных модулей Друпала, благодаря которым эту СMS можно рассматривать как самого настоящего крутого ниндзя. Более подробно остановлюсь на работе с аргументами Views, а точнее просто покажу практический пример работы - что как известно всегда лучше любых слов и теоретических изысканий.

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

Понятно, что такую листалку можно делать только через аргументы. Но моя задача усложнялась ещё и тем, что в фиксированном формате была только дата, а кроме даты там же администратор по ТЗ мог указывать и время - например 03-25-2009 12:23. И все эти записи нужно было отображать в моём виде. Только записи по конкретной дате.

Итак - добавляете в качестве аргумента то поле, в котором у Вас и содержится дата (например, у меня дата указывалась в заголовке комментария). Соответственно в аргументе и будет передаваться Ваша дата. Но как сделать, чтоб можно было включить туда все записи - не только те, которые имеют жёсткий фиксированный формат ММ-ДД-ГГГГ.

В итоге мне помог режим глоссария. Или же словарный режим - как кому больше нравится. Дело в том, что в настройках аргумента этот режим применяется для ограничения числа символов, используемых в аргументе. Причём - символами могут выступать как буквы, так и цифры. Таким образом в настройках аргумента я поставил птичку напротив надписи словарный режим - и поставил десятку - ведь дата в формате ММ-ДД-ГГГГ - это как раз десять символов. Ну и в базовых настройках я выбрал ПОКАЗАТЬ ВСЕ ЗНАЧЕНИЯ.

Всё - теперь в мой вид попадают и значения 03-25-2009 и 03-25-2009 12:23, и так далее. Точно так же можно показывать даты по месяцам - поставить 2 вместо десяти в поле ограничения символов, и тогда вид будет показан только по двум первым цифрам, то есть можно группировать записи по месяцам. И так далее - возможности на самом деле безграничны.

Ну, теперь осталось сделать саму листалку - для этого в основных настройках вида я использовал поле Подвал (Footer) и вводил туда свой код. Я использовал функцию для даты mktime(). Можно также использовать strtotime(). Или работать с преобразовыванием даты в формат JDC. Способов на самом деле масса - благо и функций для работы с датами в PHP немало:

<?php
$view
= views_get_current_view(); // Получаем доступ к текущему виду

if(!count($view->args))
  return
''; // Если нету ни одного аргумента, ничего не выводим

$date1=explode("-",$view->args[0]); // Записываем дату из нашего аргумента в переменную $date1

$yesterday = mktime (0,0,0,$date1[0] ,$date1[1]-1,$date1[2]);// Вчера
$tomorrow = mktime (0,0,0,$date1[0],$date1[1]+1,$date1[2]);// Завтра

$before = l('Предыдущий день <<', 'all/'.date("m-d-Y",$yesterday));
$after = l('Следующий день >>', 'all/'.date("m-d-Y",$tomorrow));

// Формируем ссылки и выводим их оператором return

return "<p>$before</p><p>$after</p>";
?>

Всё. Сохраняем изменения - наша задача выполнена :)

Ёж

Друпал – Работа с БД

Между Вашей БД (MySQL или PostgreSQL) и кодом PHP сайта в Друпале существует слой абстракции базы данных, благодаря которому можно использовать разные типы баз данных, используя один и тот же код. Это позволяет избежать многих ошибок, и к тому же не несёт никаких ограничений в использовании SQL. И очень удобно – например, Вам нужно сменить сервер баз данных с PostgreSQL на MySQL. Без абстракционного слоя Вам пришлось бы вручную изменять все SQL запросы, а так – ничего не нужно делать вообще. Слой абстракции сам будет по-другому обращаться к другому типу сервера.

Как Друпал определяет тип БД? Активация БД для последующих запросов осуществляется через функцию db_set_active. Сперва проверяется значение переменной $db_url в файле settings.php. Если переменная начинается с mysql, тогда Друпал использует оператор include() с файлом includes/database.mysql.inc; если же она начинается с pgsql – тогда с файлом includes/database.pgsql.inc.

Чаще всего запрос к активной БД осуществляется через функцию db_query. Рассмотрю простейшие запросы SELECT, INSERT, UPDATE и DELETE.

db_query('SELECT * FROM {joke} WHERE vid = %d', $node->vid);

Данный запрос возвращает все ряды из таблицы joke, у которых значение поля vid является целочисленным значением (integer – спецификатор %d), равным значению переменной $node->vid.

db_query("INSERT INTO {joke} (nid, vid, punchline) VALUES (%d, %d, '%s')", $node->nid, $node->vid, $node->punchline);

Данный запрос вставляет в таблицу joke ряд. Новый ряд включает в себя три значения. Два целочисленных (поля nid и vid – в них вставляются значения переменных $node->nid и $node->vid) и одно строковое, что мы и обозначили спецификатором %s – string (вставляется значение переменной $node->punchline).

db_query("UPDATE {joke} SET punchline = '%s' WHERE vid = %d", $node->punchline, $node->vid);

Данный запрос изменяет значение поля punchline для ряда, в котором значение поля vid равно значению переменной $node->vid. Вставляется новое значение, равное значению переменной $node->punchline.

db_query('DELETE FROM {joke} WHERE nid = %d', $node->nid);

Данный запрос удаляет из таблицы joke все ряды, для которых значение поля nid является равным значению переменной $node->nid.

Напоследок давайте рассмотрим пример файла .install, который осуществляет установку модуля – а для нода-модулей обычно необходимо создать таблицу. На этот раз пример для версии 5.x (из файла book.install):

<?php

/**
* Реализация функции hook_install().
*/
function book_install() {
switch (
$GLOBALS['db_type']) {
case
'mysql': // Запрос идентичен запросу для mysqli.
case 'mysqli':
db_query
("CREATE TABLE {book}
(
vid int unsigned NOT NULL default '0',
nid int unsigned NOT NULL default '0',
PRIMARY KEY (vid),
KEY nid (nid),
) /*!40100 DEFAULT CHARACTER SET UTF8 */ "
);
break;
case
'pgsql':
db_query
("CREATE TABLE {book}
(
vid int_unsigned NOT NULL default '0',
nid int_unsigned NOT NULL default '0',
PRIMARY KEY (vid)
)
"
);
db_query("CREATE INDEX {book}_nid_idx ON {book} (nid)");
break;
}
}
?>

Как мы видим – с помощью оператора switch корректируется запрос для разных серверов баз данных.

В статье я опирался на книгу Pro Drupal Development первого издания и на справочник API Друпала.

Ёж

FormAPI в Друпале 6

В этой статье хочу поговорить об одном важном изменении, которое произошло в FormAPI шестого Друпала. Очень удобном для разработчика изменении. Предыдущие версии Друпала использовали комбинацию значений $form_values, глобальных переменных и различных флагов, использующихся в обработчиках форм, для того, чтобы собрать всю необходимую информацию и текущие значения переменных, необходимые в рабочем процессе обработки формы. А в шестёрке всё это делается с помощью одной-единственной переменной $form_state - эта переменная передаётся по ссылке на каждом этапе обработки формы. Я хочу поговорить о некоторых стандартных ключах этой переменной, принятых в шестом Друпале.

$form_state['values'] - как известно, все наши формы работают путём передачи POST-значений, поэтому передать их нужно правильно. Использование $form_state с данным ключом, это по сути дела замена переменной $form_values, которая была до этого. Как известно, $form_values раньше использовалась в функциях обработки и валидации формы для передачи значений.

Следующие три ключа используются для контроля рабочего процесса обработки формы. Функции валидации и функции-обработчики могут изменять значения переменной $form_state с данными тремя ключами для того, чтобы правильно организовать рабочий процесс, основываясь на значениях, вводимых пользователем в поля формы.

$form_state['redirect'] - здесь Вы управляете тем, что должно произойти после того, как работа с формой завершена. По умолчанию Вы просто возвращаетесь на страницу формы, и все поля в форме очищаются. Если же Вы присваиваете этой переменной значение какого-либо пути, например $form_state['redirect']='user/edit', то после завершения обработки формы Друпал перекинет Вас на эту страницу. Если же Вы установите значение данной переменной в FALSE, то пользователь никуда не будет перенаправлен, а значения, введённые в форму, так и останутся "висеть" в полях формы.

$form_state['rebuild'] - значение данной переменной отменяет значение переменной $form_state['redirect']; когда значение этой переменной установлено в TRUE - то форма перестраивается, позволяя разработчику добавлять дополнительные поля или изменять структуру формы, основываясь на действиях пользователя (например, перестраивание формы путём прибавления ей дополнительных полей в том случае, когда пользователь нажимает на кнопку "Прошу предоставить мне дополнительный выбор"). Если этот флаг будет выставлен в функции валидации, то функция обработчика формы будет пропущена. Если же этот флаг будет выставлен в функции-обработчике, то форма будет перестроена и выведена на экран после того, как все обработчики завершат свою работу с формой.

$form_state['storage'] - иногда приходится строить многошаговые формы, и в этих случаях важно сохранить данные, введёные в форму на каждом из шагов. Все данные, помещённые в переменную $form_state['storage'] автоматически попадают в кэш и перезагружаются для следующего шага обработки формы. Таким образом Вы можете накапливать данные на каждом шаге работы с формой, и обработать на финальном шаге те данные, которые Вы например ввели в самой первой форме.

Ну, и ещё.

$form_state['clicked_button'] - в данной переменной содержится полная копия элемента кнопки, которая была нажата для запуска функции обработчика формы. использование этого элемента более надёжно, чем работа через $form_values['op'], в этой переменной также помещается любая дополнительная информация, которая может быть в определении данного элемента типа 'submit'(кнопка).

Полный список изменений для FormAPI шестого Друпала Вы можете прочитать здесь.

Спасибо за внимание, Ёж

Модуль Page Title

Для работы этого модуля нужен Token.

Известно, что каждая единица контента сайта Друпала имеет свой заголовок (title). Естественно, то же самое относится и к страницам (page title). Заголовок страницы обычно помещается в теге title в хэдере Вашей HTML-страницы. Это весьма помогает улучшить SEO Вашего сайта.

Модуль page title позволяет добавлять теги на каждой странице. Настоятельно рекомендуется устанавливать этот модуль.</p> <p>Для того, чтобы Ваша тема взаимодействовала с модулем Page Title, Вы должны будете добавить немного кода в файл template.php Вашей темы. </p> <p>Вот код, который туда нужно добавить:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">_phptemplate_variables</span><span style="color: #007700">(</span><span style="color: #0000BB">$hook</span><span style="color: #007700">, </span><span style="color: #0000BB">$vars</span><span style="color: #007700">) {<br />  </span><span style="color: #0000BB">$vars </span><span style="color: #007700">= array();<br />  if (</span><span style="color: #0000BB">$hook </span><span style="color: #007700">== </span><span style="color: #DD0000">'page'</span><span style="color: #007700">) {<br /><br />    </span><span style="color: #FF8000">// These are the only important lines<br />    </span><span style="color: #007700">if (</span><span style="color: #0000BB">module_exists</span><span style="color: #007700">(</span><span style="color: #DD0000">'page_title'</span><span style="color: #007700">)) {<br />      </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'head_title'</span><span style="color: #007700">] = </span><span style="color: #0000BB">page_title_page_get_title</span><span style="color: #007700">();<br />    }<br /><br />  }<br />  return </span><span style="color: #0000BB">$vars</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div><br /> </h4> <p>Таким образом переменная $head_title, которая выводится в шаблоне page.tpl.php, будет теперь определяться нашим модулем Page Title.</p> <p>Для настройки модуля необходимо проследовать на страницу:</p> <p>/admin/content/page_title</p> <p>Там Вы, собственно говоря, и можете назначить заголовки для страниц нод того или иного типа.</p> <p>Также, если на странице настроек установить флажок Show Field (Показать Поле) напротив какого-либо типа ноды, то при редактировании каждой ноды данного типа вы сможете увидеть поле Page Title - в которое можете вводить любой заголовок для этой ноды, и заголовок этот будет написан на окне браузера при отображении этой ноды.</p> </div> <div id="node-25" class="section-2"> <h1 class="book-heading">Drupal - Новый модуль для построения форм</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-png"><img class="field-icon-image-png" alt="image/png icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/lullabot.png">lullabot.png</a></div> </div> </div> </div> <p>Если кто не знает, есть такой очень нужный для друпалеров сайт Lullabot.com. На сайте куча всего полезного и интересного, есть также видео уроки, и масса другой разнообразной информации. 3 декабря Lullabot объявил о будущем релизе нового модуля, разработанного для Друпала – модуль Form Builder для создания форм.</p> <p>Модуль использует AJAX и интерфейс Drag and Drop, специально для шестого Друпала – с его помощью Вы можете легко строить свои собственные формы. Есть предположение, что модуль легко заменит собой построение форм с помощью таких модулей, как CCK, Webform, Profile и так далее. То есть, можно сказать – настоящая маленькая революция!</p> <p>Модуль работает с Form API . Но Вы всё делаете с помощью простейшего интерфейса в настройках модуля. Например, Вы изменяете заголовок или описание поля, а модуль работает с FAPI Друпала. Вы можете также посмотреть превью того, что у Вас получилось без необходимости сохранять форму.</p> <p><em>Внедрение Form Builder</em>.</p> <p>Form Builder используется только для того, чтобы создавать формы. То есть вы не сможете использовать формы, построенные с помощью этого модуля до тех пор, пока какой-нибудь другой модуль не использует хуки, предоставленные Form Builder’ом для того, чтобы сохранить требуемые изменения.<br /> Например, возьмём форму создания обычной ноды. В Друпале есть несколько модулей, которые модифицируют эту форму:</p> <p>- Taxonomy. Этот модуль добавляет возможность выбора терминов из словаря при создании ноды.<br /> - Menu. Предоставляет настройки для размещения ноды в меню.<br /> - CCK. Добавляет к ноде различные поля.</p> <p>Итак, Form Builder создаёт форму и предоставляет её другим модулям для изменения (или же заполнения). Каждый модуль, который будет работать с формой, говорит что-то вроде этого: «Эй, ребята, внимание, я буду работать с такими-то полями в этой форме», например, только с первым и третьим полем. Каждый элемент (поле) формы, который требуется конкретному модулю, будет предоставлен модулю для изменения. То есть Form Builder говорит как бы следующее: «Пожалуйста, дорогой модуль, бери и работай с первым и третьим полем, но остальные мои поля трогать ты не сможешь, не позволю, дорогой товарищ».</p> <p>А после того, как изменение соответствующего поля сохранено, новый сформированный массив FAPI возвращается к каждому модулю, которому это требуется. Каждый модуль просматривает массив, и соответствующим образом меняет свои собственные настройки, чтобы внедрённые изменения были сохранены. Понятно, что пока что обо всём этом можно говорить только на пальцах, поконкретнее можно будет поговорить только когда будет более менее стабильный релиз. </p> <p>Модуль пока совсем новый, и на данный момент его нельзя применять для работающих сайтов. Его API совсем свежее, незадокументировано и может быть изменено. Модуль пока содержит множество багов и тестирование продолжается.<br /> Пока всё, что можно сделать – это попробовать демо, вот по этому адресу <a href="http://quicksketch.org/demos/form-builder-example" title="http://quicksketch.org/demos/form-builder-example">http://quicksketch.org/demos/form-builder-example</a>. Разработка продолжается, будет создана система контекстной помощи для разработчиков, и также многое ещё предстоит сделать для совмещения работы этого модуля с другими. </p> <p>Ну что ж, будем следить за новостями. Этот модуль – одна из тех фич, за которыми стоит будущее Друпала. Возможно, это даже будет один из модулей ядра для Drupal 7.x, кто знает. </p> <p>Оригинал статьи на английском <a rel="nofollow" href="http://www.lullabot.com/blog/drupals-form-building-future">здесь</a>.</p> <p>Ёж.</p> </div> <div id="node-61" class="section-2"> <h1 class="book-heading">Learning Drupal 6 Development </h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/2415557716_5aede507a6_m.jpg">2415557716_5aede507a6_m.jpg</a></div> </div> </div> </div> <p>Открыл тут книжку Learning Drupal 6 Development товарища Мэтта Бутчера (Matt Butcher), и сразу же - в первом же примере натолкнулся на интересный момент. Конечно, момент не дотягивает вот например до такого:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /> phpinfo</span><span style="color: #007700">();<br />if (</span><span style="color: #0000BB">file_exist</span><span style="color: #007700">(</span><span style="color: #DD0000">'../../../../etc/passwd'</span><span style="color: #007700">))  {<br />    include(</span><span style="color: #DD0000">'../../../../etc/passwd'</span><span style="color: #007700">);<br />  }<br /></span><span style="color: #0000BB">?></span></span></code></div><br /> </h4> <p>или вообще вот такого: </p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br />temp </span><span style="color: #007700">= </span><span style="color: #0000BB">a<br />a </span><span style="color: #007700">= </span><span style="color: #0000BB">b<br />b </span><span style="color: #007700">= </span><span style="color: #0000BB">temp<br />?></span></span></code></div><br /> </h4> <p>Но тоже не совсем понятно, что хотел сказать автор в нижеследующем коде:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">_goodreads_block_content</span><span style="color: #007700">(</span><span style="color: #0000BB">$doc</span><span style="color: #007700">, </span><span style="color: #0000BB">$num_items</span><span style="color: #007700">=</span><span style="color: #0000BB">3</span><span style="color: #007700">) </span><span style="color: #FF8000">//!НЕНУЖНЫЙ параметр $num_items<br /></span><span style="color: #007700">{<br /> </span><span style="color: #0000BB">$items </span><span style="color: #007700">= </span><span style="color: #0000BB">$doc</span><span style="color: #007700">-></span><span style="color: #0000BB">channel</span><span style="color: #007700">-></span><span style="color: #0000BB">item</span><span style="color: #007700">;<br /><br /> </span><span style="color: #0000BB">$count_items </span><span style="color: #007700">= </span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$items</span><span style="color: #007700">);<br /><br /> </span><span style="color: #0000BB">$len </span><span style="color: #007700">= (</span><span style="color: #0000BB">$count_items </span><span style="color: #007700">< </span><span style="color: #0000BB">$num_items</span><span style="color: #007700">) ? </span><span style="color: #0000BB">$count_items </span><span style="color: #007700">: </span><span style="color: #0000BB">$num_items</span><span style="color: #007700">; </span><span style="color: #FF8000">// НЕПОНЯТНАЯ переменная<br /> </span><span style="color: #0000BB">$template </span><span style="color: #007700">= </span><span style="color: #DD0000">'<div class="goodreads-item">'<br /> </span><span style="color: #007700">.</span><span style="color: #DD0000">'<img src="%s"/><br/>%s<br/>by %s</div>'</span><span style="color: #007700">;<br /> </span><span style="color: #FF8000">// Default image: 'no cover'<br /> </span><span style="color: #0000BB">$default_img </span><span style="color: #007700">= </span><span style="color: #DD0000">'http://www.goodreads.com/images/nocover-60x80.jpg'</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">$default_link </span><span style="color: #007700">= </span><span style="color: #DD0000">'http://www.goodreads.com'</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">$out </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">;<br />  foreach (</span><span style="color: #0000BB">$items </span><span style="color: #007700">as </span><span style="color: #0000BB">$item</span><span style="color: #007700">) <br /> {<br />  </span><span style="color: #0000BB">$author </span><span style="color: #007700">= </span><span style="color: #0000BB">check_plain</span><span style="color: #007700">(</span><span style="color: #0000BB">$item</span><span style="color: #007700">-></span><span style="color: #0000BB">author_name</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$title </span><span style="color: #007700">= </span><span style="color: #0000BB">strip_tags</span><span style="color: #007700">(</span><span style="color: #0000BB">$item</span><span style="color: #007700">-></span><span style="color: #0000BB">title</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$link </span><span style="color: #007700">= </span><span style="color: #0000BB">check_url</span><span style="color: #007700">(</span><span style="color: #0000BB">trim</span><span style="color: #007700">(</span><span style="color: #0000BB">$item</span><span style="color: #007700">-></span><span style="color: #0000BB">link</span><span style="color: #007700">));<br />  </span><span style="color: #0000BB">$img </span><span style="color: #007700">= </span><span style="color: #0000BB">check_url</span><span style="color: #007700">(</span><span style="color: #0000BB">trim</span><span style="color: #007700">(</span><span style="color: #0000BB">$item</span><span style="color: #007700">-></span><span style="color: #0000BB">book_image_url</span><span style="color: #007700">));<br />  if (empty(</span><span style="color: #0000BB">$author</span><span style="color: #007700">)) </span><span style="color: #0000BB">$author </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">;<br />  if (empty(</span><span style="color: #0000BB">$title</span><span style="color: #007700">)) </span><span style="color: #0000BB">$title </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">;<br />  if (empty(</span><span style="color: #0000BB">$link</span><span style="color: #007700">)) </span><span style="color: #0000BB">$link </span><span style="color: #007700">= </span><span style="color: #0000BB">$default_link</span><span style="color: #007700">;<br />  if (empty(</span><span style="color: #0000BB">$img</span><span style="color: #007700">)) </span><span style="color: #0000BB">$img </span><span style="color: #007700">= </span><span style="color: #0000BB">$default_img</span><span style="color: #007700">;<br />  </span><span style="color: #0000BB">$book_link </span><span style="color: #007700">= </span><span style="color: #0000BB">l</span><span style="color: #007700">(</span><span style="color: #0000BB">$title</span><span style="color: #007700">, </span><span style="color: #0000BB">$link</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$out </span><span style="color: #007700">.= </span><span style="color: #0000BB">sprintf</span><span style="color: #007700">(</span><span style="color: #0000BB">$template</span><span style="color: #007700">, </span><span style="color: #0000BB">$img</span><span style="color: #007700">, </span><span style="color: #0000BB">$book_link</span><span style="color: #007700">, </span><span style="color: #0000BB">$author</span><span style="color: #007700">);<br /> }<br /> </span><span style="color: #0000BB">$out </span><span style="color: #007700">.= </span><span style="color: #DD0000">'<br/><div class="goodreads-more">'<br /> </span><span style="color: #007700">. </span><span style="color: #0000BB">l</span><span style="color: #007700">(</span><span style="color: #DD0000">'Goodreads.com'</span><span style="color: #007700">, </span><span style="color: #DD0000">'http://www.goodreads.com'</span><span style="color: #007700">)<br /> .</span><span style="color: #DD0000">'</div>'</span><span style="color: #007700">;<br /> return </span><span style="color: #0000BB">$out</span><span style="color: #007700">;<br />} <br /></span><span style="color: #0000BB">?></span></span></code></div><br /> </h4> <p>Дело в том, что это функция, которая получает данные из объекта SimpleXML и потом отображает их в блоке, но это неважно, интересно другое - второй параметр $num_items, которые по идее должен бы был использоваться для вывода количества элементов, на самом деле не делает ровным счётом ничего. То есть вообще никак не используется, только зачем-то его использует непонятная переменная $len, которая тоже в свою очередь не используется.</p> <p>Книгу ВанДюка помню костерили неслабо, неужели книга Мэтта Бутчера не лучше? Какие вообще книги по разработке модулей на Друпале можно рекомендовать людям? Без индусского кода. И есть ли вообще такие? Как Вы думаете?</p> <p>Но кстати в остальном вышеприведённый код не так уж и плох, даже используется защита от XSS-атак.</p> </div> <div id="node-62" class="section-2"> <h1 class="book-heading">Learning Drupal 6 Development - часть 2</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-png"><img class="field-icon-image-png" alt="image/png icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/2009-07-03_2243.png">2009-07-03_2243.png</a></div> </div> </div> </div> <p>Ну что ж, не думал, что продолжу, но всё-таки продолжу эту тему. </p> <p>Итак, довелось открыть главу под номером три книжки Мэтта Бутчера, в которой он начал рассказывать о том, как создаётся подтема, на основе какой-либо базовой темы. Дело в том, что в Друпале 6.x создание подтем существенно упростилось, просто надо создать новую папку в sites/all/themes, назвать её каким нибудь <именем_подтемы>, и потом создать файл <имя_подтемы>.info, в котором достаточно просто написать одну единственную строчку, говорящую Друпалу о том, на основе какой собственно темы создана данная подтема:</p> <p>base theme = <имя_базовой_темы></p> <p>например, base theme = marinelli</p> <p>Можно переопределить стили базовой темы, создав например в папке базовой темы файл new.css, в котором собственно говоря и указать все изменения, отличающиеся от базовой темы. Ну и затем нужно просто добавить в <имя_подтемы>.info строчку: </p> <p>stylesheets[all][] = new.css</p> <p>Но Мэтт Бутчер не ищет лёгких путей. Он почему то считает, что нужно писать вот так:</p> <p>stylesheets[all][] = style.css<br /> stylesheets[all][] = new.css</p> <p>style.css - это в данном случае файл стилей, который есть в базовой теме, например Marinelli. Так вот, на самом деле так писать не нужно, а нужно писать как раз-таки только вот так</p> <p>stylesheets[all][] = new.css</p> <p>а файл style.css подключится сам, потому что мы ведь указали базовую тему, и ничего лишнего городить тут не нужно. Наоборот, style.css никуда не подключится, если прописать его ещё и в файле <имя_подтемы>.info.</p> <p>Как вообще выбираются люди, которые пишут книжки про Друпал? Вот что мне интересно. Я бы например предложил выбирать голосованием. Потому что косяки косяками, но надо же и меру знать.</p> <p>P.S. Здесь должна бы быть ссылка на эту книжку, но я её давать не буду.</p> </div> <div id="node-41" class="section-2"> <h1 class="book-heading">jQuery в Друпале</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-gif"><img class="field-icon-image-gif" alt="image/gif icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/jquery-logo.gif">jquery-logo.gif</a></div> </div> </div> </div> <p>JavaScript в наше время повсюду – куда ни сунься, везде он. Но в то же время – не всем и не всегда так уж приятно с ним работать. И именно поэтому таким популярным стал jQuery – JavaScript-фреймворк, придуманный Джоном Ресигом(John Resig) и опубликованный им в 2006-ом году. На данный момент последняя версия jQuery – 1.3.1.</p> <p>Так в чём же преимущества jQuery? В первую очередь это конечно удобство использования, в отличие от JS. В JS есть целые кучи библиотек, позволяющие реализовать в принципе почти любой Ваш каприз. Но пока со всем этим разберёшься, прольёшь немало пота и скушаешь немало витаминов. </p> <p>То ли дело jQuery. В первую очередь – это простота получения какого-либо элемента страницы с помощью jQuery-селектора. И затем – манипулируем любым узлом DOM, как хотим. Создаём, перемещаем, изменяем узлы в иерархии объектов страницы.</p> <p>Итак – как работает jQuery-селектор? Его работа основа на принципах CSS. Точно так же, как мы определяем какой-либо элемент с помощью CSS, так же и находим его jQuery-селектором. Приведём несколько примеров.</p> <p>$(“div#header”) – получаем элемент div с id=header.<br /> $(“p”) – получаем все элементы p.<br /> $(”ul li:first”) - получить первый элемент li из списка ul.<br /> $(“#wrapper .class1”) – получаем все элементы с классом “class1”, которые находятся в диве с id=wrapper.</p> <p>В Друпале же jQuery уже есть - нам нужно просто подключить его с помощью функции drupal_add_js. </p> <p>Итак, перейду к простому примеру. Создайте на Вашем сайте простую страницу Page. Введите какой-нибудь заголовок, и в Input format укажите тип PHP Code. Введите следующий текст для данной ноды:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br />drupal_add_js</span><span style="color: #007700">(<br /></span><span style="color: #DD0000">'$(document).ready(function(){<br />$("p").slideDown("slow");<br />});'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'inline'<br /></span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?></span></span></code></div><br /> <div class="codeblock"><code><p id="one">Пункт один</p><br /><p id="two">Пункт два</p><br /><p>Пункт три</p></code></div><br /> </h4> <p>Перезагрузите страницу. Вы увидите, как Ваши три пункта медленно как бы плывут вниз :).</p> <p>Как видите я первым двум элементам присвоил id. Например - можно заменить строчку $("p").slideDown("slow"); на $("#one").slideDown("slow"); - и тогда медленно будет сползать вниз только самый первый элемент. И так далее.</p> <p>Вторым параметром функции drupal_add_js является 'inline' - в данном случае он просто говорит Друпалу о том, что код нужно записать внутри контейнера <code><script></script></code>. Ну а первым параметром является непосредственно сам наш JS-код. Напоследок рассмотрю его немного поподробнее.</p> <h4> <div class="codeblock"><code>$(document).ready(function(){<br />// Здесь будет находиться Ваш код.<br />});</code></div><br /> </h4> <p>Событие READY говорит о том, что функция будет выполнена тогда, когда DOM (напоминаю - это объектная модель документа, Document Object Model) будет готов. Ну и внутри фигурных скобок располагаете Ваш код. В данном случае мы находим селектором все элементы p, и затем визуально плавно спускаем их вниз. В данном случае мы вызвали метод jQuery через функцию $ - так вызываются методы, являющиеся методами объекта jQuery. Вторым способом является вызов через $. - методы, не являющиеся методами объекта jQuery, но на этом возможно остановимся в другой раз.</p> <p>Ёж </p> <div id="node-42" class="section-3"> <h1 class="book-heading">BeautyTips – новый jQuery плагин</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/diwd-schedule-1.jpg">diwd-schedule-1.jpg</a></div> </div> </div> </div> <p>Ну что ж, сегодня пятница 13-ое, но я хотел бы поговорить не об этом, а рассказать Вам об информации с замечательного сайта Lullabot. Дело в том, что не так давно Jeff Robbins выпустил jQuery плагин BeautyTips. Плагин создаёт всплывающее окошко с информацией для любого элемента на Вашей странице. Как это выглядит – можете посмотреть на рисунке слева. Неправда ли – неплохое решение :).</p> <p>Зачем вообще Джефф написал этот плагин? В первую очередь конечно для собственных нужд, то, что было - его не устраивало, и хотелось чего-то более крутого. Как видите - более чем тривиальная причина. Ну так в чём же преимущества? Во-первых, вычисляется наилучшая позиция для контекстной справки – окошко появится там, где это будет смотреться лучше всего. Окошко может появиться сверху, снизу, справа или слева. Ну и конечно - удобство и простота использования тоже тут как тут. Можно делать круглые края, легко регулировать прозрачность, цвет и так далее. Плагин использует элемент Canvas HTML 5 – в основном он используется для простой анимации и при разработке браузерных игр.</p> <p>Элемент Canvas поддерживается в современных версиях браузеров Opera, Firefox и Safari. Но правда в Internet Explorer отсутствует поддержка тега <code><canvas></code>. Но Google решил эту проблему, разработав библиотеку <noindex><a rel="nofollow" href="http://excanvas.sourceforge.net/">ExplorerCanvas.</a></noindex> Соответственно всё, что нужно сделать – это просто включить в код страницы тег <code><script></code>, который будет загружать эту библиотеку и вуаля – BeautyTips в IE будут работать точно так же.</p> <p>Это <noindex><a href="http://plugins.jquery.com/project/bt">страница проекта на jQuery.com</a></noindex>.</p> <p>Ну что ж - Enjoy! Наслаждайтесь! :)</p> <p>С уважением, Ёж</p> </div> </div> <div id="node-60" class="section-2"> <h1 class="book-heading">Друпал - работа с Token</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/367134318_7197d7be21.jpg">367134318_7197d7be21.jpg</a></div> </div> </div> </div> <p>Токены могут использоваться для разных целей. Например, одна из целей - этой хранение в лексемах некоторых значений, возможно объёмных или повторяющихся. </p> <p>К примеру, подробный адрес со всеми контактами можно записать в созданный токен, и потом просто использовать его в тексте. А если адрес предприятия изменится? Или изменятся какие-нибудь данные - например номер телефона. И в то же время на сайте есть много страниц, на которых уже указан старый адрес. Неужели придётся исправлять телефон на КАЖДОЙ такой странице? А если таких страниц несколько сотен???</p> <p>А при хранении значения в токене - можно просто исправить в одном-единственном месте, и Ваши изменения отобразятся везде, по всему сайту. </p> <p>Но это лишь один из примеров - примеров может быть много. Тем более, что в созданном Вами токене можно также хранить и PHP-код, который будет выполняться при каждом использовании лексемы. </p> <p>Самый простой способ - не касаясь API, это использование связки модулей <noindex><a href="http://drupal.org/project/token" rel="nofollow">Token</a></noindex>, <noindex><a href="http://drupal.org/project/token_filter" rel="nofollow">Token Filter</a></noindex> и <noindex><a href="http://drupal.org/project/token_custom" rel="nofollow">Custom Tokens</a></noindex>.</p> <p>Итак, включаете модули. Переходите к настройке.</p> <p><strong>Token Filter:</strong> на странице admin/settings/filters - включите Token Filter для каждого из требуемх Вам форматов ввода, например для Full HTML. Напротив соответствующего формата нажимаете на <em>configure</em> и просто ставите птичку напротив Token filter.</p> <p>Всё. В принципе токены уже работают. Уже можно использовать такие предопределённые токены, как например [site-name]. Только записывать надо вот таким образом: [token global site-name], поскольку данный токен относится к категории Global tokens.<br /> Перечисление всех токенов можно посмотреть на странице admin/build/tokens/help (конечно, при том условии, что Вы включили модуль Custom Tokens).</p> <p>Теперь о создании своих токенов. Идёте сюда - admin/build/tokens/list, нажимаете Create и заполняете все необходимые поля. Token ID должен начинаться с token_custom_ (<em>читайте все пояснения</em>). В поле PHP Replacement Вы должны возвращать некое значение оператором return. Например:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">return </span><span style="color: #DD0000">"Сидорова, 10, корпус 13 - двор девятый, телефон 111-11-11"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span></span></code></div><br /> </h4> <p>Но в данном случае я возвращаю обычный статический текст.</p> <p>Всё. Таким образом вы можете создавать токены, какие Вашей душе угодны. При использовании токена в ноде не забывайте про указание полного имени при объявлении!</p> <p>Спасибо за внимание.</p> <p>Ёж.</p> </div> <div id="node-49" class="section-2"> <h1 class="book-heading">Друпал: Модуль Node Clone</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/2435327737_d6278c72fd.jpg">2435327737_d6278c72fd.jpg</a></div> </div> </div> </div> <p>Хочу рассказать Вам об одном очень полезном модуле Node Clone - который лично я использую в последнее время достаточно часто.</p> <p>Не секрет - что каждому клиенту хочется получить как можно более автоматизированную систему управления. Такова тенденция - теперь можно нажать одну кнопочку и сделать те же самые действия, на которые раньше могло уйти гораздо больше времени администратора сайта. В Друпале для этого есть масса полезных модулей - всех наверное не перечислить, да и стоит ли пытаться? Но один из самых полезных лично для меня - модуль Node Clone, который позволяет уменьшить объём работы не только администратора, но и разработчика, что, согласитесь, тоже не помешает.</p> <p>Итак, модуль можно скачать <a rel="nofollow" href="http://drupal.org/project/node_clone">здесь</a>. Настройка модуля очень проста - по сути дела достаточно только его включить и определить, для каких типов материалов будет работать клонирование. Есть также дополнительные настройки, которые в принципе можно и не использовать - они находятся на <strong><em>admin/settings/clone</em></strong>. </p> <p>Можно выбрать два способа клонирования: создаётся форма создания ноды с уже заполненными полями (термины таксономии, оглавление подшивки, настройки публикации и так далее - всё это будет взято из клонируемой ноды), или же второй способ - клонируемая нода будет полностью воссоздана, со всеми заполенными полями - а Вы затем будете её редактировать. Для разных нужд могут быть полезны оба способа клонирования. Думаю - не стоит перечислять все те варианты, при которых может понадобиться этот модуль.</p> <p>С уважением, Ёж.</p> </div> <div id="node-76" class="section-2"> <h1 class="book-heading">Кэширование</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/IMG_0477.jpg">IMG_0477.jpg</a></div> </div> </div> </div> <p>Кэширование нужно использовать не всегда. Кэширование лучше использовать для данных, которые не меняются слишком быстро. Например - можно закэшировать список лучших статей недели - для пользователей это будет очень удобно, ведь список этот не будет меняться целую неделю. И в то же время кэшировать последние пять комментариев на самом активном форуме - согласитесь, не лучшее решение - так как эти данные могут меняться каждые пять минут. В некоторых случаях ненужного использования кэширования Вы можете "благодаря" кэшу ещё и увеличить нагрузку на сайт, сделав его скорее медленнее, а не быстрее (что, собственно говоря, и является изначальной целью кэширования - то есть, сделать быстрее).</p> <p>Как работает кэширование<br /> Модулям зачастую приходится делать частые и весьма "тяжеловесные" запросы к базе, или же обращаться за данными на отдалённые серверы - как Вы понимаете, нет смысла каждый раз, когда Вам нужны одни и те же данные, использовать все эти ресурсы. Лучше хранить кэш со своими данными в одной из таблиц БД, зарезервированных специально для этого в БД Друпала. Или можно создать для каждого модуля свою отдельную таблицу, и складывать закэшированные данные туда. И в следующий раз, когда данные понадобятся, можно быстренько их получить одним-единственным запросом к этой табличке. </p> <p>Таблица, которую Ваш модуль может по умолчанию использовать для закэшированных данных, называется cache. Её лучше использовать в тех случаях, когда вы собираетесь использовать немного закэшированной информации; но если же вы кэшируете информацию для каждой ноды, пункта меню или пользователя - то лучше создавать свои собственные таблицы и складывать эти данные туда. Если создаёте для кэша свою таблицу, то структуру этой таблицы нужно делать идентичной структуре таблицы cache. Отличное решение - использовать префикс cache_ для каждой такой таблицы: например, cache_node - и т.д.</p> <p>Структура таблицы cache:</p> <p><strong>Field*</strong> Type Null Default<br /> <strong>cid</strong> varchar(255) NO —<br /> <strong>data</strong> longblob YES —<br /> <strong>expire</strong> int NO 0<br /> <strong>created</strong> int NO 0<br /> <strong>headers</strong> text YES NULL<br /> <strong>serialized</strong> smallint NO 0</p> <p>Field - первичный ключ таблицы.</p> </div> <div id="node-79" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.1</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-jpeg"><img class="field-icon-image-jpeg" alt="image/jpeg icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/2984450280_6b0829c365_m.jpg">2984450280_6b0829c365_m.jpg</a></div> </div> </div> </div> <p>Здесь я расскажу немного а том, как Вы можете легко и без усилий создать в своем модуле меню - и в частности остановимся на разных тонкостях. Итак - начнем пожалуй с хука hook_perm()</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Implementation of hook_perm().<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_perm</span><span style="color: #007700">() {<br />return array(</span><span style="color: #DD0000">'receive'</span><span style="color: #007700">);<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>Здесь всё понятно, просто ставим разрешение тем ролям, которым нужно. Затем уже, собственно говоря, начинаем строить непосредственно само меню, используя для этого hook_menu. В приведенном ниже коде я строю две страницы - с адресом menufun и menufun/farewell</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Implementation of hook_menu().<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_menu</span><span style="color: #007700">() {<br /></span><span style="color: #0000BB">$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'menufun'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_hello'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'access callback' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'type' </span><span style="color: #007700">=> </span><span style="color: #0000BB">MENU_CALLBACK</span><span style="color: #007700">,<br />);<br /></span><span style="color: #0000BB">$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'menufun/farewell'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Farewell'</span><span style="color: #007700">,       </span><span style="color: #FF8000">// No! don't use t() in menu item titles or descriptions.<br /></span><span style="color: #DD0000">'title callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_title'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_goodbye'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'access callback' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'type'</span><span style="color: #007700">=></span><span style="color: #0000BB">MENU_DEFAULT_LOCAL_TASK</span><span style="color: #007700">, <br />);<br />return </span><span style="color: #0000BB">$items</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>В page callback мы указываем функцию, которая будет отвечать за вывод контента на странице. В частности функция menufun_hello используется для вывода содержимого на странице menufun.</p> </div> <div id="node-80" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.2</h1> <p>Итак, теперь описываем функции - которые в предыдущей статье указаны как функции, которые служат для отображения пунктов меню menufun и menufun/farewell.</p> <p>Пока выводим две обычные текстовые записи:</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Page callback.<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_hello</span><span style="color: #007700">() {<br />return </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Hello!'</span><span style="color: #007700">);<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Page callback.<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_goodbye</span><span style="color: #007700">() {<br />return </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Goodbye!'</span><span style="color: #007700">);<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>ПУТЬ <a href="http://example.com/?q=menufun" title="http://example.com/?q=menufun">http://example.com/?q=menufun</a> (при невключенных Clean URLs)!!! А теперь приведем пример использования вызова функций меню, но уже с атрибутами:</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_hello</span><span style="color: #007700">(</span><span style="color: #0000BB">$first_name </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">, </span><span style="color: #0000BB">$last_name </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">) {<br />return </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Hello @first_name @last_name'</span><span style="color: #007700">,<br />array(</span><span style="color: #DD0000">'@first_name' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$first_name</span><span style="color: #007700">, </span><span style="color: #DD0000">'@last_name' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$last_name</span><span style="color: #007700">));<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> </div> <div id="node-81" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.3</h1> <p>Теперь перейдем к тому, что называется wildcards (обозначается через знак процента %). Переходим сразу к примерам, не откладывая дела в долгий ящик:</p> <h4> <div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_menu</span><span style="color: #007700">() {<br /></span><span style="color: #0000BB">$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'menufun/%'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Hi'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_hello'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'access callback' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br />);<br />return </span><span style="color: #0000BB">$items</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div><br /> </h4> <p>Подобная запись будет работать для следующих пунктов меню - menufun/hi, menufun/foo/bar, menufun/123, menufun/file.html - и так далее, для всех этих страниц вывод будет определяться функцией menufun_hello. Но заметим - что для пути menufun это работать не будет.</p> <p>Или вот например определение пункта меню - user/%/edit будет работать для определения страницы по адресу user/2375/edit, и так далее - для всех остальных путей, имеющих подобную структуру.</p> <p>(Такой пункт меню типа MENU_NORMAL_ITEM не появится в Навигации)</p> </div> <div id="node-82" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.4</h1> <p>Используем значение параметра wildcard(%):</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_menu</span><span style="color: #007700">() {<br /></span><span style="color: #0000BB">$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'menufun/%/bar/baz'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Hi'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_hello'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page arguments' </span><span style="color: #007700">=> array(</span><span style="color: #0000BB">1</span><span style="color: #007700">), </span><span style="color: #FF8000">// The matched wildcard.<br /></span><span style="color: #DD0000">'access callback' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br />);<br />return </span><span style="color: #0000BB">$items</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>Выше мы объявили коллбэк страницы, а теперь описываем непосредственно функцию menufun_hello(), которая будет обрабатывать этот вызов:</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Page callback.<br />*/<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">menufun_hello</span><span style="color: #007700">(</span><span style="color: #0000BB">$a </span><span style="color: #007700">= </span><span style="color: #0000BB">NULL</span><span style="color: #007700">, </span><span style="color: #0000BB">$b </span><span style="color: #007700">= </span><span style="color: #0000BB">NULL</span><span style="color: #007700">) {<br />return </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Hello. $a is @a and $b is @b'</span><span style="color: #007700">, array(</span><span style="color: #DD0000">'@a' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #DD0000">'@b' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$b</span><span style="color: #007700">));<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>Здесь мы передаём часть пути как параметр в функцию. array(1) - это запись означает, что в качестве первого аргумента мы берём второй элемент массива (счёт начинается с нуля, array(0) в данном случае будет равен menufun). Ну и второй аргумент берётся из той части пути, которая идёт после baz. То есть - тут всё по-прежнему, берём параметр из конца URL. Например, путь menufun/one/bar/baz/two передаст в функцию первый аргумент $a равный one, и второй аргумент $b будет равен two.</p> </div> <div id="node-83" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.5</h1> <p>node/%node/edit - использование такого пути запускает функцию node_load(). </p> <p>Например - возьмём вот такой вот пример:</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br />$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'user/%user_uid_optional'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'My account'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'title callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'user_page_title'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'title arguments' </span><span style="color: #007700">=> array(</span><span style="color: #0000BB">1</span><span style="color: #007700">),<br /></span><span style="color: #DD0000">'file' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'user_pages.inc'</span><span style="color: #007700">,<br />);<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>Обратите внимание вот на это - %user_uid_optional. С каким аргументом вызывается функция user_page_title для например пути user/356. Так вот - на этот раз она вызывается не с аргументом 356, а вот с таким user_uid_optional_load('356'), то есть входным параметром служит объект пользователя, uid которого равен 356, а не просто 356.</p> <p>А теперь еще пример использования to_arg():</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">/**<br />* Implementation of hook_menu().<br />*/<br /></span><span style="color: #0000BB">function_menufun_menu</span><span style="color: #007700">() {<br /></span><span style="color: #0000BB">$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'menufun/%a_zoo_animal'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Hi'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'menufun_hello'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page arguments' </span><span style="color: #007700">=> array(</span><span style="color: #0000BB">1</span><span style="color: #007700">),<br /></span><span style="color: #DD0000">'access callback' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'type' </span><span style="color: #007700">=> </span><span style="color: #0000BB">MENU_NORMAL_ITEM</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'weight' </span><span style="color: #007700">=> -</span><span style="color: #0000BB">10<br /></span><span style="color: #007700">);<br />return </span><span style="color: #0000BB">$items</span><span style="color: #007700">;<br />}<br /><br />function </span><span style="color: #0000BB">a_zoo_animal_to_arg</span><span style="color: #007700">(</span><span style="color: #0000BB">$arg</span><span style="color: #007700">) {<br />return </span><span style="color: #DD0000">'tiger'</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>Таким образом (благодаря функции to_arg()) пункт меню появляется в Навигации.</p> </div> <div id="node-84" class="section-2"> <h1 class="book-heading">Меню на Друпале, ч.6</h1> <p><strong>Передача дополнительных аругментов в функцию загрузки.</strong> </p> <p>Рассмотрим пример:</p> <h4><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br />$items</span><span style="color: #007700">[</span><span style="color: #DD0000">'node/%node/revisions/%/view'</span><span style="color: #007700">] = array(<br /></span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'Revisions'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'load arguments' </span><span style="color: #007700">=> array(</span><span style="color: #0000BB">3</span><span style="color: #007700">),<br /></span><span style="color: #DD0000">'page callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'node_show'</span><span style="color: #007700">,<br /></span><span style="color: #DD0000">'page arguments' </span><span style="color: #007700">=> array(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">NULL</span><span style="color: #007700">, </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">),<br /></span><span style="color: #DD0000">'type' </span><span style="color: #007700">=> </span><span style="color: #0000BB">MENU_CALLBACK</span><span style="color: #007700">,<br />);<br /></span><span style="color: #0000BB">?></span></span></code></div></h4> <p>В данном примере строка 'load arguments' => array(3) подгружает дополнительные аргумент в функцию node_load. Рассмотрим на примере конкретного пути - node/3/revisions/4/view. Если бы мы не прописали 'load arguments', то функция node_load вызвалась бы только вот так вот - node_load('3'), но теперь она будет вызываться уже как node_load('3','4'). </p> <p>Ну а функция, которая отображает страницу - node_show, в свою очередь будет вызвана вот так - node_show($node, NULL, TRUE), первым параметром здесь передаётся объект данной ноды. </p> <p>Ну вот - это собственно говоря такой - краткий обзор возможностей программирования, которые в принципе открываются тем, кто хочет чтобы они перед ним открылись. </p> <p>С уважением, Ёж</p> </div> <div id="node-102" class="section-2"> <h1 class="book-heading">Модуль Multiping</h1> <p>Multiping - это модуль, которые позволяет сообщать различным сервисам (например Ping-o-matic, Яндекс или MSN) об обновлениях и появлении новых материалов на Вашем сайте.</p> <p>Таким образом, различные пинг-сервисы побуждают поисковые системы почаще заглядывать на Ваш сайт и индексировать его страницы. </p> <p>Ваш сайт можно пинговать при очередном запуске крона, или же сразу же после добавления некоторого материала - для этого собственно говоря достаточно поставить птичку <em>Ping after post</em> в настройках на странице <strong>/admin/settings/multiping</strong>.</p> <p>Данный модуль пока находится в деве, но совсем скоро планируется вторая, стабильная версия модуля для шестерки, и для семерки. Но модулем пользоваться можно - его главное преимущество в том, что с его помощью мы можем пинговать свой сайт сразу в нескольких сервисах.</p> </div> <div id="node-101" class="section-2"> <h1 class="book-heading">Модуль Nodewords</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-png"><img class="field-icon-image-png" alt="image/png icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/sy47ti.png">sy47ti.png</a></div> </div> </div> </div> <p>Позволяет добавить метатеги для каждой ноды.</p> <p>Поддерживаемые мета-теги: ABSTRACT, COPYRIGHT, DESCRIPTION, GEOURL, KEYWORDS и ROBOTS.</p> <p>Каждый из этих мета-тегов можно переопределить для КАЖДОЙ отдельной ноды.</p> <p>Есть поддержка для Views и Panels, модуль nodewords может генерировать мета-теги в том числе и на страницах, генерируемых этими модулями. </p> <p>Можно по умолчанию установить чекбокс, говорящий о том что по умолчанию в мета-теге DESCRIPTION будет отображаться тизер ноды, в случае - если DESCRIPTION для данной ноды не будет заполнен.</p> <p>Мета-теги благодаря этому модулю можно переопределить и для главной страницы сайта. </p> </div> <div id="node-98" class="section-2"> <h1 class="book-heading">Открыт сайт группы "Рокаш"</h1> <div class="field field-type-image field-field-blog"> <div class="field-items"> <div class="field-item odd"> <div class="filefield-file clear-block"><div class="filefield-icon field-icon-image-png"><img class="field-icon-image-png" alt="image/png icon" src="http://www.ezh-leon.ru/sites/all/modules/filefield/icons/protocons/16x16/mimetypes/image-x-generic.png" /></div><a href="http://www.ezh-leon.ru/sites/default/files/rock.png">rock.png</a></div> </div> </div> </div> <p>Дорогие друзья - спешу сообщить об открытии мною сайта группы "Рокаш". Тем кому интересна фолк-музыка - беларусская и не только, тому будет интересен и этот сайт. Сайт будет в ближайшем времени доработан, дополнен видео и аудио материалами, а также блогом басиста и автора текстов песен группы Лявона Казакова, и не только этим.</p> <p>Сайт сделан конечно же на Друпале ). </p> <p>Дизайнер сайта - Наталья Кравченко.</p> <p>Адрес сайта - <a href="http://rokash.com" title="http://rokash.com">http://rokash.com</a></p> <p>Прошу комментить и отписываться! )</p> </div> </div> </body> </html>