Drupal 7. Модуль подписок своими руками

Вместо предисловия

Функциональность подписок на какой-либо контент – одна из востребованных в веб-индустрии. Многие сайты могут похвастаться подобным. И наш проект не стал исключением. Дано: сайт на 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/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *