Использование метода Feature injection на примере сборки CommerceBox

06.06.2014
Share on FacebookShare on TwitterShare on GooglePlusShare on Linkedin
Feature Injection
Автор:

Эта информация может быть полезной как для тех, кто активно использует модуль Features, так и для тех, кто с ним только планирует ознакомиться.

Как у нас вообще возникла идея использовать feature injection? В Друпал существует инструмент быстрого развертывания сайтов, так называемые Apps.

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

Используя Apps мы столкнулись с тем, что нам нужно хранить в фиче (features) определенный функционал для apps, хотя в данный момент он может быть даже не включен. То есть возник вопрос, можно ли как-то разделить фичу таким образом, чтобы в сборке была только сама фича без функционала app-а, а в самом app сохранялась остальная фича, которая при его включении дополняла бы основную. При этом, они должны работать как одна целостная единица. Поэтому мы разработали метод, который помогает в этом процессе, и назвали его Feature Injection.

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

1. Для начала создадим вьюшку, которая выводит только одно поле title типа материала Article:

В'юшка для типу контента Article.

2. Создаем фичу, которая добавляет эту же вьюшку.

Створення фічі.

3. Сохраненную фичу извлекаем из архива и включаем.

После того, как фича включена и работает, можно приступать непосредственно к feature injection. Предположим, что нам нужно добавить для вывода еще одно поле во вьюшку, не меняя самой фичи (например, краткое содержание поля body в типе материала Article), однако мы заранее не знаем, нужно ли оно в фиче, или нет. Мы добавляем любое поле кодом во вьюшку таким образом, чтобы фича думала, что она сама добавляет это поле. Для этого создаем свой ​​собственный модуль, который будет добавлять необходимые изменения в нашей фиче при его включении. Когда этот модуль выключен, то эти трансформации учитываться не будут и наша оригинальная фича будет целой и ​​невредимой. Вот в этом и есть суть feature injection. Для продолжения, нам нужно установить модуль Diff.

4. После включения модуля Diff, добавим в нашу вьюшку поле, которое будет дополнительным для нашей фичи (т.е. при включении созданного нами модуля это поле будет присутствовать, а при выключении - отсутствовать). Для примера возьмем краткое содержание поля body, настроим его и выведем после заголовка. В результате вы получите следующий вывод (помните, что необходимо сохранить вьюшку после добавления нового поля):

В'юшка статей

5. Теперь, если мы посмотрим на нашу фичу на странице admin/structure/features, то увидим ее в статусе Overriden. При клике на этот статус вы перейдете на вкладку VIEW. Если включить модуль Diff, то появится и вкладка REVIEW OVERRIDES, где можно увидеть изменения, которые добавляются в фичу (отмеченные знаком “+”).

+ /* Field: Content: Body */
+ $handler->display->display_options['fields']['body']['id'] = 'body';
+ $handler->display->display_options['fields']['body']['table'] = 'field_data_body';
+ $handler->display->display_options['fields']['body']['field'] = 'body';
+ $handler->display->display_options['fields']['body']['label'] = '';
+ $handler->display->display_options['fields']['body']['element_label_colon'] = FALSE;
+ $handler->display->display_options['fields']['body']['type'] = 'text_summary_or_trimmed';
+ $handler->display->display_options['fields']['body']['settings'] = array(
     'trim_length' => '300',
   );

 

Наконец у нас есть код, который будет дополнять фичу (когда она будет включаться), чтобы появилось поле.

Но куда теперь его нужно вставлять? Ищем hook, в который и нужно будет записывать полученный код в созданном нами модуле.

6. Ищем в коде, где добавляется наша вьюшка (в данном случае, это файл show_articles_view.views_default.inc) и видим, что для ее создания используется hook_views_default_views( ). Далее переходим к созданию собственного модуля.

7. Назовем модуль Feature Injection. Создаем 2 файла: feature_injection.info и feature_injection.module. Вот пример .info файла:

name = Feature injection
description = Add body field to view.
package = "Feature injection"
core = 7.x
dependencies[] = views
dependencies[] = features

 

Пример уже рабочего файла .module.

