1+ <?php
2+ /**
3+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
4+ */
5+
6+ namespace tuyakhov \jsonapi \actions ;
7+
8+
9+ use tuyakhov \jsonapi \Inflector ;
10+ use yii \data \ActiveDataProvider ;
11+ use yii \data \DataFilter ;
12+ use Yii ;
13+
14+ class IndexAction extends Action
15+ {
16+ /**
17+ * @var callable a PHP callable that will be called to prepare a data provider that
18+ * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead.
19+ * The signature of the callable should be:
20+ *
21+ * ```php
22+ * function (IndexAction $action) {
23+ * // $action is the action object currently running
24+ * }
25+ * ```
26+ *
27+ * The callable should return an instance of [[ActiveDataProvider]].
28+ *
29+ * If [[dataFilter]] is set the result of [[DataFilter::build()]] will be passed to the callable as a second parameter.
30+ * In this case the signature of the callable should be the following:
31+ *
32+ * ```php
33+ * function (IndexAction $action, mixed $filter) {
34+ * // $action is the action object currently running
35+ * // $filter the built filter condition
36+ * }
37+ * ```
38+ */
39+ public $ prepareDataProvider ;
40+ /**
41+ * @var DataFilter|null data filter to be used for the search filter composition.
42+ * You must setup this field explicitly in order to enable filter processing.
43+ * For example:
44+ *
45+ * ```php
46+ * [
47+ * 'class' => 'yii\data\ActiveDataFilter',
48+ * 'searchModel' => function () {
49+ * return (new \yii\base\DynamicModel(['id' => null, 'name' => null, 'price' => null]))
50+ * ->addRule('id', 'integer')
51+ * ->addRule('name', 'trim')
52+ * ->addRule('name', 'string')
53+ * ->addRule('price', 'number');
54+ * },
55+ * ]
56+ * ```
57+ *
58+ * @see DataFilter
59+ *
60+ * @since 2.0.13
61+ */
62+ public $ dataFilter ;
63+
64+
65+ /**
66+ * @return ActiveDataProvider
67+ * @throws \yii\base\InvalidConfigException
68+ */
69+ public function run ()
70+ {
71+ if ($ this ->checkAccess ) {
72+ call_user_func ($ this ->checkAccess , $ this ->id );
73+ }
74+
75+ return $ this ->prepareDataProvider ();
76+ }
77+
78+ /**
79+ * Prepares the data provider that should return the requested collection of the models.
80+ * @return mixed|null|object|DataFilter|ActiveDataProvider
81+ * @throws \yii\base\InvalidConfigException
82+ */
83+ protected function prepareDataProvider ()
84+ {
85+ $ filter = $ this ->getFilter ();
86+
87+ if ($ this ->prepareDataProvider !== null ) {
88+ return call_user_func ($ this ->prepareDataProvider , $ this , $ filter );
89+ }
90+
91+ /* @var $modelClass \yii\db\BaseActiveRecord */
92+ $ modelClass = $ this ->modelClass ;
93+
94+ $ query = $ modelClass ::find ();
95+ if (!empty ($ filter )) {
96+ $ query ->andWhere ($ filter );
97+ }
98+
99+ return Yii::createObject ([
100+ 'class ' => ActiveDataProvider::className (),
101+ 'query ' => $ query ,
102+ 'pagination ' => [
103+ 'params ' => Yii::$ app ->getRequest ()->getQueryParam ('page ' , []),
104+ 'pageSizeParam ' => 'size '
105+ ],
106+ 'sort ' => [
107+ 'enableMultiSort ' => true
108+ ]
109+ ]);
110+ }
111+
112+ protected function getFilter ()
113+ {
114+ if ($ this ->dataFilter === null ) {
115+ return null ;
116+ }
117+ $ requestParams = Yii::$ app ->getRequest ()->getQueryParam ('filter ' , []);
118+ $ attributeMap = [];
119+ foreach ($ requestParams as $ attribute => $ value ) {
120+ $ attributeMap [$ attribute ] = Inflector::camel2id (Inflector::variablize ($ attribute ), '_ ' );
121+ if (strpos ($ value , ', ' ) !== false ) {
122+ $ requestParams [$ attribute ] = ['in ' => explode (', ' , $ value )];
123+ }
124+ }
125+ $ config = array_merge (['attributeMap ' => $ attributeMap ], $ this ->dataFilter );
126+ /** @var DataFilter $dataFilter */
127+ $ dataFilter = Yii::createObject ($ config );
128+ if ($ dataFilter ->load (['filter ' => $ requestParams ])) {
129+ return $ dataFilter ->build ();
130+ }
131+ return null ;
132+ }
133+ }
0 commit comments