diff --git a/docs/guide/rest-quick-start.md b/docs/guide/rest-quick-start.md
index e04121c..d1cc8ad 100644
--- a/docs/guide/rest-quick-start.md
+++ b/docs/guide/rest-quick-start.md
@@ -195,6 +195,42 @@ Additionally, you can sort collections like `http://localhost/users?sort=email`
`http://localhost/users?filter[email][like]=gmail.com` could be implemented using
data filters. See [Resources](rest-resources.md#filtering-collections) section for details.
+## Customizing Pagination and Sorting in the list
+
+In order to change the default [pagination](output-pagination.md) and [sorting](output-sorting.md) of the model list
+you can configure the [[yii\rest\IndexAction]] in your controller. For example:
+
+```php
+ [
+ 'pagination' => [
+ 'pageSize' => 10,
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'created_at' => SORT_DESC,
+ ],
+ ],
+ ],
+ ]);
+ }
+}
+```
+
+Please see [Extending ActiveController](rest-controllers#extending-active-controller) for more information on how to
+configure actions of the ActiveController.
## Summary
diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index ba60ef4..dc7f5f5 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -8,6 +8,7 @@ Yii Framework 2 Change Log
- Bug #19138: Allow digits in language code (ntesic)
- Bug #19148: Fix undefined array key errors in `yii\db\ActiveRelationTrait` (stevekr)
- Bug #19041: Fix PHP 8.1 issues (longthanhtran, samdark, pamparam83, sartor, githubjeka)
+- Enh #19171: Added `$pagination` and `$sort` to `\yii\rest\IndexAction` for easy configuration (rhertogh)
2.0.44 December 30, 2021
diff --git a/framework/rest/IndexAction.php b/framework/rest/IndexAction.php
index 6ced938..25fae9a 100644
--- a/framework/rest/IndexAction.php
+++ b/framework/rest/IndexAction.php
@@ -10,6 +10,9 @@ namespace yii\rest;
use Yii;
use yii\data\ActiveDataProvider;
use yii\data\DataFilter;
+use yii\data\Pagination;
+use yii\data\Sort;
+use yii\helpers\ArrayHelper;
/**
* IndexAction implements the API endpoint for listing multiple models.
@@ -87,6 +90,24 @@ class IndexAction extends Action
/**
+ * @var array|Pagination|false The pagination to be used by [[prepareDataProvider()]].
+ * If this is `false`, it means pagination is disabled.
+ * Note: if a Pagination object is passed, it's `params` will be set to the request parameters.
+ * @see Pagination
+ * @since 2.0.45
+ */
+ public $pagination = [];
+
+ /**
+ * @var array|Sort|false The sorting to be used by [[prepareDataProvider()]].
+ * If this is `false`, it means sorting is disabled.
+ * Note: if a Sort object is passed, it's `params` will be set to the request parameters.
+ * @see Sort
+ * @since 2.0.45
+ */
+ public $sort = [];
+
+ /**
* @return ActiveDataProvider
*/
public function run()
@@ -135,15 +156,39 @@ class IndexAction extends Action
$query = call_user_func($this->prepareSearchQuery, $query, $requestParams);
}
+ if (is_array($this->pagination)) {
+ $pagination = ArrayHelper::merge(
+ [
+ 'params' => $requestParams,
+ ],
+ $this->pagination
+ );
+ } else {
+ $pagination = $this->pagination;
+ if ($this->pagination instanceof Pagination) {
+ $pagination->params = $requestParams;
+ }
+ }
+
+ if (is_array($this->sort)) {
+ $sort = ArrayHelper::merge(
+ [
+ 'params' => $requestParams,
+ ],
+ $this->sort
+ );
+ } else {
+ $sort = $this->sort;
+ if ($this->sort instanceof Sort) {
+ $sort->params = $requestParams;
+ }
+ }
+
return Yii::createObject([
'class' => ActiveDataProvider::className(),
'query' => $query,
- 'pagination' => [
- 'params' => $requestParams,
- ],
- 'sort' => [
- 'params' => $requestParams,
- ],
+ 'pagination' => $pagination,
+ 'sort' => $sort,
]);
}
}
diff --git a/tests/framework/rest/IndexActionTest.php b/tests/framework/rest/IndexActionTest.php
index 385749c..ffbf6e9 100644
--- a/tests/framework/rest/IndexActionTest.php
+++ b/tests/framework/rest/IndexActionTest.php
@@ -3,6 +3,9 @@
namespace yiiunit\framework\rest;
use Yii;
+use yii\data\ActiveDataProvider;
+use yii\data\Pagination;
+use yii\data\Sort;
use yii\db\ActiveRecord;
use yii\db\Query;
use yii\rest\ActiveController;
@@ -63,6 +66,123 @@ class IndexActionTest extends TestCase
$sql
);
}
+
+ /**
+ * @dataProvider dataProviderTestPrepareDataProviderWithPaginationAndSorting
+ *
+ * @param string $sql
+ * @param array $params
+ * @param string $expectedRawSql
+ */
+ public function testPrepareDataProviderWithPaginationAndSorting(
+ $pagination,
+ $sort,
+ $expectedPaginationPageSize = null,
+ $expectedPaginationDefaultPageSize = null,
+ $expectedSortOrders = [],
+ $expectedSortDefaultOrder = null
+ ) {
+ Yii::$app->getRequest()->setBodyParams([
+ 'per-page' => 11,
+ 'sort' => '-test-sort'
+ ]);
+
+ $controller = new RestController(
+ 'rest',
+ new Module('rest'), [
+ 'modelClass' => IndexActionModel::className(),
+ 'actions' => [
+ 'index' => [
+ 'class' => IndexAction::className(),
+ 'modelClass' => IndexActionModel::className(),
+ 'pagination' => $pagination,
+ 'sort' => $sort,
+ ],
+ ],
+ ]);
+
+ /** @var ActiveDataProvider $dataProvider */
+ $dataProvider = $controller->createAction('index')->runWithParams([]);
+ $actualPagination = $dataProvider->getPagination();
+ $actualSort = $dataProvider->getSort();
+
+ if ($pagination === false) {
+ $this->assertFalse($actualPagination);
+ } else {
+ $this->assertEquals($expectedPaginationPageSize, $actualPagination->pageSize);
+ $this->assertEquals($expectedPaginationDefaultPageSize, $actualPagination->defaultPageSize);
+ }
+
+ if ($sort === false) {
+ $this->assertFalse($actualSort);
+ } else {
+ $this->assertEquals($expectedSortOrders, $actualSort->getOrders());
+ $this->assertEquals($expectedSortDefaultOrder, $actualSort->defaultOrder);
+ }
+ }
+
+ /**
+ * Data provider for [[testPrepareDataProviderWithPaginationAndSorting()]].
+ * @return array test data
+ */
+ public function dataProviderTestPrepareDataProviderWithPaginationAndSorting()
+ {
+ return [
+ [ // Default config
+ [],
+ [],
+ 11, // page size set as param in test
+ (new Pagination())->defaultPageSize,
+ [],
+ null
+ ],
+ [ // Default config
+ [],
+ [
+ 'attributes' => ['test-sort'],
+ ],
+ 11, // page size set as param in test
+ (new Pagination())->defaultPageSize,
+ ['test-sort' => SORT_DESC], // test sort set as param in test
+ null
+ ],
+ [ // Config via array
+ [
+ 'pageSize' => 12, // Testing a fixed page size
+ 'defaultPageSize' => 991,
+ ],
+ [
+ 'attributes' => ['test-sort'],
+ 'defaultOrder' => [
+ 'created_at_1' => SORT_DESC,
+ ],
+ ],
+ 12,
+ 991,
+ ['test-sort' => SORT_DESC], // test sort set as param in test
+ ['created_at_1' => SORT_DESC]
+ ],
+ [ // Config via objects
+ new Pagination([
+ 'defaultPageSize' => 992,
+ ]),
+ new Sort([
+ 'attributes' => ['created_at_2'],
+ 'defaultOrder' => [
+ 'created_at_2' => SORT_DESC,
+ ],
+ ]),
+ 11, // page size set as param in test
+ 992,
+ ['created_at_2' => SORT_DESC], // test sort set as param in test is ignored
+ ['created_at_2' => SORT_DESC]
+ ],
+ [ // Disable pagination and sort
+ false,
+ false,
+ ]
+ ];
+ }
}
class RestController extends ActiveController