display['default'];

    /* Field: Content: Body */
    $display->display_options['fields']['body']['id'] = 'body';
    $display->display_options['fields']['body']['table'] = 'field_data_body';
    $display->display_options['fields']['body']['field'] = 'body';
    $display->display_options['fields']['body']['label'] = '';
    $display->display_options['fields']['body']['element_label_colon'] = FALSE;
    $display->display_options['fields']['body']['type'] = 'text_summary_or_trimmed';
    $display->display_options['fields']['body']['settings'] = array(
      'trim_length' => '300',
    );
  }
}

 

Прокомментируем каждый шаг. Для начала используем alter для хука, которым создается наша вьюшка. То есть если хук назывался hook_views_default_views(), то теперь он будет называться hook_views_default_views_alter(). Именно в этот хук по ссылке и передается переменная $data, в которую мы и будем записывать наше поле. В этой переменной (в данном случае) содержатся все вьюшки, которые добавлены с помощью фичи, и мы можем дописать свои изменения в $data так, что наша фича будет думать, что это она сама задает эти изменения. Далее проверяем, существует ли наша вьюшка: if (isset ($ data [' show_all_articles '])) (где show_all_articles - машинное название вьюшки).

После этого переменной $display присваиваем значение "display" в переменной $data. То  есть сюда мы подставляем необходимый код, где $handler->display заменяем на нашу переменную $display.

Вот и все, теперь можно удалить поле body из вьюшки либо сделать revert элементов в фиче (т.е. вернуть все изменения к исходным, используя фичу), и проверить, работает ли ваш модуль feature injection. Итак, сейчас у вас должна быть вьюшка, которая создается фичей, без поля body. Включите свой ​​модуль, который вы создали. Теперь во вьюшку добавится созданное вами ранее поле body. При выключении модуля поле body должно пропасть.

Если у вас все работает - поздравляем! Вы сделали feature injection! А если что-то не получилось - попробуйте очистить кэш, это можно сделать на странице admin/config/development/performance.

Если возникают некоторые проблемы с записью в переменную $data, попробуйте ее сначала просмотреть с помощью функции debug(), чтобы узнать, куда записывать необходимые вам изменения. Если у вас установлен модуль Devel, то вместо debug() можно воспользоваться функцией dpm().

Где это может использоваться? Например, если вы делаете сборку магазина на Drupal 7 и заранее не знаете, нужно ли вам добавлять некоторые поля: комментарии, ссылки, изображения и т.д., то можно использовать feature injection. Так каждый пользователь сам будет решать, что ему нужно в конкретном случае. Поля будут добавляться включением отдельного модуля, а фича при этом будет думать, что это она сама его задает. То есть включили один модуль - у вас появились ссылки во вьюшке, включили другой - появилось изображение, и т.д.

Сейчас feature injection активно используется в сборке CommerceBox с помощью app-ов. Например, при включении app product status можно добавлять метки товаров New, не редактируя самой вьюшки, и при желании можно из вьюшки удалить это поле безболезненно. Соответственно, при выключении app данный функционал пропадает.

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

Данный метод продемонстрирован на простом примере для легкого понимания. Однако, Feature Injection можно использовать не только для вьюшек, но и для любого другого функционала, который вы добавляете для вашей фичи.

custom_feature_injection.zip
1 vote, Rating: 5
Share on FacebookShare on TwitterShare on GooglePlusShare on Linkedin

Также по теме

1

Быть членом Drupal сообщества очень ответственно. Именно поэтому компания InternetDevels организовала 3-месячный код-спринт посвященный совершенствованию CMF. Результаты...

2

Node.js  - это мощная платформа для построения всех видов приложений, которая, в частности, может интегрироваться с Drupal 7. Как установить и настроить этот...

3

Часто в адрес Drupal можно увидеть заявления в стиле: “На этом фреймворке не создать high-load веб-сайта”. Мы опровергнем этот миф не красивыми...

4

При принятии решения запустить собственный вебсайт одним из самых важных вопросов является реализация - CMS или сапомис? Читайте дальше о преимуществах фреймворка...

5

Очень часто многие разработчики сталкиваются с проблемой гибкой сортировки материалов на сайте. Одним из вариантов решений этой задаче в Drupal есть модуль Radioactivity. Узнайте больше о его...

Need a quote? Let's discuss the project

Are you looking for someone to help you with your Drupal Web Development needs? Let’s get in touch and discuss the requirements of your project. We would love to hear from you.

Join the people who have already subscribed!

Want to be aware of important and interesting things happening? We will inform you about new blog posts on Drupal development, design, QA testing and more, as well news about Drupal events.

No charge. Unsubscribe anytime