Вместо предисловия
Функциональность подписок на какой-либо контент – одна из востребованных в веб-индустрии. Многие сайты могут похвастаться подобным. И наш проект не стал исключением. Дано: сайт на Drupal 7. Что требуется: найти или написать модуль, реализующий все необходимые функции. Какой вариант был выбран и что из этого вышло, Вы можете прочитать далее.
Поиск подходящих модулей
Самый очевидный и угадываемый вариант – модуль Subscriptions. Данный модуль позволяет пользователям подписываться на изменения нод и таксономии (в том числе, новые комментарии к контенту). Главной причиной отказа от этого варианта послужило отсутствие возможности подписки без перезагрузки страницы и ориентированность модуля в основном на email-рассылки.
Другой вариант – модуль Notifications. В принципе, его расширяемость и масштабируемость нам подходили (для создания своих типов подписок), но отсутствие стабильной версии под 7.x не позволило нам его использовать.
Итак, решение оставалось только одно – написать модуль самим.
Первоначальная настройка
Полностью описывать весь модуль не имеет смысла (это точно выйдет за пределы темы статьи), поэтому опишу основной функционал и начну с основных моментов: настройки админки. Во-первых, необходимо создать тип контента (в моём примере – это Item) с некоторым количеством полей. Здесь и далее основное внимание будет уделяться полям Title, Body, Image.
Во-вторых, следующий этап – создание Views для вывода нод данного типа. К примеру, как на следующем рисунке:
Помимо описанных ранее полей в данной Views выводится также Nid. Для чего же это требуется? Темизировав это поле (к которому впоследствии будет привязано событие подписки), мы можем настроить его вывод по своему усмотрению.
Файлы модуля и их описание
Чтобы начать разработку модуля, создадим в sites/all/modules папку custom_subscriptions. Нам понадобятся 4 файла: custom_subscriptions.info (основная информация о модуле), custom_subscriptions.install (настройки инсталляции), custom_subscriptions.module (собственно, сам файл модуля) и custom_subscriptions.js (в скрипте будет реализован механизм подписки без перезагрузки страницы). Теперь о каждом из них подробнее.
Инфо-файл
Содержимое файла custom_subscriptions.info:
name = "Custom Subscriptions" description = "Allows users to follow content" core = 7.x version = 7.x-1.0 php = 5.1 scripts[] = custom_subscriptions.js
Как видим, файл скрипта был подключён именно здесь.
Файл инсталляции
Для примера, размещённого здесь, будет достаточно одной таблицы в базе данных, содержащей поля uid (идентификатор пользователя) и nid (идентификатор ноды, на которую пользователь подписан).
Содержимое файла custom_subscriptions.install:
<?php /** * Implements hook_schema() */ function custom_subscriptions_schema() { $schema['custom_subscriptions'] = array( 'description' => t('The base table for subscriptions'), 'fields' => array( 'sid' => array( 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'uid' => array( 'type' => 'int', 'length' => 10, 'not null' => TRUE, ), 'nid' => array( 'type' => 'int', 'length' => 10, 'not null' => TRUE, ), ), 'primary key' => array('sid'), ); return $schema; }
После инсталляции таблица будет иметь следующую структуру:
Настройка темы
Прежде всего, следует создать шаблон для вывода Nid во Views. В нашем случае он имеет имя views-view-field—items—page—nid.tpl.php (имя для шаблона можно получить в разделе Advanced / Theme в настройках Views). Файл шаблона размещается в теме (была использована подтема Zen под названием STARTERKIT), в папке templates.
Содержимое файла views-view-field—items—page—nid.tpl.php:
<?php global $user; ?> <?php if ($user->uid != 0): ?> <?php $following = db_select('custom_subscriptions', 'cs') ->fields('cs') ->condition('uid', $user->uid) ->condition('nid', $output) ->execute() ->rowCount(); ?> <?php if ($following == 0):?> <?php print('<a href="follow/' . $output . '" class="follow">FOLLOW</a>'); ?> <?php else:?> <?php print('<a href="unfollow/' . $output . '" class="following">FOLLOWING</a>'); ?> <?php endif; ?> <?php endif; ?>
Как видно из представленного кода, поле подписок доступно только для авторизированных пользователям. Кроме того, в зависимости от наличия записи в таблице custom_subscriptions, заголовок поля меняется с FOLLOW (если пользователь ещё не подписан на ноду) на FOLLOWING (если подписка уже имеется). Информация о совершаемом действии (follow/unfollow) и идентификатор ноды nid будут храниться в атрибуте href.
Разработка механизма подписки
Так как функциональность файла модуля и скрипта взаимосвязаны, они будут рассмотрены в совокупности.
Начнём с визуальных эффектов: в файле скрипта добавим появление поля подписок по наведению на контент, а также изменение текста надписи с FOLLOWING на UNFOLLOW при наведении на это поле (так же, как это осуществлено в Twitter).
Содержимое файла custom_subscriptions.js:
(function ($) { Drupal.behaviors.collectiveMove = { attach: function(context, settings) { // show buttons on hover $('.view-items .views-row').hover(function() { $(this).find('.views-field-nid a').css('display', 'block'); }); // hide buttons on mouseleave $('.view-items .views-row').mouseleave(function() { $(this).find('.views-field-nid a.follow, .views-field-nid a.unfollow').css('display', 'none'); }); // show 'unfollow' when user has already had a subscription $('.view-items .views-row .views-field-nid .following').live('mouseover', function() { $(this).text('UNFOLLOW'); $(this).addClass('unfollow'); }); // hide 'unfollow' when user has already had a subscription $('.view-items .views-row .views-field-nid .following').live('mouseout', function() { $(this).text('FOLLOWING'); $(this).removeClass('unfollow'); }); } }; })(jQuery);
Теперь начинается самое интересное – передача данных между файлом модуля и скриптом. Основная идея в следующем: при нажатии на FOLLOW post-запрос передаёт данные о действии (‘follow’) и идентификаторе ноды в модуль, где полученные данные записываются в базу. Для UNFOLLOW механизм сходен, но действие будет другим (‘unfollow‘), и полученные данные будут удаляться из таблицы базы данных.
Для начала создадим страницу, на которую будет отправляться запрос, используя hook_menu.
Содержимое файла custom_subscriptions.module:
<?php /* Implements hook_menu() */ function custom_subscriptions_menu() { $items = array(); $items['custom_subscriptions_ajax'] = array( 'title' => 'Ajax callback', 'page callback' => 'custom_subscriptions_ajax', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; }
Напоминаю, что по правилам оформления кода модулей для Drupal, ставится только открывающий тег php.
Страница готова – добавим функционал.
Содержимое файла custom_subscriptions.module:
<?php /* Implements hook_menu() */ function custom_subscriptions_menu() { ... } /** * Implements ajax callback function */ function custom_subscriptions_ajax() { global $user; if($_POST['type'] == 'follow') { if ($_POST['nid']) { db_insert('custom_subscriptions') ->fields(array( 'uid' => $user->uid, 'nid' => $_POST['nid'], )) ->execute(); print(1); } } else if($_POST['type'] == 'unfollow') { if ($_POST['nid']) { db_delete('custom_subscriptions') ->condition('uid', $user->uid) ->condition('nid', $_POST['nid']) ->execute(); print(1); } } else { print(0); } }
В зависимости от полученного из post-запроса действия (follow/unfollow), добавляем либо удаляем запись из таблицы. Каждая запись идентифицируется по uid (берём идентификатор глобального юзера) и nid. В случае успеха печатаем ‘1’.
Теперь осталось самое важное – передать данные по нажатию на поле nid на странице, сформированной с помощью Views.
Содержимое файла custom_subscriptions.js:
(function ($) { Drupal.behaviors.collectiveMove = { attach: function(context, settings) { ... // click on follow/unfollow buttons $('.view-items .views-row .views-field-nid a').bind('click', function(e) { e.preventDefault(); var href = $(this).attr('href'); var strs = href.split('/'); var item = $(this); $.post( Drupal.settings.basePath + 'custom_subscriptions_ajax', { type: strs[0], nid: strs[1], }, function (data) { if (data == 1) { if (strs[0] == 'follow') { item.text('UNFOLLOW'); item.removeClass('follow'); item.addClass('following unfollow'); item.attr('href', 'unfollow/' + strs[1]); } if (strs[0] == 'unfollow') { item.text('FOLLOW'); item.removeClass('following'); item.removeClass('unfollow'); item.addClass('follow'); item.attr('href', 'follow/' + strs[1]); } } } ); }); } }; })(jQuery);
При нажатии на ссылку в поле nid мы проходим следующие шаги:
- запрет выполнения действия по умолчанию (чтобы предотвратить перезагрузку страницы);
- получение действия и nid из атрибута href, в который они были записаны в шаблоне;
- передача полученных данных на подготовленную в модуле страницу;
- после получения успешного результата меняем название и некоторых атрибуты выводимой ссылки.
Вместо послесловия
В данной статье был описан процесс создания простейшего модуля подписок на ноды в Drupal 7. Основным моментом можно назвать осуществление подписок без перезагрузки страницы, используя post-запрос.
На готовый модуль можно взглянуть здесь: github.com/Sacret/custom_subscriptions
ссылка на оригинал статьи http://habrahabr.ru/post/200908/
Добавить комментарий