{{tag>drupal cms}}

====== Простой Drupal workflow ======

Несколько разработчиков, каждый работает на своем локальном сервере: нужно делиться изменениями
Тестовый сервер: нужно переносить настройки и контент
Боевой сервер: нужно переносить настройки, сохраняя контент
 
Что делать?
Что нам нужно:
  * отслеживать изменения в конфигурации
  * переносить изменения в конфигурации
  * 
Подходы:
  * работать с миграциями изменений в БД
  * настройки - в код (code-driven development): экосистема Features
  * Drush: лучший друг разработчика
  * cc - очистка кэша
  * dl, en, dis - работа с модулями
  * sql-dump, sql-sync - работа с дампами БД
  * rsync - синхронизация файлов
  * remote-backup, remote-restore - бэкапы
  * Migraine: наш опыт
  * Migraine by Noosphere Networks 
  http://ashearer.com/software/server-administration/migraine 
  * модификация для D6 by mukesh.agarwal17
   http://www.blisstering.com/migraine-synchronize-your-development-staging-and-production-sites-databases-drupal-6
  * drush
  * скрипты для drush от Данила Семеленова
  * от Данила Семеленова
  http://www.slideshare.net/drupalindia/migraine-drupal-syncing-your-staging-and-live-sites-presentation

**Что делает Migraine**
Migraine: разделение таблиц
config_tables: blocks blocks_roles boxes, filters filter_formats, imagecache_action, imagecache_preset...
content_tables*: node, node_revisions, search_dataset, search_index, term_data, term_node...
temp_tables: accesslog, watchdog...
cache_tables: cache, cache_block, cache_filter, cache_menu, cache_page, cache_views...
ignore_tables: ...

**- все таблицы content_type_ и content_field_ определяются как контентные автоматически**

====== Расширения Drush ========

Оболочка для команд Migraine
migrate-db-dump — создание дампа локальной БД
migrate-db-restore — восстановление БД из локального дампа
migrate - полная миграция сайта, включая исходные файлы и БД
sync - cинхронизация файлов локальной версии сайта с удаленной.
Что еще нужно подготовить
/sites/xxxx для всех площадок
aliases.drushrc.php: алиасы площадок @dev, @test, @prod, реквизиты доступа (см. drush/examples/example.aliases.drushrc.php)
settings.php для индивидуальных настроек внутри /sites/xxxx

======= Migraine: workflow ========
Разработчик 1
Работаем над кодом и конфигурацией
Делаем дамп migrate-db-dump (можно повесить на pre-commit hook для git)
  возможно, занесение новых таблиц в tables.py или tables.php
commit, push
 
Разработчик 2
pull (возможно, разрешаем конфликты)
Делаем migrate-db-restore
Изменения в конфигурации мигрировали
Migraine: workflow
drush @dev migrate @test:
drush @dev migrate-db-dump
drush @dev sync @test
миграция БД
 
drush @dev migrate @prod:
drush @dev migrate-db-dump
drush @dev sync @prod
миграция БД (кроме содержимого контентных таблиц)
(возможно) изменение схемы контентных таблиц (при изменении типов данных через CCK)
 
Migraine: плюсы и минусы
Хорошо:
таблицы классифицированы - больше думать не надо
нет зависимости от предоставления модулями каких-то интерфейсов для экспорта-импорта
 
Плохо:
в случае конфликтов разбираться в дампах тяжело, легко ошибиться
каша остается кашей
все равно приходится думать

======== Features =========
Code-driven development!
Конфигурация - в код!
 
Features так или иначе умеют: типы нод, поля CCK, таксономия, imagecahe, роли и права, Views, Rules...
Features: экосистема
Features 
Ctools exportables
Strongarm - переменные  
Boxes - кастомные блоки (альтернатива стандартному add block)  
Context - блоки, breadcrumbs и т.д.  
Diff - инструмент для работы с различиями в состояниях feature
Анатомия feature
feature - это модуль
feature_name.info - мета-информация, зависимости
feature_name.module - место для кастомного кода
feature_name.features.inc 
feature_name.install
 
Фрагменты конфигурации:
feature_name.context.inc
feature_name.features.content.inc
feature_name.views_default.inc
feature_name.features.user_permission.inc
...
Возможные состояния feature
Features сравнивает для feature:
состояние кода (1)
предыдущее состояние кода (2)
актуальное состояние (обычно в БД) (3)
 
В зависимости от разницы между ними:
Default: (1) == (3) или (3) не существует, для обновления feature достаточно обновления кода
Overridden: (1)!=(3), для обновления feature нужно сделать revert
  Needs review: (1)!=(2)!=(3), для обновления нужно разбираться вручную
Rebuildable (для faux-exportables): (1)!=(3), (3)==(2)

Workflow отдельно взятой feature
Разработчик 1
Создание
Включение
Работа по изменению конфигурации
Обновление кода
commit, push
Разработчик 2
pull
Установка/Обновление из кода
Конфигурация перенесена!
Управление Features
Веб-интерфейс
Drush
drush features (fl) - список всех доступных feature
drush features-export (fe) [feature name] [component list] - создание новой feature с указанными компонентами
drush features-update (fu) [feature name] - из БД в код
drush features-revert (fr) [feature name] - из кода в БД
drush features-diff (fd) [feature name] - различия между состоянием в кодe и в БД

======= Feature: без UI ========
Создание
feature_name.info: мета-информаци, зависимости и т.д.
feature_name.module: include_once('feature_name.features.inc');
feature_name.features.inc
drush en feature_name
drush fu feature_name
Добавление чего-нибудь
Добавляем зависимость в .info (например: features[views][] = &quot;view_news&quot;)
drush fu feature_name
Подумаем о других
Изменения не сводятся только к конфигурации. Но feature - модуль, поэтому есть hook_install() и hook_update().
 
включение модулей
добавление ролей
добавление словарей
любой код
...
hook_update() - делимся с теми, кто работает параллельно
drush updatedb -y && drush cc all
hook_install() - делимся с новыми разработчиками
Controller Feature: центр управления всем остальным
Включаются все остальные features:
dependencies[] = &quot;feature_name_1&quot; dependencies[] = &quot;feature_name_2&quot; ...
 
hook_update и hook_install - отражают общие изменения в состоянии системы
function feature_controller_update_6003() { $return = array(); $modules = array('feature_name_1', 'feature_name_2'); drupal_install_modules($modules); $return[] = array('success' => TRUE, 'query' => 'Enabling some cool features'); return $return; }
Features: собираем все вместе
project.profile: включаем необходимые модули и Controller Feature
Работаем: пишем код, добавляем модули, меняем структуру и настройки, разрабатываем и подключаем новые features.
Поддерживаем актуальность .install Controller Feature (пишем код вручную).
Поддерживаем актуальность кода остальных features (drush fu feature_name)
Вся история в репозитории в виде кода!

Features
Хорошо:
с кодом легко работать в системе контроля версий
законченные куски функционала, которые можно использовать повторно
красиво
 
Плохо: 
требует больше внимания к вынесению изменений в код 
на самом деле сложно правильно разделить на куски из-за зависимостей
не все компоненты exportable (решаемо)