Статьи

Drupal: как создать собственную команду Drush

Drush — это инструмент командной строки, созданный, чтобы помочь вам в работе с Drupal из терминала. Он поставляется по умолчанию с кучей полезных команд, таких как загрузка, включение или даже обновление модулей. Но модули могут определять свои собственные команды, чтобы Drush выполнял операции, используя их код.

В этой статье мы рассмотрим создание команды Drush для вымышленного модуля, который действительно ничего не делает. Цель состоит в том, чтобы проиллюстрировать, что вам нужно делать на стороне Drush, и не беспокоиться о реальной функциональности модуля, определяющего команду. Если вы хотите следовать, я предполагаю, что у вас уже есть собственный настроенный модуль. Неважно, что он делает.

Весь код, который мы пишем, доступен в этом репозитории, поэтому, если вы хотите следовать или даже пропустить, вы можете проверить его. Каждый коммит представляет собой отдельный шаг, который мы делаем в учебнике.

Наш модуль

demo_drush модуля demo_drush мы хотим demo_drush будет очень простой. Это функция, которая устанавливает Hello world! сообщение:

 function demo_drush_print_statement() { drupal_set_message(t('Hello world!')); } 

Это немного, но это поможет нам понять, как использовать Drush для вывода этого оператора на экран терминала и, как это сделать, как настроить команду для выполнения всевозможных мощных операций. Мы будем корректировать его в ходе этого урока, чтобы продемонстрировать различные возможности.

Командный файл Drush

Первое, что нам нужно сделать, это добавить новый файл в папку нашего модуля с именем, заканчивающимся на .drush.inc . Drush просканирует кодовую базу и подберет ее на основе этого имени, чтобы загрузить функции, которые мы объявили внутри.

Также рекомендуется именовать этот файл после того модуля, в который вы его demo_drush.drush.inc . В нашем случае это будет demo_drush.drush.inc (мой модуль называется demo_drush ). А пока просто откройте теги php ( <?php ) вверху и сохраните файл.

Командный хук и обратный вызов

В архитектуре команд Drush есть 2 основных компонента: реализация ловушки, в которой мы определяем команды и их конфигурации, и функции обратного вызова, которые запускаются командой. Конечно, есть и другие функции, которые вызываются в процессе (такие как проверка или обратные вызовы до / после), но мы не будем рассматривать их в этом руководстве.

Для начала давайте реализуем hook_drush_command () и определим простую команду drush-demo-command с псевдонимом ddc :

 /** * Implements hook_drush_command(). */ function drush_demo_drush_command() { $items['drush-demo-command'] = array( 'description' => 'Demonstrate how Drush commands work.', 'aliases' => array('ddc'), ); return $items; } 

С помощью этой реализации ловушки (далее именуемой the hook ) мы возвращаем новый ключ в массиве, который будет полным именем команды. Внутри этого массива мы его настраиваем. На данный момент мы указали простое описание и псевдоним для команды. Поэтому, если мы запустим drush help ddc , мы drush help ddc на наш терминал описание и псевдоним команды.

Вторая часть архитектуры команды Drush — это функция обратного вызова. Как и сейчас, Drush ожидает, что будет объявлена ​​функция с именем drush_drush_demo_command() . Эта структура имен по умолчанию начинается с drush за которым следует имя команды, связанной с подчеркиванием. Итак, давайте быстро объявим об этом и используем его для вызова функции demo_drush_print_statement() мы написали ранее:

 /** * Callback for the drush-demo-command command */ function drush_drush_demo_command() { demo_drush_print_statement(); } 

Теперь, если вы очистите кеш drush ( drush cc drush ), вы можете запустить команду drush ddc и вы должны увидеть Hello world! выводится на экран. Поздравляю, ваша самая основная команда Drush работает.

Несмотря на то, что в оставшейся части руководства мы продолжим использовать это соглашение об именах по умолчанию, вы не обязательно ограничены им. Если вы хотите дать функции обратного вызова другое имя, вы можете добавить новый ключ в hook указав имя:

 ... 'callback' => 'drush_demo_test' ... 

Теперь вы можете объявить функцию drush_demo_test() и эта функция будет вызываться автоматически этой командой. Пока что мы будем придерживаться нашего имени drush_drush_demo_command() .

Аргументы и варианты

Одна из основных вещей, которую вы можете сделать с помощью команд Drush, — передать им аргументы и параметры. Основное различие между ними заключается в том, что первые обязательны, а вторые — нет. Другое различие заключается в способе передачи значений в функцию обратного вызова. Аргументы передаются как параметры функции (по порядку), в то время как параметры извлекаются в обратном вызове с использованием специальной вспомогательной функции ( drush_get_option ).

Итак, внутри хука для нашей команды давайте добавим информацию об аргументах и ​​опциях:

 ... 'arguments' => array( 'type' => 'The type of statement (error or success).', ), 'options' => array( 'repeat' => 'The number of statement repeats.', ), ... 

