From ac8801bc639e4fab23d2aa856e6119c9400d3d3b Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 19 Jul 2013 20:40:51 -0400 Subject: [PATCH] Added SortTest --- framework/yii/data/Sort.php | 89 +++++++------- tests/unit/framework/data/SortTest.php | 175 ++++++++++++++++++++++++++++ tests/unit/framework/web/UrlManagerTest.php | 3 - 3 files changed, 223 insertions(+), 44 deletions(-) create mode 100644 tests/unit/framework/data/SortTest.php diff --git a/framework/yii/data/Sort.php b/framework/yii/data/Sort.php index d64906b..eb66754 100644 --- a/framework/yii/data/Sort.php +++ b/framework/yii/data/Sort.php @@ -29,8 +29,10 @@ use yii\helpers\Inflector; * 'attributes' => array( * 'age', * 'name' => array( - * 'asc' => array('last_name', 'first_name'), - * 'desc' => array('last_name' => true, 'first_name' => true), + * 'asc' => array('first_name' => Sort::ASC, 'last_name' => Sort::ASC), + * 'desc' => array('first_name' => Sort::DESC, 'last_name' => Sort::DESC), + * 'default' => Sort::DESC, + * 'label' => 'Name', * ), * ), * )); @@ -96,7 +98,7 @@ class Sort extends Object * ~~~ * array( * 'age', - * 'user' => array( + * 'name' => array( * 'asc' => array('first_name' => Sort::ASC, 'last_name' => Sort::ASC), * 'desc' => array('first_name' => Sort::DESC, 'last_name' => Sort::DESC), * 'default' => Sort::DESC, @@ -164,9 +166,9 @@ class Sort extends Object * @var array separators used in the generated URL. This must be an array consisting of * two elements. The first element specifies the character separating different * attributes, while the second element specifies the character separating attribute name - * and the corresponding sort direction. Defaults to `array('-', '.')`. + * and the corresponding sort direction. Defaults to `array('.', '-')`. */ - public $separators = array('-', '.'); + public $separators = array('.', '-'); /** * @var array parameters (name => value) that should be used to obtain the current sort directions * and to create new sort URLs. If not set, $_GET will be used instead. @@ -178,15 +180,21 @@ class Sort extends Object * @see defaults */ public $params; + /** + * @var \yii\web\UrlManager the URL manager used for creating sort URLs. If not set, + * the "urlManager" application component will be used. + */ + public $urlManager; /** * 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). * This can be passed to [[\yii\db\Query::orderBy()]] to construct a DB query. */ - public function getOrders() + public function getOrders($recalculate = false) { - $attributeOrders = $this->getAttributeOrders(); + $attributeOrders = $this->getAttributeOrders($recalculate); $orders = array(); foreach ($attributeOrders as $attribute => $direction) { $definition = $this->getAttribute($attribute); @@ -198,32 +206,6 @@ class Sort extends Object return $orders; } - /** - * Generates a hyperlink that links to the sort action to sort by the specified attribute. - * Based on the sort direction, the CSS class of the generated hyperlink will be appended - * with "asc" or "desc". - * @param string $attribute the attribute name by which the data should be sorted by. - * @param array $options additional HTML attributes for the hyperlink tag - * @return string the generated hyperlink - * @throws InvalidConfigException if the attribute is unknown - */ - public function link($attribute, $options = array()) - { - if (($direction = $this->getAttributeOrder($attribute)) !== null) { - $class = $direction ? 'desc' : 'asc'; - if (isset($options['class'])) { - $options['class'] .= ' ' . $class; - } else { - $options['class'] = $class; - } - } - - $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); - } - private $_attributeOrders; /** @@ -248,7 +230,7 @@ class Sort extends Object } } - if (($this->getAttribute($attribute)) !== false) { + if (($this->getAttribute($attribute)) !== null) { $this->_attributeOrders[$attribute] = $descending; if (!$this->enableMultiSort) { return $this->_attributeOrders; @@ -277,6 +259,32 @@ class Sort extends Object } /** + * Generates a hyperlink that links to the sort action to sort by the specified attribute. + * Based on the sort direction, the CSS class of the generated hyperlink will be appended + * with "asc" or "desc". + * @param string $attribute the attribute name by which the data should be sorted by. + * @param array $options additional HTML attributes for the hyperlink tag + * @return string the generated hyperlink + * @throws InvalidConfigException if the attribute is unknown + */ + public function link($attribute, $options = array()) + { + if (($direction = $this->getAttributeOrder($attribute)) !== null) { + $class = $direction ? 'desc' : 'asc'; + if (isset($options['class'])) { + $options['class'] .= ' ' . $class; + } else { + $options['class'] = $class; + } + } + + $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); + } + + /** * Creates a URL for sorting the data by the specified attribute. * This method will consider the current sorting status given by [[attributeOrders]]. * For example, if the current page already sorts the data by the specified attribute in ascending order, @@ -289,7 +297,7 @@ class Sort extends Object */ public function createUrl($attribute) { - if (($definition = $this->getAttribute($attribute)) === false) { + if (($definition = $this->getAttribute($attribute)) === null) { throw new InvalidConfigException("Unknown attribute: $attribute"); } $directions = $this->getAttributeOrders(); @@ -313,15 +321,15 @@ class Sort extends Object $params = $this->params === null ? $_GET : $this->params; $params[$this->sortVar] = implode($this->separators[0], $sorts); $route = $this->route === null ? Yii::$app->controller->getRoute() : $this->route; - - return Yii::$app->getUrlManager()->createUrl($route, $params); + $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|boolean the sort definition (column names => sort directions). - * False is returned if the attribute cannot be sorted. + * @return array the sort definition (column names => sort directions). + * Null is returned if the attribute cannot be sorted. * @see attributes */ public function getAttribute($name) @@ -332,10 +340,9 @@ class Sort extends Object return array( 'asc' => array($name => self::ASC), 'desc' => array($name => self::DESC), - 'label' => Inflector::camel2words($name), ); } else { - return false; + return null; } } } diff --git a/tests/unit/framework/data/SortTest.php b/tests/unit/framework/data/SortTest.php new file mode 100644 index 0000000..f5611cf --- /dev/null +++ b/tests/unit/framework/data/SortTest.php @@ -0,0 +1,175 @@ + + * @since 2.0 + */ +class SortTest extends TestCase +{ + public function testGetOrders() + { + $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, + )); + + $orders = $sort->getOrders(); + $this->assertEquals(3, count($orders)); + $this->assertEquals(Sort::ASC, $orders['age']); + $this->assertEquals(Sort::DESC, $orders['first_name']); + $this->assertEquals(Sort::DESC, $orders['last_name']); + + $sort->enableMultiSort = false; + $orders = $sort->getOrders(true); + $this->assertEquals(1, count($orders)); + $this->assertEquals(Sort::ASC, $orders['age']); + } + + public function testGetAttributeOrders() + { + $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, + )); + + $orders = $sort->getAttributeOrders(); + $this->assertEquals(2, count($orders)); + $this->assertEquals(Sort::ASC, $orders['age']); + $this->assertEquals(Sort::DESC, $orders['name']); + + $sort->enableMultiSort = false; + $orders = $sort->getAttributeOrders(true); + $this->assertEquals(1, count($orders)); + $this->assertEquals(Sort::ASC, $orders['age']); + } + + public function testGetAttributeOrder() + { + $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, + )); + + $this->assertEquals(Sort::ASC, $sort->getAttributeOrder('age')); + $this->assertEquals(Sort::DESC, $sort->getAttributeOrder('name')); + $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( + 'baseUrl' => '/index.php', + 'cache' => null, + )); + + $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, + 'urlManager' => $manager, + 'route' => 'site/index', + )); + + $this->assertEquals('/index.php?r=site/index&sort=age-desc.name-desc', $sort->createUrl('age')); + $this->assertEquals('/index.php?r=site/index&sort=name.age', $sort->createUrl('name')); + } + + public function testLink() + { + $this->mockApplication(); + $manager = new UrlManager(array( + 'baseUrl' => '/index.php', + 'cache' => null, + )); + + $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, + 'urlManager' => $manager, + 'route' => 'site/index', + )); + + $this->assertEquals('Age', $sort->link('age')); + } +} diff --git a/tests/unit/framework/web/UrlManagerTest.php b/tests/unit/framework/web/UrlManagerTest.php index 54e88ab..5e55c71 100644 --- a/tests/unit/framework/web/UrlManagerTest.php +++ b/tests/unit/framework/web/UrlManagerTest.php @@ -257,9 +257,6 @@ class UrlManagerTest extends TestCase public function testParseRESTRequest() { - $manager = new UrlManager(array( - 'cache' => null, - )); $request = new Request; // pretty URL rules