Кто здесь работает или как быстро узнать информацию о callback`е для меню Drupal`а

в 12:43, , рубрики: debug, drupal, drupal 6, drush, Песочница, метки: , , ,

Привет читатель!

Я являюсь WEB разработчиком, программирую на PHP. Основным моим направлением является разработка сайтов с использованием CMS/CMF Drupal. Я работаю в небольшой IT организации, проекты бывают всякие (большие, маленькие, новые, прибывшие на допил и т.д.). В последнее время (в моём случае это уже год) я сталкиваюсь с такими проектами на которых работали одни, потом другие, третьи… И в осномном на таких проектах заказчик просит поправить как правило что-то по мелочи (там элемент в форму вставить, там-то класс дополнительный нужен и т.д.) Но поскольку проеты большие иногда случается такое что даже толком не всегда получается определить «а что же тут работает? какой модуль?». С года 2 назад я узнал про drush, весьма удобен, полезен, но самое главное не тратиться время на рендеринг страниц (его уходит очень много для построения страницы). И тут я понял что было бы хорошо как-то узнавать такую мелочную информацию через консоль, получилось довольно быстро и удобно как мне кажется.

На большинстве проектов, основанных на какой-то готовой модульной базе (как Drupal), всегда присутствуют свои, написанные исключительно под цели конкретного проекта, модули. Ну и стоит задействовать в нашем случае один из них для интеграции с drush. Пусть модуль называется cm. Используется Drupal 6. Далее я привожу код из файла cm.drush.inc

Стандартные хуки для описания функционала drush команд:

/**
 * Implementation of hook_drush_help().
 */
function cm_drush_help($section) {
  switch ($section) {
    case 'drush:browse-url':
      return dt('Show URL's info');
    case 'drush:browse-theme':
      return dt('Show theme function info');
  }
}

/**
 * Implements hook_drush_command().
 */
function cm_drush_command() {
  $items = array();

  $items['browse-url'] = array(
    'description' => dt('Show URL's info.'),
    'arguments' => array(
      'url' => dt('URL from browser'),
    ),
    'aliases' => array('burl'),
  );

  $items['browse-theme'] = array(
    'description' => dt('Show theme function info.'),
    'arguments' => array(
      'theme_item' => dt('theme function'),
    ),
    'aliases' => array('btheme'),
  );

  return $items;
}

Теперь непосредственно по командам

browse-url (burl)

выводит на экран информацию о callback`е которую передали этой команде

function drush_cm_browse_url($url) {
  $url = drupal_get_normal_path($url);
  drush_print(dt('Original path is: "!path"', array('!path' => $url)));
  $router_item = menu_get_item($url);
  if($router_item['file']) {
    require_once($router_item['file']);
  }

  $data = array();
  $data['path'] = $router_item['path'];
  $data['access_callback'] = $router_item['access_callback'];
  $data['access_arguments'] = implode(", ", unserialize($router_item['access_arguments']));
  $data['page_callback'] = $router_item['page_callback'];
  $data['page_arguments'] = implode(", ", unserialize($router_item['page_arguments']));
  $data['tab_root'] = $router_item['tab_root'];
  $data['title'] = $router_item['title'];
  $data['title_callback'] = $router_item['title_callback'];
  drush_print(_cm_getting_function_info($router_item['page_callback']));
  drush_print_table(drush_key_value_to_array_table($data));
}

function _cm_getting_function_info($function_name) {
  include_once './includes/install.inc';
  drupal_load_updates();

  if (strpos($function_name, '::') === FALSE) {
    if (!function_exists($function_name)) {
      return drush_set_error(dt('Function not found'));
    }
    $reflect = new ReflectionFunction($function_name);
  }
  else {
    list($class, $method) = explode('::', $function_name);
    if (!method_exists($class, $method)) {
      return drush_set_error(dt('Method not found'));
    }
    $reflect = new ReflectionMethod($class, $method);
  }
  $func_info = array('!file' => $reflect->getFileName(), '!startline' => $reflect->getStartLine(), '!endline' => $reflect->getEndLine());
  //drush_print_pipe(dt("!file -line !startline", $func_info));
  return dt("Execute in : !file, lines !startline-!endline", $func_info);
}

Результат работы команды довольно симпотичный

$ drush burl admin
Original path is: "admin"
Execute in : /var/www/d6/modules/system/system.admin.inc, lines 11-59
 path               :  admin                       
 access_callback    :  user_access                 
 access_arguments   :  access administration pages 
 page_callback      :  system_main_admin_page      
 page_arguments     :                              
 tab_root           :  admin                       
 title              :  Administer                  
 title_callback     :  t                

видим original path (это на случай если тут вдруг система алиасов уже постаралась), в каком файле, какие строки и сообственно описание меню. Довольно удобно, не так ли? но правда есть такие callback`и-формы как тут например:

drush burl admin/settings/file-system
Original path is: "admin/settings/file-system"
Execute in : /var/www/d6/includes/form.inc, lines 70-149
 path               :  admin/settings/file-system    
 access_callback    :  user_access                   
 access_arguments   :  administer site configuration 
 page_callback      :  drupal_get_form               
 page_arguments     :  system_file_system_settings   
 tab_root           :  admin/settings/file-system    
 title              :  File system                   
 title_callback     :  t

В этом случае скрипт будет полезен хотя бы с той точки зрения что покажет хотя бы имя функции для генерации формы.

В описании хуков есть ещё одна команда.

browse-theme (btheme)

function drush_cm_browse_theme($theme_item) {
  init_theme();
  $hooks = theme_get_registry();
  var_dump($hooks[$theme_item]);
}

Она показывает информацию о функции темизации, но правда тут стоит оговориться что она сделана в черновом варианте, так сказать as is.

$ drush btheme item_list
array(7) {
  ["arguments"]=>
  array(4) {
    ["items"]=>
    array(0) {
    }
    ["title"]=>
    NULL
    ["type"]=>
    string(2) "ul"
    ["attributes"]=>
    NULL
  }
  ["type"]=>
  string(6) "module"
  ["theme path"]=>
  string(14) "modules/system"
  ["function"]=>
  string(15) "theme_item_list"
  ["include files"]=>
  array(0) {
  }
  ["theme paths"]=>
  array(1) {
    [0]=>
    string(14) "modules/system"
  }
  ["preprocess functions"]=>
  array(1) {
    [0]=>
    string(19) "template_preprocess"
  }
}

Это пример вывода информации о функции темизации item_list


Для того чтобы адаптировать всё это под Drupal 7 много не потребуется времени (а может и вообще не надо будет, я не проверял если честно), просто на допил мне эти проекты на 6ой версии пришли потому и соорудил для этой версии.

Автор: YurkinPark

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js