Блог

Часто при разработке сайтов необходимо выполнять сортировку нод по какому-либо отдельному критерию. Для её выполнения используются Views, Nodequeue, Flag и другие похожие модули. Но иногда функционала таких модулей бывает недостаточно для удовлетворения хитрых требований заказчика. Конечно же, можно наплодить nodequeue и дальше рассказывать заказчику, которая из них за что отвечает, но такая система, с точки зрения юзабилити, выглядит по меньшей мере сомнительной. Другим вариантом решения может стать добавление cck-поля “weight”, когда вручную для каждой ноды выставляется ее вес и уже по нему производиться сортировка. Но опять же, при наличии тысяч нод, данный способ не представляется реализуемым.

Адекватным же решением этой проблемы будет обращение к “drag-and-drop” интерфейсу, и то, как это реализуется, является темой данной статьи. Первым делом мы, все-таки, добавляем к нужному типу контента cck-поле “weight”. Затем в hook_menu объявляем страницу, на которой будет draggable-интерфейс и, собственно, сама форма:

function my_module_drag_form($form_state, $node) { 
  $form['my_items']['#tree'] = TRUE; 
  $vids = my_module_select_vids_function(); // выбираем нужные ноды
  //правильный способ выполнения запроса к ссk-полям 
  $type_name  = 'product'; 
  $field_name = 'field_product_weight'; 
  $type = content_types($type_name); 
  $field = $type['fields'][$field_name]; 
  $data = content_database_info($field); 
  $join  = $data['table']; 
  $field = $data['columns'][end(array_keys($data['columns']))]['column']; 
  //выбираем тайтлы нод и значение поля "weight" 
  $q = db_query("SELECT f.%s, n.title, n.nid, n.vid 
                 FROM {node} n 
                 INNER JOIN {%s} f ON f.vid = n.vid 
                 WHERE n.vid IN (" . db_placeholders($vids, 'int') . ") ORDER BY f.%s ASC", array_merge(array($field), array($join), $vids, array($field)));
  //собственно сама форма 
  while ($d = db_fetch_array($q)) { 
    $form['my_items'][$d['vid']] = array( 
      'name' => array( 
              '#type' => 'markup', 
              '#value' => l($d['title'], 'node/' . $d['nid']),
      ), 
      'weight' => array( 
              '#type' => 'weight', 
              '#delta' => 10, 
              '#default_value' => $d[$field], 
              '#attributes' => array('class' => 'weight'),
      ), 
    ); 
  } 
  $form['submit'] = array( 
      '#type' => 'submit', 
      '#value' => t('Save Changes'), 
  ); 
   
  return $form; 
}

 С тем, чтобы внести изменения в базу данных, добавляем submit к форме:

function my_module_drag_form_submit($form, &$form_state) {
  $type_name  = 'product'; 
  $field_name = 'field_product_weight'; 
  $type = content_types($type_name); 
  $field = $type['fields'][$field_name]; 
  $data = content_database_info($field); 
  $join  = $data['table']; 
  $field = $data['columns'][end(array_keys($data['columns']))]['column']; 
  //обновляем значение поля "weight" в базе данных 
  foreach ($form_state['values']['my_items'] as $k => $item) { 
    $q = db_query("UPDATE {%s} SET %s=%d WHERE %s.vid=%d", $join, $field, $item['weight'], $join, $k);
  } 
}

 Объявляем для нашей формы функцию темизации :

function my_module_theme() { 
  return array( 
    'my_module_drag_form' => array( 
        'arguments' => array('form' => NULL), 
    ), 
  ); 
}

Функция темизации:

function theme_my_module_drag_form($form) { 
  // переменная, которая будет содержать возвращаемое значение
  $output = ''; 
  // проходимся по каждому элементу массива таблицы 
  foreach($form['my_items'] as $id => $row) { 
    // если $id не число - пропускаем эту строчку 
    if (!intval($id)) 
        continue; 
    // этот массив будет содержать ячейки строки 
    $this_row = array(); 
    // генерируем markup name 
    $this_row[] = drupal_render($row['name']); 
    // добавляем поле с весом 
    $this_row[] = drupal_render($row['weight']); 
    // добавляем строку в массив строк 
    $table_rows[] = array('data' => $this_row, 'class'=>'draggable');
  } 
  // убеждаемся, что количесво заголовков совпадает с количеством столбцов
  $header = array( 
    'Name', 
    'Weight', 
  ); 
  $table_id = 'my_items'; 
  // добавляем draggable 
  drupal_add_tabledrag($table_id, 'order', 'sibling', 'weight');   
  // переопределяем элемент формы 'my_items' маркапом, сгенерированным нашей таблицей
  $form['my_items'] = array( 
      '#type' => 'markup', 
      '#value' => theme('table', $header, $table_rows, array('id' => $table_id)),
      '#weight' => '1', 
      ); 
  // генерируем форму 
  $output = drupal_render($form); 

  return $output; 
}

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

Join the conversation
0 Comments