Ctools тип контента для Panels

12.10.2012
Share on FacebookShare on TwitterShare on GooglePlusShare on Linkedin
Автор:

Наша компания веб разработчиков очень часто использует модуль Panels для построения сайтов. Хоть это решение добавляет немало HTML-структуры, но взамен мы получаем гибкий, удобный, простой в обслуживании механизм. Но иногда встроенных возможностей модуля бывает недостаточно (нестандартные требования заказчика либо внутренний порыв сделать что-то так же, но лучше). Ctools типы контента чем то похожи на стандартные блоки в Drupal, но у них есть свои преимущества:

  • возможность вывода любой информации - вьюшки, формы, HTML
  • эти сущности хорошо структурируются - теминг, препроцесс и форма настроек для каждого ctools content type описывается внутри него самого
  • они работают с контекстами панелей
  • легко реализовать форму настроек отображения.

Рассмотрим процесс создания ctools типа контента. Для этого создадим модуль "ctools_example". В модуле вызываем hook_ctools_plugin_directory(), который сообщает ctools расположение папки с плагинами указанного типа. У хука есть два параметра:

  • $plugin_type - название параметра говорит само за себя - это строковое название типа плагина('Panels', 'layouts', 'styles' и т.д.)
  • $owner - обязательный параметр, ибо ctools соблюдает пространство имен по плагинам в зависимости от того какому модулю они принадлежат. Обычно используется путь "plugins/$plugin_type".
/*
 * Implements hook_ctools_plugin_directory -
 */
function ctools_example_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'ctools' && $plugin_type == 'content_types') {
    return 'plugins/content_types';
  }
}

Далее создаем папку "plugins/content_types" и помещаем туда файл с нашим плагином, например "ctools_example_content_type.inc". В этом файле первым делом описываем плагин. Доступные параметры:

  • 'title' - название нашего типа контента
  • 'description' - детальное его описание
  • 'single' - если здесь TRUE, то в этом типе контента подтипов нет
  • 'content_types' - массив определений типа контента либо функция, возвращающая этот массив 
  • 'render callback' - название функции, которая будет отвечать за вывод блока
  • 'defaults' - контекст по умолчанию
  • 'edit form' - название функции, которая будет отвечать за вывод формы редактирования типа контента
  • 'icon' - иконка, которая будет отображаться в админ интерфейсе. Иконка должна находиться в папке с плагином
  • 'category' - категория, к которой будет относиться новосозданный тип контента 

Весь перечень параметров можно посмотреть установив модуль Advanced help.

 /**
 * Plugins are described by creating a $plugin array which will be used
 * by the system that includes this file.
 */
$plugin = array(
  'title' => t('Example block'),
  'description' => t('Example block.'),
  // 'single' => TRUE means has no subtypes.
  'single' => TRUE,
  // Constructor.
  'content_types' => array('no_context_content_type'),
  // Name of a function which will render the block.
  'render callback' => 'ctools_example_static_block_render',
  // The default context.
  'defaults' => array(),

  // This explicitly declares the config form. Without this line, the func would be
  // ctools_plugin_example_no_context_content_type_edit_form.
  'edit form' => 'ctools_example_example_block_edit_form',
  'icon' => 'favicon.ico',
  'category' => array(t('Example'), -9),
);

Думаю, вы уже догадались, что далее нам нужно объявить функции вывода и редактирования нашего творения. Создадим простой тип контента, который будет с помощью автозаполнения подтягивать некую ноду и выводить ее заголовок и текст. Вывод заголовка, вывод его ссылкой/не ссылкой и вывод текста будет опциональным. Вот собственно и сама форма:

/**
 * Generates example block edit form.
 */
