diff --git a/framework/yii/data/Sort.php b/framework/yii/data/Sort.php index eb66754..5132188 100644 --- a/framework/yii/data/Sort.php +++ b/framework/yii/data/Sort.php @@ -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 * @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; - } - } } diff --git a/framework/yii/widgets/LinkSorter.php b/framework/yii/widgets/LinkSorter.php new file mode 100644 index 0000000..4921af5 --- /dev/null +++ b/framework/yii/widgets/LinkSorter.php @@ -0,0 +1,57 @@ + + * @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))); + } +} diff --git a/tests/unit/framework/data/SortTest.php b/tests/unit/framework/data/SortTest.php index f5611cf..80f485c 100644 --- a/tests/unit/framework/data/SortTest.php +++ b/tests/unit/framework/data/SortTest.php @@ -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( diff --git a/tests/unit/framework/helpers/ArrayHelperTest.php b/tests/unit/framework/helpers/ArrayHelperTest.php index 3ec80fd..5ace571 100644 --- a/tests/unit/framework/helpers/ArrayHelperTest.php +++ b/tests/unit/framework/helpers/ArrayHelperTest.php @@ -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(