Создаём тему для Drupal 6. Часть 1

    image
    По созданию тем для друпала в интернете можно найти несколько статей (хорошая статья, советую почитать), однако обычно всё заканчивается банальным набором шаблонов и инфо-файлом. В этом топике я постараюсь доступно рассказать как создать гибкую и не самую простую тему.

    Начало


    Для начала нам потребуется создать директорию в каталоге sites/all/themes с названием нашей темы. Я назвал тему mytheme и создал каталог sites/all/themes/mytheme.
    В созданном каталоге создаем директории css — для стилей, js — для скриптов, images — для картинок, templates — для шаблонов, preprocess — об этом позже. Также создаем файл template.php в котором мы будем писать всю логику темы и mytheme.info для описания темы. Можно еще добавить favicon.ico и logo.png.

    mytheme.info


    Файл содержит всю информацию, необходимую ядру для работы с темой.
    Создадим файл примерно со следующим содержанием:
    Copy Source | Copy HTML
    1. ; Название темы, как оно будет отображаться в админке
    2. name = MyTheme
    3. ; Описание темы
    4. description = Моя новая тема
    5. ; Версия ядра
    6. core = 6.x
    7. ; Шаблонизатор используемый темой, по умолчанию phptemplate
    8. engine = phptemplate
    9. ; Версия темы
    10. version = 6.x-1.01
    11.  
    12. ; Путь к скриншоту темы
    13. screenshot = images/screenshot.png
    14.  
    15. ; Регионы темы, в которые можно будет вставлять блоки
    16. regions[sidebar_right] = Right sidebar
    17. regions[sidebar_left] = Left sidebar
    18. regions[header_line] = Line in header
    19. regions[footer_line] = Line in footer
    20. regions[content_top] = Content top
    21. regions[content_bottom] = Content bottom
    22. regions[content_right] = Content right
    23. regions[comments_rigth] = Comments right
    24. regions[page_bottom] = Page bottom
    25.  
    26. ; Настройки темы, которые будут доступны из админки
    27. ;features[] = name
    28. features[] = node_user_picture
    29. features[] = comment_user_picture
    30. features[] = search
    31. ;features[] = favicon
    32. ;features[] = primary_links
    33. ;features[] = secondary_links
    34.  
    35. ; Стили
    36. stylesheets[all][] = css/blocks.css
    37. stylesheets[all][] = css/comments.css
    38. stylesheets[all][] = css/fields.css
    39. stylesheets[all][] = css/forms.css
    40. stylesheets[all][] = css/html-reset.css
    41. stylesheets[all][] = css/layout.css
    42. stylesheets[all][] = css/messages.css
    43. stylesheets[all][] = css/navigation.css
    44. stylesheets[all][] = css/nodes.css
    45. stylesheets[all][] = css/pages.css
    46. stylesheets[all][] = css/tabs.css
    47.  
    48. ;stylesheets[print][] = css/print.css
    49.  
    50. ;stylesheets[handheld][] = css/mobile.css
    51. ;stylesheets[only screen and (max-device-width: 480px)][] = css/iphone.css
    52.  
    53. ; Скрипты
    54. ;scripts[] = js/script.js


    Этого достаточно, чтобы друпал увидел и опознал нашу тему. Я выбрал такой набор стилей и регионов, т.к. нахожу его удобным. Вы можете изменить на свой вкус.

    template.php


    Самая вкусная часть темы. В этом файле мы будем писать всю логику — хуки.

    Для начала определим HOOK_theme().
    Copy Source | Copy HTML
    1. function mytheme_theme(&$existing, $type, $theme, $path) {
    2.     // Определяем базовую тему, если наша тема дочерняя
    3.     static $base_themes = array();
    4.     $base_themes[] = $theme;
    5.  
    6.     // Добавляем хук "process", который будет вызываться после "preprocess".
    7.     if ($type == 'theme') {
    8.         foreach (array_keys($existing) as $hook) {
    9.             if (function_exists($theme . '_preprocess')) {
    10.                 $existing[$hook]['preprocess functions'][] = $theme . '_preprocess';
    11.             }
    12.             if (function_exists($theme . '_preprocess_' . $hook)) {
    13.                 $existing[$hook]['preprocess functions'][] = $theme . '_preprocess_' . $hook;
    14.             }
    15.             foreach ($base_themes as $base_theme) {
    16.                 if (function_exists($base_theme . '_process')) {
    17.                     $existing[$hook]['preprocess functions'][] = $base_theme . '_process';
    18.                 }
    19.                 if (function_exists($base_theme . '_process_' . $hook)) {
    20.                     $existing[$hook]['preprocess functions'][] = $base_theme . '_process_' . $hook;
    21.                 }
    22.             }
    23.         }
    24.     }
    25.  
    26.     // Добавляем препроцессы только для данной темы, они не распространятся на дочерние темы
    27.     if ($theme == 'mytheme') {
    28.         return array(
    29.             // Добавляем регион. Это необходимо, чтобы мы могли использовать шаблоны для регионов
    30.             'region' => array(
    31.                 // Аргументы, которые будут доступны
    32.                 'arguments' => array('elements' => NULL),
    33.                 // Путь к шаблону
    34.                 'path' => drupal_get_path('theme', 'mytheme') . '/templates',
    35.                 // Название шаблона. Полное имя файла будет region.tpl.php
    36.                 'template' => 'region',
    37.                 // Функции, которые будут подготавливать переменные для шаблонизации
    38.                 'preprocess functions' => array(
    39.                     'template_preprocess',
    40.                     'mytheme_preprocess',
    41.                     'mytheme_preprocess_region',
    42.                     'mytheme_process',
    43.                 ),
    44.             ),
    45.             // Выносим header и footer в отдельные шаблоны
    46.             'header' => array(
    47.                 'arguments' => array('elements' => NULL),
    48.                 'path' => drupal_get_path('theme', 'mytheme') . '/templates',
    49.                 'template' => 'header',
    50.                 'preprocess functions' => array(
    51.                     'template_preprocess',
    52.                     'mytheme_preprocess',
    53.                     'mytheme_preprocess_header',
    54.                     'mytheme_process',
    55.                 ),
    56.             ),
    57.             'footer' => array(
    58.                 'arguments' => array('elements' => NULL),
    59.                 'path' => drupal_get_path('theme', 'mytheme') . '/templates',
    60.                 'template' => 'footer',
    61.                 'preprocess functions' => array(
    62.                     'template_preprocess',
    63.                     'mytheme_preprocess',
    64.                     'mytheme_preprocess_footer',
    65.                     'mytheme_process',
    66.                 ),
    67.             ),
    68.         );
    69.     }
    70.     return array();
    71. }


    Определим theme_blocks($region). Функция возвращает набор блоков, доступных для текущего пользователя в заданном регионе.
    Copy Source | Copy HTML
    1. function mytheme_blocks($region) {
    2.     if ($region) {
    3.         $output = '';
    4.  
    5.         if ($list = block_list($region)) {
    6.             foreach ($list as $key => $block) {
    7.                 $output .= theme('block', $block);
    8.             }
    9.         }
    10.  
    11.         // Контент для данного региона
    12.         $output .= drupal_get_content($region);
    13.  
    14.         $elements['#children'] = $output;
    15.         $elements['#region'] = $region;
    16.  
    17.         // Возвращаем темизированный регион с блоками. Используется region.tpl.php
    18.         return $output ? theme('region', $elements) : '';
    19.     }
    20. }


    Определим template_preprocess(&$variables, $hook). Функция подготавливает переменные, которые будут переданы в шаблон.
    Copy Source | Copy HTML
    1. function mytheme_preprocess(&$vars, $hook) {
    2.     $key = ($hook == 'page' || $hook == 'maintenance_page') ? 'body_classes' : 'classes';
    3.  
    4.     if (array_key_exists($key, $vars)) {
    5.         if (is_string($vars[$key])) {
    6.             $vars['classes_array'] = explode(' ', $vars[$key]);
    7.             unset($vars[$key]);
    8.         }
    9.     }
    10.     else {
    11.         $vars['classes_array'] = array($hook);
    12.     }
    13.  
    14.     // Тут немного магии.
    15.     // Для каждого хука типа hook_preprocess_anything() мы ищем соответствующий файл
    16.     // в каталоге preprocess и вызываем его
    17.     $name = 'preprocess/preprocess-'. str_replace('_', '-', $hook) .'.inc';
    18.     if (is_file(drupal_get_path('theme', 'mytheme') . '/' . $name)) {
    19.         include($name);
    20.     }
    21. }


    Определим HOOK_process() описанный ранее.
    Copy Source | Copy HTML
    1. function mytheme_process(&$vars, $hook) {
    2.     if (array_key_exists('classes_array', $vars)) {
    3.         // Сливаем в строку все стили для элемента
    4.         $vars['classes'] = implode(' ', $vars['classes_array']);
    5.     }
    6. }
    7.  


    Определим функцию, которая вернет путь к нашей теме.
    Copy Source | Copy HTML
    1. function _mytheme_path() {
    2.     static $path = FALSE;
    3.     if (!$path) {
    4.         $matches = drupal_system_listing('mytheme\.info$', 'themes', 'name',  0);
    5.         if (!empty($matches['mytheme']->filename)) {
    6.             $path = dirname($matches['mytheme']->filename);
    7.         }
    8.     }
    9.     return $path;
    10. }
    11.  


    Ну и наконец, добавим пару функций для обработки классов и id для страниц
    Copy Source | Copy HTML
    1. if (!function_exists('drupal_html_class')) {
    2.     function drupal_html_class($class) {
    3.         $class = strtr(drupal_strtolower($class), array(' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => ''));
    4.  
    5.         $class = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $class);
    6.  
    7.         return $class;
    8.     }
    9. }
    10.  
    11. if (!function_exists('drupal_html_id')) {
    12.     function drupal_html_id($id) {
    13.         $id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
    14.         $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id);
    15.         return $id;
    16.     }
    17. }


    Часть 2, Часть 3
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 16
    • +1
      Спасибо! Давно искал статью, где было бы так хорошо расписано создание темы для drupal)
      • 0
        Да уж. На мой взгляд это какой-то чудовищный процесс, далекий от всякого удобства.
        • +5
          Программирование и веб-разработка, насколько я могу судить, штуки вообще не из легких :)
          • +1
            Процесс создания темы может и кажется чудовищным. Зато на основе созданного шаблона потом можно будет с лёгкостью делать готовые темы.
            • +1
              спорный вопрос.
              Процесс создания темы для drupal может быть и не самый быстрый и понятный, но когда познаешь всю гибкость и возможности, то всё очень круто! )
              • –2
                Потому что весь Друпал левой пяткой написан, что тут удивляться.
              • 0
                Огромнейшее спасибо! Этот вопрос меня давно интересовал, теперь уйдёт меньше времени и сил.
                • 0
                  Выскакивают вот такие ошибки:
                  # warning: Invalid argument supplied for foreach() in Z:\home\site\includes\theme.inc on line 463.
                  # warning: Invalid argument supplied for foreach() in Z:\home\site\includes\theme.inc on line 468.
                  • 0
                    Я не выкладывал исходники темы рассчитывая на то, что вы, прежде чем копировать код, посмотрите на него и поймете как он работает, оставите только нужное и сделаете свою тему. Готовые темы можно скачать на drupal.org
                  • 0
                    Очень удобно начинать разработку собственной темы на основе темы ZEN
                  • +1
                    Не зря я вам когда-то инвайт дал, отличный цикл статей.
                    • 0
                      Большое спасибо! Очень полезная информация.
                      • 0
                        Нифига себе ещё и 3 части ах**ть!
                        • 0
                          После того, как корректируешь код уже готового шаблона, нужно обновить кэш в админке друпала, чтобы изменения отобразились на рабочем шаблоне.
                          Некоторых может это тормозить… =)

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.