Как искать, что и где изменить или немного фантазии не помешает.

Аватар пользователя ser_house ser_house 23 июня 2012 в 18:21

Навеяно вот этим и подобными вопросами — как изменить то, что выводим не мы а, скажем, ядро Drupal. Или сторонние модули.

Смысл нижеописанных действий: найти код, который отвечает за вывод и по возможности изменить его без взлома (т.е. без изменения кода не месте).

Ни в коей мере не претендуя на полноту охвата материала, надеюсь, всё же, что мой скромный опыт кому-нибудь да поможет )

Итак, представим, что нам надо отредактировать блок «Последние материалы». Для тех, кому лень лишний раз кликать, вкратце: необходимо убрать авторов последних нод.

Задача условно разбивается на четыре этапа:

  1. найти что-то, что уникально идентифицирует именно этот кусок страницы
  2. найти кто и где это что-то уникальное выводит
  3. найти кто и где выводит то, что нам не нужно (возможно, предыдущий пункт уже снял этот)
  4. изменить что и как надо

1. Найти что-то, что уникально идентифицирует именно этот кусок страницы

Самое простое (и остающееся при этом уникальным) — взять название блока за основу поиска. В самом деле — кто-то же выводит этот заголовок «Последние материалы».
Очевидно, что в коде php не будет строки «Последние материалы», скорее будет использован английский. Следовательно, надо найти строку на английском. Идем в переводы (admin/config/regional/translate/translate), вводим «Последние материалы» и видим, что в оригинале это «Recent content». Теперь мы знаем, что надо искать.

2. Найти кто и где это что-то уникальное выводит

Пару слов, о том, чем, собственно, найти. Искать будем по содержимому файлов и желательно иметь для этого удобный инструмент. Лично я (под WinXp) пользуюсь расширением для проводника StExBar с включенным инструментом grepWin:

Где искать? Ну, если есть желание включить мозг, можно попредполагать различные места. Если такого желания не возникает (хм, странно, не правда ли?) — ищите хоть по всем исходникам сайта, благо grep работает достаточно быстро.

Я, как видно из скриншота, искал по всем стандартным модулям Drupal и получил следующий результат:

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

Ну-с, откроем и посмотрим, что там у нас. А там у нас вот что:

    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'] = theme('node_recent_block', array(
            'nodes' => $nodes,
          ));
        } else {
          $block['content'] = t('No content available.');
        }
      }
      break;

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

 $block['content'] = theme('node_recent_block', array(
   'nodes' => $nodes,
 ));

выводится содержимое блока ('content'), конкретно — нод (переменная $nodes).

Мы нашли, кто и где выводит заголовок нашего блока и следовательно — вывод самого блока. Как видим, этого мало — автор выводится не здесь. Посмотрим глубже.

3. Найти кто и где выводит то, что нам не нужно

Итак, как формируются названия функций темизации мы знаем (если не знаем — это нехорошо. Нехорошо и стыдно…), посмотрим, что можно сделать. Нужная функция находится в этом же файле (если нет — проведем дополнительный поиск) и называется, как мы знаем (если не знаем — это нехорошо и т.д., см. выше) theme_node_recent_block:

function theme_node_recent_block($variables) {
  $rows = array();
  $output = '';

  $l_options = array('query' => drupal_get_destination());
  foreach ($variables['nodes'] as $node) {
    $row = array();
    $row[] = array(
      'data' => theme('node_recent_content', array('node' => $node)),
      'class' => 'title-author',
    );
    $row[] = array(
      'data' => node_access('update', $node) ? l(t('edit'), 'node/' . $node->nid . '/edit', $l_options) : '',
      'class' => 'edit',
    );
    $row[] = array(
      'data' => node_access('delete', $node) ? l(t('delete'), 'node/' . $node->nid . '/delete', $l_options) : '',
      'class' => 'delete',
    );
    $rows[] = $row;
  }

  if ($rows) {
    $output = theme('table', array('rows' => $rows));
    if (user_access('access content overview')) {
      $output .= theme('more_link', array('url' => 'admin/content', 'title' => t('Show more content')));
    }
  }

  return $output;
}

Определение, где именно в коде происходит «взятие» данных без подготовки может оказаться несколько сложным, но ведь это, извините, Drupal! Какая-то подготовка, прежде чем что-то изменять в коде, просто необходима, не так ли?

Как видим, в этой строке
'data' => theme('node_recent_content', array('node' => $node)),
непосредственно данные ноды выводятся с помощью другой функции темизации, которая называется (как мы знаем, или все ещё нет?) theme_node_recent_content и находится, что характерно, в этом же файле:

function theme_node_recent_content($variables) {
  $node = $variables['node'];

  $output = '

';
  $output .= l($node->title, 'node/' . $node->nid);
  $output .= theme('mark', array('type' => node_mark($node->nid, $node->changed)));
  $output .= '
';
  $output .= theme('username', array('account' => user_load($node->uid)));
  $output .= '
';

  return $output;
}

Имя автора выводится с помощью очередной (вот она, темизация Drupal) функции темизации и в неё мы, конечно же, не полезем (разве что в исследовательских целях).
Выполнен пункт за номером 3 — мы нашли, кто и где выводит ненужное нам имя автора.

4. Изменить что и как надо

То, что мы нашли (theme_node_recent_content) называется реализацией по умолчанию. Имеется в виду вот что: если мы не реализуем функцию с таким же именем в нашем модуле или в нашей теме, то вызвана будет эта умолчальная. Наша собственная реализация должна быть либо в модуле (приставка theme заменяется на название нашего модуля: MY_MODULE_node_recent_content), либо в шаблоне темы template.php (приставка theme заменяется на название нашей темы: MY_THEME_node_recent_content). Модуль мы, конечно, создавать не будем, а скопируем всю функцию theme_node_recent_content в template.php (находится в папке темы, если что) и заменим theme на название нашей темы. Удалим вывод имени вместе в оберткой из div-ов:

function MY_THEME_node_recent_content($variables) {
  $node = $variables['node'];

  $output = '

';
  $output .= l($node->title, 'node/' . $node->nid);
  $output .= theme('mark', array('type' => node_mark($node->nid, $node->changed)));
  $output .= '
;

  return $output;
}

Чистим кэш Drupal (admin/config/development/performance) и наслаждаемся.

Если не работает:

  • Ошиблись в названии функции. Помните, слово theme заменяется на название Вашей темы!
  • Очистили кэш браузера, а не Drupal.
  • Больше ничего в голову не приходит…

Дополнительно
Кроме поиска по видимому тексту можно точно таким же алгоритмом искать и по любым другим критериями, вроде классов css. Например, классы «tabs» и «primary» к табам локальных задач добавляются в theme_menu_local_tasks. Функция находится поиском строки «tabs primary». Ну и так далее…
Дополнительно 2
На примере достаточно простого случая я хотел показать, как «влёт» искать кто и где выводит конкретные данные в итоговый код страницы. Для описанного простого случая перекрытие функции темизации вполне подходит для решения задачи. Если же требуются более серьёзные изменения (т.е. не просто убрать что-то из вывода, а, например, добавить какие-то данные, особенно вычисляемые) то рекомендуется делать это не в функции вывода, но на этапе подготовки данных к выводу (в функции препроцесса).

И напоследок:
Default theme implementations (умолчальные реализации функций темизации в файле includes/theme.inc)
Using the theme layer (Drupal 7.x) (из названия понятно, о чём)
#187;.
Очевидно, что в коде php не будет строки

ВложениеРазмер
Иконка изображения stexbar.png9.91 КБ
Иконка изображения search_results.png6.98 КБ

Комментарии