function ctools_example_example_block_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  // We don't want to use standart pane title functionallity.
  $form['override_title']['#access'] = FALSE;
  $form['override_title_text']['#access'] = FALSE;
  $form['override_title_markup']['#access'] = FALSE;
  $form['title_nid'] = array(
    '#type' => 'textfield',
    '#title' => t('Enter content title'),
    '#autocomplete_path' => 'ctools_example/autocomplete',
    '#default_value' =>  $conf['title_nid'] ? $conf['title_nid'] : '',
  );
  $form['show_body'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show body'),
    '#default_value' =>  $conf['show_body'] ? TRUE : FALSE,
  );
  $form['display_title'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display title'),
    '#default_value' =>  $conf['display_title'] ? TRUE : FALSE,
  );
  $form['title_as_link'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display title as link'),
    '#default_value' =>  $conf['title_as_link'] ? TRUE : FALSE,
    '#states' => array(
      'visible' => array(
        ':input[name="display_title"]' => array('checked' => TRUE),
      ),
    ),
  );

  return $form;
}

К форме редактирования ctools типа контента можно добавлять submit/validate - обработчики также как и к стандартным формам в Drupal. В нашем случае validate - обработчик будет проверять правильность ввода в поле автозаполнения, а submit - обработчик будет сохранять настройки для конкретного блока:

/**
 * Validate handler for example block edit form.
 */
function ctools_example_example_block_edit_form_validate($form, &$form_state) {
  $text = $image = $video = $audio = FALSE;
  if (!preg_match('/.*\[nid:([\d]+)\]/', $form_state['values']['title_nid'], $m)) {
    form_set_error('title_nid', t('Title should be in format "Title [nid:xxx]"'));
  }
}

/**
 * Submit handler for example block edit form.
 */
function ctools_example_example_block_edit_form_submit($form, &$form_state) {
  foreach (array('title_nid', 'display_title', 'title_as_link', 'show_body') as $key) {
    $form_state['conf'][$key] = $form_state['values'][$key];
  }
}

Ну и в завершение функция, отвечающая за вывод контента нашего блока. Как видно из кода логика вывода напоминает логику, которая используется в hook_block_view(). При выводе нам нужно сформировать объект со следующими возможными свойствами:

  • 'title' - заголовок блока
  • 'content' - контент блока
  • 'links' - массив ссылок, относящихся к контенту. Формат массива должен быть в таком же формате как и для функции theme_links
  • 'more' - опциональная ссылка наподобие "Читать далее" 

Полный перечень свойств можно посмотреть установив все тот же модуль Advanced help.

/**
 * Run-time rendering of the body of the block.
 *
 * @param $subtype
 * @param $conf
 *   Configuration as done at admin time.
 * @param $args
 * @param $context
 *   Context - in this case we don't have any.
 *
 * @return
 *   An object with at least title and content members.
 */
function ctools_example_example_block_render($subtype, $conf, $args, $context) {
  $block = new stdClass();
  $block->content = '';
  if (!empty($conf)) {
    preg_match('/(.*) \[nid:([\d]+)\]/', $conf['title_nid'], $m);
    if (isset($m[1]) && is_numeric($m[2])) {
      $nid = $m[2];
      $node = node_load($nid);
      if ($conf['display_title']) {
        $block->title = $conf['title_as_link'] ? l($node->title, "node/{$node->nid}") : $node->title;
      }
      $lang = field_language('node', $node, 'body');
      if ($conf['show_body']) {
        $block->content .= $node->body[$lang][0]['value'];
      }
    }
  }
  return $block;
}

Весь код модуля смотрите в прикрепленных файлах, приблизительный вид админ интерфейса на скриншотах.

Спасибо за внимание.

1 vote, Rating: 5
Share on FacebookShare on TwitterShare on GooglePlusShare on Linkedin

Также по теме

1

Queue API — специальный функционал в Drupal, который позволяет формировать очередь и контролировать выполнение трудоемких операций на сайте. В отличии от Batch API, Queue...

2

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

4

В наши дни все знают о таких интернет-магазинах как eBay, Amazon и.т.д. Но мало...

5

Не все знают, что модуль Views предоставляет довольно обширный ...

Need a quote? Let's discuss the project

Are you looking for someone to help you with your Drupal Web Development needs? Let’s get in touch and discuss the requirements of your project. We would love to hear from you.

Join the people who have already subscribed!

Want to be aware of important and interesting things happening? We will inform you about new blog posts on Drupal development, design, QA testing and more, as well news about Drupal events.

No charge. Unsubscribe anytime