IndexAction   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 33
c 1
b 0
f 0
dl 0
loc 117
rs 10
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getFilter() 0 20 6
A run() 0 7 2
A prepareDataProvider() 0 24 3
1
<?php
2
/**
3
 * @author Anton Tuyakhov <[email protected]>
4
 */
5
6
namespace tuyakhov\jsonapi\actions;
7
8
9
use tuyakhov\jsonapi\Inflector;
10
use tuyakhov\jsonapi\Pagination;
11
use yii\data\ActiveDataProvider;
12
use yii\data\DataFilter;
13
use Yii;
14
15
class IndexAction extends Action
16
{
17
    /**
18
     * @var callable a PHP callable that will be called to prepare a data provider that
19
     * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead.
20
     * The signature of the callable should be:
21
     *
22
     * ```php
23
     * function (IndexAction $action) {
24
     *     // $action is the action object currently running
25
     * }
26
     * ```
27
     *
28
     * The callable should return an instance of [[ActiveDataProvider]].
29
     *
30
     * If [[dataFilter]] is set the result of [[DataFilter::build()]] will be passed to the callable as a second parameter.
31
     * In this case the signature of the callable should be the following:
32
     *
33
     * ```php
34
     * function (IndexAction $action, mixed $filter) {
35
     *     // $action is the action object currently running
36
     *     // $filter the built filter condition
37
     * }
38
     * ```
39
     */
40
    public $prepareDataProvider;
41
    /**
42
     * @var DataFilter|null data filter to be used for the search filter composition.
43
     * You must setup this field explicitly in order to enable filter processing.
44
     * For example:
45
     *
46
     * ```php
47
     * [
48
     *     'class' => 'yii\data\ActiveDataFilter',
49
     *     'searchModel' => function () {
50
     *         return (new \yii\base\DynamicModel(['id' => null, 'name' => null, 'price' => null]))
51
     *             ->addRule('id', 'integer')
52
     *             ->addRule('name', 'trim')
53
     *             ->addRule('name', 'string')
54
     *             ->addRule('price', 'number');
55
     *     },
56
     * ]
57
     * ```
58
     *
59
     * @see DataFilter
60
     *
61
     * @since 2.0.13
62
     */
63
    public $dataFilter;
64
65
66
    /**
67
     * @return ActiveDataProvider
68
     * @throws \yii\base\InvalidConfigException
69
     */
70
    public function run()
71
    {
72
        if ($this->checkAccess) {
73
            call_user_func($this->checkAccess, $this->id);
74
        }
75
76
        return $this->prepareDataProvider();
77
    }
78
79
    /**
80
     * Prepares the data provider that should return the requested collection of the models.
81
     * @return mixed|null|object|DataFilter|ActiveDataProvider
82
     * @throws \yii\base\InvalidConfigException
83
     */
84
    protected function prepareDataProvider()
85
    {
86
        $filter = $this->getFilter();
87
88
        if ($this->prepareDataProvider !== null) {
89
            return call_user_func($this->prepareDataProvider, $this, $filter);
90
        }
91
92
        /* @var $modelClass \yii\db\BaseActiveRecord */
93
        $modelClass = $this->modelClass;
94
95
        $query = $modelClass::find();
96
        if (!empty($filter)) {
97
            $query->andWhere($filter);
98
        }
99
100
        return Yii::createObject([
101
            'class' => ActiveDataProvider::className(),
0 ignored issues
show
Deprecated Code introduced by
The function yii\base\BaseObject::className() has been deprecated: since 2.0.14. On PHP >=5.5, use `::class` instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

101
            'class' => /** @scrutinizer ignore-deprecated */ ActiveDataProvider::className(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
102
            'query' => $query,
103
            'pagination' => [
104
                'class' => Pagination::className(),
0 ignored issues
show
Deprecated Code introduced by
The function yii\base\BaseObject::className() has been deprecated: since 2.0.14. On PHP >=5.5, use `::class` instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

104
                'class' => /** @scrutinizer ignore-deprecated */ Pagination::className(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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 (is_string($value) && strpos($value, ',') !== false) {
122
                $requestParams[$attribute] = ['in' => explode(',', $value)];
123
            }
124
        }
125
        $config = array_merge(['attributeMap' => $attributeMap], $this->dataFilter);
0 ignored issues
show
Bug introduced by
$this->dataFilter of type yii\data\DataFilter is incompatible with the type array|null expected by parameter $array2 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
        $config = array_merge(['attributeMap' => $attributeMap], /** @scrutinizer ignore-type */ $this->dataFilter);
Loading history...
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
}