You are here

function _draggableviews_extend_view_window in DraggableViews 7

Same name and namespace in other branches
  1. 6.3 draggableviews.inc \_draggableviews_extend_view_window()

Extend View Window

In order to make it possible to drag from one page to another we have to extend the visible window of each page. We also have to make sure that parent nodes appear with all their children (..and child nodes with their parent). The view will be re-executed with the calculated range, based on the suggested range.

Parameters

$info: The structured info array. Look at _draggableviews_info(..) to learn more.

$extension_top:

$extension_bottom:

Return value

An array containing the new, calculated range.

1 call to _draggableviews_extend_view_window()
draggableviews_views_pre_render in ./draggableviews.module
Implements hook_views_pre_render

File

./draggableviews.inc, line 570
Draggableviews processing functions. Rough summary of what functions in this file do:

Code

function _draggableviews_extend_view_window(&$info, $reload = FALSE) {

  // Notice that we have two sets of pager information:
  // - The "should-be" values at $info['pager']
  // - The real, current values at $view->pager.
  // For building the new view we always use the "should-be" pager information.
  $items_per_page = isset($info['pager']->options['items_per_page']) ? $info['pager']->options['items_per_page'] : 0;
  $current_page = $info['pager']->current_page;
  $offset = $info['pager']->options['offset'];

  // Check page settings.
  if ($items_per_page <= 0) {

    // Nothing to do. Just [reload the view and] return the actual range.
    if ($reload) {

      // Re-execute the view and reload the info array.
      _draggableviews_reload_info($info);
    }
    return array(
      'first_index' => $offset,
      'last_index' => count($info['view']->result) - 1 + $offset,
    );
  }
  $first_index = $items_per_page * $current_page;
  $last_index = $items_per_page * ($current_page + 1) - 1;
  $nodes = $info['nodes'];

  // If the new index is out of range we'll use the last existing index. Calculate this index:
  $current_first_index = $info['view']->query->pager->options['items_per_page'] * $info['view']->query->pager->current_page + $info['view']->query->pager->options['offset'];
  $total_index = $current_first_index + count($nodes) - 1;
  if ($first_index > $total_index) {

    // $first_index is out of range.
    $first_index = 0;
    $last_index = $items_per_page - 1;
  }

  // Check permissions and lock.
  if (!user_access('Allow Reordering') || $info['locked']) {

    // Don't extend view window (= suggestion).
    $extension_top = 0;
    $extension_bottom = 0;
  }
  else {
    $extension_top = $info['view_window_extensions']['extension_top'];
    $extension_bottom = $info['view_window_extensions']['extension_bottom'];
  }

  // Extend on top:
  $first_index -= $extension_top;
  if ($first_index < 0) {

    // Be careful: $first_index < 0. So this is a subtraction!
    $extension_top += $first_index;
    if ($extension_top < 0) {
      $extension_top = 0;
    }
    $first_index = 0;
  }

  // Extend on bottom:
  $last_index += $extension_bottom;
  if ($last_index > $total_index) {
    $extension_bottom = $extension_bottom - ($last_index - $total_index);
    if ($extension_bottom < 0) {
      $extension_bottom = 0;
    }
    $last_index = $total_index;
  }
  $add_to_extension_top = 0;
  $add_to_extension_bottom = 0;
  if (isset($info['hierarchy'])) {

    // There are possibly some child nodes that would be cut of their parents. To avoid this we localize
    // the next parents (if needed) and use their index for the range. To analyze the nodes array we slice out
    // all nodes before (the B's) and all nodes after (the A's) the current page (the -'s):
    //
    // B B B B B B B B B - - - - - - - - A A A A A A A A A A.
    //
    // Slice out all nodes before (currently not shown):
    $nodes_before = array_slice($nodes, 0, $first_index, TRUE);

    // Slice out all nodes after  (currently not shown):
    // array_slice: In PHP version < 5.0.2 the 3rd argument (length) must not be ommited (set to NULL). The value must be the exact amount of elements.
    $nodes_after = array_slice($nodes, $last_index + 1, count($nodes) - ($last_index + 1), TRUE);

    // Slice out all nodes that are currently shown:
    $nodes_current = array_slice($nodes, $first_index, $last_index - $first_index + 1, TRUE);
    $first_node = current($nodes_current);
    if ($first_node['parent'] > 0) {

      // The first node of the current page is a child node. Look for the next parent
      // that is on the root level. We can't use foreach() because we iterate the wrong way.
      $temp_node = end($nodes_before);
      while ($temp_node !== FALSE) {
        $add_to_extension_top++;
        if ($temp_node['parent'] == 0) {
          break;
        }
        $temp_node = prev($nodes_before);
      }
    }

    // Check for possible children of the last node.
    foreach ($nodes_after as $temp_node) {
      if ($temp_node['parent'] == 0) {
        break;
      }
      $add_to_extension_bottom++;
    }

    // Update range.
    $first_index -= $add_to_extension_top;
    $last_index += $add_to_extension_bottom;
  }
  if ($reload) {

    // Re-execute the view and reload the info array. We need to add 1 to the number of items
    // to show (e.g. show from index 5 to index 5: show 5-5+1=1 item).
    _draggableviews_reload_info($info, $last_index - $first_index + 1, 0, $offset + $first_index);
  }

  // Mark extended nodes as "extension".
  $nodes =& $info['nodes'];
  for ($i = 0; $i < $extension_top + $add_to_extension_top; $i++) {
    $nid = key($nodes);
    $nodes[$nid]['extension'] = TRUE;
    next($nodes);
  }
  end($nodes);
  for ($i = 0; $i < $extension_bottom + $add_to_extension_bottom; $i++) {
    $nid = key($nodes);
    $nodes[$nid]['extension'] = TRUE;
    prev($nodes);
  }
  return array(
    'first_index' => $first_index + $offset,
    'last_index' => $last_index + $offset,
  );
}