diff --git a/code/model/behavior/sortable.php b/code/model/behavior/sortable.php index f9c584f246..8b81ae0d2b 100644 --- a/code/model/behavior/sortable.php +++ b/code/model/behavior/sortable.php @@ -12,6 +12,17 @@ /** * Sortable Model Behavior * + * By making a model sortable you give the flexibility to change how the returned data is sorted to the client. + * Clients can use the 'sort' URL parameter to control how the returned data is sorted. The sort order for each + * sort field is ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, “-“), in which case it is + * descending. + * + * Example: GET /posts?sort=-created_on,title + * This means to sort the data by its created time descended and then the title ascended. + * + * Based on the Sorting specification in the JSON API + * @link http://jsonapi.org/format/#fetching-sorting + * * @author Johan Janssens * @package Kodekit\Library\Model\Behavior */ @@ -27,8 +38,7 @@ public function onMixin(ObjectMixable $mixer) parent::onMixin($mixer); $mixer->getState() - ->insert('sort', 'cmd') - ->insert('direction', 'word', 'asc'); + ->insert('sort', 'cmd'); } /** @@ -39,17 +49,10 @@ public function onMixin(ObjectMixable $mixer) */ protected function _afterReset(ModelContextInterface $context) { - if($context->modified == 'sort' && strpos($context->state->sort, ',') !== false) + if($context->modified->contains('sort')) { - $context->state->sort = explode(',', $context->state->sort); - - foreach($context->state->sort as $key => $value) - { - if(strtoupper($value) == 'DESC' || strtoupper($value) == 'ASC') - { - unset($context->state->sort[$key]); - $context->state->direction = $value; - } + if(is_string($context->state->sort) && strpos($context->state->sort, ',') !== false) { + $context->state->sort = explode(',', $context->state->sort); } } } @@ -66,19 +69,21 @@ protected function _beforeFetch(ModelContextInterface $context) if ($model instanceof ModelDatabase && !$context->state->isUnique()) { - $state = $context->state; - - $sort = $state->sort; - $direction = strtoupper($state->direction); - $columns = array_keys($this->getTable()->getColumns()); + $sort = (array) ObjectConfig::unbox($context->state->sort); + $columns = array_keys($this->getTable()->getColumns()); if ($sort) { - $column = $this->getTable()->mapColumns($sort); - $context->query->order($column, $direction); + foreach($sort as $column) + { + $direction = substr( $column, 0, 1 ) == '-' ? 'DESC' : 'ASC'; + $column = $this->getTable()->mapColumns(ltrim($column, '-')); + + $context->query->order($column, $direction); + } } - if ($sort != 'ordering' && in_array('ordering', $columns)) { + if (!in_array('ordering', $sort) && in_array('ordering', $columns)) { $context->query->order('tbl.ordering', 'ASC'); } } diff --git a/code/template/helper/grid.php b/code/template/helper/grid.php index 1fb86071d2..09bec9435b 100644 --- a/code/template/helper/grid.php +++ b/code/template/helper/grid.php @@ -179,7 +179,6 @@ public function sort($config = array()) $config->append(array( 'title' => '', 'column' => '', - 'direction' => 'asc', 'sort' => '', 'url' => null )); @@ -191,13 +190,13 @@ public function sort($config = array()) $config->title = ucfirst($config->column); } - //Set the direction - $direction = strtolower($config->direction); - $direction = in_array($direction, array('asc', 'desc')) ? $direction : 'asc'; + //Get the direction + $direction = substr( $config->sort, 0, 1 ) == '-' ? 'desc' : 'asc'; + $sort = ltrim($config->sort, '-'); //Set the class $class = ''; - if($config->column == $config->sort) + if($config->column == $sort) { $direction = $direction == 'desc' ? 'asc' : 'desc'; // toggle $class = 'class="-koowa-'.$direction.'"'; @@ -208,16 +207,15 @@ public function sort($config = array()) $config->url = HttpUrl::fromString($config->url); } - $config->url->query['sort'] = $config->column; - $config->url->query['direction'] = $direction; + $config->url->query['sort'] = $direction == 'asc' ? $config->column : '-'.$config->column; $html = ''; $html .= $translator->translate($config->title); // Mark the current column - if ($config->column == $config->sort) + if ($config->column == $sort) { - if (strtolower($config->direction) === 'asc') { + if ($direction == 'asc') { $html .= ' '; } else { $html .= ' ';