Drupalogy_Magazine_00

Page 1

Друпалогия Журнал о Drupal и про Drupal

#00 • Январь, 2010

http://magazine.drupalogy.ru



Друпалогия #00

В этом номере: Про Drupal Доброго времени суток, дорогие читатели!

Разработка сайта на Drupal: архитектура Drupal..................4 Разработка сайта на Drupal: оптимизация Drupal................6

Перед вами пилотный выпуск журнала «Друпалогия», в котором вы найдёте статьи, посвящённые CMS/CMF Drupal.

Drush: простое средство управления сайтом из

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

Обучение

командной строки........................................................................9

Сохранение формы в Drupal с помощью AJAX..................11 Автоматическое создание нод из текстовых файлов......15 Автозаполнение текстовых полей в Drupal Forms API.....18 Smarty theme (themplate) engine: альтернатива

Если вы хотите стать автором и публиковать свои статьи, уроки или обзоры, присоединяйтесь, мы будем рады! Статьи могут быть как тематическими и посвящённые исключительно Друпалу, так и его не касающиеся, но связанными с WEB, интернеттехнологиями, серверами и ОС. Интересным статьям всегда найдётся место на страницах «Друпалогии»! Хочу выразить благодарность все тем людям, кто откликнулся на предложение поучаствовать в создании журнала, авторам статей и обзоров; всем тем, кто помогал советами и консультациями. Большое человеческое спасибо!

phptemplate для создания тем...............................................22 Советы и хитрости...................................................................24 Ликбез или повышение грамотности новичков.................27

Локализация Локализация и перевод в Drupal...........................................30

Обзоры модулей Веб-картография в Drupal.......................................................34

Хостинг для Drupal

С уважением,

Интервью с Егором Марценюком, представителем

компании IT-Patrol....................................................................39

Stan Ezersky

Не Drupal jQuery 1.4: 15 новых возможностей......................................41 Статистика использования браузеров................................46

январь, 2010

3


Друпалогия #00

Про Drupal

Разработка сайта на Drupal: архитектура Drupal Роман Архаров aka Romka Drupal построен по модульному принципу: компактный набор служебных функций (ядро), отвечающих за работу с СУБД, авторизацию, кэширование и пр. дополняется модулями, реализующими основную функциональность. Они обеспечивают обработку системных событий (авторизация пользователя, запись данных в БД, просмотр документа, поиск и т. д.), взаимодействие между модулями выполняется при помощи хуков (hooks) — определенным образом именованных функций. Drupal построен по модульному принципу: компактный набор служебных функций (ядро), отвечающих за работу с СУБД, авторизацию, кэширование и пр. дополняется модулями, реализующими основную функциональность. Они обеспечивают обработку системных событий (авторизация пользователя, запись данных в БД, просмотр документа, поиск и т. д.), взаимодействие между модулями выполняется при помощи хуков (hooks) — определенным образом именованных функций. Описав хук в модуле, можно перехватить любое событие (например, сохранение записи) и запрограммировать свою логику его обработки. Благодаря такой системе программист может расширить возможности любого существующего модуля, не вмешиваясь в его исходный текст, а также создать свои собственные типы событий. В ядре Drupal реализован набор функций (API) для работы со всеми необходимыми компонентами: СУБД, формами, кэшем, пользователями и их правами. Для взаимодействия с СУБД используется абстрактный интерфейс DB API, ядро Drupal оперирует ANSI-совместимым SQL для работы с БД, а структуры (таблицы) для БД определяются программистом в массивах специального вида. При этом преобразование определений таблиц и запросов под особенности конкретной СУБД (официально система Drupal совместима с MySQL и PostgreSQL) выполняется специальной библиотекой, и разработчику не приходится заботиться об особенностях работы СУБД. Определив собствен-

январь, 2010

ную библиотеку функций, можно подключить другие СУБД, — например, существуют библиотеки для IBM DB2, Oracle и MSSQL. Не менее важная часть Drupal — интерфейс обработки экранных форм (Forms API). С точки зрения разработчика, форма Drupal — это определенным образом подготовленный массив данных, содержащий информацию об элементах формы и их параметрах. На основе этого массива системные функции генерируют HTML-код. Такой подход позволяет модулям модифицировать одну и ту же форму, а также с помощью функций темизации менять оформление отдельных элементов. Разработчики модулей могут добавлять дополнительные поля (например, защиту от автоматических публикаций — CAPTCHA) или заменять существующие (заменить текстовое поле WYSIWYG-редактором). По умолчанию Drupal предоставляет пользоватлю базовый тип материала с минимумом стандартных полей и атрибутов: заголовок, текст, автор и ряд служебных полей. Программный интерфейс Node API позволяет дополнять базовый тип новыми полями: ссылками, картинками, файлами, списками и др. Для управления правами доступа к материалам и службам сайта в Drupal реализованы два механизма. Первый обеспечивает проверку доступа к отдельным сервисам сайта — каждый модуль через специальный хук объявляет свои разрешения на

4


Друпалогия #00 использование тех или иных своих функций, затем администратор сайта может разрешить или запретить различным группам пользователей доступ к тому или иному функционалу. Второй механизм — права доступа к отдельным документам на создание, просмотр, изменение и удаление. Модули реализуют собственные интерфейсы проверки прав, основываясь на данном механизме. Например, есть модули, разграничивающие доступ пользовательских ролей к отдельным рубрикам сайта либо задающие права доступа непосредственно для отдельных пользователей, отдельных документов и даже отдельных полей документа. Еще один важный элемент архитектуры Drupal — система темизации, позволяющая, во-первых, отделить логику работы программных модулей от представления данных; во-вторых, гибко настроить внешний вид каждого выводимого на экран элемента. Чтобы изменить внешний вид сайта, необходимо или скачать готовую, или разработать собственную тему оформления — набор особым образом сформированных HTML-шаблонов, в которые интегрированы PHP-переменные с данными.

январь, 2010

Про Drupal Важно отметить, что подсистема темизации Drupal не принуждает разработчика применять один тип шаблонов. Drupal позволяет задействовать различные «движки» шаблонов, на базе которых строятся темы оформления. Стандартом де-факто для тем оформления в Drupal стал механизм PHPtemplate, но можно также использовать Smarty, PHPTAL, Easy Template System и др. Темы оформления позволяют создать каркас сайта, который будет наполнен данными, генерируемыми модулями. При разработке модулей программисты, придерживающиеся принятых в Drupal стандартов кодирования, выносят весь код, связанный с выводом данных на экран, в отдельные, именованные специальным образом функции. Такие функции — функции темизации, обычно не реализуют никакой логики, а лишь принимают набор данных и возвращают HTML-код. Эти функции могут быть переопределены в теме оформления: таким образом, не изменяя код исходного модуля, разработчик может настроить внешний вид для задач конкретного сайта.

5


Друпалогия #00

Про Drupal

Разработка сайта на Drupal: оптимизация Drupal Александр Графов aka Axel Способы оптимизации сильно зависят от конкретной задачи и системного окружения. Свою роль в выборе способов оптимизации играют набор используемых на сайте модулей и соотношение трафика от анонимных и зарегистрированных посетителей. Обычно окончательное заключение об эффективности того или иного метода можно дать только после его тестирования на реальном сайте. По умолчанию Drupal ориентирован на хранение максимума информации в базе данных. Контент, служебные переменные и настройки сайта, кэши данных — все это складывается в БД. Не всегда такая схема может быть эффективна, и Drupal предлагает ряд альтернатив.

Методы оптимизации «из коробки» Сначала рассмотрим, что предлагает Drupal в стандартной поставке. Настройки производительности задаются в меню Administer — Settings — Performance (admin/settings/performance). Первый раздел настроек — страничный кэш, в Drupal эта разновидность кэширования отвечает за показ страниц анонимным посетителям сайта. При включении нормального режима кэширования полностью сгенерированная страница сохраняется в кэше (по умолчанию это таблица БД) и отдается анонимным посетителям, пока в кэш не будут помещены новые данные. Число запросов к СУБД при этом уменьшается до нескольких штук на страницу. Агрессивный режим работы кэша страниц обеспечивает более высокую производительность, чем нормальный, но он несовместим с некоторыми модулями, которые сообщают об этом на странице администрирования. Дополнительно при агрессивном режиме кэширования можно указать минимальное время, которое кэшированные данные будут отображаться посетителям, т. е. никакие обновления сайта не будут видны анонимным посетителям, пока не пройдет минимальное вре-

январь, 2010

мя. Следует помнить, что кэш страниц не действует для вошедших под своим логином пользователей — они будут всегда видеть актуальную информацию. Если же на сайте большую часть составляют зарегистрированные посетители, то кэш страниц даже в агрессивном режиме не даст значимого эффекта. Тем не менее практически всегда стоит включать нормальный режим кэширования. Отметим, что полностью выключить кэширование в Drupal нельзя. Функция в настройках производительности отвечает только за страничный кэш, но Drupal также кэширует меню, фильтры ввода, блоки; дополнительные модули могут создавать свои кэши — все эти данные сохраняются в отдельных таблицах БД. Внизу страницы настроек есть кнопка очистки кэша, которая очищает только кэш страниц. Последний режим в этом разделе — компрессия страниц. Современные браузеры позволяют получать компрессированные данные, снижая объем данных, передаваемых по сети, в среднем в 6–8 раз — разумеется, если сервер умеет отдавать данные в таком сжатом виде. При активации этого режима сжатие выполняется на уровне Drupal, т. е. средствами PHP. В то же время, лучше поручить эту операцию Web-серверу, поскольку он справится с ней эффективнее. Эта операция в Drupal сделана на случай, когда нет возможности включить компрессию страниц на Web-сервере.

6


Друпалогия #00 Практически из той же серии другой раздел настроек оптимизации — оптимизация трафика. Здесь можно включить слияние CSS и Javascript, отдаваемых сайтом. Различные модули сайта могут добавлять свои стили и скрипты на страницы, в результате запрос страницы браузером влечет за собой десятки мелких файлов со стилями. Эффективнее объединять все файлы в один и отдавать его один раз, что и делает Drupal при включении опций на этой закладке. Держать настройки слияния выключенными имеет смысл только во время разработки сайта, когда стили и скрипты часто меняются и дополняются новыми. Как правило, основное содержимое сайта сопровождается множеством сопутствующих данных, которые в Drupal принято выводить блоками. Блоки реализуются разными модулями и могут содержать весьма сложные алгоритмы по выборке данных. Имеет смысл кэшировать данные блоков, и Drupal умеет это делать. Причем, в отличие от кэша страниц, кэш блоков действует на всех пользователей сайта, а не только на анонимов. Блоки могут кэшироваться персонально для каждого пользователя, для каждой роли пользователей на сайте, для каждой страницы или глобально для всего сайта. Эти настройки указываются при программировании модулей, в настройках Drupal предлагается только включить или отключить кэш для всех блоков целиком.

Дополнительные модули для оптимизации Drupal позволяет подменять стандартный механизм кэширования альтернативными реализациями, что и используется несколькими модулями, предоставляющими свои методы кэширования данных. Обычно суть всех этих модулей сводится к подмене механизма хранения кэша — вместо БД используются хранение в файлах или в оперативной памяти. Наиболее комплексное решение предоставляет модуль cacherouter. Он реализует механизмы кэширования в файлы, в память через «демон»

январь, 2010

Про Drupal memcached либо использование памяти акселераторов APC и XCache. Как уже отмечалось, Drupal использует в БД разные таблицы под кэши различного назначения. Удобство модуля cacherouter в том, что можно указать для каждого вида кэша, где он должен храниться, например комбинировать кэширование страниц в файлах с кэшированием блоков в memcached.

