Пишем модуль под Drupal. Часть 6. Хуки form_alter и nodeapi

вт, 13.04.2010 14:39 :: olk
Теперь нам надо позволить пользователям (с разрешением на закрепление ноды вверху трэкера и/или запрещением публикации ноды в трэкере) при редактировании материала как-то устанавливать данные признаки. В этом нам поможет хук form_alter.
Хук form_alter позволяет добавить либо изменить элементы формы еще до рендеринга этой самой формы, причем если это форма редактирования (добавления) ноды, то в элементе $form['#node'] будет присутствовать текущий объект ноды.

В нашем случае, мы проверяем, является ли объект нодой (причем тип материала должен быть включен в настройках нашего трэкера) и добавляем в отдельную область (fieldset) два чекбокса, которые будут отвечать за наши дополнительные параметры у ноды. Доступ к этим элементам зависит от прав пользователя, которые мы определили в предыдущей части (см. хук perm).

Шаг номер 14:

Данную функцию мы помещаем в основной файл модуля cctracker.module.

  1. function cctracker_form_alter(&$form, &$form_state, $form_id) {
  2.   if (isset($form['type']) && isset($form['#node']) &&
  3.     $form['type']['#value'] .'_node_form' == $form_id &&
  4.     (in_array($form['type']['#value'], variable_get('cctracker_node_types', array()), TRUE) ||
  5.      in_array($form['type']['#value'], variable_get('cctracker_tab_types', array()), TRUE))
  6.      ) {
  7.     $cctracker = db_fetch_object(db_query("SELECT cc_sticky,cc_not_public,cc_sticky_weight FROM {node_cctracker} WHERE nid = %d", $form['#node']->nid));
  8.     $form['cctracker'] = array(
  9.       '#type' => 'fieldset',
  10.       '#title' => t('Cctracker settings'),
  11.       '#collapsible' => TRUE,
  12.       '#collapsed' => !($cctracker->cc_sticky || $cctracker->cc_not_public),
  13.       '#access' => user_access('access not place cctracker') || user_access('access sticky cctracker'),
  14.       '#weight' => 30,
  15.     );
  16.       $form['cctracker']['cc_sticky'] = array(
  17.         '#type' => 'checkbox',
  18.         '#title' => t('Sticky this node on top tracker'),
  19.         '#access' => user_access('access sticky cctracker'),
  20.         '#default_value' => $cctracker->cc_sticky,
  21.       );
  22.       $form['cctracker']['cc_sticky_weight'] = array(
  23.       '#type' => 'weight',
  24.       '#title' => t('Sticky Weight'),
  25.       '#default_value' => $cctracker->cc_sticky_weight,
  26.       '#access' => user_access('access sticky cctracker'),
  27.       '#delta' => 10,
  28.       '#description' => t('Optional. In the tracker, the heavier items will sink and the lighter items will be positioned nearer the top.'),
  29.       );
  30.       $form['cctracker']['cc_not_public'] = array(
  31.         '#type' => 'checkbox',
  32.         '#title' => t('Not public in cctracker'),
  33.         '#access' => user_access('access not place cctracker'),
  34.         '#default_value' => $cctracker->cc_not_public,
  35.       );
  36.   }
  37. }
Теперь при редактировании ноды (если у нас есть соответствующие права и тип материала включен в настройках cctraker) у нас появляется возможность изменить соответствующие опции для нашей ноды. Но нам еще надо как то сохранить эти опции в нашей таблице. Прекрасное место где это можно сделать, хук nodeapi
Хук nodeapi позволяет модулям реагировать на действия, затрагивающие все типы узлов. Как правило, хук nodeapi используется в сочетании с хук form_alter. Модули могут использовать хук form_alter, чтобы разместить дополнительные элементы в форме, а хук nodeapi для чтения и из базы данных и записи в базу дополнительных данных из добавленных полей формы.

Шаг номер 15: Определяем хук nodeapi в нашем файле cctracker.module

В данном хуке нас интересуют только три действия
  • insert - запись новой ноды
  • update - изменение ноды
  • delete - удаление ноды

Что бы визуально не перегружать код функции, мы так-же написали вспомогательную функцию _cctracker_node_save, которая собственно и выполняет все действия с базой данных.

  1. function cctracker_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  2.   if (in_array($node->type, variable_get('cctracker_node_types', array()), TRUE) ||
  3.       in_array($node->type, variable_get('cctracker_tab_types', array()), TRUE)
  4.      ) {
  5.     switch ($op) {
  6.     case 'insert':
  7.     case 'update':
  8.         _cctracker_node_save($node, 'update');
  9.         break;
  10.     case 'delete':
  11.         _cctracker_node_save($node, 'delete');
  12.         break;
  13.     }
  14.   }
  15. }
  16.  
  17. function _cctracker_node_save($node, $op='update') {
  18.   $is_existing = db_result(db_query("SELECT COUNT(*) FROM {node_cctracker} WHERE nid = %d", $node->nid));
  19.   if ($is_existing ) {
  20.     if ($op != 'delete') {
  21.       db_query("UPDATE {node_cctracker} SET cc_sticky = %d, cc_not_public = %d, cc_sticky_weight = %d WHERE nid = %d", $node->cc_sticky, $node->cc_not_public, $node->cc_sticky_weight, $node->nid);
  22.      }
  23.     else {
  24.       db_query("DELETE FROM {node_cctracker} WHERE nid = %d", $node->nid);
  25.     }
  26.   }
  27.   else {
  28.     if ($op != 'delete') {
  29.       db_query("INSERT INTO {node_cctracker} (nid, cc_sticky, cc_not_public,cc_sticky_weight) VALUES(%d, %d, %d, %d)", $node->nid, $node->cc_sticky, $node->cc_sticky_weight, $node->cc_not_public);
  30.      }
  31.   }
  32. }
Теперь данные из ноды, корректно сохраняются в базе данных (в нашей таблице {node_cctracker}), но пока ни как не воздействуют на вывод нашего трэкера. В следующей части мы как раз подправим вывод трэкера в соответствии с дополнительными данными сохраненными в ноде.
Добавить комментарий
« Добавить комментарий
» Добавить комментарий