Створення drush-команд

28.06.2013
Creating drush-commands
Автор:

Друпал-розробники зі стажем не уявляють роботи без утіліти Drush (Drupal shell), адже з її допомогою більшість рутинних дій в друпалі випоконуються значно швидше. Перелік стандартних drush-команд, таких як установка модулів, створення дампа бази, скидання пароля для адміна і т.д., можна подивитись на сайті http://drush.ws/. Проте, як там не є, а часто виникає бажання (необхідність) додати власну команду, то ж, як це робиться, ми й розглянемо в даній статті.

Приміром, нам треба створити команду, яка б видаляла всі матеріали певного типу контента. Гадаю, із такою проблемою зіштовхувались більшість із нас. Забігаючи наперед скажу, що синтаксис команди буде таким: drush delete-content %content_type%, де %content_type% - машинне ім'я типа контенту.

Створення drush-команди включає три етапи:

  • створення файла example_drush.drush.inc
  • виклик hook_drush_command() у створеному файлі
  • опис команд

Створення файла example_module.drush.inc

Зазвичай це виконується при написанні нового модуля. Створюємо файли example_drush.info та example_drush.module. Основний файл модуля може бути пустим, проте для коректної роботи drush-комманди модуль мусить бути включений. Далі створюємо командний файл example_drush.drush.inc. Закінчення файла обов'язково мусить містити "drush.inc", аби утіліта розпізнала його як такий, що містить drush-комманди. Drush веде пошук командних файлів у таких папках:

  • папка /шлях/до/drush/commands
  • папки, перераховані в опції "include"
  • загальносистемна папка командних файлів drush. наприклад - /usr/share/drush/commands
  • папка ".drush" в домашній папці користувача
  • sites/all/drush в діючій інсталяції друпала
  • папки включених модулів

Виклик hook_drush_command() у створеному файлі

Найважливіша частина командного файла - hook_drush_command(). В ньому ми даємо опис самих команд та того, як вони будут працювати. Опис команд чимось схожий на опис елементів, що використовуються в hook_menu. Розглянемо основні компоненти:

  • aliases - список скорочених назв команд. Наприклад, замість виконання довгої команд "pm-download", можна скористатись "dl". При наявності синонімів "довга" команда все одно будет працювати.
  • callback - ім'я функції, яка буде викликатись для виконання команди. Ім'я функції повинно починатись із назви файла. В нашому випадку - це example_drush_. Параметр є опціональним, за умови його відсутності drush_invoke() створить ім'я самостійно.
  • description - опис команди.
  • arguments - масив параметрів, які розпізнаються функцією. Використовуються лише для команди "drush help".
  • required-arguments - по замовчуванню встановлено на FALSE. При установці на TRUE - параметри будуть обов'язковими.
  • drupal dependenices - друпал модулі, котрі повинні бути включені.
  • drush dependencies - drush-файли, необходні для виконання команди.
  • bootstrap - фаза завантаження друпала, з якою команда буде працювати.

Так hook_drush_command() виглядає у нашому випадку:

 /**
 * Implements hook_drush_command().
 */
function example_drush_drush_command() {
  $items = array();
  $items['delete-content'] = array(
    'description' => 'Delete test content',
    'drupal dependencies' => array('example_drush'),
    'aliases' => array('dc'),
    'arguments' => array(
      'type' => 'Nodes of this type will be deleted',
    ),
  );
  return $items;
} 

Опис виконання команди

Функція, котра виконує опис команди, в нашому випадку, виглядатиме так: 

/**
 * Deletes content of specific type.
 */
function drush_example_drush_delete_content($type) {
  if ($type) {
    $nids = db_query("SELECT nid FROM {node} WHERE type = :type", array(':type' => $type))->fetchCol();
    if ($nids) {
      $deleted = 0;
      foreach ($nids as $nid) {
        node_delete($nid);
        $deleted++;
        _drush_print_progress($deleted / count($nids));
      }
      $message = $deleted ? t('Quantity of deleted "@type" nodes: !qty', array('!qty' => $deleted, '@type' => $type)) : t('There are no nodes of type "@type"', array('@type' => $type));
    }
    else {
      $message = t('There are no nodes of specified content type.');
    }
    drush_print($message);
  }
  else {
    drush_print(t('Specify content type'));
  }
}

Для виклику новоствореної команди требa ввести в терміналі "drush delete-content %content_type%", або "drush dc %content_type%", де %content_type% - машинне ім'я типу контенту.

Перед і після виконання drush-команди відбувається виклик послідовності службових функцій. Перелік варіантів можна проглянути ось тут. Наш приклад демонструє виконання функції валідації:

 /**
 * Validate handler for delete-content command.
 */
function drush_example_drush_delete_content_validate($type) {
  $types = node_type_get_types();
  if ($type && !in_array($type, array_keys($types))) {
    return drush_set_error('error', t('Content type "@type" is not exists', array('@type' => $type)));
  }
} 

Таким чином, команда буде виконуватись лише у випадку, коли вказується існуючий тип контента.

Оскільки матеріалу на сайті може бути досить багато, і відповідно, виконання команди триватиме певний час, нам треба показати користувачу, що все йде за планом і контент перебуває в процесі видалення. Із цією метою виведемо "прогрес-бар", що виконується з допомогою функції _drush_print_progress(): 

 /**
 * Provides progress bar.
 */
function _drush_print_progress($ratio) {
  $percentage = floor($ratio * 100) . '%';
  $columns = drush_get_context('DRUSH_COLUMNS', 80);
  // Subtract 8 characters for the percentage, brackets, spaces and arrow.
  $progress_columns = $columns - 8;
  // If ratio is 1 (complete), the > becomes a = to make a full bar.
  $arrow = ($ratio < 1) ? '>' : '=';
  // Print a new line if ratio is 1 (complete). Otherwise, use a CR.
  $line_ending = ($ratio < 1) ? "\r" : "\n";

  // Determine the current length of the progress string.
  $current_length = floor($ratio * $progress_columns);
  $progress_string = str_pad('', $current_length, '=');

  $output  = '[';
  $output .= $progress_string . $arrow;
  $output .= str_pad('', $progress_columns - $current_length);
  $output .= ']';
  $output .= str_pad('', 5 - strlen($percentage)) . $percentage;
  $output .= $line_ending;

  print $output;
} 

Детальніше про це можна почитати тут.

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

Також по темі

1

Трапляються ситуації коли потрібно використовувати обидва інтернет-протоколи HTTP та...

2

Сьогодні iPhone та iPad - далі iГаджети - перестали бути для нас у дивовижу, і все частіше розробники наштовхуються на проблему реалізації функціоналу під ці пристрої.

3

Ні для кого не секрет, що Google Analytics (далі — GA) — наймогутніший інструмент для збору даних...

4

Queue API - спеціальний функціонал в Drupal, який дозволяє формувати чергу і контролювати виконання трудомістких операцій на сайті. На відміну від Batch API, Queue API...

5

Інколи виникає необхідність реалізувати правила контролю доступу, які не відповідають жодним критеріям. Наприклад Ви хочете створити дозволи для окремих нод одного типу матеріалу, або потрібно...

Subscribe to our blog updates