Как написать модуль для друпал- часть 2, хуки

Продолжаю серию статей, о том как написать модуль для друпала, в этой статье речь пойдет о хуках. Погуглив «что такое hook», находил статьи, где хуки объяснялись как магические порталы и как порог вхождения в друпал, на практике оказалось, что есть 251 хук ядра друпала и функция module_hook, которая сканирует модули на наличие префиксов функций, по которым можно добавлять код своей функции в ядро друпала или в другие модули.

Происходит это следующем образом:

  1. Функция в которую можно добавить свой код должна иметь префикс hook_ , чтобы запретить использовать функцию другими модулями надо в начале функции вставить _ (знак нижнего подчеркивания).
  2. Чтобы вставить свой код в другую функцию, надо вместо hook написать название своего модуля, например для hook_help() надо mymodule_help(), где mymodule название модуля.
  3. Затем функция module_hook() определяет был ли реализован хук в модуле, если возвращается значение TRUE, то задействуется API загрузки и взаимодействия модулей

Пример 1, как программно создать блок, используя хуки.

Есть в друпале модуль block, в api которого есть 8 хуков, нам для простого блока понадобятся 2 хука, hook_block_info и hook_block_view

В листинге хуков видем следующий пример кода:

  1. hook_block_info
    function hook_block_info() {
      // This example comes from node.module.
      $blocks['syndicate'] = array(
        'info' => t('Syndicate'),
        'cache' => DRUPAL_NO_CACHE,
      );
    
      $blocks['recent'] = array(
        'info' => t('Recent content'),
        // DRUPAL_CACHE_PER_ROLE will be assumed.
      );
    
      return $blocks;
    }
  2. hook_block_view
    function hook_block_view($delta = '') {
      // This example is adapted from node.module.
      $block = array();
    
      switch ($delta) {
        case 'syndicate':
          $block['subject'] = t('Syndicate');
          $block['content'] = array(
            '#theme' => 'feed_icon',
            '#url' => 'rss.xml',
            '#title' => t('Syndicate'),
          );
          break;
    
        case 'recent':
          if (user_access('access content')) {
            $block['subject'] = t('Recent content');
            if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
              $block['content'] = array(
                '#theme' => 'node_recent_block',
                '#nodes' => $nodes,
              );
            }
            else {
              $block['content'] = t('No content available.');
            }
          }
          break;
      }
      return $block;
    }

Немного переписав код, получаем такое содержимое файла mymodule.module:

t('mymodule-Syndicate'),
    'cache' => DRUPAL_NO_CACHE,
  );

  $blocks['mymodule-recent'] = array(
    'info' => t('mymodule-Recent content'),
    // DRUPAL_CACHE_PER_ROLE will be assumed.
  );

  return $blocks;
}

function mymodule_block_view($delta = '') {
  // This example is adapted from node.module.
  $block = array();

  switch ($delta) {
    case 'mymodule-syndicate':
      $block['subject'] = t('mymodule-Syndicate');
      $block['content'] = array(
        '#theme' => 'feed_icon',
        '#url' => 'rss.xml',
        '#title' => t('mymodule-Syndicate'),
      );
      break;

    case 'mymodule-recent':
      if (user_access('access content')) {
        $block['subject'] = t('mymodule-Recent content');
        if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
          $block['content'] = array(
            '#theme' => 'node_recent_block',
            '#nodes' => $nodes,
          );
        }
        else {
          $block['content'] = t('No content available.');
        }
      }
      break;
  }
  return $block;
}

На странице настройки блоков (admin/structure/block) видим наши 2 созданных блока.

Указав для них Sidebar first и нажав сохранить, видим наши 2 созданных блока в первом сайдбаре.

Пример 2, как программно создать страницу, используя хуки.

Для создания страницы надо использовать hook_menu(), на странице с описанием модуля видим листинг:

function hook_menu() {
  $items['example'] = array(
    'title' => 'Example Page',
    'page callback' => 'example_page',
    'access arguments' => array('access content'),
    'type' => MENU_SUGGESTED_ITEM,
  );
  $items['example/feed'] = array(
    'title' => 'Example RSS feed',
    'page callback' => 'example_feed',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

Немного переписав код из примера получаем:

function mymodule_menu() {
 
  $items['hello'] = array(
    'title' => 'hello world',
    'page callback' => 'mymodule_hello',
    'access callback' => TRUE,
    'menu_name' => 'main-menu',
    'options' => array('attributes' => array('class' => array('test-class'))),
  );
 
  return $items;
}

function mymodule_hello() {
  return 'hello world';
}

Теперьпо адресу /hello, будет доступна страница созданная с помощью hook_menu()