Використання Feature injection, на прикладі збірки CommerceBox

06.06.2014
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.

<?php

/**
* @file
* Extends drupal functionality.
*/

/**
* Implements hook_views_default_views_alter().
*
* @ingroup features_injection
*/
function feature_injection_views_default_views_alter(&$data) {
  if (isset($data['show_articles_view'])) {
    $display = &$data['show_articles_view']->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 можна використовувати не лише для в’юшок, але й для будь-якого функціоналу, який  ви додаєте для фічі.

Голосів: 1 Рейтинг: 5

Також по темі

1

Apps - це модуль, що позиціонується як наступний крок у розвитку...

2

В даній статті мова піде про можливість встановлення ядра Drupal 8 як сабмодуля. Ми не розважатимемо за саме поняття сабмодулів, ні за їх недоліки чи переваги, а лише зобразимо в деталях, спосіб у...

3

Вигляд форми авторизації/реєстрації тепер можна змінити через інтерфейс адміністратора за допомогою нашого модуля Customize login form.

4

Завдання імпорту контента часто буває нетривіальним. Написання імпорту "з нуля" для кожного випадку - варіант ...

5

В даній статті описано процес розгортання CMS Drupal із використанням Oracle DB на Debian сервері.

Subscribe to our blog updates