Способы снижения нагрузки на хостинг Один из ресурсоёмких компонентов Drupal — механизм поиска и индексации контента. Для ускорения поиска по содержимому сайта Drupal строит поисковый индекс, эта операция производится в фоне, при срабатывании планировщика заданий, но отбирает свою долю ресурсов. Реализация поиска в Drupal неплоха и приемлема для большинства небольших сайтов, но при большом объеме контента и высокой посещаемости реализация поиска на PHP может не справляться с нагрузкой. Эффективнее использовать сторонние поисковые системы. Простейший выход здесь — интеграция с поиском Google. Но по многим причинам это не всегда удачный выход. Однако есть великолепные OpenSource-решения для поиска, которые удобно использовать при условии их интеграции с сайтом. Для Drupal разных версий предлагались модули интеграции с несколькими поисковыми движками, в частности для Drupal 6 есть модуль интеграции с поисковым движком Sphinx, выпускаемым под лицензией GPL. Sphinx реализован на языке Cи и предлагает быстрое и масштабируемое решение для поиска по большим объемам данных. В примерах на сайте разработчиков упоминаются хранилища данных емкостью более терабайта и сайты с потоком поисковых запросов в несколько миллионов в день. Даже если объемы данных и число ожидаемых поисковых запросов меньше, использование внешнего поискового движка позволит разгрузить Drupal. Модуль sphinxsearch (http:// drupal.org/project/sphinxsearch) заменяет стандартный модуль search на интерфейс к поисковому движку Sphinx. Он сложнее в конфигурировании (благодаря обширным настройкам, предлагаемым в Sphinx), но позволяет реализовать методы поиска, которые имеются в Drupal: по документам, ком-

7


Друпалогия #00 ментариям, пользователям и таксономии. Модуль в настоящее время находится в разработке, но версия для Drupal 6 уже доступна для загрузки.

январь, 2010

Про Drupal Стоит помнить, что оптимизация работы Drupal — только один из этапов в оптимизации сайта. Настройки Web-сервера и СУБД, акселерация PHP, настройки ОС и «железа» — все это влияет на работу сайта, поэтому оптимизация работы системы должна проводиться на всех уровнях.

8


Друпалогия #00

Про Drupal

Drush: простое средство управления сайтом из командной строки Павел Шаров aka Master Of Tragedy Бывают ситуации, когда по каким-то причинам нет возможности зайти на сайт Друпал для проведения нужных действий. Или же просто не хочется тратить трафик, если вы используйте мобильное соединение с интернетом. Решение этой проблемы очень простое и носит оно название drush aka «Drupal Shell». До написания этой статьи я слышал довольно много об этой утилите, но практических обзоров так и не нашел. Итак, почему же стоит использовать Drush: • Удобная утилита позволяет практически полностью управлять сайтом • Не потребляет трафика • Экономия времени

Рассмотрим некоторые возможности данного инструмента. В интерактивном режиме можно посмотреть статус системы и ее версию. Для этого я ис-пользовал команду # ./drush st Посмотрим, что у нас получилось: master@master-laptop:~/public_html/indepimport/ drush$ ./drush st PHP configuration Drupal Root indepimport Drupal version Site Path Site URI Database Driver Database Hostname Database Username Database Name Database Password Database Drupal Bootstrap Drupal User

январь, 2010

: /opt/lampp/etc/php.ini : /home/master/public_html/ : : : : : : : : : : :

6.15 sites/default http://default mysqli localhost root indepimport Connected Successful Anonymous

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

Управление модулями Установка, включение, отключение и деинсталяция дополнительных модулей Drupal. Для установки дополнительных модулей мы воспользуемся командой ./drush en master@master-laptop:~/public_html/indepimport/ drush$ ./drush en forum The following modules will be enabled: forum Do you really want to continue? (y/n): y Forum was enabled successfully.

Аналогичное действие служит для отключения модуля: master@master-laptop:~/public_html/indepimport/ drush$ ./drush dis forum The following modules will be disabled: forum Do you really want to continue? (y/n): y Forum was disabled successfully.

9


Друпалогия #00 Кроме того, программа позволяет нам установить дополнительные модули, что называется, "не отходя от кассы". Для этого служит команда # ./drush dl Посмотрим пример: master@master-laptop:~/public_html/indepimport/ drush$ ./drush dl cck Project cck (6.x-2.6) downloaded to [success] /home/master/public_html/corp/sites/all/ modules/.

Как видим, программа успешно загрузила нужный нам модуль с drupal.org. Осталось лишь его включить, используя команду выше.

Обновление модулей Как правило, процедура обновления модулей в Drupal является довольно утомительной. Сначала нужно посмотреть какие модули доступны для обновления, затем зайти на drupal.org, чтобы загрузить последнюю версию, затем распаковать в нужный нам каталог, запустить скрипт update.php... Итого, получаем массу лишних действий, которые можно заменить буквально одной командой. В утилите Drush реализован собственный сценарий обновления модулей, который автоматически проверяет наличие новой версии модуля или темы, загружает новый код и выполняет все необходимые процедуры обновления модуля, включающие в себя изменения в базе данных, если таковые имеются. Для просмотра доступных обновлений воспользуемся командой upc или up

январь, 2010

Обучение Сценарий составит список установленных модулей и сравнит версию с имеющимися на сервере drupal.org. Внимание! Для выполнения процедуры обновления необходимо включить модуль update. После выполнения команды мы видим таблицу, в которой отображаются названия модулей, установленная версия и текущая версия модуля на drupal. org Если для одного или нескольких модулей имеются обновления, утилита дает нам об этом знать и предлагает выполнить обновления, заранее предупреждая о последствиях, которых обычно быть не должно. Тем не менее, сценарий создает резервную копию имеющегося модуля, чтобы в случае возникновения проблем можно было вернуться к установленной ранее версии. Далее соглашаемся с продолжением процедры, ждем несколько секунд и новая версия модуля успешно установлена. Несмотря на две имеющиеся команды обновления, я рекомендую использовать команду up, поскольку она в отличие от upc выполняет также соответствующие изменения в базе данных, если таковые необходимы. К сожалению, обновлять ядро этим инструментом на настоящий момент нельзя. Будем надеяться, что разработчики включат эту возможность в следующих версиях утилиты. Более подробную информацию о командах вы можете посмотреть набрав ./drush help в строке терминала. Приятного использования!

10


Друпалогия #00

Обучение

Сохранение формы в Drupal с помощью AJAX Роман Грачёв aka Graker Сегодня речь пойдет о том, как запрограммировать сохранение формы в Друпале через AJAX. В принципе, для этих целей уже существует модуль Ajax. Но вдруг у нас крайне хитрые потребности, или мы просто не хотим ради сабмита пары форм тащить за собой целый модуль? В общем, задача такова: создать средствами Друпала простую форму, вывести ее на страницу, а затем — сохранять через AJAX-запросы, выводя на ту же страницу результаты сохранения и ошибки валидации формы, если таковые были. Без обновления страницы, естественно. Для решения задачи будем использовать Forms API Друпала и jQuery с плагином Form. Оформим все в виде отдельного модуля. Рассмотрим решение по порядку. Начнем с создания страницы с формой: function jf_test_menu() { $items = array(); //страница для теста формы $items['jf_test'] = array( 'title' => 'Тест jQuery Form', 'page callback' => '_generate_page', 'access arguments' => array(TRUE), 'type' => MENU_NORMAL_ITEM, ); return $items; } //function jf_test_menu function _generate_page() { $output = ""; //выведем текст $output .= '<div class="test_messages">'; $output .= '<strong>Messages:</strong>'; $messages = variable_get('jft_ messages',array()); foreach ($messages as $index => $message) { $output .= '<p>' .$message .'</p>'; } $output .= '</div>';

январь, 2010

//выведем форму $output .= drupal_get_form('_jft_form'); return $output; } //function generate_page function _jft_form(&$form_state) { $form = array(); $form['message'] = array( '#type' => 'textarea', '#title' => 'Enter message', '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => 'Send', ); return $form; } //function _jft_form function _jft_form_submit($form,&$form_state) { //добавляем сообщение в массив $messages = variable_get('jft_ messages',array()); $messages[] = $form_state['values'] ['message']; variable_set('jft_messages',$messages); } //function _jft_form_submit

Теперь если пользователь зайдет по адресу / jf_test, напишет что-нибудь в форме и нажмет «Send», набранный текст будет накапливаться в блоке под надписью «Messages». Пока отправка текста происходит обычным сохранением формы с перезагрузкой страницы. Сделаем, чтобы сообщения отправлялись с помощью AJAX.

11


Друпалогия #00 Прежде всего, нужно добавить скрипт с плагином jQuery Form. Сама библиотека jQuery включена в Друпал и добавится автоматически. Плагин Form тоже включен в состав Друпала, но версия очень старая, а мы скачаем новую и подключим ее при генерации страницы. Заодно сразу добавим js-файл со скриптом, которым будем сохранять форму: function _generate_page() { $output = ""; //добавим скрипт для сабмита формы и плагин jQuery Form drupal_add_js(drupal_get_path('module','jf_ test').'/jquery.form.js'); drupal_add_js(drupal_get_path('module','jf_ test').'/jf_test.js'); //...

Теперь напишем сам скрипт jf_test.js: Drupal.behaviors.jf_testBehavior = function (context) { $("#-jft-form").ajaxForm(successCallback); //устанавливаем обработчик сабмита формы $("#-jft-form").submit(function () { //возвращаем false чтобы предотвратить обычный сабмит return false; }); } //callback вызывается после успешного сабмита формы function successCallback(responseText,statusTe xt) { $("div.test_messages").append(responseText); }

Drupal.behaviors заменяет $(document).ready() для нашего модуля. Подробнее об этом можно почитать в описании Javascript, AJAX, AHAH API.

январь, 2010

Обучение А пока посмотрим на новоиспеченный скрипт. Вызов функции ajaxForm() подготавливает нашу форму к сохранению через AJAX. Аргументом функции является название callback-а, который будет вызван в случае успешного сохранения формы (successCallback). Функция ajaxForm() сама вытащит из формы адрес скрипта для сохранения, установленный Друпалом, так что мы можем об этом не заботиться, и сама же настроит все остальное для сохранения через AJAX при нажатии на кнопку. Затем мы устанавливаем для события submit, то есть сохранения формы, свой обработчик. В нем возвращается false — для того чтобы избежать обычного сохранения с обновлением страницы. Ну а в функции successCallback мы добавляем в блок «Messages» тот текст, который получили от сервера. Однако, если мы попытаемся выполнить все, что написали, то увидим, что в блок «Messages» добавилось не последнее введенное сообщение, а целая страница, сгенерированная Друпалом заново. Поэтому теперь нам нужно позаботиться об адекватных ответах на AJAX-запросы при сохранении формы. То есть, нужно возвращать не всю страницу, а только последнее введенное сообщение. Кроме того, мы бы хотели получать сообщения об ошибках валидации формы, которые возникнут, например, если мы оставим поле ввода сообщения пустым. Для этого напишем валидатор нашей формы, а также немного изменим функцию сохранения: function _jft_form_validate($form,&$form_state) { //мы хотим показать все ошибки Друпала, //которые могли возникнуть при валидации формы $output = ""; $output .= theme('status_messages','error'); if ($output != "") {

12


Друпалогия #00

Обучение

print $output; exit();

$("div.test_messages").append(responseText); //сбрасываем форму $("#-jft-form").resetForm();

} } //function _jft_form_validate

} }

