Как оформить requirements для сторонних библиотек

Как оформить requirements для сторонних библиотек

На странице контрибных модулей, авторы обычно указывают версии и ссылки для скачивания библиотек, которые использует их модуль. Необходимо также при установке/работе модуля напомнить пользователю о требуемых библиотеках, если он их еще не установил, иначе это может породить множество ошибок. Списать все это на проблемы пользователя (не досмотрел, не скачал, не поставил и т.д.) - не лучший подход.
При решении данного вопроса поможет хук hook_requirements().
Для примера возьмем библиотеку Jcrop (используется для обрезки изображений). Хук располагается в MYMODULE.install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
 * Implements hook_requirements().
 */
function MYMODULE_requirements($phase) {
  $requirements = array();
  $t = get_t();
 
  if (in_array($phase, array('runtime', 'install'))) {
    // Инициализируем пути для дефолтного расположения библиотек и для библиотек в текущем профиле.
    $profile_path = 'profiles/' . drupal_get_profile() . '/libraries';
    $default_path = 'sites/all/libraries';
 
    // Инициализируем массив библиотеки.
    $download_link = 'http://code.google.com/p/jcrop/downloads/detail?name=jquery.Jcrop-0.9.8.zip&can=2';
    $info = array(
      'jcrop' => array(
        'title' => $t('MYMODULE: Jcrop'),
        'general_path' => $default_path . '/Jcrop/js/jquery.Jcrop.js',
        'profile_path' => $profile_path . '/Jcrop/js/jquery.Jcrop.js',
        'download_url' => l($t('jcrop library'), $download_link),
      ),
    );
 
    // Массив всех установленных библиотек.
    $libraries = array();
    if (function_exists('libraries_get_libraries')) {
      $libraries = libraries_get_libraries();
    }
 
    foreach ($info as $lib_name => $data) {
      $requirements[$lib_name]['title'] = $data['title'];
 
      // Проверяем исполняемые файлы на существование.
      $is_file_general = file_exists($data['general_path']);
      $is_file_profile = file_exists($data['profile_path']);
 
      // Проверяем условия.
      if (isset($libraries[$lib_name]) || $is_file_general || $is_file_profile) {
        $requirements[$lib_name]['value'] = $t('Installed');
        $requirements[$lib_name]['severity'] = REQUIREMENT_OK;
      }
      else {
        $requirements[$lib_name]['value'] = $t('Not installed');
        $requirements[$lib_name]['severity'] = REQUIREMENT_ERROR;
        $requirements[$lib_name]['description'] = $t('Please download the %lib library from !link', array(
          '%lib'  => ucfirst($lib_name),
          '!link' => $data['download_url'],
        ));
      }
    }
  }
  return $requirements;
}

Входной аргумент $phase сигнализирует о том, в какой фазе сейчас находится модуль (install, update, runtime). Возможные значения severity сообщений:

  • REQUIREMENT_INFO - исключительно для информативного сообщения
  • REQUIREMENT_OK - требование выполнено
  • REQUIREMENT_WARNING - требование не выполнено, предупреждение
  • REQUIREMENT_ERROR - требование не выполнено, ошибка

Кроме того, информация об установленных библиотеках будет доступна на странице статуса (admin/reports/status).
страница статуса
В данном случае при попытке включить кастомный модуль без установленной библиотеки будет выведена соответствующая ошибка.
ошибка при установке модуля
В хуке hook_requirements() можно проверять не только наличие библиотек, но и версии php, jQuery и т.д., практически всего, что требуется для работы вашего модуля. Например, проверить версию jQuery можно так

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if ($phase == 'runtime') {
  // Читаем 360 байт файла jquery.js. Как правило этим количеством 
  // байт мы захватим комментарий, который содержит версию.
  $script = DRUPAL_ROOT . "/misc/jquery.js";
  $handle = fopen($script, "r");
  $string = fread($handle, 360);
  fclose($handle);
 
  // Требуемая версия jQuery.
  $required = '1.11.3';
 
  // Парсим текущую версию и инициализируем массив $requirements.
  $version = preg_replace('/.*v([\d.]+).*/is', '$1', $string);
  $requirements['jquery'] = array(
    'title' => $t('MYMODULE: jQuery'),
    'value' => $t('Compatible'),
    'severity' => REQUIREMENT_OK,
  );
 
  // Сравниваем строки и выводим ошибку, если не совпадают.
  if ($version !== $required) {
    $requirements['jquery']['value'] = $t('Not compatible');
    $requirements['jquery']['severity'] = REQUIREMENT_ERROR;
    $requirements['jquery']['description'] = $t('Module works correctly only with jQuery v%v. Current version - %c. Please update the jQuery.', array(
      '%v' => $required,
      '%c' => $version,
    ));
  }
}

Вышеописанный метод определения версии jQuery не претендует на абсолютную истину, но может быть использован как вполне рабочий вариант. На странице статуса сообщение будет выглядеть так
jquery requirements

Дополнительная информация по статье

  1. https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_requirements/7 - полное описание hook_requirements().