From 9fa1bec0cb4605ffdc00002b4d9e7fe4b039ae67 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 14 Dec 2010 18:21:39 -0800 Subject: [PATCH] Move Controller::paginate() into PaginatorComponent --- cake/libs/controller/components/paginator.php | 251 +++++++++ cake/libs/controller/controller.php | 219 +------- cake/libs/route/cake_route.php | 8 +- cake/libs/router.php | 28 +- .../controller/components/paginator.test.php | 485 ++++++++++++++++++ .../cases/libs/controller/controller.test.php | 373 ++------------ cake/tests/cases/libs/router.test.php | 107 ++++ 7 files changed, 910 insertions(+), 561 deletions(-) create mode 100644 cake/libs/controller/components/paginator.php create mode 100644 cake/tests/cases/libs/controller/components/paginator.test.php diff --git a/cake/libs/controller/components/paginator.php b/cake/libs/controller/components/paginator.php new file mode 100644 index 000000000..cb1bf7f0e --- /dev/null +++ b/cake/libs/controller/components/paginator.php @@ -0,0 +1,251 @@ + 1, 'limit' => 20), (array)$settings); + $this->Controller = $collection->getController(); + parent::__construct($collection, $settings); + } + +/** + * Handles automatic pagination of model records. + * + * @param mixed $object Model to paginate (e.g: model instance, or 'Model', or 'Model.InnerModel') + * @param mixed $scope Conditions to use while paginating + * @param array $whitelist List of allowed options for paging + * @return array Model query results + */ + public function paginate($object = null, $scope = array(), $whitelist = array()) { + if (is_array($object)) { + $whitelist = $scope; + $scope = $object; + $object = null; + } + $assoc = null; + + if (is_string($object)) { + $assoc = null; + if (strpos($object, '.') !== false) { + list($object, $assoc) = pluginSplit($object); + } + + if ($assoc && isset($this->Controller->{$object}->{$assoc})) { + $object = $this->Controller->{$object}->{$assoc}; + } elseif ( + $assoc && isset($this->Controller->{$this->Controller->modelClass}) && + isset($this->Controller->{$this->Controller->modelClass}->{$assoc} + )) { + $object = $this->Controller->{$this->Controller->modelClass}->{$assoc}; + } elseif (isset($this->Controller->{$object})) { + $object = $this->Controller->{$object}; + } elseif ( + isset($this->Controller->{$this->Controller->modelClass}) && isset($this->Controller->{$this->Controller->modelClass}->{$object} + )) { + $object = $this->Controller->{$this->Controller->modelClass}->{$object}; + } + } elseif (empty($object) || $object === null) { + if (isset($this->Controller->{$this->Controller->modelClass})) { + $object = $this->Controller->{$this->Controller->modelClass}; + } else { + $className = null; + $name = $this->Controller->uses[0]; + if (strpos($this->Controller->uses[0], '.') !== false) { + list($name, $className) = explode('.', $this->Controller->uses[0]); + } + if ($className) { + $object = $this->Controller->{$className}; + } else { + $object = $this->Controller->{$name}; + } + } + } + + if (!is_object($object)) { + throw new MissingModelException($object); + } + $options = array_merge($this->Controller->request->params, $this->Controller->params['url'], $this->Controller->passedArgs); + + if (isset($this->settings[$object->alias])) { + $defaults = $this->settings[$object->alias]; + } else { + $defaults = $this->settings; + } + + if (isset($options['show'])) { + $options['limit'] = $options['show']; + } + + if (isset($options['sort'])) { + $direction = null; + if (isset($options['direction'])) { + $direction = strtolower($options['direction']); + } + if ($direction != 'asc' && $direction != 'desc') { + $direction = 'asc'; + } + $options['order'] = array($options['sort'] => $direction); + } + + if (!empty($options['order']) && is_array($options['order'])) { + $alias = $object->alias ; + $key = $field = key($options['order']); + + if (strpos($key, '.') !== false) { + list($alias, $field) = explode('.', $key); + } + $value = $options['order'][$key]; + unset($options['order'][$key]); + + if ($object->hasField($field)) { + $options['order'][$alias . '.' . $field] = $value; + } elseif ($object->hasField($field, true)) { + $options['order'][$field] = $value; + } elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) { + $options['order'][$alias . '.' . $field] = $value; + } + } + $vars = array('fields', 'order', 'limit', 'page', 'recursive'); + $keys = array_keys($options); + $count = count($keys); + + for ($i = 0; $i < $count; $i++) { + if (!in_array($keys[$i], $vars, true)) { + unset($options[$keys[$i]]); + } + if (empty($whitelist) && ($keys[$i] === 'fields' || $keys[$i] === 'recursive')) { + unset($options[$keys[$i]]); + } elseif (!empty($whitelist) && !in_array($keys[$i], $whitelist)) { + unset($options[$keys[$i]]); + } + } + $conditions = $fields = $order = $limit = $page = $recursive = null; + + if (!isset($defaults['conditions'])) { + $defaults['conditions'] = array(); + } + + $type = 'all'; + + if (isset($defaults[0])) { + $type = $defaults[0]; + unset($defaults[0]); + } + + $options = array_merge(array('page' => 1, 'limit' => 20), $defaults, $options); + $options['limit'] = (int) $options['limit']; + if (empty($options['limit']) || $options['limit'] < 1) { + $options['limit'] = 1; + } + + extract($options); + + if (is_array($scope) && !empty($scope)) { + $conditions = array_merge($conditions, $scope); + } elseif (is_string($scope)) { + $conditions = array($conditions, $scope); + } + if ($recursive === null) { + $recursive = $object->recursive; + } + + $extra = array_diff_key($defaults, compact( + 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' + )); + if ($type !== 'all') { + $extra['type'] = $type; + } + + if (method_exists($object, 'paginateCount')) { + $count = $object->paginateCount($conditions, $recursive, $extra); + } else { + $parameters = compact('conditions'); + if ($recursive != $object->recursive) { + $parameters['recursive'] = $recursive; + } + $count = $object->find('count', array_merge($parameters, $extra)); + } + $pageCount = intval(ceil($count / $limit)); + + if ($page === 'last' || $page >= $pageCount) { + $options['page'] = $page = $pageCount; + } elseif (intval($page) < 1) { + $options['page'] = $page = 1; + } + $page = $options['page'] = (integer)$page; + + if (method_exists($object, 'paginate')) { + $results = $object->paginate( + $conditions, $fields, $order, $limit, $page, $recursive, $extra + ); + } else { + $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); + if ($recursive != $object->recursive) { + $parameters['recursive'] = $recursive; + } + $results = $object->find($type, array_merge($parameters, $extra)); + } + $paging = array( + 'page' => $page, + 'current' => count($results), + 'count' => $count, + 'prevPage' => ($page > 1), + 'nextPage' => ($count > ($page * $limit)), + 'pageCount' => $pageCount, + 'defaults' => array_merge(array('limit' => 20, 'step' => 1), $defaults), + 'options' => $options + ); + if (!isset($this->Controller->request['paging'])) { + $this->Controller->request['paging'] = array(); + } + $this->Controller->request['paging'] = array_merge( + (array)$this->Controller->request['paging'], + array($object->alias => $paging) + ); + + if (!in_array('Paginator', $this->Controller->helpers) && !array_key_exists('Paginator', $this->Controller->helpers)) { + $this->Controller->helpers[] = 'Paginator'; + } + return $results; + } +} \ No newline at end of file diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 7bc58f024..9afc3e315 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -94,26 +94,6 @@ class Controller extends Object { */ protected $_responseClass = 'CakeResponse'; -/** - * Holds pagination defaults for controller actions. The keys that can be included - * in this array are: 'conditions', 'fields', 'order', 'limit', 'page', and 'recursive', - * similar to the keys in the second parameter of Model::find(). - * - * Pagination defaults can also be supplied in a model-by-model basis by using - * the name of the model as a key for a pagination array: - * - * {{{ - * public $paginate = array( - * 'Post' => array(...), - * 'Comment' => array(...) - * ); - * }}} - * - * @var array - * @link http://book.cakephp.org/view/1231/Pagination - */ - public $paginate = array('limit' => 20, 'page' => 1, 'maxLimit' => 100); - /** * The name of the views subfolder containing views for this controller. * @@ -362,6 +342,8 @@ class Controller extends Object { return isset($this->request->params['action']) ? $this->request->params['action'] : ''; case 'params': return $this->request; + case 'paginate': + return $this->Components->load('Paginator')->settings; } return null; } @@ -382,6 +364,8 @@ class Controller extends Object { return $this->request->params['action'] = $value; case 'params': return $this->request->params = $value; + case 'paginate': + return $this->Components->load('Paginator')->settings = $value; } return $this->{$name} = $value; } @@ -961,201 +945,10 @@ class Controller extends Object { * @param array $whitelist List of allowed options for paging * @return array Model query results * @link http://book.cakephp.org/view/1232/Controller-Setup + * @deprecated Use PaginatorComponent instead */ public function paginate($object = null, $scope = array(), $whitelist = array()) { - if (is_array($object)) { - $whitelist = $scope; - $scope = $object; - $object = null; - } - $assoc = null; - - if (is_string($object)) { - $assoc = null; - if (strpos($object, '.') !== false) { - list($object, $assoc) = pluginSplit($object); - } - - if ($assoc && isset($this->{$object}->{$assoc})) { - $object = $this->{$object}->{$assoc}; - } elseif ( - $assoc && isset($this->{$this->modelClass}) && - isset($this->{$this->modelClass}->{$assoc} - )) { - $object = $this->{$this->modelClass}->{$assoc}; - } elseif (isset($this->{$object})) { - $object = $this->{$object}; - } elseif ( - isset($this->{$this->modelClass}) && isset($this->{$this->modelClass}->{$object} - )) { - $object = $this->{$this->modelClass}->{$object}; - } - } elseif (empty($object) || $object === null) { - if (isset($this->{$this->modelClass})) { - $object = $this->{$this->modelClass}; - } else { - $className = null; - $name = $this->uses[0]; - if (strpos($this->uses[0], '.') !== false) { - list($name, $className) = explode('.', $this->uses[0]); - } - if ($className) { - $object = $this->{$className}; - } else { - $object = $this->{$name}; - } - } - } - - if (!is_object($object)) { - trigger_error(sprintf( - __('Controller::paginate() - can\'t find model %1$s in controller %2$sController'), $object, $this->name - ), E_USER_WARNING); - return array(); - } - $options = array_merge($this->request->params, $this->request->query, $this->passedArgs); - - if (isset($this->paginate[$object->alias])) { - $defaults = $this->paginate[$object->alias]; - } else { - $defaults = $this->paginate; - } - - if (isset($options['show'])) { - $options['limit'] = $options['show']; - } - - if (isset($options['sort'])) { - $direction = null; - if (isset($options['direction'])) { - $direction = strtolower($options['direction']); - } - if ($direction != 'asc' && $direction != 'desc') { - $direction = 'asc'; - } - $options['order'] = array($options['sort'] => $direction); - } - - if (!empty($options['order']) && is_array($options['order'])) { - $alias = $object->alias ; - $key = $field = key($options['order']); - - if (strpos($key, '.') !== false) { - list($alias, $field) = explode('.', $key); - } - $value = $options['order'][$key]; - unset($options['order'][$key]); - - if ($object->hasField($field)) { - $options['order'][$alias . '.' . $field] = $value; - } elseif ($object->hasField($field, true)) { - $options['order'][$field] = $value; - } elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) { - $options['order'][$alias . '.' . $field] = $value; - } - } - $vars = array('fields', 'order', 'limit', 'page', 'recursive'); - $keys = array_keys($options); - $count = count($keys); - - for ($i = 0; $i < $count; $i++) { - if (!in_array($keys[$i], $vars, true)) { - unset($options[$keys[$i]]); - } - if (empty($whitelist) && ($keys[$i] === 'fields' || $keys[$i] === 'recursive')) { - unset($options[$keys[$i]]); - } elseif (!empty($whitelist) && !in_array($keys[$i], $whitelist)) { - unset($options[$keys[$i]]); - } - } - $conditions = $fields = $order = $limit = $page = $recursive = null; - - if (!isset($defaults['conditions'])) { - $defaults['conditions'] = array(); - } - - $type = 'all'; - - if (isset($defaults[0])) { - $type = $defaults[0]; - unset($defaults[0]); - } - - $options = array_merge(array('page' => 1, 'limit' => 20, 'maxLimit' => 100), $defaults, $options); - $options['limit'] = min((int)$options['limit'], $options['maxLimit']); - if (empty($options['limit']) || $options['limit'] < 1) { - $options['limit'] = 1; - } - - extract($options); - - if (is_array($scope) && !empty($scope)) { - $conditions = array_merge($conditions, $scope); - } elseif (is_string($scope)) { - $conditions = array($conditions, $scope); - } - if ($recursive === null) { - $recursive = $object->recursive; - } - - $extra = array_diff_key($defaults, compact( - 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' - )); - if ($type !== 'all') { - $extra['type'] = $type; - } - - if (method_exists($object, 'paginateCount')) { - $count = $object->paginateCount($conditions, $recursive, $extra); - } else { - $parameters = compact('conditions'); - if ($recursive != $object->recursive) { - $parameters['recursive'] = $recursive; - } - $count = $object->find('count', array_merge($parameters, $extra)); - } - $pageCount = intval(ceil($count / $limit)); - - if ($page === 'last' || $page >= $pageCount) { - $options['page'] = $page = $pageCount; - } elseif (intval($page) < 1) { - $options['page'] = $page = 1; - } - $page = $options['page'] = (int)$page; - - if (method_exists($object, 'paginate')) { - $results = $object->paginate( - $conditions, $fields, $order, $limit, $page, $recursive, $extra - ); - } else { - $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); - if ($recursive != $object->recursive) { - $parameters['recursive'] = $recursive; - } - $results = $object->find($type, array_merge($parameters, $extra)); - } - $paging = array( - 'page' => $page, - 'current' => count($results), - 'count' => $count, - 'prevPage' => ($page > 1), - 'nextPage' => ($count > ($page * $limit)), - 'pageCount' => $pageCount, - 'defaults' => array_merge(array('limit' => 20, 'step' => 1), $defaults), - 'options' => $options - ); - if (!isset($this->request->params['paging'])) { - $this->request->params['paging'] = array(); - } - $this->request->params['paging'] = array_merge( - (array)$this->request->params['paging'], - array($object->alias => $paging) - ); - - if (!in_array('Paginator', $this->helpers) && !array_key_exists('Paginator', $this->helpers)) { - $this->helpers[] = 'Paginator'; - } - return $results; + return $this->Components->load('Paginator', $this->paginate)->paginate($object, $scope, $whitelist); } /** diff --git a/cake/libs/route/cake_route.php b/cake/libs/route/cake_route.php index 706323f3a..979f90dcf 100644 --- a/cake/libs/route/cake_route.php +++ b/cake/libs/route/cake_route.php @@ -343,7 +343,13 @@ class CakeRoute { if (!empty($params['named']) && is_array($params['named'])) { $named = array(); foreach ($params['named'] as $key => $value) { - $named[] = $key . $separator . $value; + if (is_array($value)) { + foreach ($value as $namedKey => $namedValue) { + $named[] = $key . "[$namedKey]" . $separator . $namedValue; + } + } else { + $named[] = $key . $separator . $value; + } } $params['pass'] = $params['pass'] . '/' . implode('/', $named); } diff --git a/cake/libs/router.php b/cake/libs/router.php index 010511cb2..91261c6ce 100644 --- a/cake/libs/router.php +++ b/cake/libs/router.php @@ -937,8 +937,15 @@ class Router { } if (!empty($named)) { - foreach ($named as $name => $value) { - $output .= '/' . $name . self::$named['separator'] . $value; + foreach ($named as $name => $value) { + if (is_array($value)) { + $flattend = Set::flatten($value, ']['); + foreach ($flattend as $namedKey => $namedValue) { + $output .= '/' . $name . "[$namedKey]" . self::$named['separator'] . $namedValue; + } + } else { + $output .= '/' . $name . self::$named['separator'] . $value; + } } } return $output; @@ -1202,7 +1209,22 @@ class Router { if ($passIt) { $pass[] = $param; } else { - $named[$key] = $val; + if (preg_match_all('/\[([A-Za-z0-9_-]+)?\]/', $key, $matches, PREG_SET_ORDER)) { + $matches = array_reverse($matches); + $key = array_shift(explode('[', $key)); + $arr = $val; + foreach ($matches as $match) { + if (empty($match[1])) { + $arr = array($arr); + } else { + $arr = array( + $match[1] => $arr + ); + } + } + $val = $arr; + } + $named = array_merge_recursive($named, array($key => $val)); } } else { $pass[] = $param; diff --git a/cake/tests/cases/libs/controller/components/paginator.test.php b/cake/tests/cases/libs/controller/components/paginator.test.php new file mode 100644 index 000000000..eebdd3304 --- /dev/null +++ b/cake/tests/cases/libs/controller/components/paginator.test.php @@ -0,0 +1,485 @@ + + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake + * @subpackage cake.cake.tests.cases.libs.controller.components + * @since CakePHP(tm) v 2.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::import('Controller', 'Controller', false); +App::import('Core', array('CakeRequest', 'CakeResponse')); + +/** + * PaginatorTestController class + * + * @package cake + * @subpackage cake.tests.cases.libs.controller.components + */ +class PaginatorTestController extends Controller { +/** + * name property + * + * @var string 'PaginatorTest' + * @access public + */ + public $name = 'PaginatorTest'; + +/** + * uses property + * + * @var array + * @access public + */ + //public $uses = null; + +/** + * components property + * + * @var array + * @access public + */ + public $components = array('Paginator'); +} + +/** + * ControllerPost class + * + * @package cake + * @subpackage cake.tests.cases.libs.controller.components + */ +class ControllerPost extends CakeTestModel { + +/** + * name property + * + * @var string 'ControllerPost' + * @access public + */ + public $name = 'ControllerPost'; + +/** + * useTable property + * + * @var string 'posts' + * @access public + */ + public $useTable = 'posts'; + +/** + * invalidFields property + * + * @var array + * @access public + */ + public $invalidFields = array('name' => 'error_msg'); + +/** + * lastQuery property + * + * @var mixed null + * @access public + */ + public $lastQuery = null; + +/** + * beforeFind method + * + * @param mixed $query + * @access public + * @return void + */ + function beforeFind($query) { + $this->lastQuery = $query; + } + +/** + * find method + * + * @param mixed $type + * @param array $options + * @access public + * @return void + */ + function find($type, $options = array()) { + if ($type == 'popular') { + $conditions = array($this->name . '.' . $this->primaryKey .' > ' => '1'); + $options = Set::merge($options, compact('conditions')); + return parent::find('all', $options); + } + return parent::find($type, $options); + } +} + +/** + * ControllerPaginateModel class + * + * @package cake + * @subpackage cake.tests.cases.libs.controller.components + */ +class ControllerPaginateModel extends CakeTestModel { + +/** + * name property + * + * @var string 'ControllerPaginateModel' + * @access public + */ + public $name = 'ControllerPaginateModel'; + +/** + * useTable property + * + * @var string 'comments' + * @access public + */ + public $useTable = 'comments'; + +/** + * paginate method + * + * @return void + */ + public function paginate($conditions, $fields, $order, $limit, $page, $recursive, $extra) { + $this->extra = $extra; + } + +/** + * paginateCount + * + * @access public + * @return void + */ + function paginateCount($conditions, $recursive, $extra) { + $this->extraCount = $extra; + } +} + +/** + * ControllerComment class + * + * @package cake + * @subpackage cake.tests.cases.libs.controller.components + */ +class ControllerComment extends CakeTestModel { + +/** + * name property + * + * @var string 'Comment' + * @access public + */ + public $name = 'Comment'; + +/** + * useTable property + * + * @var string 'comments' + * @access public + */ + public $useTable = 'comments'; + +/** + * alias property + * + * @var string 'ControllerComment' + * @access public + */ + public $alias = 'ControllerComment'; +} + +class PaginatorTest extends CakeTestCase { + +/** + * fixtures property + * + * @var array + * @access public + */ + public $fixtures = array('core.post', 'core.comment'); + +/** + * testPaginate method + * + * @access public + * @return void + */ + function testPaginate() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->uses = array('ControllerPost', 'ControllerComment'); + $Controller->passedArgs[] = '1'; + $Controller->params['url'] = array(); + $Controller->constructClasses(); + + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($results, array(1, 2, 3)); + + $results = Set::extract($Controller->Paginator->paginate('ControllerComment'), '{n}.ControllerComment.id'); + $this->assertEqual($results, array(1, 2, 3, 4, 5, 6)); + + $Controller->modelClass = null; + + $Controller->uses[0] = 'Plugin.ControllerPost'; + $results = Set::extract($Controller->Paginator->paginate(), '{n}.ControllerPost.id'); + $this->assertEqual($results, array(1, 2, 3)); + + $Controller->passedArgs = array('page' => '-1'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual($results, array(1, 2, 3)); + + $Controller->passedArgs = array('sort' => 'ControllerPost.id', 'direction' => 'asc'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual($results, array(1, 2, 3)); + + $Controller->passedArgs = array('sort' => 'ControllerPost.id', 'direction' => 'desc'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual($results, array(3, 2, 1)); + + $Controller->passedArgs = array('sort' => 'id', 'direction' => 'desc'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual($results, array(3, 2, 1)); + + $Controller->passedArgs = array('sort' => 'NotExisting.field', 'direction' => 'desc'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1, 'Invalid field in query %s'); + $this->assertEqual($results, array(1, 2, 3)); + + $Controller->passedArgs = array('sort' => 'ControllerPost.author_id', 'direction' => 'allYourBase'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->ControllerPost->lastQuery['order'][0], array('ControllerPost.author_id' => 'asc')); + $this->assertEqual($results, array(1, 3, 2)); + + $Controller->passedArgs = array('page' => '1 " onclick="alert(\'xss\');">'); + $Controller->Paginator->settings = array('limit' => 1); + $Controller->Paginator->paginate('ControllerPost'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1, 'XSS exploit opened %s'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['options']['page'], 1, 'XSS exploit opened %s'); + + $Controller->passedArgs = array(); + $Controller->Paginator->settings = array('limit' => 0); + $Controller->Paginator->paginate('ControllerPost'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); + + $Controller->passedArgs = array(); + $Controller->Paginator->settings = array('limit' => 'garbage!'); + $Controller->Paginator->paginate('ControllerPost'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); + + $Controller->passedArgs = array(); + $Controller->Paginator->settings = array('limit' => '-1'); + $Controller->Paginator->paginate('ControllerPost'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); + } + +/** + * testPaginateExtraParams method + * + * @access public + * @return void + */ + function testPaginateExtraParams() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + + $Controller->uses = array('ControllerPost', 'ControllerComment'); + $Controller->passedArgs[] = '1'; + $Controller->params['url'] = array(); + $Controller->constructClasses(); + + $Controller->passedArgs = array('page' => '-1', 'contain' => array('ControllerComment')); + $result = $Controller->Paginator->paginate('ControllerPost'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(1, 2, 3)); + $this->assertTrue(!isset($Controller->ControllerPost->lastQuery['contain'])); + + $Controller->passedArgs = array('page' => '-1'); + $Controller->Paginator->settings = array('ControllerPost' => array('contain' => array('ControllerComment'))); + $result = $Controller->Paginator->paginate('ControllerPost'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(1, 2, 3)); + $this->assertTrue(isset($Controller->ControllerPost->lastQuery['contain'])); + + $Controller->Paginator->settings = array('ControllerPost' => array('popular', 'fields' => array('id', 'title'))); + $result = $Controller->Paginator->paginate('ControllerPost'); + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(2, 3)); + $this->assertEqual($Controller->ControllerPost->lastQuery['conditions'], array('ControllerPost.id > ' => '1')); + + $Controller->passedArgs = array('limit' => 12); + $Controller->Paginator->settings = array('limit' => 30); + $result = $Controller->Paginator->paginate('ControllerPost'); + $paging = $Controller->params['paging']['ControllerPost']; + + $this->assertEqual($Controller->ControllerPost->lastQuery['limit'], 12); + $this->assertEqual($paging['options']['limit'], 12); + + $Controller = new PaginatorTestController($request); + $Controller->uses = array('ControllerPaginateModel'); + $Controller->params['url'] = array(); + $Controller->constructClasses(); + $Controller->Paginator->settings = array( + 'ControllerPaginateModel' => array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id') + ); + $result = $Controller->Paginator->paginate('ControllerPaginateModel'); + $expected = array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id'); + $this->assertEqual($Controller->ControllerPaginateModel->extra, $expected); + $this->assertEqual($Controller->ControllerPaginateModel->extraCount, $expected); + + $Controller->Paginator->settings = array( + 'ControllerPaginateModel' => array('foo', 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id') + ); + $Controller->Paginator->paginate('ControllerPaginateModel'); + $expected = array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'type' => 'foo'); + $this->assertEqual($Controller->ControllerPaginateModel->extra, $expected); + $this->assertEqual($Controller->ControllerPaginateModel->extraCount, $expected); + } + +/** + * testPaginatePassedArgs method + * + * @return void + */ + public function testPaginatePassedArgs() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->uses = array('ControllerPost'); + $Controller->passedArgs[] = array('1', '2', '3'); + $Controller->params['url'] = array(); + $Controller->constructClasses(); + + $Controller->Paginator->settings = array( + 'fields' => array(), + 'order' => '', + 'limit' => 5, + 'page' => 1, + 'recursive' => -1 + ); + $conditions = array(); + $Controller->Paginator->paginate('ControllerPost',$conditions); + + $expected = array( + 'fields' => array(), + 'order' => '', + 'limit' => 5, + 'page' => 1, + 'recursive' => -1, + 'conditions' => array() + ); + $this->assertEqual($Controller->params['paging']['ControllerPost']['options'],$expected); + } + +/** + * Test that special paginate types are called and that the type param doesn't leak out into defaults or options. + * + * @return void + */ + function testPaginateSpecialType() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->uses = array('ControllerPost', 'ControllerComment'); + $Controller->passedArgs[] = '1'; + $Controller->params['url'] = array(); + $Controller->constructClasses(); + + $Controller->Paginator->settings = array('ControllerPost' => array('popular', 'fields' => array('id', 'title'))); + $result = $Controller->Paginator->paginate('ControllerPost'); + + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(2, 3)); + $this->assertEqual($Controller->ControllerPost->lastQuery['conditions'], array('ControllerPost.id > ' => '1')); + $this->assertFalse(isset($Controller->params['paging']['ControllerPost']['defaults'][0])); + $this->assertFalse(isset($Controller->params['paging']['ControllerPost']['options'][0])); + } + +/** + * testDefaultPaginateParams method + * + * @access public + * @return void + */ + function testDefaultPaginateParams() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->modelClass = 'ControllerPost'; + $Controller->params['url'] = array(); + $Controller->constructClasses(); + $Controller->Paginator->settings = array('order' => 'ControllerPost.id DESC'); + $results = Set::extract($Controller->Paginator->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['defaults']['order'], 'ControllerPost.id DESC'); + $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['order'], 'ControllerPost.id DESC'); + $this->assertEqual($results, array(3, 2, 1)); + } + +/** + * test paginate() and virtualField interactions + * + * @return void + */ + function testPaginateOrderVirtualField() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->uses = array('ControllerPost', 'ControllerComment'); + $Controller->params['url'] = array(); + $Controller->constructClasses(); + $Controller->ControllerPost->virtualFields = array( + 'offset_test' => 'ControllerPost.id + 1' + ); + + $Controller->Paginator->settings = array( + 'fields' => array('id', 'title', 'offset_test'), + 'order' => array('offset_test' => 'DESC') + ); + $result = $Controller->Paginator->paginate('ControllerPost'); + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(4, 3, 2)); + + $Controller->passedArgs = array('sort' => 'offset_test', 'direction' => 'asc'); + $result = $Controller->Paginator->paginate('ControllerPost'); + $this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(2, 3, 4)); + } + + function testPaginateMissingModel() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new PaginatorTestController($request); + $Controller->constructClasses(); + $this->expectException('MissingModelException'); + $Controller->Paginator->paginate('MissingModel'); + } +} \ No newline at end of file diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index 089955373..0521283b2 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -597,350 +597,6 @@ class ControllerTest extends CakeTestCase { Configure::write('Cache.disable', true); } -/** - * testPaginate method - * - * @access public - * @return void - */ - function testPaginate() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPost', 'ControllerComment'); - $Controller->passedArgs[] = '1'; - $Controller->params['url'] = array(); - $Controller->constructClasses(); - - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($results, array(1, 2, 3)); - - $results = Set::extract($Controller->paginate('ControllerComment'), '{n}.ControllerComment.id'); - $this->assertEqual($results, array(1, 2, 3, 4, 5, 6)); - - $Controller->modelClass = null; - - $Controller->uses[0] = 'Plugin.ControllerPost'; - $results = Set::extract($Controller->paginate(), '{n}.ControllerPost.id'); - $this->assertEqual($results, array(1, 2, 3)); - - $Controller->passedArgs = array('page' => '-1'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual($results, array(1, 2, 3)); - - $Controller->passedArgs = array('sort' => 'ControllerPost.id', 'direction' => 'asc'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual($results, array(1, 2, 3)); - - $Controller->passedArgs = array('sort' => 'ControllerPost.id', 'direction' => 'desc'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual($results, array(3, 2, 1)); - - $Controller->passedArgs = array('sort' => 'id', 'direction' => 'desc'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual($results, array(3, 2, 1)); - - $Controller->passedArgs = array('sort' => 'NotExisting.field', 'direction' => 'desc'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1, 'Invalid field in query %s'); - $this->assertEqual($results, array(1, 2, 3)); - - $Controller->passedArgs = array('sort' => 'ControllerPost.author_id', 'direction' => 'allYourBase'); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->ControllerPost->lastQuery['order'][0], array('ControllerPost.author_id' => 'asc')); - $this->assertEqual($results, array(1, 3, 2)); - - $Controller->passedArgs = array('page' => '1 " onclick="alert(\'xss\');">'); - $Controller->paginate = array('limit' => 1); - $Controller->paginate('ControllerPost'); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1, 'XSS exploit opened %s'); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['options']['page'], 1, 'XSS exploit opened %s'); - - $Controller->passedArgs = array(); - $Controller->paginate = array('limit' => 0); - $Controller->paginate('ControllerPost'); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); - - $Controller->passedArgs = array(); - $Controller->paginate = array('limit' => 'garbage!'); - $Controller->paginate('ControllerPost'); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); - - $Controller->passedArgs = array(); - $Controller->paginate = array('limit' => '-1'); - $Controller->paginate('ControllerPost'); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); - $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); - } - -/** - * testPaginateExtraParams method - * - * @access public - * @return void - */ - function testPaginateExtraParams() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - - $Controller->uses = array('ControllerPost', 'ControllerComment'); - $Controller->passedArgs[] = '1'; - $Controller->params['url'] = array(); - $Controller->constructClasses(); - - $Controller->passedArgs = array('page' => '-1', 'contain' => array('ControllerComment')); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(1, 2, 3)); - $this->assertTrue(!isset($Controller->ControllerPost->lastQuery['contain'])); - - $Controller->passedArgs = array('page' => '-1'); - $Controller->paginate = array('ControllerPost' => array('contain' => array('ControllerComment'))); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['page'], 1); - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(1, 2, 3)); - $this->assertTrue(isset($Controller->ControllerPost->lastQuery['contain'])); - - $Controller->paginate = array('ControllerPost' => array('popular', 'fields' => array('id', 'title'))); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(2, 3)); - $this->assertEqual($Controller->ControllerPost->lastQuery['conditions'], array('ControllerPost.id > ' => '1')); - - $Controller->passedArgs = array('limit' => 12); - $Controller->paginate = array('limit' => 30); - $result = $Controller->paginate('ControllerPost'); - $paging = $Controller->params['paging']['ControllerPost']; - - $this->assertEqual($Controller->ControllerPost->lastQuery['limit'], 12); - $this->assertEqual($paging['options']['limit'], 12); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPaginateModel'); - $Controller->params['url'] = array(); - $Controller->constructClasses(); - $Controller->paginate = array( - 'ControllerPaginateModel' => array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id') - ); - $result = $Controller->paginate('ControllerPaginateModel'); - $expected = array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id'); - $this->assertEqual($Controller->ControllerPaginateModel->extra, $expected); - $this->assertEqual($Controller->ControllerPaginateModel->extraCount, $expected); - - $Controller->paginate = array( - 'ControllerPaginateModel' => array('foo', 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id') - ); - $Controller->paginate('ControllerPaginateModel'); - $expected = array('contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'type' => 'foo'); - $this->assertEqual($Controller->ControllerPaginateModel->extra, $expected); - $this->assertEqual($Controller->ControllerPaginateModel->extraCount, $expected); - } - -/** - * testPaginateMaxLimit - * - * @return void - * @access public - */ - function testPaginateMaxLimit() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - - $Controller->uses = array('ControllerPost', 'ControllerComment'); - $Controller->passedArgs[] = '1'; - $Controller->params['url'] = array(); - $Controller->constructClasses(); - - $Controller->passedArgs = array('contain' => array('ControllerComment'), 'limit' => '1000'); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['limit'], 100); - - $Controller->passedArgs = array('contain' => array('ControllerComment'), 'limit' => '1000', 'maxLimit' => 1000); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['limit'], 100); - - $Controller->passedArgs = array('contain' => array('ControllerComment'), 'limit' => '10'); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['limit'], 10); - - $Controller->passedArgs = array('contain' => array('ControllerComment'), 'limit' => '1000'); - $Controller->paginate = array('maxLimit' => 2000); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['limit'], 1000); - - $Controller->passedArgs = array('contain' => array('ControllerComment'), 'limit' => '5000'); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['limit'], 2000); - } - -/** - * testPaginateFieldsDouble method - * - * @return void - * @access public - */ - function testPaginateFieldsDouble(){ - $request = new CakeRequest('controller_posts/index'); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPost'); - $Controller->request = $this->getMock('CakeRequest'); - $Controller->request->params['url'] = array(); - $Controller->constructClasses(); - - $Controller->paginate = array( - 'fields' => array( - 'ControllerPost.id', - 'radians(180.0) as floatvalue' - ), - 'order' => array('ControllerPost.created'=>'DESC'), - 'limit' => 1, - 'page' => 1, - 'recursive' => -1 - ); - $conditions = array(); - $result = $Controller->paginate('ControllerPost',$conditions); - $expected = array( - array( - 'ControllerPost' => array( - 'id' => 3, - ), - 0 => array( - 'floatvalue' => '3.14159265358979', - ), - ), - ); - $this->assertEqual($result, $expected); - } - - -/** - * testPaginatePassedArgs method - * - * @return void - */ - public function testPaginatePassedArgs() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPost'); - $Controller->passedArgs[] = array('1', '2', '3'); - $Controller->params['url'] = array(); - $Controller->constructClasses(); - - $Controller->paginate = array( - 'fields' => array(), - 'order' => '', - 'limit' => 5, - 'page' => 1, - 'recursive' => -1 - ); - $conditions = array(); - $Controller->paginate('ControllerPost',$conditions); - - $expected = array( - 'fields' => array(), - 'order' => '', - 'limit' => 5, - 'maxLimit' => 100, - 'page' => 1, - 'recursive' => -1, - 'conditions' => array() - ); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options'],$expected); - } - -/** - * Test that special paginate types are called and that the type param doesn't leak out into defaults or options. - * - * @return void - */ - function testPaginateSpecialType() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPost', 'ControllerComment'); - $Controller->passedArgs[] = '1'; - $Controller->params['url'] = array(); - $Controller->constructClasses(); - - $Controller->paginate = array('ControllerPost' => array('popular', 'fields' => array('id', 'title'))); - $result = $Controller->paginate('ControllerPost'); - - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.id'), array(2, 3)); - $this->assertEqual($Controller->ControllerPost->lastQuery['conditions'], array('ControllerPost.id > ' => '1')); - $this->assertFalse(isset($Controller->params['paging']['ControllerPost']['defaults'][0])); - $this->assertFalse(isset($Controller->params['paging']['ControllerPost']['options'][0])); - } - -/** - * testDefaultPaginateParams method - * - * @access public - * @return void - */ - function testDefaultPaginateParams() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - $Controller->modelClass = 'ControllerPost'; - $Controller->params['url'] = array(); - $Controller->paginate = array('order' => 'ControllerPost.id DESC'); - $Controller->constructClasses(); - $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['defaults']['order'], 'ControllerPost.id DESC'); - $this->assertEqual($Controller->params['paging']['ControllerPost']['options']['order'], 'ControllerPost.id DESC'); - $this->assertEqual($results, array(3, 2, 1)); - } - -/** - * test paginate() and virtualField interactions - * - * @return void - */ - function testPaginateOrderVirtualField() { - $request = new CakeRequest('controller_posts/index'); - $request->params['pass'] = $request->params['named'] = array(); - - $Controller = new Controller($request); - $Controller->uses = array('ControllerPost', 'ControllerComment'); - $Controller->params['url'] = array(); - $Controller->constructClasses(); - $Controller->ControllerPost->virtualFields = array( - 'offset_test' => 'ControllerPost.id + 1' - ); - - $Controller->paginate = array( - 'fields' => array('id', 'title', 'offset_test'), - 'order' => array('offset_test' => 'DESC') - ); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(4, 3, 2)); - - $Controller->passedArgs = array('sort' => 'offset_test', 'direction' => 'asc'); - $result = $Controller->paginate('ControllerPost'); - $this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(2, 3, 4)); - } - /** * testFlash method * @@ -1648,4 +1304,33 @@ class ControllerTest extends CakeTestCase { $this->assertType('SecurityComponent', $Controller->Security); $this->assertType('ControllerComment', $Controller->ControllerComment); } + +/** + * test that using Controller::paginate() falls back to PaginatorComponent + * + * @return void + */ + function testPaginateBackwardsCompatibility() { + $request = new CakeRequest('controller_posts/index'); + $request->params['pass'] = $request->params['named'] = array(); + + $Controller = new Controller($request); + $Controller->uses = array('ControllerPost', 'ControllerComment'); + $Controller->passedArgs[] = '1'; + $Controller->params['url'] = array(); + $Controller->constructClasses(); + $this->assertEqual($Controller->paginate, array('page' => 1, 'limit' => 20)); + + $results = Set::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); + $this->assertEqual($results, array(1, 2, 3)); + + $Controller->passedArgs = array(); + $Controller->paginate = array('limit' => '-1'); + $this->assertEqual($Controller->paginate, array('limit' => '-1')); + $Controller->paginate('ControllerPost'); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['page'], 1); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['pageCount'], 3); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['prevPage'], false); + $this->assertIdentical($Controller->params['paging']['ControllerPost']['nextPage'], true); + } } diff --git a/cake/tests/cases/libs/router.test.php b/cake/tests/cases/libs/router.test.php index ffe168ac8..e0def56f9 100644 --- a/cake/tests/cases/libs/router.test.php +++ b/cake/tests/cases/libs/router.test.php @@ -383,6 +383,113 @@ class RouterTest extends CakeTestCase { $this->assertEqual($result, $expected); } +/** + * Tests using arrays in named parameters + * + * @return void + */ + function testArrayNamedParameters() { + $result = Router::url(array('controller' => 'tests', 'pages' => array( + 1, 2, 3 + ))); + $expected = '/tests/index/pages[0]:1/pages[1]:2/pages[2]:3'; + $this->assertEqual($result, $expected); + + $result = Router::url(array('controller' => 'tests', + 'pages' => array( + 'param1' => array( + 'one', + 'two' + ), + 'three' + ) + )); + $expected = '/tests/index/pages[param1][0]:one/pages[param1][1]:two/pages[0]:three'; + $this->assertEqual($result, $expected); + + $result = Router::url(array('controller' => 'tests', + 'pages' => array( + 'param1' => array( + 'one' => 1, + 'two' => 2 + ), + 'three' + ) + )); + $expected = '/tests/index/pages[param1][one]:1/pages[param1][two]:2/pages[0]:three'; + $this->assertEqual($result, $expected); + + $result = Router::url(array('controller' => 'tests', + 'super' => array( + 'nested' => array( + 'array' => 'awesome', + 'something' => 'else' + ), + 'cool' + ) + )); + $expected = '/tests/index/super[nested][array]:awesome/super[nested][something]:else/super[0]:cool'; + $this->assertEqual($result, $expected); + + $result = Router::url(array('controller' => 'tests', 'namedParam' => array( + 'keyed' => 'is an array', + 'test' + ))); + $expected = '/tests/index/namedParam[keyed]:is an array/namedParam[0]:test'; + $this->assertEqual($result, $expected); + + $result = Router::parse('/tests/action/var[]:val1/var[]:val2'); + $expected = array( + 'controller' => 'tests', + 'action' => 'action', + 'named' => array( + 'var' => array( + 'val1', + 'val2' + ) + ), + 'pass' => array(), + 'plugin' => null + ); + $this->assertEqual($result, $expected); + + $result = Router::parse('/tests/action/theanswer[is]:42/var[]:val2/var[]:val3'); + $expected = array( + 'controller' => 'tests', + 'action' => 'action', + 'named' => array( + 'theanswer' => array( + 'is' => 42 + ), + 'var' => array( + 'val2', + 'val3' + ) + ), + 'pass' => array(), + 'plugin' => null + ); + $this->assertEqual($result, $expected); + + $result = Router::parse('/tests/action/theanswer[is][not]:42/theanswer[]:5/theanswer[is]:6'); + $expected = array( + 'controller' => 'tests', + 'action' => 'action', + 'named' => array( + 'theanswer' => array( + 5, + 'is' => array( + 6, + 'not' => 42 + ) + ), + ), + 'pass' => array(), + 'plugin' => null + ); + $this->assertEqual($result, $expected); + } + /** * Test generation of routes with query string parameters. *