function _jft_form_submit($form,&$form_state) { //... //выведем последнее сообщение print '<p>' .$form_state['values']['message'] .'</p>'; exit(); } //function _jft_form_submit

Теперь мы получаем от сервера либо последнее сообщение пользователя, либо ошибку валидации. Окончательный jf_test.js выглядит так: Drupal.behaviors.jf_testBehavior = function (context) { //отмечаем, что наша форма будет сохраняться по AJAX //и указываем callback, вызываемый после успешного сабмита $("#-jft-form").ajaxForm(successCallback); //устанавливаем обработчик сабмита формы $("#-jft-form").submit(function () { //убираем старые ошибки $("div.messages").remove(); //возвращаем false чтобы предотвратить обычный сабмит return false; }); } //callback вызывается после успешного сабмита формы function successCallback(responseText,statusTe xt) { if ($(responseText).hasClass("error")) { //есть ошибки при валидации, показываем их в начале формы $("#-jft-form").prepend(responseText); } else { //выводим сообщение

январь, 2010

На всякий случай уточняю: функции ajaxForm и resetForm — это функции из API плагина jQuery Form, без него ничего работать не будет. Наконец, позаботимся о злоумышленниках, коварно отключивших в своих браузерах JavaScript. Ведь если оставить все как есть, после сохранения формы они будут видеть только текст последнего сообщения и больше ничего. Чтобы все работало нормально и без JavaScript-а, будем проверять способ сохранения формы в функциях валидатора и сохранения. Окончательный текст этих функций: function _jft_form_validate($form,&$form_state) { //проверка, используется ли AJAX для сабмита if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { //мы хотим показать все ошибки Друпала, //которые могли возникнуть при валидации формы $output = ""; $output .= theme('status_messages','error'); if ($output != "") { print $output; exit(); } } } //function _jft_form_validate

function _jft_form_submit($form,&$form_state) { //добавляем сообщение в массив $messages = variable_get('jft_ messages',array()); $messages[] = $form_state['values'] ['message'];

13


Друпалогия #00 variable_set('jft_messages',$messages); //выводим последнее сообщение только если для сабмита используется AJAX if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { //выведем последнее сообщение print '<p>' .$form_state['values'] ['message'] .'</p>'; exit(); } } //function _jft_form_submit

январь, 2010

Обучение Теперь с выключенным JavaScript-ом все будет работать так, как будто его и не было никогда. Задача решена. Рабочие исходники модуля можно раздобыть по адресу: http://graker.ru/sites/default/files/ jf_test.tar.gz.

14


Друпалогия #00

Обучение

Автоматическое создание нод из текстовых файлов Мария Таран aka gagaga В некоторых случаях, ручное создание нод может стать весьма трудоемкой работой. Основной причиной является количество таких нод, которое иногда зашкаливает за десятки тысяч, а ручное создание занимает неоправданно много времени. В такой ситуации и необходим модуль для автоматического создания нод. В общем виде процесс создания ноды представляет собой импорт каких-либо данных в объект $node. Соответственно, все данные должны уже существовать в каком-то объективном виде. Например, в файлах .xml, .txt, .csv или на сторонних интернет-сайтах. В данной статье будет создана функция, которая сможет создавать ноду из простых текстовых файлов. Импорт из других типов файлов будет освещен в последующих статьях. Чтобы выполнить поставленную задачу необходимо выполнить несколько подготовительных действий. Во-первых, создать базовые файлы для модуля. Во-вторых, создать все необходимые, на Ваш взгляд, функции. Например, можете сделать страницу с настройками в административном разделе или определить свой тип контента. В-третьих, определитесь, как именно должен происходить запуск функции: использовать cron или запускать вручную, т.е. нажатием на кнопку. Подразумевается, что читатели данной статьи уже знакомы с основами создания модулей, поэтому я ограничусь описанием одной функции, которая будет выполнять только импорт данных и создание ноды. От чего же мы будем отталкиваться в начале? Вопервых, документов может быть достаточно большое количество. Чтобы их полноценно обработать, нужно знать их структуру, т.е. какие данные содержит каждая из строк. Предположим, что каждый файл будет выглядеть так: • 1 строка – Заголовок; • 2 строка – Теги через запятую;

январь, 2010

• 3 строка - Специфические данные для текстового CCK-поля; • 4 строка и далее - Основное содержимое документа, т.е. тело документа. Во-вторых, определим какие поля и дополнительные возможности нам понадобятся. В нашем случае это: 1. Добавление тегов в таксономию. 2. Добавление данных в текстовое CCK-поле. 3. Прикрепление файла к ноде. 4. Публикация ноды через какое-то время после создания. Модули, которые должны быть включены: Taxonomy, CCK, Upload, Scheduler. Примерный план работы такой функции не зависит от типов файлов или других предпосылок и выглядит так: 1. Открытие файла или страницы. 2. Извлечение и обработка данных. 3. Создание и заполнение объекта $node 4. Проверка, подготовка и сохранение $node. Итак, приступим к созданию модуля. Создаем папку, в которую будем копировать базовые текстовые файлы. Следующий код ищет и открывает файлы, которые лежат в заданной папке. К друпалу код относится мало: $path_default=file_directory_path().'/ autoupload'; //Путь к папке, где будут лежать исходные файлы $files=file_scan_directory($path_admin, '.*'); //Сканирует папку на наличие файлов любых расширений

15


Друпалогия #00 Лучше всего точно определять расширение файлов, чтобы в будущем избежать возможных ошибок. foreach($files as $file) { $f=file($file->filename); //пробует открыть файл и создать массив if (!$f) { drupal_set_message('<strong>Не получается открыть и прочитать файл. Попробуйте повторить попытку позднее.</strong><br />'); exit; }

Теперь, если файл удачно открылся и прочитался, получаем массив вида $f[key]= value, где key равен номеру строки, а value её значению. Так как тело документа может содержать более одной строки, выполняем следующий код: $i=2; // номер строки, которая начинает основной контент $body=''; while ($i<=count($f)) { $body.= ltrim(drupal_convert_to_utf8($f[$i], 'cp1251')); // Если кодировка текстового файла отличается от utf-8, необходимо выполнить конвертацию $i++; }

Теперь займемся прикреплением файла к ноде. Если Вам зачем-то понадобится перенеси файлы в другую папку, то воспользуйтесь следующей функцией. В данный момент она копирует текущий файл в директорию 'sites/default/files/'. Если такой файл уже существует, то он заменяется новым. file_copy($file->filename, file_directory_ path(),FILE_EXISTS_REPLACE) //переносим файл из созданной нами папки в /files

Прикрепление файла отчасти похоже на создание самой ноды. Точно также мы создаем объект, который должны заполнить некоторыми данными.

январь, 2010

Обучение $file_upload = new stdClass(); $file_upload->filepath= $file->filename; // полный путь к файлу $file_upload->filename= $file->basename; // Имя файла с расширением $file_upload->filesize = filesize($file->filename); // размер файла $file_upload->timestamp = time(); // время создания $file_upload->filemime = file_get_mimetype($file>filename); $file_upload->uid = 1; // id юзера от имени которого прикрепляется файл $file_upload->status = 1; // активный // записываем файл в бд drupal_write_record('files', $file_upload);

Получаем fid для текущего файла, далее мы должны будем вставить его в ноду. $file_upload->fid = db_last_insert_ id('files','fid'); // получаем fid для прикрепления к ноде

Аналогично этому коду сработает и такая конструкция, так что выбор остается за вами: $file_upload->fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $file_upload>filepath)); //создаем объект для ноды $node = new stdClass(); $node->title = drupal_convert_to_utf8($f[0], 'cp1251'); //Заголовок ноды $node->body = $body; // Тело ноды $node->type = 'test'; // Тип материала, к которому будет относится нода $node->name = 'leyt'; // Логин пользователя от имени которого будет создана нода $node->uid = 1; // Uid пользователя $node->status = 0; //По умолчанию нода не опубликована $node->taxonomy['tags'][vid] =drupal_convert_ to_utf8($f[1], 'cp1251') ; // Добавляем теги таксономии

16


Друпалогия #00 Вместо vid поставьте id словаря таксономии, в который будете добавлять теги. Вместо field_myfield подставьте название своего поля. $node->field_myfield[0]['value']= drupal_convert_ to_utf8($f[2], 'cp1251'); // Добавляем инфу в CCK-поле $node->format = 2; $node->promote = 1;

Теперь подключаем отложенное опубликование, если включен модуль Scheduler. if(module_exists('scheduler')){ $time=time(); // текущее время $seconds_plus=300; //количество секунд, которое прибавим к текущему времени $time_publish_on=$time+$seconds_plus; $node->publish_on=$time_publish_on;

Обучение И последний этап. Проводится проверка на заполненность основных полей. Дальше подготовка ноды. На этом этапе в ноду могут быть внесены изменения другими модулями. И, наконец, сохранение ноды. После этого нода будет окончательно создана. // записываем в бд node_submit($node); node_save($node); // сохранение db_query("INSERT INTO {upload} (fid, nid, vid, description, list) VALUES (%d, %d, %d, '%s', %d)", $file_upload->fid, $node->nid, $node->vid, $file_upload->filename, 1);

Если Вы все сделали правильно, теперь Вы научились автоматически импортировать данные из любого количества текстовых файлов. Здесь описаны лишь примерные варианты работы подобного скрипта. Не бойтесь экспериментировать и добавлять новые возможности. Удачи в изучении и применении CMF Drupal!

январь, 2010

17


Друпалогия #00

Обучение

Автозаполнение текстовых полей в Drupal Forms API Андрей Олищук Автозаполнение текстовых полей прочно вошло в жизнь рядового пользователя сети Интернет вместе с его внедрением в ведущих поисковиках — Google и Яндекс. При попытке набрать первые буквы поискового запроса, пользователь получает выпадающий список с наиболее вероятными вариантами полного текста. На сайте юмористических цитат bash.org.ru ������������������������������������������������������������� ������������������������������������������������� даже появился целый пласт шуток в стиле «а попробуйте набрать слово... и посмотрите какие варианты поисковик предложит». В CMF Drupal поля с автозаполнением получили наибольшее распространение в административной панели, например в контексте использования таких модулей CCK ��������������������������������� ����������������������������� как nodereference ������������������������� ����������� и userefer��������� ence —���������������������������������������� для быстрого поиска нод или пользователей по части их имени. Такой элемент во многом более удобен, чем ввод ID по памяти или выбор из полного списка. Иногда возникает необходимость, реализовать элемент с автозаполнением самостоятельно.

Принципы автозаполнения Автозаполнение в CMF Drupal работает в рамках Forms API как атрибут текстового элемента. Этот атрибут имеет в качестве значения адрес, по которому система обращается за данными в ожидании массива �������������������������������������� Java Script. Массив ������������������������� данных подгружается и предлагается пользователю как выпадающий список из подобранных вариантов. Проще говоря, работу автозаполнения можно условно разбить на клиентскую и серверную части. Клиент обращается с запросом к серверу, передавая введённые пользователем символы, сервер генерирует набор данных и возвращает их клиенту. Клиент показывает данные пользователю в нужном виде. В рамках этой статьи мы напишем небольшой модуль, который будет выводить форму с одним текстовым автозаполняемым полем. В поле будет осуществляться поиск ID ноды по её заголовку. Создание обычного текстового поля Для начала, вспомним как создаётся обычное тек-

январь, 2010

стовое поле, с использованием Forms API. function aut_form() { $form['aut'] = array( '#type'=> 'textfield' ); return $form; }

Теперь нам нужно оформить это в виде модуля, который будет отвечать за генерацию страницы с формой. <?php /** * Реализация хука menu **/ function aut_menu() { $items = array(); $items['aut/form'] = array( 'page callback' => 'aut_formpage', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } /** * Задел под обработку формы **/ function aut_formpage() {

18


Друпалогия #00 return drupal_get_form('aut_form'); }

/** * Непосредственно сама форма **/ function aut_form() { $form['aut'] = array( '#type'=> 'textfield' ); return $form; }

Дело сделано. Теперь необходимо подготовить всё для автозаполнения.

Формирование выборки и атрибут автозаполнения Для того, чтобы превратить обычное поле в «умное», добавим к его атрибутам ещё один - #au���� tocomplete_path. function aut_form() { $form['aut'] = array( '#type'=> 'textfield', '#autocomplete_path'=> 'aut/nodes' ); return $form; }

Значение атрибута — aut/nodes взято произвольно. Здесь можно указать любой другой существующий путь. В нашем случае, создадим обработчик этого пути, добавив нужный код в хук aut_menu и написав функцию самого обработчика. function aut_menu() { $items = array(); $items['aut/form'] = array( 'page callback' => 'aut_formpage', 'access arguments' => array('access

январь, 2010

Обучение content'), 'type' => MENU_CALLBACK, ); $items['aut/nodes'] = array( 'page callback' => 'aut_handler', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; }

В функцию обработчика автоматически передаётся строка, содержащая символы, введённые пользователем. Задача обработчика — выбрать из БД (или другого источника) подходящие данные, сформировать из них массив JavaScript и вывести их посредством print или echo. Схематически, порядок действий такой: формируем массив PHP, затем, с помощью функции Drupal API drupal_to_js() ������������������������������ превращаем его в массив JavaS������ cript и этот массив отдаём. /** * Поиск совпадений с пользовательским вводом **/ function aut_handler($string) { $matches = array(); $result = db_query_range("SELECT nid, title FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%')", $string, 0, 10); while ($node = db_fetch_object($result)) { $matches[$node->nid] = check_plain($node>title); } print drupal_to_js($matches); exit(); }

Обратите внимание на формат генерируемого массива — он имеет значение. То что передаётся как значение элемента — будет показано пользователю в выпадающем списке как предлагаемый вариант. Однако, при клике на одном из вариантов, в текстовое поле будет вставлен ключ элемен-

19


Друпалогия #00 та массива. Т.е. элемент ����������������������������������� $match['55'] = “Прошла �������������������� выставка работ художника” даст ситуацию, когда при вводе символов, скажем, «прош» пользователю в выпадающем списке будет предложена строка “Прошла выставка работ художника”, но при клике на ней, в текстовое поле подставится цифра 55.

В итоге, полный код модуля: <?php /** * Реализация хука menu **/ function aut_menu() { $items = array(); $items['aut/form'] = array( 'page callback' => 'aut_formpage', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items['aut/nodes'] = array( 'page callback' => 'aut_handler', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; }

/** * Поиск совпадений с пользовательским вводом **/ function aut_handler($string) { $matches = array(); $result = db_query_range("SELECT nid, title FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%')", $string, 0, 10); while ($node = db_fetch_object($result)) { $matches[$node->nid] = check_plain($node>title);

январь, 2010

Обучение } print drupal_to_js($matches); exit(); }

/** * Задел под обработку формы **/ function aut_formpage() { return drupal_get_form('aut_form'); }

/** * Непосредственно сама форма **/ function aut_form() { $form['aut'] = array( '#type'=> 'textfield', '#autocomplete_path'=> 'aut/nodes' ); return $form; }

Передача дополнительных параметров Бывают случаи, когда помимо строки с набранными символами в обработчик автозаполнения нужно передать какие-либо дополнительные параметры. Например, когда требуется создать один обработчик на несколько различных ситуаций. Допустим, в одной форме нам нужно предлагать все ноды, а в другой форме — только опубликованные (т.е. нужно передавать ещё и статус выбираемых нод). Это решается с помощью дополнительного параметра (параметров) функции обработчика. В форму добавим дополнительный сегмент GET для пути автозаполнения: function aut_form()

20


Друпалогия #00 { $status = 1; $form['aut'] = array( '#type'=> 'textfield', '#autocomplete_path'=> 'aut/nodes/'.$status ); return $form; }

И тогда функция aut_handler() получит сразу два

январь, 2010

Обучение параметра: function aut_handler($status, $string)

Здесь нужно учесть, что строка с введёнными пользователями символами автоматически дописывается в конец GET ������������������������������� запроса, ��������������������������� поэтому внутри обработчика эти символы будут переданы в последний объявленный параметр. В нашем примере это $string.

21


Друпалогия #00

Обучение

Smarty theme (themplate) engine: альтернатива phptemplate для создания тем Егор Марценюк aka Gor В этой статье я не буду рассматривать причины, плюсы и минусы использования smarty theme (themplate) engine. Я ограничусь инструкцией по установке и приведу примеры применения. Чтение документации по всем возможностям Smarty, а также решение использовать или не использовать, всецело останется за вами.

Инсталяция Вам надо скачать подходящий для вашей версии друпала архив со страницы проекта http://drupal. org/project/smarty . Далее вы должны распаковать архив в директорию (drupal_base)/sites/all/themes/engines/. Должна получится директория (drupal_base)/sites/ all/themes/engines/smarty, в которой будут файлы и папки : • • • • • • • • •

block.tpl box.tpl comment.tpl default.tpl libs node.tpl plugins smarty.engine templates_c

Затем скачайте с http://www.smarty.net/download. php архив Smarty 2.6.25. Я пользуюсь именно этой версией. Если вы хотите попробовать бетаверсию, используйте её на свой страх и риск. В архиве будет директория libs. Содержимое директории libs из этого архива вам необходимо залить в папку (drupal_base)/sites/all/themes/engines/smarty/libs . После того как вы это сделаете, в (drupal_base)/sites/all/themes/engines/smarty должны быть файлы и директории: • Config_File.class.php • debug.tpl

январь, 2010

• internals • plugins • Smarty_Compiler.class.php • Smarty.class.php Убедитесь что ваш вебсервер может писать в директорию (drupal_base)/themes/engines/smarty/ templates_c . На эту директорию должны быть точно такие же права как и на директорию sites/ default/files. Если вы можете залить файлы через друпал в директорию sites/default/files и на директорию (drupal_base)/themes/engines/smarty/ templates_c стоят такие же права, значит всё порядке. Вот и все. Smarty theme (themplate) engine установлен.

Создание своей темы на базе Smarty theme (themplate) engine Для этой статьи я решил взять достаточно простую тему simplex2 и переделать её под Smarty: Качаем тему http://drupal.org/project/simplex2 в директорию themes (обычно это директория sites/ all/themes) и переименовываем директорию в simplex2_smarty, simplex2.info в simplex2_smarty.info и меняем содержимое на name = Simplex (smarty engine clone) description = 2 column, fixed width core = 6.x engine = smarty screenshot = screenshot.png

22


Друпалогия #00 Далее переименовываем все файлы из *.tpl.php в *.tpl и включаем в настройках друпала нашу новую тему - как тему по умолчанию. Получаем белую страницу, в код которой, если заглянуть, увидим что это необработанный PHP код. Теперь осталось преобразовать файлы node.tpl и page.tpl в формат smarty.

Переделывание page.tpl & node.tpl С Smarty theme (themplate) engine в комплекте идет файл README.txt. Открываем этот файл и ищем строку "Template variables available" Это перечень переменных, которые мы можем использовать. Открываем файл page.tpl на редактирование и первое что мы встречаем это: <html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language->language ?>" xml:lang="<?php print $language->language ?>">

В списке доступных переменных есть $language, значит ее можно использовать. После модификации эта строчка приобретает вид: <html xmlns="http://www.w3.org/1999/ xhtml" lang="{$language->language}" xml:lang="{$language->language}">

Обучение Вместо:

?>

<?php if (count($primary_links)) : ?> <div id="topmenu"> <?php print theme('links', $primary_links); </div> <?php endif; ?>

Получится: {if count($primary_links) } <div id="topmenu"> {drupal theme="links" links="$primary_ links"} </div> {/if}

Как по мне, намного читабельнее и лаконичнее. По аналогии меняем все остальные вставки PHPкода в page.tpl и node.tpl.

Заключение Вот собственно и всё. Так как тема состояла всего из двух файлов *.tpl и набора css, изменение не отняло у нас много времени. Теперь у вас готовая тема на базе Simplex и smarty. В следующих статьях я постараюсь рассмотреть более премудрые вещи при использовании Smarty и функций темизации друпал.

Я приведу еще один короткий пример, вариант IF блока и вызов функции темизации из теплейта:

январь, 2010

23


Друпалогия #00

Обучение

Drupal: советы и хитрости Стани́слав Езерский aka Stan Не хватает знаний по программированию? Воспользуйтесь готовыми решениями! Код, представленный ниже, является работоспособным и проверенным на десятке сайтов.

Форматируем текст «Добавлено...»

Откройте page.tpl.php пропишите следующее:

//Форматирование в ноде

<script type="text/javascript"> $().ready(function() { $("#comment-form").validate(); }); </script>

Итак, нам нужно переопределить две функции в template.php. Вот они: function ВАША_ТЕМА_node_submitted($node) { return t('Posted by !username on @date', array( '!username' => theme('username', $node), '@date' => format_date($node->created, 'custom', 'd / M / Y- H:i') )); } //Форматирование в комментарие function ВАША_ТЕМА_comment_submitted($comment) { return t('Posted by !username on @date at about @time.', array( '!username' => theme('username', $comment), '@date' => format_date($comment->timestamp, 'custom', 'd / M / Y- H:i'), '@time' => format_date($comment->timestamp, 'custom', 'H:i') )); }

Проверка заполнения полей с jQuery Мне лично не нравится валидатор Drupal'а и я интегрировал jquery.validate Собственно интегрировать его не проблема. Скачайте плагин. Создайте директорию js в директории вашей темы и поместите туда jquery.validate.min.js. Откройте ВАША_ТЕМА.info и подключите там плагин: scripts[] = js/jquery.validate.min.js

январь, 2010

Если вы хотите проверять заполнены ли поля при регистрации или авторизации, сделайте так: <script type="text/javascript"> $().ready(function() { $("#comment-form, #userregister, #user-login, #user-pass").validate(); }); </script> Всё!

target=_blank

Многие разработчики хотят, чтобы код их страниц успешно проходил валидатор, но почему-то не все знают, как вставить ссылку, открывающуюся в новом окне. Вот собственно решение на jQuery <script type="text/javascript"> $(function(){ $('._blank a').click(function(){ window.open(this.href); return false; }); }); </script>

Класс _blank - это обёртка для ссылки. Пример использования <span class="_blank"><a href="http://www.lipsum. com/">Lorem ipsum</a></span>

24


Друпалогия #00 Или, если контентная часть записи содержит ссылки только на сторонние ресурсы, так <div class="_blank"> <p> <a href="http://www.lipsum.com/">Lorem ipsum</ a> dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p> </div>

Добавление тега span в primary/secondary_links В page.tpl.php <script type="text/javascript"> // Wrap span tags around the anchor text in the primary menu. $(document).ready(function(){ $("#primary li a") .wrapInner("<span>" + "</span>"); }); </script>

и в template.php <?php /** * Override the theme_links function **/ function ВАША_ТЕМА_links($links, $attributes = array('class' => 'links')) { $output = ''; if (count($links) > 0) { $output = '<ul'. drupal_ attributes($attributes) .'>'; $num_links = count($links); $i = 1; foreach ($links as $key => $link) { $class = $key; // Add first, last and active classes to the list of links to help out themers. if ($i == 1) { $class .= ' first'; } if ($i == $num_links) { $class .= ' last';

январь, 2010

Обучение } if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) { $class .= ' active'; } $output .= '<li'. drupal_ attributes(array('class' => $class)) .'>'; // wrap <span>'s around the anchor text if (isset($link['href'])) { $link['title'] = '<span>' . check_ plain($link['title']) . '</span>'; $link['html'] = TRUE; // Pass in $link as $options, they share the same keys. $output .= l($link['title'], $link['href'], $link); } else if (!empty($link['title'])) { // Some links are actually not links, but we wrap these in <span> for adding title and class attributes if (empty($link['html'])) { $link['title'] = check_ plain($link['title']); } $span_attributes = ''; if (isset($link['attributes'])) { $span_attributes = drupal_attributes($ link['attributes']); } $output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>'; } $i++; $output .= "</li>\n"; } $output .= '</ul>'; } return $output; } ?>

Упорядочиваем шаблоны Views Очень неприятно, когда шаблонов в /sites/all/ themes/наша_тема/ становится очень много. Даже до безобразия много. Путаницы конечно не будет, если именно вы делали тему для своего сайта

25


Друпалогия #00 или блога, но большое количество файлов в директории с темой напрягает! Есть решение! Создаём в директории с темой папку views и переносим туда все свои шаблоны вида views-viewfields--gallery-page.tpl.php (или подобные). Переходим в настройки тем (/admin/build/themes/settings) и нажимаем сохранить. Если возникли проблемы, например, вывод ошибок о том, что что-то не найдено, идём в любое созданное представление и нажимаем Rescan (пересканировать), сохраняем представление. Всё. Теперь более-менее порядок.

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

Обучение if ( !is_file($path."/".$file) && ($file !== ".") ) chmod_R($path . "/" . $file, $perm); } } closedir($handle); } $path = $_SERVER["QUERY_STRING"]; if ( $path{0} != "/" ) $path = $_SERVER["DOCUMENT_ROOT"] . "/" . $path; chmod_R($path, 0777); echo $path; ?>

Сохраняем его как chmod.php и копируем файл на сервер, в корневую директорию сайта и запускаем: http://my-site.dom/chmod.php?/home/USER/public_ html/FOLDER, где http://my-site.dom - адрес вашего сайта, /home/USER/public_html/ - путь к вашему сайту, FOLDER - директория, права которой нужно изменить.

Вот решение:

Примечание к статье

Создадим файл с таким содержанием:

Конструкцию $().ready(function() {} стоит заменить на Drupal.behaviors.jf_myBehavior = function (context) {}

<?php function chmod_R($path, $perm) { $handle = opendir($path); while ( false !== ($file = readdir($handle)) ) { if ( ($file !== "..") ) { @chmod($path . "/" . $file, $perm);

январь, 2010

Подробнее об этом можно почитать в описании Javascript, AJAX, AHAH API.

26


Друпалогия #00

Обучение

Ликбез или повышение грамотности новичков Виктор Степаньков aka RxB Каждый день в русскоязычном сообществе задаются одни и те же вопросы. Каждый день, новички наступают на одни и те же грабли, набивают шишки и идут к следующему мирно лежащему инструменту. В этой статье я рассмотрю наиболее популярные ошибки, начиная с этапа установки движка и заканчивая выходом сайта в свет. Вопрос: Как поставить свой дизайн на Drupal?

вить в текст запрос.

Ответ: Под этим вопросом чаще всего понимается вопрос о разработке темы для Друпала, для этого, как минимум, необходимо владеть HTML + CSS + немного php, или же логическое мышление. Если не требуется супер-ультра-дизайн после которого бы Артемий Лебедев сказал, что он не тру и уходит в грузчики, то можно воспользоваться программой Artisteer, которая позволяет визуально наваять темплейт и сохранить его как тему для Drupal

Так же не исключён вариант, когда в момент изучения системы ограничения доступа к сайту (admin/ user/rules), было создано правило ограничивающее доступ, для самого же ученика. В данном случае в таблице access необходимо найти нужное правило и удалить его, либо выполнить SQLзапрос:

Вопросы: 1. Сам себя забанил 2. Сам себя заблокировал 3. Удалил всех пользователей, включая админа. Как войти? Ответ: Частый вопрос, задаётся, как правило, после того как будущий друпал-гуру игрался с системой управления пользователями, тут собственно возможны два варианта: TRUNCATE TABLE `users`; INSERT INTO `users` VALUES (0, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, NULL, '', '', '', NULL); INSERT INTO `users` VALUES (1, 'admin', MD5('test'), 'admin@admin.admin', 0, 0, 0, '', '', 1240608324, 1240608729, 1240608342, 1, NULL, '', '', 'admin@admin.admin', 'a:0:{}');

Данные SQL-запросы удалят всех пользователей с сайта и добавят двух пользователей, анонима и админа с логином admin, паролем test и админским е-майлом admin@admin.admin. Естественно, после проведения данной операции следует сменить данные на корректные, либо сразу их подста-

январь, 2010

TRUNCATE TABLE `access`;

Вопросы: 1. Как истребить вирусы на сайте 2. Захожу на сайт, антивирус ругается! 3. Гугл повесил табличку, что сайт может нанести вред вашему компьютеру! Ответ: Это говорит о том, что вами было словлено вредоносное ПО называемое iframe’ мами, т.е. вы посетили сайт сомнительного или не очень содержания, который вычислил уязвимости в вашем браузере и через него заразил ваш компьютер. Ну а далее, ваши пароли от FTP ушли к злому хакеру и ваш сайт заразили, обычно это выражается в том, что в index’ных файлов, в js-файлах, в CSS, появляются вставки непонятного javascript-кода, или же кода вида: <iframe src="http://dnlfnkwh.cn/enter. php?refid=lklshfhsf&track=767" frameborder="0" width="1" height="1"></iframe>

Ну а далее процесс повторяется, посетитель заходит на ваш сайт, его компьютер заражается, на http://dnlfnkwh.cn стоит «атакующее ПО», а что произойдёт с заражённым пользователем можно только гадать. Обычно такие сайты являются по-

27


Друпалогия #00 средниками и продают так называемые «загрузки», т.е у хакера, владельца http://dnlfnkwh.cn, другой хакер покупает «10кил загрузок для USA», это означает, что владелец http://dnlfnkwh.cn продаёт 10000 заражённых американцев, у которых может быть воруют деньги, может используют для накрутки счётчиков, а может вообще для формирования botnet’а. Иногда такое возможно в случае неверно выставленных форматов ввода, в частности когда анониму или авторизованному пользователю предоставлен формат ввода «Full HTML», вредоносный код приводить не буду, поверьте на слово. Если ваш сайт всё-таки проайфреймили, то порядок действий такой: 1. Очистить и больше не оставлять, сохраненные пароли в FTP-менеджерах и браузере 2. Поменять пароли на фтп с ЗАВЕДОМО ЧИСТОГО компьютера 3. Вычистить вредоносный код с php-файлов, для начала перезалить тему и index.php, в особо тяжёлых случаях перезалить дистрибутив движка и модулей. Вопрос: Ввожу данные коннекта к БД, нажимаю сохранить, страница перезагружается!!! Ответ: 1. "Copy default.settings.php "! 2. "Rename default.settings.php" 3. "Move default.settings.php " В начале установки, инсталлятор Drupal’а просил скопировать default.settings.php в settings.php, вы переименовали, что является ошибкой. Не нужно думать, что вы всё знаете и всё умеете, нужно следовать инструкциям. Вопрос: Перенос сайта на «боевой» хостинг Ответ: • Не надо устанавливать друпал на новом хосте • Не стоит использовать phpMyAdmin для переноса дампа базы данных

январь, 2010

• Не надо забывать изменять параметры коннекта к базе данных в файле sites/all/settings.php на нужные, хост, имя пользователя, пароль, тип базы данных можно уточнить у хостера. • Не стоит полагаться только на свою интуицию. Т.е. весь процесс переноса сводится к такому набору инструкций: 1. На локальном компьютере очистить таблицы cache_* 2. Сделать дамп базы данных, как его сделать, написано ниже 3. Скопировать файлы движка на хост 4. Развернуть дамп базы данных 5. Прописать новые параметры доступа в sites/all/ settings.php Не исключено, что потребуется выставить правильные права доступа на директорию files и на файл settings.php, но это чаще всего зависит от хостера. Вопросы: 1. Лишние символы перед контентом страницы. 2. Постоянно вставляется непонятный тег в шаблон перед выводом блока. 3. Непонятный символ в начале страницы Ответ: Как правило появляется из-за того, что какой-то из файлов сохранён в кодировке отличной от UTF without BOM. Особое внимание на слово «without», т.е. БЕЗ BOM-сигнатуры. Вспоминайте, что редактировали перед появлением данной ошибки и пересохраняйте эти файлы в верной для Друпала кодировке. Вопросы: • Перевёл сайт в оффлайн режим. Как зайти? • Отключил блок логина в админке, как зайти? • Установил сайт, поставил на offline-режим и вышел... Теперь никак не зайти в админку. Ответ: Второй способ авторизации, кроме как через форму авторизации состоит в том, чтобы пройти по пути: http://domain.zone/?q=user

28


Друпалогия #00 Обычно советуют просто путь /user, но иногда бывают ситуации, когда чистые ссылки отключены. Вопрос: 1. Maximum execution time of 30 seconds exceeded in… 2. Открывается белый экран при попытке открыть страницу управления 3. Вместо сайта лицезрею белую страницу 4. Сайт пишет «500 error» Ответ: Смотрим WSOD Вопрос: Создал блок и вставил в него php-код, включил блок и сайт не работает. Ответ: 1. Открываем phpMyAdmin\консоль mysql\db Forge studio\etc 2. Заходим в базу данных, куда установлен друпал 3. Идём в таблицу blocks 4. Находим проблемный блок 5. Меняем значение поля статус с 1 на 0 Вопрос: Как сделать дамп базы данных? Ответ: Самый простой способ используя утилиту Sypex Dumper (http://sypex.net/) Если есть доступ к SSH и хотя бы скромные познания консоли, то mysqldump --opt -uлогин -pпароль -hхост -Dбаза | gzip -c имя_архива.gz Курсив следует заменить на соответствующие данные для доступа к БД. Архивированный дамп будет сохранён в текущую директорию

Вопрос: WSOD Ответ: WSOD – White Screen Of Death. Объединяет под собой огромную кучу причин и ошибок, начиная от файлов сохранённых в неверной кодировке и заканчивая нехваткой жалкого килобайта оперативной памяти. Универсальных советов давать не буду, лучше обращаться на форум. При обращении, желательно указать: 1. Версию Drupal и установленные модули 2. Вывод phpinfo() 3. Логи веб-сервера (ошибок, error log), их можно попросить у хостера 4. Какие действия предпринимали и после чего начала появляться ошибка. Так же в диагностике поможет модуль wsod. Неплохо рассказано о диагностике на странице http://drupal.org/node/158043

Полезные ссылки по теме ликбеза 1. Google Translate - http://translate.google.com/. Онлайн-переводчик, поможет избежать многих глупых вопрос из-за незнания английского, да и большинства других языков 2. Drupal modules - http://drupalmodules.com/. Сайт с удобным поиском модулей, описаниями и статистикой. 3. Незаслуженно игнорируемая ссылка «Документация. http://www.drupal.ru/book. Есть ответы на большинство вопросов

Благодарности. В составлении данного мини-ликбеза были использованы материалы с http://drupal.org, http:// drupal.ru, может быть даже и с других сайтов, конкретно чьи не помню, могу назвать только двух человек: Axel – http://drupal.ru neochief – http://drupaldance.com/

январь, 2010

29


Друпалогия #00

Локализация

Локализация и перевод в Drupal Василий Пинчук aka PVasili CMF������������������������������������������������������������������������������������������ Drupal ����������������������������������������������������������������������������������������� ���������������������������������������������������������������������������������� разрабатывалась, продолжает развиваться и поддерживаться многоголосым международным сообществом, которое разговаривает на огромном количестве языков. Благодаря использованию в своей основе набора символов кодировки UTF-8, и программным средствам, система поддерживает все существующие письменные языки, варианты с письмом справа налево (арабские языки, иврит), иероглифы (Япония, Китай). При создании и редактировании материалов вы можете использовать абсолютно любой язык, символы которого входят в набор UTF-8. Интерфейс, для взаимодействия с пользователем содержит набор слов, фраз и предложений, которые отображаются пользователю. Все эти фразы, при выводе пропускаются через функцию t() [пример: t('Hello world');] (н���������������������� ������������������������ азвание �������������� функции������� сокра������ щено��������������������������������������������� от������������������������������������������ �������������������������������������������� слова translation из-�������������������� за������������������ частоты���������� ����������������� использо��������� вания).�������������������������������������� Поми��������������������������������� мо работы над переводом эта функция, так же обрабатывает вставку значений заполнителя внутри строк, что важно с точки зрения безопасности (значения, вводимые пользователем [пример: t('Hello %name',array('%name'=>'Ma sha'));]). Весь процесс трансляции интерфейса со стороны системы сводится к попросту замена одних фраз и выражений на другие (переведённые). Хорошо это или нет, но Drupal хранит данные для перевода, и переведённые строки в 2 таблицах базы данных: locales_source и locales_target соответственно. В первую из них собираются все строки из активизируемых модулей, тем, а так же кода PHP в блоках(сниппеты) и другие, использующие функцию t(). Для корректной работы локализации необходимо включить её поддержку в системе и заполнить вторую таблицу строками перевода. Если посетители сайта знают английский, и им не нужна локализация, дальнейшие описания можно пропустит, если же сайт нуждается в локализации, то дальнейшая информация должна быть полезна.

январь, 2010

Настройка локализации Исходя из философии, заложенной в Drupal — предоставлять функциональность только при необходимости: по умолчанию, язык всего интерфейса — английский. Эта концепция позволяет добавить поддержку нескольких языков на ваш сайт путем активизации соответствующих модулей. Так, для смены языка интерфейса достаточно включить модуль locale из ���������������������������� основной поставки (перейдя по адресу /admin/build/modules). Е�������������� сли Drupal ���������� ��� инсталлируется с использованием языка, отличного английского, то этот модуль будет активизирован ещё на этапе инсталляции. Далее, необходимо выбрать язык (или несколько языков), на который будет переводится интерфейс (по адресу /admin/settings/language/add). Здесь же, на вкладках, можно выбрать язык (/admin/settings/ language), используемый по умолчанию в интерфейсе сайта и способ переключения языков (/ admin/settings/language/configure), если их используется несколько, в зависимости от префикса пути, домена и других параметров.

Варианты перевода Ручной После предварительной настройки, выполненной в предыдущем шаге, система готова к работе с ис-

30


Друпалогия #00 пользованием в интерфейсе выбранных языков. По умолчанию, все вновь инсталлируемые модули и темы будут пытаться найти и загрузить перевод на установленный в системе язык. При этом система будет пытаться обнаружить файл с переводом в под папке translations соответствующего модуля (для �������������������������������������������� Drupal 5 ����������������������������������� версии для этой цели существует отдельный модуль Autolocale). Самый простой метод — это ручной перевод слов и фраз. Довольно часто бывает необходимо поправить или изменить 1-2 строки в существующем переводе «под себя», для этого достаточно (по адресу /admin/build/translate/search) ввести нужное слово или фразу, и в найденных местах изменить её на нужную, для соответствующих языков (если на сайте используется больше одного дополнительного языка). Способ хорош, но не всегда эффективен. Модуль Localization client позволяет быстро заменить все текстовые строки интерфейса для данной страницы, в удобном JS интерфейсе.

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

январь, 2010

Локализация используя инструментарий для работы на локальном компьютере. Этот вариант, может оказаться более предпочтительным. Он позволяет создавать, хранить и обмениваться файлами перевода, в формате PO.���������������������������������� ������������������������������������� В качестве редактора можно порекомендовать свободно распространяемый кроссплатформенный продукт Poedit. Этот редактор позволяет использовать так называемую TM (память переводов) и пытается перевести фразы, с учётом уже накопленной информации о переводах.

Для получения строк (����������������������� PO файла �������������������� для работы of��� fline) из уже установленных модулей тем и ядра системы существет модуь Translation template extractor. После ������������������������������������� его установки на странице с переводами строк (по адресу /admin/build/translate/ extract) у вас появится возможность выбрать и импортировать строки из модуля в соответствующий PO файл. Там же, на вкладе (по адресу /admin/ build/translate/import) можно ������������������������� импортировать готовый результат локальной работы. Необходимо обратить внимание на язык в который будет загружаться файл перевода и вариант с заменой строки или нет. Эта страница может быть полезна, при наличии ошибок в автоматически импортируемом переводе, который идёт с модулем. Необходимо обратить внимание на использование правильной плюральной формы (������������ ������������� форма множественных числительный). Для русского языка она выглядит так: nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?( 0):(((((n%10)>=2)&&((n%10)<=4))&&(((n%100)<10)||( (n%100)>=20)))?(1):2))

31


Друпалогия #00

Локализация

Использование сервера локализации Постоянно растущее количество разрабатываемых модулей и тем, а так же большое количество и разрозненность вариантов PO файлов грозило перерасти в новый Вавилон. Эта ситуация натолкнула Gábor Hojtsy на создание модуля Localization server. Модуль является хранилищем для исходных строки и строк перевода всех модулей и тем. Переводы возможно хранить и вести для нескольких языков. При этом, все вновь добавляемые строки, из новых версий и автоматически будут получать уже существующие переводы. Сервер локализации работает в двух режимах: как сервер для отдачи готовых переводов, и как интерфейс для удобного локального или удаленного перевода строк модулей и тем. Для получения PO файла перевода достаточно выбрать соответствующий язык, версию и формат файлов. Полученный перевод можно импортировать на работающий сайт. Если необходимо обновлять много модулей, то можно воспользоваться модулем Live Translation, после установки которого (по адресу /admin/ reports/live-translation) можно в любой установке проверить % перевода модулей, установленных в этой систем и перевести его нужные на текущий язык. (Обратите внимание, что для перевода на русский, необходимо указать (на странице /admin/ settings/live-translation) в качестве сервера http:// drupaler.ru).

Переводы на сервере осуществляются коллективным сообществом, и если кроме потребления возникает желание помочь сообществу — необходимо всего лишь 2 простых вещи: желание и наличие учётной записи на http://drupaler.ru. При наличии регистрации, со страницы http://drupaler.ru/groups необходимо отправить заявку на вступление в соответствующую языковую группу, в которую планируется добавлять переводы. После одобрения — будет доступен удобный ��������������������� WEB������������������ интерфейс для добавления переводов, одобрения, модерирования и импорта прямо с сервера локализации. Сервер локализации полностью поддерживает шаринг-передачу ваших переводов из локальной установки Drupal. Мы можете, работая с Localization client автоматически отправлять переведённые строки на сервер переводов. Для настройки работы необходимо выполнить 4 простых шага: • Скачать и включить модуль Localization client • Указать на своем сайте сервер, с которым будем работать (http://drupaler.ru) (на странице / admin/settings/language/configure/l10n_client).

январь, 2010

32


Друпалогия #00

• Получить ключ (Localization Server API key), для разрешения получения переводов сервером. Открыть профиль (user/ваш_ник/edit) на сайте и перейти по ссылке вида http://drupaler. ru?q=translate/remote/userkey/xxxxxxxxxxxxxxxxx. Получив код, введите его в соответствующее поле. (Необходимо иметь учётную запись на сервере переводов и быть в группе языка, в который вы собираетесь добавлять переводы).

Локализация

• Далее, кликнув по кнопке переводить текст, как и при обычной работы с Localization client . При сохранении каждой строки — строки автоматически будет добавляться на сервер переводов. (если всё було сделалано правильно и встретилась ошибка, при отправке — попробуйте добавить патч из: http://drupal.org/ node/323917#comment-1682844) Надеемся, что с ростом вашего мастерства и знаний в Drupal, ����������������������������������������� ��������������������������������� вы сможете помочь всем членам сообщества в деле — полезном для всех.

январь, 2010

33


Друпалогия #00

Модули

Веб-картография в Drupal Даниил Бейлинсон aka integral Этой статьей я хотел бы открыть рубрику связанную с веб-картографией в Друпале и не только. Сегодня я попробую дать поверхностный обзор основных модулей веб-картографии в Друпале, а так же некоторых ресурсов связанных с ними. Мы будем говорить о способах вывода на карту множества материалов, таким образом модули позволяющие вставить в материал какую-ту конкретную карту остаются в стороне. свой интерфейс прикладного программирования Глобально подходы основных модулей этого типа для того чтобы другие пакеты могли��������������� работать �������������� с���� со��� схожи. Несколько модулей работают в связке: бранными им данными и использовать возможноодин позволяет фиксировать географические координаты вместе с сопутствующей информацией и сти геокодирования. привязывать их к определенному типу материала (узлу, термину таксономии, пользователю), другой выводит эту информацию на карту в точке с заданными координатами. Давайте рассмотрим несколько таких модулей.

Mapedelic (Location + GMap) Mapedelic – маленький, но разрастающийся набор модулей от Chicago Technology Cooperative, позволяющий использовать Друпал для ряда разных задач веб-картографии и взаимодействовать с другими геосервисами.������������������������������� Чаще ������������������������������ всего ������������������� Mapedelic���������� используют именно для вывода различных материалов сайта на карту. В набор входят три пакета модулей: Location, GMap Module и GMap Addons.

Location Э��������������������������������������������� тот пакет модулей позволяет связывать географические локации с узлами Друпала, например c людьми, местами и прочим контентом.������������ Т���������� акже Loca����� tion ������������������������������������������ дает возможность администраторам сайта собирать адреса и геокодировать их (то есть переводить адреса в координаты) с последующей привязкой к тем же узлам или пользователям. Полученная информация автоматически используется для генерации GeoRSS данных ���������������� внутри уже существующих RSS лент. Модуль также предоставляет

январь, 2010

В пакет входит восемь модулей: Location: основной ������������������������������������ модуль со своим API, предоставляющий способ записи адресов и геокодирования, позволяет прекреплять локации к узлам. В каждой ноде собирается указанное количество локаций в виде набора полей: Location name, Street location, Additional, City, State/Province, Postal code, Country, Province name, Country name, ссылка на карту, координаты - каждое из которых может быть выключено для указанного типа контента. User Locations: позволяет связывать каждого пользователя с определенной точкой на карте. Location Phone and Location Fax: эти два модуля добавляют телефон и факс в дополнение к вышеуказанным полям. Location Search: интегрирует ������������������������������ поиск схожих локаций в модуль поиска Друпала. Location CCK: предоставялет поля для модуля Сontent Construction Kit (CCK) и ������������������� возможность собирать данные именно через них. Location Generate: генерирует локации для тестирования модуля (интеграция с пакетом модулей Devel). Location Add Another: п����������������������� озволяет быстро прикре-

34


Друпалогия #00

пить новые локации к узлу не редактируя его.

GMap Module Модуль ������������������������������������ GMap предоставляет ������������������������������� доступ через Друпал к API карт Google. Он итегрирован с модулем Location��������������������������������������� и позволяет вводидить координаты локаций щелчком на карте от Google взамен ручного ввода который предоставляет модуль Location поумолчанию. Также модуль предоставляет две карты, на которые выводяться все узлы сайта и все пользователи сайта. GMap �������������������������� Module �������������� может быть использован для создания интерактивных карт с различными маркерами, различным контентом во всплывающих окнах и прочими возможностями. И самое важное - модуль предоставляет displayплагин к Views��������������������������������� �������������������������������������� , который дает пользователям возможность увидеть результат представления прямо на карте Google! Вы указываете плагину какие из полей содержат географические координаты, а вся остальная информация привязывается к указанной точке на карте. В пакет входит четыре модуля: • GMap: предоставляет GMap API, интеграцию с модулями Views, Location и макросами Google Maps. • GMap Location: предоставляет карту со всеми узлами сайта и и карту со всеми пользователями сайта. • GMap Taxonomy: п�������������������������� озволяет использовать различные маркеры в зависимости от таксономии узла. • GMap Macro Builder: предоставляет ���������������������� графический интерфейс для создания макросов (текстовой настройки капризного GMaps). Для того чтобы воспользоваться модулем, Вам нужно преобрести бесплатный Google Maps API key. Чего же боле?

январь, 2010

Модули Мы умеем привязывать координаты к материалам, умеем выводить эти материалы через Views прямо на карту гугл, что еще может понадобиться? Собственно популярность связки модулей Location+GMap Module+Views как раз и говорит о том, что в большинстве случаев ничего больше и не нужно, но мы пойдем дальше. Как насчет того чтобы менять карты? В самом деле Google Maps предоставляет нам всего три слоя, что если мы хотим воспользоваться другими картами, другими сервисами предоставляющими те же услуги или быть может мы хотим нарисовать карту сами? И выделять вовсе не точки на карте, а области? Все это возможно.

Mapstraction

Проект Mapstraction – это библиотека предоставляющая общий API для многих вебс������������������������������������������������ ервисов картографии, таких как������������������ Google Maps, Virtual Earth, и Yahoo!, к��������������������������� аждый их которых предоставляет свой �������������������������������������� API для ���������������������������������� интеграции�������������������� . Р����������������� азный API ����������� подраз������� умевает под собой, что при добавлении картографических возможностней на сайт Вам приходится начинать с выбора сервиса карт. Проблема в том, что если Вы выбрали сервис, то сменить его будет непросто – еще бы, ведь для того чтобы использовать новый ���������������������������������� API������������������������������� придется переписать весь интеграционный код! Тут-то напомощь нам и приходит Mapstraction! Ф��������������������������������� ундамент его �������������������� API позволяет ���������������� разработчикам переключаться между разными сервисами не меняя кода! Модуль Mapstraction разработанный есть ни что иное как display-����������������������������� плагин для Views������������� ������������������ , который позволяет выбрать поля с координатами и переключатья на лету между сервисами веб-картографии. Views������������������������������������������ выведет карту с выбранными узлами на карте в качестве точек. Если Вам захочеться поменять сервис, то достаточно всего лишь поменять настройки представления. Сервис смениться, а точки остануться на том же месте что и раньше!

35


Друпалогия #00 На данный момент Mapstarction подерживает 11 геосервисов: • Google Maps • Map24 • MultiMap • OpenSpace • ViaMichelin • Yahoo Maps • MapQuest • Microsoft Virtual Earth • OpenLayers • FreeEarth Также поддерживается загрузка кастомных тайлов карт предоставляемых сервисом CloudMade. Вы можете создать свой стиль карт в редакторе������� CloudMade и���������������������������������������� ли выбрать какой-нибудь из уже существующих нескольких тысяч и����������������������� ������������������������ указать ID �������������� стиля ����������� в настройках представления.

Модули В пакет входит три модуля: • Geo: API предоставляющий доступ к базе данных и функциям запросов для других модулей. • Geo Field: п������������������������������� редоставляет поле ввода географических данных в форме точек, линий и многоугольников для любого типа материала. Это позволит вам зафиксировать геоинформацию вводимую пользователями. • Geo Data: В�������������������������������� ы можете скачать Shape файлы содержащие геометрическую информацию и импортировать в свой сайт. После того как это будет сделано вы сможете создать выпадающее поле CCK, которое будет ссылаться на эту информацию. К примеру Вы можете импортировать границы регионов и позволить пользователям выбирать регион из списка.

Geo

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

Пакет модулей Geo – следующее ������������������������� поколение модулей веб-картографии в Друпале, как и Location они предосталяют возможность регистрировать координаты точек, но кроме этого поддерживаются линии и многоугольники!

Д��������������������������������������������� ля того чтобы воспользоваться API������������ ��������������� Geo ����������� вам ������� понадобится версия MySQL ������������������������������ н����������������������� е меньше �������������� 4.1, и�������� ли������ PostgreSQL c расширением PostGIS. Ну и конечно для того чтобы сделать что-нибудь осмысленное вам понадобяться установленные модули CCK и Views.

Чем это полезно? Дело в том, что локации - это не просто адреса или точки на карте. Например, у мельницы в поле адреса нет, но ее координаты тоже нужно регистрировать и отображать на карте. И такие данные как автомобильная трасса, граница города или маршрут полета тоже где-то хранятся и должны иметь свои критерии поиска отличные от простой точки на карте. К счастью, существует открытый стандарт Simple Features для выражения этого типа данных и модуль ������������������� Geo���������������� выгодно отличается своей просторанственно-ориентированной базой данных – для хранения используются PostGIS и MySQL Spatial что приводит к более быстрым и содержательным запросам.

январь, 2010

Так как PostGIS �������������������������������������� предоставляет ������������������������������ куда лучшую поддержку для пространственных возможностей, то этот вариант базы данных предпочтительнее для всего, чему необходима точность и настраиваемость. С другой стороны расщирение MySQL ���������� spatial включено в MySQL по-умоланию, что позволяет куда быстрее начать работу. Стоит еще упомянуть модуль Geocode, позволяющий геокодировать данные, в том числе линии и многоугольники! Модуль так же предоставляет свой виджет для �������������������������������� Geo Field����������������������� , который позволяет собирать информацию из других полей, например, индекс, город или даже картинка с прикрепленными к ней географическими данными.

36


Друпалогия #00 OpenLayers OpenLayers – OpenSource библиотека, написанная на JavaScript, предназначенная для создания карт на основе программного интерфейса (API), подобного GoogleMap API или MSN Virtual Earth API. Библиотека включает в себя компоненты из JavaScript-библиотек Rico и Prototype JavaScript Framework. OpenLayers позволяет очень быстро и легко создать веб-интерфейс для отображения картографических материалов, представленных в различных форматах и расположенных на различных серверах. Благодаря OpenLayers разработчик имеет возможность создать, к примеру, собственную карту, включающую слои, предоставляемые WMS (и WFS) серверами, такими как Mapserver, ArcIMS или Geoserver, и данными картографических сервисов Google Библиотека является разработкой с открытым исходным кодом и разрабатывается при спонсорской поддержке проекта MetaCarta, который использует OpenLayers в своих разработках. Тем не менее, OpenLayers является независимым свободно распространяемым продуктом. Проект OpenLayers в Drupal – это набор модулей интегрирующих OpenLayers JS библиотеку в Dru���� pal�������������������������������������������� .������������������������������������������� Модули ������������������������������������������ предоставляют возможность пользователям создавать свои динамические и уникальные карты на сайте. Зачем?

Модули части пакета воедино. Пакет OpenLayers имеет очень гибкую архитектуру, в центре которой находится этот модуль, остальные модули добавлюят свой функционал через этот API. OpenLayers Preset UI Э��������������������������������������������� тот модуль позволит создать и сохранить заготовку карты, которая может быть использована, например, для ввода данных через CCK�������� ����������� или вывода через Views. Эти заготовки также могут быть созданы непосредственно кодом, храниться в базе данных и быть интегрированы с Features. OpenLayers Layers П������������������������������������������� редостаялет широкие возможности по добавлению слоев на вашу карту������������������������ . В��������������������� ы можете добавить базовый слой Google, Yahoo, Microsoft, Cloudmade, и OpenStreetMap. Т����������������������������� ак же вы можете добавить����� дан���� ные с сервера картографии (WMS), с����������� ервера географических возможностей (WFS), и KML ленты к���������������������������������������������� ак базовый слой карты������������������������� или��������������������� ������������������������ д������������������� ополнительный������ . Так���� же он может отображать данные импортированные из shape-файлов с помощью модуля Geo Data. OpenLayers Behaviors Дает ���������������������������������������� возможность использовать специальные режимы для воспроизведения и редакции карт. На данный момент позволяет редактировать геометрические фигуры, тултипы, всплывающие окна, перемещять точки, центрировать карту и открывать ее в режиме полного экрана. OpenLayers CCK

OpenLayers предоставляет гибкость кода open source ���������������������������������������� и возможность воспроизводить большое количество форматов данных GIS. Также эти модули предоставляют возможность ввода пространственных данных!

OpenLayers CCK ������������������������������ добавляет карту для ввода геопространственных данных модуля Geo или данных в формате WKT, таким образом ввод координат становится естественным и приятным занятием.

В пакет входят 7 модулей:

OpenLayers Views

OpenLayers API

Воссоединяет все типы геоданных Drupal, будь они из модулей Location или Geo, из кастомных пар

OpenLayers API – модуль, который склеивает все

январь, 2010

37


Друпалогия #00 полей широты/долготы или записаны в формате WKT. Все они могут быть спроецированы на карту через специальный Views плагин. OpenLayers Filters Предоставляет фильтр для вставки карт в текст. Используя примерно такой синтаксис [openlayers имя_заготовки], вы можете сгенерировать карту прямо в контенте. Также модуль ��������������������������������������� �������������������������������� OpenLayers���������������������� предоставляет следующие дополнительные возможности: Интеграция с модулями Features, Module Builder, Advanced Help (здесь куча документации) и Domain (позволяет настроить openlayers для каждого домена отдельно). А так же базовые возможности SimpleTests!

январь, 2010

Модули MapBox MapBox – разработка фирмы Development Seed – по сути дела н�������������������������� абор ��������������������� OpenSource����������� инструментов в помощь созданию красивых кастомных карт в вычислительном облаке Amazon. Проект предоставляет утилиту TileMill, с����������������� озданную для рендеринга карт в сочетании с любым набор данных будь-тo открытых или из вашего личного архива. MapBox также имеет общедоступные хранилища данных, такие как OpenStreetMap Planet, доступные внутри облака Amazon. Модуль MapBox для друпала предоставляет свой слой включающий тайлы MapBox для модулей OpenLayers и GMap.

Таким образом, связка Geo + OpenLayers куда мощнее чем Location + GMap Module. Конечно она не всегда оправдана, но ее возможности заметно шире. Пакеты Geo �������������������������������� и ���������������������������� OpenLayers �������������������������� ��������������� невероятно гибкие и предоставляют огромный функционал, который мы надеюсь рассмотрим подробнее в следующем номере журнала.

38


Друпалогия #00

Хостинг

Интервью с представителем компании IT-Patrol Стани́слав Езерский aka Stan Существует огромное количество хостинг-провайдеров, предоставляющих услуги по размещению сайтов. Но сайту, сделанному на Drupal, зачастую нужно немного больше, чем сайту, сделанного на обычной CMS. Это и ресурсоёмкость, скорость работы, поддержка пользователей. Мы побеседовали с представителем компании IT-Patrol, Егором Марценюком aka Gor, который ответил на наши скромные вопросы. Сейчас на рынке хостинга - куча провайдеров, площадки которых позволяют полноценно использовать Drupal. Почему и чем вы лучше?

ших разработок- патчей, для портирования релиза под нашу платформу.

Gor: В первую очередь, мало кто из конкурентов может похвастаться такой же скоростью работы сайтов на базе CMS��������������������������� /CMF Drupal. �������������� Во вторую очередь, в случае проблем с сайтом - мы подсказываем источник проблемы. Как минимум какой модуль или какой запрос (часто это касается не оптимальных запросов views). В третью очередь - человеческий подход к клиенту. Правда иногда приходится отказывать в хостинге клиентам, которые предпочитают хамский способ общения. Есть еще много разных мелочей, но вышеперечисленные пункты – основные.

Где находится дата-центр?

Что вы можете предложить потенциальным клиентам, чем вы их, на ваш взгляд, можете заинтересовать? Gor: Быстрой работой сайтов на CMS Drupal. Это краеугольный камень всего проекта. К сожалению, пока что в ущерб удобству, но мы двигаемся в этом направлении. Недавно мы запустили еще более ускоренный вариант хостинга , где не надо даже ставить CMS Drupal. Основными преимуществами нового варианта являются конечно же скорость работы сайтов. Но изюминкой предложения является автообновление всех contrib модулей ежедневно и обновление ядра - в течении пяти дней после выхода новой версии ветки 6.х. Задержка связана с необходимостью применения на-

январь, 2010

Gor: Когда мы только начинали, было перепробовано много дата-центров: к сожалению, часто по вине дата-центра были проблемы с доступностью к серверам. Методом проб и ошибок было принято решение использовать не один ДЦ, а сразу несколько, потому на сейчас сервера размещены в городах по всему миру: Санкт-Петербург(Россия), Монреаль (Канада); Амстердам (Голландия), Глочестер (Великобритания), Франкфурт (Германия). Полную информацию о серверах и их географическом расположении можно узнать на страницах нашего сайта. Каков аптайм серверов? Gor: Согласно оценки сервиса host-tracker - аптайм серверов колеблется между 99.35% и 99.99%. Пользователи могут получить эту информацию в любой момент времени на странице серверов и в РобинПанели, раздел "Пользователи". Можете рассказать о технической стороне (расписать какое железо стоит, сколько предоставлено памяти, тип ОС, apache или nginx)?

39


Друпалогия #00 Gor: Железо стоит разное. Сейчас используется 5 серверов разной конфигурации и только один перечень конфигураций займет много места. Лучше посетите http://it-patrol.ru/drupal_hosting/ техническая-информация, там вы сможете найти полную техническую информацию на каждый сервер, перечень используемого ПО и ОС. Коротко могу сказать, что на всех сервизах используется Linux CentOS 5.x последней версии, с NGINX +APACHE + PHP 5 версии. Как быстро вы обеспечиваете поддержку пользователям? Gor: Наблюдение за серверами в автоматическом режиме - круглосуточно и все критические вопросы решаются максимально быстро. Вопросы клиентов решаются в основном между 16 и 24 по Москве . Возможен ли MoneyBack (возврат денег), если пользователю что-то не понравилось в работе, обслуживании или технической поддержке? Gor: Нет, данная возможность не предоставляется. Часто ли к вам уходят с других площадок?

Хостинг Предоставляете ли вы бесплатный хостинг интересным проектам? Gor: Иногда такое делаем, но не часто. Есть ли у вас свои механизмы защиты от DdoS-атак? Gor: Да есть. В этой сфере я лично приобрел достаточно много опыта, работая в других компаниях. Так что с этим проблем у нас нет. Считаете ли вы, что у вас есть отрицательные стороны? Расскажите о них Gor: Я бы это назвал недоработками, так как все эти "пробелы" будут со временем закрыты. • РОбинПанель - еще не так удобна, как должна быть. Не хватает некоторых некритичных функций. • Не круглосуточная поддержка клиентов. На сейчас вопросы клиентов решаются в основном между 16 и 24 по Москве. • Не хватает Документации по использованию хостинга.

Gor: Такой статистики у нас нет. Но основная масса клиентов, уже с готовыми сайтами. Так что откуда-то они все-таки уходят.

Могут ли расчитывать ваши клиенты на юридически грамотное оформление договоров на услуги, например, вы высылаете "Договор на размещение (colocation) и аренду (dedicated) сервера"?

Считаете ли вы себя строгим хостером по отношению к пользователям: есть ли цензура на web-проекты?

Gor: На текущий момент юридического оформления договора на услуги не осуществляется. Так что, ответ отрицательный.

Gor: Да у нас есть строгие ограничения. Запрещены ресурсы которые нарушают авторские права, распространяющие спам, порнографию. А также разные финансовые пирамиды, HYIP проекты.

январь, 2010

40


Друпалогия #00

Не Drupal

jQuery 1.4: 15 новых возможностей Василий Котов aka basilkot /перевод оригинальной статьи 14 января появился на свет jQuery 1.4. Этот релиз содержит множество новых возможностей и улучшений. В этой статье рассматриваются те, которые вы, возможно, найдёте самыми полезными.

1. Передача атрибутов jQuery(...) Раньше, до версии 1.4, jQuery поддерживал добавление атрибутов к элементам коллекции с помощью удобного метода attr, который принимал в качестве параметров или имя атрибута и его значение, или объект, определяющий сразу несколько атрибутов. В jQuery 1.4 появилась возможность передачи атрибутов, как второй аргумент при создании элемента. Допустим вам необходимо создать гиперссылку с несколькими атрибутами. Используя версию 1.4 это делается таким образом: jQuery('<a/>', { id: 'foo', href: 'http://google.com', title: 'Become a Googler', rel: 'external', text: 'Go to Google!' });

Вы, наверное, заметили атрибут text и, возможно, удивились, что он здесь делает, ведь у ссылок нет такого атрибута! Дело в том, что jQuery 1.4 использует свои собственные методы для их обработки. Таким образом, встретив атрибут text, jQuery вызывает функцию .text() и передаёт значение «Go to Google!». Ещё один замечательный пример: jQuery('<div/>', { id: 'foo', css: { fontWeight: 700, color: 'green' }, click: function(){ alert('Foo has been clicked!'); } });

январь, 2010

Атрибут id обрабатывается как обычный атрибут, а css и click как вызовы соответствующих методов. В предыдущих версиях jQuery вы бы написали так: jQuery('<div/>') .attr('id', 'foo') .css({ fontWeight: 700, color: 'green' }) .click(function(){ alert('Foo has been clicked!'); });

2. «until» ко всему! В арсенал обхода DOM появилось три новых метода: «nextUntil», «prevUntil» и «parentsUntil». Каждый из этих методов будет обходить DOM в заданном направлении пока не будет выполнено условие переданного селектора. Итак, допустим у вас есть список фруктов: <ul>

</ul>

<li>Apple</li> <li>Banana</li> <li>Grape</li> <li>Strawberry</li> <li>Pear</li> <li>Peach</li>

Вам необходимо выбрать все элементы после «Apple» и остановиться на «Strawberry». Это выглядит очень просто: jQuery('ul li:contains(Apple)'). nextUntil(':contains(Pear)');

41


Друпалогия #00

Не Drupal

3. Мультибиндинг обработчиков событий

5. Новые события для метода live.

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

В jQuery 1.4 появилась поддержка обработчиков событий "submit", "change", "focus" и "blur". В jQuery используется метод .live() для добавления обработчиков событий. Это полезно, когда вы добавляете обработчики сразу для нескольких элементов, а также при добавлении новых.

jQuery('#foo).bind({ click: function() { // что-то делаем }, mouseover: function() { // что-то делаем }, mouseout: function() { // что-то делаем } })

Обратите внимание, что вам необходимо использовать имена 'focusin' и 'focusout' для использования событий «focus» и «blur»! jQuery('input').live('focusin', function(){ // do something with this });

Это работает и с методом .one().

6. Управление контекстом функций. 4. Новое в анимации Теперь, вместо того, чтобы определять одну функцию для одного типа анимации, вы можете определить различные функции для каждого анимируемого свойства. jQuery включает два типа анимации: качание (по умолчанию) и линейное изменение. Другие вам необходимо скачать отдельно. ать функцию анимации для каждого свойства, необходимо просто определить массив, первое значение каждого элемента — это анимируемое свойство, а второе используемая функция: jQuery('#foo').animate({ left: 500, top: [500, 'easeOutBounce'] }, 2000);

Примерчик. Вы также можете использовать объект specialEasing, то есть такую запись: jQuery('#foo').animate({ left: 500, top: 500 }, { duration: 2000, specialEasing: { top: 'easeOutBounce' } });

январь, 2010

jQuery 1.4 предоставляет новую «proxy»-функцию в пространстве имён jQuery. Эта функция принимает два аргумента: «область видимости» и имя метода. Давайте рассмотрим пример. Ниже создаётся объект «app» с двумя свойствами: «clickHandler» и «config». var app = { config: { clickMessage: 'Hi!' }, clickHandler: function() { alert(this.config.clickMessage); } };

У метода ".clickHandler()" контекст выполнения будет «app», это подразумевает что «this» ссылается именно на него. Это работает, как и ожидается: app.clickHandler(); // "Hi!"

Давайте попробуем прицепиться к событию: jQuery('a').bind('click', app.clickHandler);

При нажатии на ссылку ничего не произойдёт. Потому что jQuery будет, по умолчанию, устанавливать для контекста обработчика искомый элемент (в нашем случае ссылку), то есть this в этом примере — это гиперссылка. Но мы этого не хотим! Мы хотим чтобы this в этом случае означал объект

42


Друпалогия #00 «app». В jQuery 1.4 этого можно добиться очень просто: jQuery('a').bind( 'click', jQuery.proxy(app, 'clickHandler') );

Теперь нажатие на ссылку приведёт к ожидаемому результату. Функция proxy вернёт «обёрнутую» версию вашей функции, а также установит для «this» указанный вами объект. Это полезно в таких случаях, когда вам необходимо передать функцию в качестве параметра другому методу jQuery или в какой-либо плагин.

7. Пауза перед выполнением анимации. Теперь вы можете добавить паузу перед выполнением обработки очереди событий анимации. Фактически это работает с любой очередью событий, но наиболее востребована эта возможность именно при работе с анимацией, то есть с очередью 'fx'. Это избавит вас с путаницей вызова setTimeout и передачей методов. Выглядит это так: jQuery('#foo') .slideDown() // анимация раз .delay(200) // пауза .fadeIn(); // анимация два

Если вы хотите использовать метод для очереди, отличной от очереди эффектов (используемой по умолчанию), то вам необходимо передать её имя, как второй параметр функции.

Не Drupal ментов div, которые содержат элемент ul. В этой ситуации, конечно, удобнее использовать селектор (:has()), но метод полезен в случаях когда вам необходимо отфильтровать коллекцию динамически. jQuery 1.4 также предоставляет функцию «contains». Это низкоуровневая функция, которая принимает в качестве аргументов два элемента DOM и возвращает логический результат, показывающий, содержится ли второй элемент в первом. Например: jQuery.contains(document.documentElement, document. body); // Результат true - <body> находится внутри <html>

9. Unwrap! Мы все знаем о методе .wrap(). В jQuery 1.4 появилась функция .unwrap(), которая действует строго наоборот. К примеру нас есть такая структура: <div> <p>Foo</p> </div>

Вызов такого кода: jQuery('p').unwrap();

… вернёт нам следующую структуру: <p>Foo</p>

Другими словами, метод удаляет родителя у любого элемента.

10. Удаление элементов без удаления данных. 8. Функция .has() jQuery 1.4 упрощает проверку наличия элемента в другом. Это эквивалентно фильтру :has() в селекторе. Этот метод возвращает все элементы, в которых содержится по крайней мере один элемент, соответствующий переданному селектору. jQuery('div').has('ul');

В этом случае результатом будет коллекция эле-

январь, 2010

Новый метод .detach() позволит вам удалить элементы из документа, подобно тому как это делает метод .remove(). Ключевая разница в том, что новый метод не удаляет информацию об этих элементов из jQuery. Это подразумевает, что и данные добавленные методом .data(), и любой обработчик событий, добавленный через систему событий jQuery, останутся активными. Это может быть полезно в случаях, когда вы уда-

43


Друпалогия #00 ляете элемент, но знаете, что он может вам понадобиться позднее. Его события и данные будут в этом случае актуальны. var foo = jQuery('#foo'); // важный обработчик foo.click(function(){ alert('Foo!'); }); foo.detach(); // удаляем объект из DOM // … много кода foo.appendTo('body'); // добавляем объект foo.click(); // "Foo!"

11. Улучшения index(...) jQuery 1.4 позволяет вам использовать метод .index() двумя новыми способами. Раньше вы могли передать элемент в качестве параметра, а в результате получали индекс этого элемента в текущей коллекции. Если методу не передавать аргументов, то он возвращает индекс элемента в коллекции, в которой он находится. Например: <ul> <li>Apple</li> <li>Banana</li> <li>Grape</li> <li>Strawberry</li> <li>Pear</li> <li>Peach</li> </ul>

При нажатии на элемент списка, появится сообщение с его индексом. Это делается так: jQuery('li').click(function(){ alert( jQuery(this).index() ); });

jQuery 1.4 также позволяет вам указать селектор в качестве аргумента функции .index(), что позволит вам узнать индекс в коллекции полученной в результате обработки селектора. Возвращаемое значение имеет тип integer, и результатом будет -1, если элемент не найден в коллекции.

январь, 2010

Не Drupal 12. Методы управления DOM, принимающие в качестве аргументов функции. Большинство методов управления моделью доку мента теперь могут принимать функцию в качестве аргумента. Эта функция будет вызываться для каждого элемента в коллекции, которая определена с помощью искомого метода. Такую возможность имеют следующие функции: • • • • • • • • • • • • • • • •

after

before append prepend addClass toggleClass removeClass wrap wrapAll wrapInner val text replaceWith css attr html

В этой функции, текущий элемент — это this, а его индекс передаётся аргументом. jQuery('li').html(function(i){ return 'Индекс текущего элемента: ' + i; });

Также, с некоторыми функциями вы можете воспользоваться вторым аргументом. Если вы вызываете, так называемый, метод установки (например .html() или .attr('href')), вторым аргументом будет значение. Например: jQuery('a').attr('href', function(i, currentHref){ return currentHref + '?foo=bar'; });

Как видите, методам .css() и .attr() можно передавать вторым аргументом функцию, а первым — свойство, которое вы хотите изменить:

44


Друпалогия #00 jQuery('li').css('color', function(i, currentCssColor){ return i % 2 ? 'red' : 'blue'; });

Не Drupal 14. Улучшения метода closest(...) Метод .closest() теперь может принимать в качестве параметра массив селекторов. Это очень полезно когда вы хотите выбрать более одного элемента с конкретными характеристиками.

13. Определение типа объекта jQuery 1.4 содержит две новых вспомогательных функции, которые помогут вам определить тип целевого объекта. Во-первых, функция isEmptyObject. Эта функция возвращает результат типа boolean, и показывает является ли переданный объект пустым (лишённый свойств напрямую или косвенно). Во-вторых, это функция isPlainObject, которая показывает является ли переданный объект, объектом javascript, созданным либо через '{}', либо через 'new Object()'. jQuery.isEmptyObject({}); // true jQuery.isEmptyObject({foo:1}); // false jQuery.isPlainObject({}); // true jQuery.isPlainObject(window); // false jQuery.isPlainObject(jQuery()); // false

январь, 2010

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

15. Новые события 'focusin' и 'focusout' Эти события вы должны использовать при работе с focus и blur. Эти события позволят вам выполнять какие-нибудь действия когда элемент получает или теряет фокус. jQuery('form') .focusin(function(){ jQuery(this).addClass('focused'); }); .focusout(function(){ jQuery(this).removeClass('focused'); });

45


Друпалогия #00

Не Drupal

Статистика использования броузеров 2009

IE8

IE7

IE6

Firefox

Chrome

Safari

Opera

Декабрь

13.5%

12.8%

10.9%

46.4%

9.8%

3.6%

2.3%

Ноябрь

13.3%

13.3%

11.1%

47.0%

8.5%

3.8%

2.3%

Октябрь

12.8%

14.1%

10.6%

47.5%

8.0%

3.8%

2.3%

Сентябрь

12.2%

15.3%

12.1%

46.6%

7.1%

3.6%

2.2%

Август

10.6%

15.1%

13.6%

47.4%

7.0%

3.3%

2.1%

Июль

9.1%

15.9%

14.4%

47.9%

6.5%

3.3%

2.1%

Июнь

7.1%

18.7%

14.9%

47.3%

6.0%

3.1%

2.1%

Май

5.2%

21.3%

14.5%

47.7%

5.5%

3.0%

2.2%

Апрель

3.5%

23.2%

15.4%

47.1%

4.9%

3.0%

2.2%

Март

1.4%

24.9%

17.0%

46.5%

4.2%

3.1%

2.3%

Февраль

0.8%

25.4%

17.4%

46.4%

4.0%

3.0%

2.2%

Январь

0.6%

25.7%

18.5%

45.5%

3.9%

3.0%

2.3%

Использованы данные с сайта http://www.w3schools.com

по дням | по неделям | по месяцам

количество посетителей с разными браузерами значения: среднесуточные Firefox 3 Explorer 7 Opera 10 Explorer 8 Opera 9 Explorer 6

январь 2010 г. 7,943,288 5,505,022 4,976,369 3,932,429 3,447,223 3,090,721

23.7% 16.4% 14.8% 11.7% 10.3% 9.2%

декабрь 2009 г. 7,887,616 5,822,930 4,570,238 3,781,871 3,711,223 3,612,088

23.3% 17.2% 13.5% 11.2% 11.0% 10.7%

в среднем за 3 месяца 7,651,168 5,700,655 4,301,084 3,672,286 3,706,161 3,490,369

23.2% 17.3% 13.1% 11.2% 11.3% 10.6%

Использованы данные с сайта http://www.liveinternet.ru

январь, 2010

46


Друпалогия #00

Информация об использовании Распространяемый журнал является бесплатным! Журнал выходит 28 числа каждого месяца. Все права на статьи, опубликованные в этом номере, принадлежат их авторам и не могут публиковаться где-либо без их согласия.

Связаться с авторами , задать вопросы, обсудить конкретную статью или поучаствовать в дискуссиях можно на сайте журнала http://magazine.drupalogy.ru Так же, на сайте можно предложить свои статьи, обзоры, уроки или переводы.

Ответы, на интересующие вопросы, можно получить связавшись с редакцией журнала

январь, 2010

47



Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.