Commit c92b4263 authored by Karim Ratib's avatar Karim Ratib
Browse files

#336014 by kratib: Make PHP custom fields sortable

parent ba1e7d94
Loading
Loading
Loading
Loading
+106 −2
Original line number Diff line number Diff line
@@ -9,6 +9,11 @@
/**
 * Field handler to display row-specific custom text using PHP.
 */
define('VIEWS_CUSTOMFIELD_SORTABLE_NO', 0);
define('VIEWS_CUSTOMFIELD_SORTABLE_NUMERIC', 1);
define('VIEWS_CUSTOMFIELD_SORTABLE_ALPHA', 2);
define('VIEWS_CUSTOMFIELD_SORTABLE_ALPHA_NOCASE', 3);

class views_customfield_handler_field_phpcode extends views_handler_field {
  var $static;
  
@@ -19,6 +24,7 @@ class views_customfield_handler_field_phpcode extends views_handler_field {
  function option_definition() {
    $options = parent::option_definition();
    $options['value'] = array('default' => '');
    $options['sortable'] = array('default' => VIEWS_CUSTOMFIELD_SORTABLE_NO);
    return $options;
  }

@@ -40,6 +46,82 @@ class views_customfield_handler_field_phpcode extends views_handler_field {
        .t('$static: can be used to store reusable data per row.')
      ,
    );
    $form['sortable'] = array(
      '#type' => 'radios',
      '#title' => t('Sortable'),
      '#default_value' => $this->options['sortable'],
      '#options' => array(
        VIEWS_CUSTOMFIELD_SORTABLE_NO => t('No'),
        VIEWS_CUSTOMFIELD_SORTABLE_NUMERIC => t('Numeric'),
        VIEWS_CUSTOMFIELD_SORTABLE_ALPHA => t('Alphanumeric'),
        VIEWS_CUSTOMFIELD_SORTABLE_ALPHA_NOCASE => t('Alphanumeric (case-insensitive)'),
      ),
    );
  }

  function click_sortable() {
    return $this->options['sortable'] != VIEWS_CUSTOMFIELD_SORTABLE_NO;
  }

  var $sort_order = NULL;
  function click_sort($order) {
    $this->sort_order = $order;
  }

  function pre_execute() {
    // If we're sorting, save the original pager and let Views get all results.
    if ($this->options['sortable'] != VIEWS_CUSTOMFIELD_SORTABLE_NO && $this->sort_order) {
      $this->pager = $this->view->pager; // save the pager
      $this->view->set_items_per_page(0);
    }
  }

  function pre_render($results) {
    // Evaluate the PHP code.
    foreach ($this->view->result as $i => $row) {
      $this->view->result[$i]->{$this->field_alias} = $this->render_row($row);
    }
    
    // If we're sorting, do the actual sorting then fix the results as per the pager info.
    if ($this->options['sortable'] != VIEWS_CUSTOMFIELD_SORTABLE_NO && $this->sort_order) {
      usort($this->view->result, array(new views_customfield_sorter($this->options['sortable'], $this->sort_order, $this->field_alias), 'sort'));

      // Handle paging logic as in view::execute()
      if (!empty($this->pager['items_per_page'])) {

        if (!empty($this->pager['use_pager']) || !empty($this->view->get_total_rows)) {
          $this->view->total_rows = count($this->view->result) - $this->pager['offset'];
        }

        if (!empty($this->pager['use_pager'])) {
          // dump information about what we already know into the globals
          global $pager_page_array, $pager_total, $pager_total_items;
          // total rows in query
          $pager_total_items[$this->pager['element']] = $this->view->total_rows;
          // total pages
          $pager_total[$this->pager['element']] = ceil($pager_total_items[$this->pager['element']] / $this->pager['items_per_page']);

          // What page was requested
          $pager_page_array = isset($_GET['page']) ? explode(',', $_GET['page']) : array();

          // If the requested page was within range. $this->pager['current_page']
          // defaults to 0 so we don't need to set it in an out-of-range condition.
          if (!empty($pager_page_array[$this->pager['element']])) {
            $page = intval($pager_page_array[$this->pager['element']]);
            if ($page > 0 && $page < $pager_total[$this->pager['element']]) {
              $this->pager['current_page'] = $page;
            }
          }
          $pager_page_array[$this->pager['element']] = $this->pager['current_page'];
        }

        $offset = $this->pager['current_page'] * $this->pager['items_per_page'] + $this->pager['offset'];
        $results = array_slice($this->view->result, $offset, $this->pager['items_per_page']);
        $this->view->result = $results;
      }
      
      $this->view->pager = $this->pager;
    }
  }

  /**
@@ -48,7 +130,7 @@ class views_customfield_handler_field_phpcode extends views_handler_field {
   * @param stdClass $values
   * @return string
   */
  function render($values) {
  function render_row($values) {
    $d = $this->view->display[$this->view->current_display];
    $field_handlers = $d->handler->handlers['field'];
    foreach ($field_handlers as $h) {
@@ -119,3 +201,25 @@ class views_customfield_handler_field_phpcode extends views_handler_field {
    return ob_get_clean();
  }
}

class views_customfield_sorter {
  var $function;
  var $factor;
  var $field_alias;

  function views_customfield_sorter($sortable, $sort_order, $field_alias) {
    $this->factor = strtoupper($sort_order) == 'ASC' ? 1 : -1;
    $functions = array(
      VIEWS_CUSTOMFIELD_SORTABLE_NUMERIC => create_function('$a,$b', 'return $a-$b;'),
      VIEWS_CUSTOMFIELD_SORTABLE_ALPHA => 'strcmp',
      VIEWS_CUSTOMFIELD_SORTABLE_ALPHA_NOCASE => 'strcasecmp',
    );
    $this->function = $functions[$sortable];
    $this->field_alias = $field_alias;
  }

  function sort($a, $b) {
    return $this->factor * call_user_func($this->function, $a->{$this->field_alias}, $b->{$this->field_alias});
  }
}
+11 −0
Original line number Diff line number Diff line
@@ -10,3 +10,14 @@ function views_customfield_views_api() {
    'api' => 2,
  );
}

function views_customfield_views_pre_execute(&$view) {
  $d = $view->display[$view->current_display];
  $field_handlers = $d->handler->handlers['field'];
  foreach ($field_handlers as $h) {
    if (is_a($h, 'views_customfield_handler_field_phpcode')) {
      $h->pre_execute();
    }
  }
}
+1 −1

File changed.

Contains only whitespace changes.