Мы объявили 1 аргумент (называемый type ) и один параметр, называемый repeat . Значения должны объяснять их назначение, но, как они используются, возможно, не так очевидно. Тип аргумента будет первой строкой, которая записывается после имени команды в терминале ( drush drush-demo-command или drush ddc ). Опция будет целочисленным значением, которое будет присвоено --repeat в команде.

Пример:

 drush ddc error --repeat=10 

Эта команда должна сделать напечатанное утверждение ошибкой и заставить его печатать 10 раз на экране терминала. Теперь давайте изменим наш код, чтобы это произошло.

Сначала давайте demo_drush_print_statement() функцию demo_drush_print_statement() :

 function demo_drush_print_statement($type = NULL) { drupal_set_message(t('Hello world!'), $type); } 

Теперь тип печатного выражения является динамическим. Во-вторых, давайте изменим функцию обратного вызова команды и изменим ее следующим образом:

 function drush_drush_demo_command($type = FALSE) { // Check for correct argument $correct_args = array('error', 'success'); if (!in_array($type, $correct_args)) { return drush_set_error(dt('"@type" is not a valid statement type. Please choose between "success" and "error".', array('@type' => $type))); } // Option $repeat = drush_get_option('repeat', 1); if ($repeat > 1 && is_numeric($repeat)) { for ($i=0; $i < $repeat; $i++) { demo_drush_print_statement($type); } } else { demo_drush_print_statement($type); } } 

Сначала мы проверяем, является ли переданный аргумент ( $type ) одним из 2 принятых типов. Если нет, мы возвращаем ошибку Drush. Если он принят, мы продолжаем и проверяем, была ли передана опция repeat , и содержит ли она числовое значение больше 1. Если нет, мы вызываем нашу demo_drush_print_statement() один раз, но если это так, мы делаем это как много раз как repeat значение. В любом случае мы также передаем аргумент $type функции в качестве параметра.

Теперь вы можете запустить команду из терминала и проверить, как работают аргумент и опция.

Пользовательский ввод

Когда вы запустите эту команду, вы заметите, что если мы передадим что-то еще, кроме двух принятых значений аргумента, она вернет ошибку Но что, если мы вообще ничего не передадим? Он возвращает общую ошибку Drush, которая жалуется на отсутствующий аргумент.

Давайте сделаем так, чтобы, если пользователь не передавал аргумент, мы спрашиваем его, какой аргумент он хотел бы передать, и используем значение, которое он предоставляет в интерактивном режиме. Для этого есть удобная функция Drush, но вся реализация может выглядеть так:

 // Check for existence of argument if (!$type) { $options = array( 'success' => dt('Success'), 'error' => dt('Error'), ); $type = drush_choice($options, dt('What kind of message you\'d like to print?')); } ... 

Это идет к вершине функции обратного вызова команды перед проверкой, был ли передан правильный аргумент. Но что мы здесь делаем?

Во-первых, все происходит, только если пользователь не передал аргумент. Во-вторых, мы создаем массив пар ключ-значение, которые будут представлять варианты, которые мы даем пользователю. Ключи массива представляют имя машины по выбору, а значения — удобочитаемое имя. В-третьих, мы передаем этот массив вдоль строки вопроса в drush_choice() которая будет возвращать имя машины по выбору пользователя. И это становится нашей новой переменной $type (аргумент).

Так что теперь мы можем попробовать это. Запустите команду без аргументов, и вам будет предложено ввести число, соответствующее одному из двух доступных вариантов. После этого вы должны увидеть соответствующее заявление.

Примеры

Как я упоминал ранее, при запуске команды справки drush help ddc для нашей собственной команды ( drush help ddc ) будет drush help ddc некоторая полезная информация об этой команде (аргументы, опции, описание, псевдонимы и т. Д.). Давайте вернемся к нашему хуку и добавим еще немного информации в нашу команду:

 ... 'examples' => array( 'drush ddc error' => 'Prints the statement once with the error flag.', 'drush ddc success --repeat=10' => 'Prints the statement 10 times with the success flag.', ), ... 

У нас есть ключи, которые представляют пример использования команды, и значение, которое описывает, что произойдет, если команда была выполнена. Теперь, если мы запустим drush help ddc , мы увидим эти полезные примеры использования этой команды.

Вывод

Вот хорошее место, чтобы закончить этот урок, так как мы рассмотрели много основных, но важных аспектов определения нашей собственной команды Drush. Мы использовали простой пример, который позволил нам проиллюстрировать многие особенности этого процесса: как определить информацию о команде и как использовать некоторые из них внутри обратного вызова. Мы смотрели на аргументы, варианты и даже видели, как мы можем получить пользовательский ввод из терминала.

Есть, конечно, еще много аспектов, которые мы не могли бы охватить здесь. Они предназначены для более продвинутых целей, но очень важны и должны иметь в виду, что они существуют. Например, вы можете указать, какой уровень начальной загрузки Drupal должен иметь Drush для запуска. Вы также можете указать зависимость модуля для команды или даже какую версию ядра она должна запустить. Так что проверьте эти вещи также на сайте Drush API и в документации для получения дополнительной информации.