Commit 9aa7b261 by Qiang Xue

Added LinkSorter.

parent ac8801bc
...@@ -65,11 +65,6 @@ use yii\helpers\Inflector; ...@@ -65,11 +65,6 @@ use yii\helpers\Inflector;
* sorted by the orders specified by the Sort object. In the view, we show two hyperlinks * 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. * 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> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
...@@ -130,6 +125,9 @@ class Sort extends Object ...@@ -130,6 +125,9 @@ class Sort extends Object
* if it is not currently sorted (the default value is ascending order). * 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 * - 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. * 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(); public $attributes = array();
/** /**
...@@ -156,7 +154,7 @@ class Sort extends Object ...@@ -156,7 +154,7 @@ class Sort extends Object
* *
* @see attributeOrders * @see attributeOrders
*/ */
public $defaults; public $defaultOrder;
/** /**
* @var string the route of the controller action for displaying the sorted contents. * @var string the route of the controller action for displaying the sorted contents.
* If not set, it means using the currently requested route. * If not set, it means using the currently requested route.
...@@ -177,7 +175,7 @@ class Sort extends Object ...@@ -177,7 +175,7 @@ class Sort extends Object
* If the element does not exist, the [[defaults|default order]] will be used. * If the element does not exist, the [[defaults|default order]] will be used.
* *
* @see sortVar * @see sortVar
* @see defaults * @see defaultOrder
*/ */
public $params; public $params;
/** /**
...@@ -187,6 +185,29 @@ class Sort extends Object ...@@ -187,6 +185,29 @@ class Sort extends Object
public $urlManager; 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. * Returns the columns and their corresponding sort directions.
* @param boolean $recalculate whether to recalculate the sort directions * @param boolean $recalculate whether to recalculate the sort directions
* @return array the columns (keys) and their corresponding sort directions (values). * @return array the columns (keys) and their corresponding sort directions (values).
...@@ -197,7 +218,7 @@ class Sort extends Object ...@@ -197,7 +218,7 @@ class Sort extends Object
$attributeOrders = $this->getAttributeOrders($recalculate); $attributeOrders = $this->getAttributeOrders($recalculate);
$orders = array(); $orders = array();
foreach ($attributeOrders as $attribute => $direction) { foreach ($attributeOrders as $attribute => $direction) {
$definition = $this->getAttribute($attribute); $definition = $this->attributes[$attribute];
$columns = $definition[$direction === self::ASC ? 'asc' : 'desc']; $columns = $definition[$direction === self::ASC ? 'asc' : 'desc'];
foreach ($columns as $name => $dir) { foreach ($columns as $name => $dir) {
$orders[$name] = $dir; $orders[$name] = $dir;
...@@ -230,7 +251,7 @@ class Sort extends Object ...@@ -230,7 +251,7 @@ class Sort extends Object
} }
} }
if (($this->getAttribute($attribute)) !== null) { if (isset($this->attributes[$attribute])) {
$this->_attributeOrders[$attribute] = $descending; $this->_attributeOrders[$attribute] = $descending;
if (!$this->enableMultiSort) { if (!$this->enableMultiSort) {
return $this->_attributeOrders; return $this->_attributeOrders;
...@@ -238,8 +259,8 @@ class Sort extends Object ...@@ -238,8 +259,8 @@ class Sort extends Object
} }
} }
} }
if (empty($this->_attributeOrders) && is_array($this->defaults)) { if (empty($this->_attributeOrders) && is_array($this->defaultOrder)) {
$this->_attributeOrders = $this->defaults; $this->_attributeOrders = $this->defaultOrder;
} }
} }
return $this->_attributeOrders; return $this->_attributeOrders;
...@@ -279,9 +300,8 @@ class Sort extends Object ...@@ -279,9 +300,8 @@ class Sort extends Object
} }
$url = $this->createUrl($attribute); $url = $this->createUrl($attribute);
$definition = $this->getAttribute($attribute); $definition = $this->attributes[$attribute];
$label = isset($definition['label']) ? $definition['label'] : Html::encode(Inflector::camel2words($attribute)); return Html::a($definition['label'], $url, $options);
return Html::a($label, $url, $options);
} }
/** /**
...@@ -297,9 +317,10 @@ class Sort extends Object ...@@ -297,9 +317,10 @@ class Sort extends Object
*/ */
public function createUrl($attribute) public function createUrl($attribute)
{ {
if (($definition = $this->getAttribute($attribute)) === null) { if (!isset($this->attributes[$attribute])) {
throw new InvalidConfigException("Unknown attribute: $attribute"); throw new InvalidConfigException("Unknown attribute: $attribute");
} }
$definition = $this->attributes[$attribute];
$directions = $this->getAttributeOrders(); $directions = $this->getAttributeOrders();
if (isset($directions[$attribute])) { if (isset($directions[$attribute])) {
$descending = !$directions[$attribute]; $descending = !$directions[$attribute];
...@@ -324,25 +345,4 @@ class Sort extends Object ...@@ -324,25 +345,4 @@ class Sort extends Object
$urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager; $urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager;
return $urlManager->createUrl($route, $params); 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 ...@@ -93,32 +93,6 @@ class SortTest extends TestCase
$this->assertNull($sort->getAttributeOrder('xyz')); $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() public function testCreateUrl()
{ {
$manager = new UrlManager(array( $manager = new UrlManager(array(
......
...@@ -117,9 +117,10 @@ class ArrayHelperTest extends TestCase ...@@ -117,9 +117,10 @@ class ArrayHelperTest extends TestCase
public function testMultisortUseSort() public function testMultisortUseSort()
{ {
// single key // single key
$sort = new Sort(); $sort = new Sort(array(
$sort->attributes = array('name', 'age'); 'attributes' => array('name', 'age'),
$sort->defaults = array('name' => Sort::ASC); 'defaultOrder' => array('name' => Sort::ASC),
));
$orders = $sort->getOrders(); $orders = $sort->getOrders();
$array = array( $array = array(
...@@ -133,9 +134,10 @@ class ArrayHelperTest extends TestCase ...@@ -133,9 +134,10 @@ class ArrayHelperTest extends TestCase
$this->assertEquals(array('name' => 'c', 'age' => 2), $array[2]); $this->assertEquals(array('name' => 'c', 'age' => 2), $array[2]);
// multiple keys // multiple keys
$sort = new Sort(); $sort = new Sort(array(
$sort->attributes = array('name', 'age'); 'attributes' => array('name', 'age'),
$sort->defaults = array('name' => Sort::ASC, 'age' => Sort::DESC); 'defaultOrder' => array('name' => Sort::ASC, 'age' => Sort::DESC),
));
$orders = $sort->getOrders(); $orders = $sort->getOrders();
$array = array( $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