'. t("Makes views draggable.") .'

'; break; } return $output; } /** * Implementing hook_admin */ function draggableviews_admin() { $form['draggableviews_nmbr_values'] = array( '#type' => 'textfield', '#title' => t('Number values'), '#default_value' => variable_get('draggableviews_nmbr_values', 3), '#size' => 4, '#maxlength' => 4, '#description' => t('The number of draggableviews value fields that will be generated'), '#required' => TRUE, '#prefix' => 'The setting above will not take effect until the views cache gets cleared!', ); return system_settings_form($form); } /** * Implementing hook_validate */ function draggableviews_admin_validate($form, &$form_state) { $value = $form_state['values']['draggableviews_nmbr_values']; if (!is_numeric($value) OR $value < 0) { drupal_set_message('Invalid value (not numeric, not >= 0)', 'error'); } } /** * Implementing hook_menu */ function draggableviews_menu() { $items = array(); $items['admin/settings/draggableviews'] = array( 'title' => 'Draggable views settings', 'description' => 'Configure settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('draggableviews_admin'), 'access arguments' => array('access administration pages'), 'type' => MENU_NORMAL_ITEM, ); return $items; } /** * Implementing hook_forms */ function draggableviews_forms() { $args = func_get_args(); $form_id = $args[0]; if (strpos($form_id, "draggableviews_view_draggabletable_form") === 0) { $forms[$form_id] = array( 'callback' => 'draggableviews_view_draggabletable_form', ); } return $forms; } /** * Build the form */ function draggableviews_view_draggabletable_form($form_state, $view) { $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); $form['#submit'][] = 'draggableviews_view_draggabletable_form_submit'; $form['#redirect'] = array('path' => $_GET['q'], 'query' => 'page='. $view->view->draggableviews_info['pager']['current_page']); return $form; } /** * Implement hook_theme */ function draggableviews_theme() { $array = array(); $array['draggableviews_ui_style_plugin_draggabletable'] = array( 'arguments' => array('form' => NULL), ); $array['draggableviews_view_draggabletable_form_new'] = array( 'template' => 'draggableviews-view-draggabletable-form', 'preprocess functions' => array( 'template_preprocess_draggableviews_view_draggabletable_form', ), 'arguments' => array('form' => NULL), ); // Register theme function for all views. $views = views_get_all_views(); foreach ($views AS $view) { foreach (array_keys($view->display) AS $display_id) { $array['draggableviews_view_draggabletable_form_'. $view->vid .'_'. $display_id] = array( 'template' => 'draggableviews-view-draggabletable-form', 'preprocess functions' => array( 'template_preprocess_draggableviews_view_draggabletable_form', ), 'arguments' => array('form' => NULL), ); } } return $array; } /** * Imlpementing hook_views_pre_render * * We distinguish between two cases A and B: * A) Click sort was used: * - Renumber the results as they are returned from the view. Simply use ascending numbers. (and re-execute the view). * * B) The view is just going to be rendered. * - Check the structure. If it's broken: * - - Repair the structure (and re-execute the view). * * In both cases extend the visible window if paging is beeing used. */ function draggableviews_views_pre_render(&$view) { // Get info array. $info = _draggableviews_info($view); // Attach the info array to the view object, // so we don't have to build it again when the theme function is called. // We need to use a reference because the info array may change. $view->draggableviews_info = &$info; if (!isset($info['order'])) { // Nothing to do. return; } if (!is_numeric($view->vid)) { // The view hasn't been saved yet. Can't do anything. return; } if ($_GET['order']) { // CASE A) Click sort was used. Assign order values manually. _draggableviews_click_sort($info); // Try to extend the visible window with the suggested values. The calculated range will be returned. $range = _draggableviews_extend_view_window($info); } else { // CASE B) Check structure. global $pager_page_array, $pager_total, $pager_total_items; // Views pager use global variables which are going to be changed in order when we // extend the visible window. As we don't want to change the pager status we backup these values now and // restore them after completing all page related operations. $backup_pager_page_array = $pager_page_array; $backup_pager_total = $pager_total; $backup_pager_total_items = $pager_total_items; // We'll later need the original pager settings for redirecting and in case of a rebuild. $info['pager'] = $info['view']->pager; // Try to extend the visible window with the suggested values. The calculated range will be returned. $range = _draggableviews_extend_view_window($info); if (!_draggableviews_quick_check_structure($info)) { // The structure is broken and has to be repaired. We restore the original page settings now because // the current settings are based on a broken structure. $info['view']->pager = $info['pager']; _draggableviews_rebuild_hierarchy($info); // Try to extend the visible window with the suggested values. The calculated range will be returned. $range = _draggableviews_extend_view_window($info); drupal_set_message('The structure was broken. It has been repaired.'); } // Restore global views pager variables. $pager_page_array = $backup_pager_page_array; $pager_total = $backup_pager_total; $pager_total_items = $backup_pager_total_items; // Restore use_pager that was set to FALSE when calling view->set_items_per_page(0). $info['view']->pager['use_pager'] = $info['pager']['use_pager']; } // Calculate depth values. These values will be used for theming. _draggableviews_calculate_depths($info); // Finally we set the selectable options of the order fields. for ($i = 0; $i < count($info['order']['fields']); $i++) { $info['order']['fields'][$i]['handler']->set_range($range['first_index'], $range['last_index']); } } /** * Implementing hook_submit */ function draggableviews_view_draggabletable_form_submit($vars) { // Check permissions. if (!user_access('Allow Reordering')) { drupal_set_message(t('You are not allowed to reorder nodes.'), 'error'); return; } // Gather all needed information. $view = $vars['#parameters'][2]->view; $results = $view->result; $input = $vars['submit']['#post']; $info = $view->draggableviews_info; if (!isset($info['order'])) return; // Loop through all resulting nodes. foreach ($results AS $row) { // set order values if (isset($info['order']['fields'])) { // The input array must have the same structure as the node array. // E.g. because of _draggableviews_get_hierarchy_depth(..). $info['input'][$row->nid]['order'][0] = $input[$info['order']['fields'][0]['field_name'] .'_'. $row->nid]; } // Set parent values. if (isset($info['hierarchy'])) { $info['input'][$row->nid]['parent'] = $input[$info['hierarchy']['field']['field_name'] .'_'. $row->nid]; } } _draggableviews_build_hierarchy($info); _draggableviews_save_hierarchy($info); if (isset($info['hierarchy'])) { // save expanded/collapsed states. global $user; foreach ($vars['submit']['#post'] AS $key => $val) { if (ereg('draggableviews_collapsed_', $key)) { $parent_nid = drupal_substr($key, 25); db_query("DELETE FROM {draggableviews_collapsed} WHERE uid=%d AND parent_nid=%d", $user->uid, $parent_nid); db_query("INSERT INTO {draggableviews_collapsed} (uid, parent_nid, collapsed) VALUES (%d, %d, %d)", $user->uid, $parent_nid, $val); } } } } /** * Discover All Implementations For Draggableviews * * @param $filter_handler * The handler to return. * * @return * Either the entire array with all handlers or the specified handler entry. */ function draggableviews_discover_handlers($filter_handler = NULL) { // @todo there's no cache functionality implemented yet. $cache = array(); // Get implementation definitions from all modules. foreach (module_implements('draggableviews_handlers') as $module) { $function = $module .'_draggableviews_handlers'; $result = $function(); if (!is_array($result)) { continue; } $path = drupal_get_path('module', $module); foreach ($result as $handler => $def) { if (!isset($def['path'])) { $def['path'] = $path; } if (!isset($def['file'])) { $def['file'] = "$handler.inc"; } if (!isset($def['handler'])) { $def['handler'] = 'draggableviews_handler_'. $handler; } // Merge the new data. $cache[$handler] = $def; } } if (isset($filter_handler)) { if (isset($cache[$filter_handler])) { return $cache[$filter_handler]; } else { return FALSE; } } return $cache; } /** * Get Handlers List * * @return * A list of all draggableviews handlers. */ function draggableviews_get_handlers_list() { $handlers = draggableviews_discover_handlers(); foreach ($handlers as $handler => $def) { $list[$handler] = $def['title']; } return $list; } /** * Implementing hook_draggableviews_handlers */ function draggableviews_draggableviews_handlers() { return array( 'native' => array( 'file' => 'implementations/draggableviews_handler_native.inc', 'title' => t('Native'), 'description' => 'Storage of structure done by draggableviews', 'handler' => 'draggableviews_handler_native', ), ); } /** * Implementing hook_perm */ function draggableviews_perm() { return array('Allow Reordering'); } /** * Impleneting hook_views_api */ function draggableviews_views_api() { return array( 'api' => 2.0, 'path' => drupal_get_path('module', 'draggableviews') .'/views', ); }