Commit 9aa7b261 by Qiang Xue

Added LinkSorter.

parent ac8801bc
......@@ -65,11 +65,6 @@ use yii\helpers\Inflector;
* sorted by the orders specified by the Sort object. In the view, we show two hyperlinks
* that can lead to pages with the data sorted by the corresponding attributes.
*
* @property array $orders Sort directions indexed by column names. The sort direction
* can be either [[Sort::ASC]] for ascending order or [[Sort::DESC]] for descending order.
* @property array $attributeOrders Sort directions indexed by attribute names. The sort
* direction can be either [[Sort::ASC]] for ascending order or [[Sort::DESC]] for descending order.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
......@@ -130,6 +125,9 @@ class Sort extends Object
* if it is not currently sorted (the default value is ascending order).
* - The "label" element specifies what label should be used when calling [[link()]] to create
* a sort link. If not set, [[Inflector::camel2words()]] will be called to get a label.
*
* Note that if the Sort object is already created, you can only use the full format
* to configure every attribute. Each attribute must include these elements: asc, desc and label.
*/
public $attributes = array();
/**
......@@ -156,7 +154,7 @@ class Sort extends Object
*
* @see attributeOrders
*/
public $defaults;
public $defaultOrder;
/**
* @var string the route of the controller action for displaying the sorted contents.
* If not set, it means using the currently requested route.
......@@ -177,7 +175,7 @@ class Sort extends Object
* If the element does not exist, the [[defaults|default order]] will be used.
*
* @see sortVar
* @see defaults
* @see defaultOrder
*/
public $params;
/**
......@@ -187,6 +185,29 @@ class Sort extends Object
public $urlManager;
/**
* Normalizes the [[attributes]] property.
*/
public function init()
{
$attributes = array();
foreach ($this->attributes as $name => $attribute) {
if (is_array($attribute)) {
$attributes[$name] = $attribute;
if (!isset($attribute['label'])) {
$attributes[$name]['label'] = Inflector::camel2words($name);
}
} else {
$attributes[$attribute] = array(
'asc' => array($attribute => self::ASC),
'desc' => array($attribute => self::DESC),
'label' => Inflector::camel2words($attribute),
);
}
}
$this->attributes = $attributes;
}
/**
* Returns the columns and their corresponding sort directions.
* @param boolean $recalculate whether to recalculate the sort directions
* @return array the columns (keys) and their corresponding sort directions (values).
......@@ -197,7 +218,7 @@ class Sort extends Object
$attributeOrders = $this->getAttributeOrders($recalculate);
$orders = array();
foreach ($attributeOrders as $attribute => $direction) {
$definition = $this->getAttribute($attribute);
$definition = $this->attributes[$attribute];
$columns = $definition[$direction === self::ASC ? 'asc' : 'desc'];
foreach ($columns as $name => $dir) {
$orders[$name] = $dir;
......@@ -230,7 +251,7 @@ class Sort extends Object
}
}
if (($this->getAttribute($attribute)) !== null) {
if (isset($this->attributes[$attribute])) {
$this->_attributeOrders[$attribute] = $descending;
if (!$this->enableMultiSort) {
return $this->_attributeOrders;
......@@ -238,8 +259,8 @@ class Sort extends Object
}
}
}
if (empty($this->_attributeOrders) && is_array($this->defaults)) {
$this->_attributeOrders = $this->defaults;
if (empty($this->_attributeOrders) && is_array($this->defaultOrder)) {
$this->_attributeOrders = $this->defaultOrder;
}
}
return $this->_attributeOrders;
......@@ -279,9 +300,8 @@ class Sort extends Object
}
$url = $this->createUrl($attribute);
$definition = $this->getAttribute($attribute);
$label = isset($definition['label']) ? $definition['label'] : Html::encode(Inflector::camel2words($attribute));
return Html::a($label, $url, $options);
$definition = $this->attributes[$attribute];
return Html::a($definition['label'], $url, $options);
}
/**
......@@ -297,9 +317,10 @@ class Sort extends Object
*/
public function createUrl($attribute)
{
if (($definition = $this->getAttribute($attribute)) === null) {
if (!isset($this->attributes[$attribute])) {
throw new InvalidConfigException("Unknown attribute: $attribute");
}
$definition = $this->attributes[$attribute];
$directions = $this->getAttributeOrders();
if (isset($directions[$attribute])) {
$descending = !$directions[$attribute];
......@@ -324,25 +345,4 @@ class Sort extends Object
$urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager;
return $urlManager->createUrl($route, $params);
}
/**
* Returns the attribute definition of the specified name.
* @param string $name the attribute name
* @return array the sort definition (column names => sort directions).
* Null is returned if the attribute cannot be sorted.
* @see attributes
*/
public function getAttribute($name)
{
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
} elseif (in_array($name, $this->attributes, true)) {
return array(
'asc' => array($name => self::ASC),
'desc' => array($name => self::DESC),
);
} else {
return null;
}
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\widgets;
use yii\base\InvalidConfigException;
use yii\base\Widget;
use yii\data\Sort;
use yii\helpers\Html;
/**
* LinkSorter renders a list of sort links for the given sort definition.
*
* LinkSorter will generate a hyperlink for every attribute declared in [[sort]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class LinkSorter extends Widget
{
/**
* @var Sort the sort definition
*/
public $sort;
/**
* @var array HTML attributes for the sorter container tag.
* Please refer to [[Html::ul()]] for supported special options.
*/
public $options = array();
/**
* Initializes the sorter.
*/
public function init()
{
if ($this->sort === null) {
throw new InvalidConfigException('The "sort" property must be set.');
}
}
/**
* Executes the widget.
* This method renders the sort links.
*/
public function run()
{
$links = array();
foreach (array_keys($this->sort->attributes) as $name) {
$links[] = $this->sort->link($name);
}
echo Html::ul($links, array_merge($this->options, array('encode' => false)));
}
}
......@@ -93,32 +93,6 @@ class SortTest extends TestCase
$this->assertNull($sort->getAttributeOrder('xyz'));
}
public function testGetAttribute()
{
$sort = new Sort(array(
'attributes' => array(
'age',
'name' => array(
'asc' => array('first_name' => Sort::ASC, 'last_name' => Sort::ASC),
'desc' => array('first_name' => Sort::DESC, 'last_name' => Sort::DESC),
),
),
'params' => array(
'sort' => 'age.name-desc'
),
'enableMultiSort' => true,
));
$attribute = array('asc' => array('age' => Sort::ASC), 'desc' => array('age' => Sort::DESC));
$this->assertEquals($attribute, $sort->getAttribute('age'));
$attribute = array(
'asc' => array('first_name' => Sort::ASC, 'last_name' => Sort::ASC),
'desc' => array('first_name' => Sort::DESC, 'last_name' => Sort::DESC),
);
$this->assertEquals($attribute, $sort->getAttribute('name'));
$this->assertNull($sort->getAttribute('xyz'));
}
public function testCreateUrl()
{
$manager = new UrlManager(array(
......
......@@ -117,9 +117,10 @@ class ArrayHelperTest extends TestCase
public function testMultisortUseSort()
{
// single key
$sort = new Sort();
$sort->attributes = array('name', 'age');
$sort->defaults = array('name' => Sort::ASC);
$sort = new Sort(array(
'attributes' => array('name', 'age'),
'defaultOrder' => array('name' => Sort::ASC),
));
$orders = $sort->getOrders();
$array = array(
......@@ -133,9 +134,10 @@ class ArrayHelperTest extends TestCase
$this->assertEquals(array('name' => 'c', 'age' => 2), $array[2]);
// multiple keys
$sort = new Sort();
$sort->attributes = array('name', 'age');
$sort->defaults = array('name' => Sort::ASC, 'age' => Sort::DESC);
$sort = new Sort(array(
'attributes' => array('name', 'age'),
'defaultOrder' => array('name' => Sort::ASC, 'age' => Sort::DESC),
));
$orders = $sort->getOrders();
$array = array(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment