Issues (902)

framework/rest/IndexAction.php (8 issues)

1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\rest;
9
10
use Yii;
11
use yii\data\ActiveDataProvider;
12
use yii\data\DataFilter;
13
use yii\data\Pagination;
14
use yii\data\Sort;
15
use yii\helpers\ArrayHelper;
16
17
/**
18
 * IndexAction implements the API endpoint for listing multiple models.
19
 *
20
 * For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers).
21
 *
22
 * @author Qiang Xue <[email protected]>
23
 * @since 2.0
24
 */
25
class IndexAction extends Action
26
{
27
    /**
28
     * @var callable|null a PHP callable that will be called to prepare a data provider that
29
     * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead.
30
     * The signature of the callable should be:
31
     *
32
     * ```php
33
     * function (IndexAction $action) {
34
     *     // $action is the action object currently running
35
     * }
36
     * ```
37
     *
38
     * The callable should return an instance of [[ActiveDataProvider]].
39
     *
40
     * If [[dataFilter]] is set the result of [[DataFilter::build()]] will be passed to the callable as a second parameter.
41
     * In this case the signature of the callable should be the following:
42
     *
43
     * ```php
44
     * function (IndexAction $action, mixed $filter) {
45
     *     // $action is the action object currently running
46
     *     // $filter the built filter condition
47
     * }
48
     * ```
49
     */
50
    public $prepareDataProvider;
51
    /**
52
     * @var callable a PHP callable that will be called to prepare query in prepareDataProvider.
53
     * Should return $query.
54
     * For example:
55
     *
56
     * ```php
57
     * function ($query, $requestParams) {
58
     *     $query->andFilterWhere(['id' => 1]);
59
     *     ...
60
     *     return $query;
61
     * }
62
     * ```
63
     *
64
     * @since 2.0.42
65
     */
66
    public $prepareSearchQuery;
67
    /**
68
     * @var DataFilter|null data filter to be used for the search filter composition.
69
     * You must set up this field explicitly in order to enable filter processing.
70
     * For example:
71
     *
72
     * ```php
73
     * [
74
     *     'class' => 'yii\data\ActiveDataFilter',
75
     *     'searchModel' => function () {
76
     *         return (new \yii\base\DynamicModel(['id' => null, 'name' => null, 'price' => null]))
77
     *             ->addRule('id', 'integer')
78
     *             ->addRule('name', 'trim')
79
     *             ->addRule('name', 'string')
80
     *             ->addRule('price', 'number');
81
     *     },
82
     * ]
83
     * ```
84
     *
85
     * @see DataFilter
86
     *
87
     * @since 2.0.13
88
     */
89
    public $dataFilter;
90
    /**
91
     * @var array|Pagination|false The pagination to be used by [[prepareDataProvider()]].
92
     * If this is `false`, it means pagination is disabled.
93
     * Note: if a Pagination object is passed, it's `params` will be set to the request parameters.
94
     * @see Pagination
95
     * @since 2.0.45
96
     */
97
    public $pagination = [];
98
    /**
99
     * @var array|Sort|false The sorting to be used by [[prepareDataProvider()]].
100
     * If this is `false`, it means sorting is disabled.
101
     * Note: if a Sort object is passed, it's `params` will be set to the request parameters.
102
     * @see Sort
103
     * @since 2.0.45
104
     */
105
    public $sort = [];
106
107
108
    /**
109
     * @return ActiveDataProvider
110
     */
111 6
    public function run()
112
    {
113 6
        if ($this->checkAccess) {
114
            call_user_func($this->checkAccess, $this->id);
115
        }
116
117 6
        return $this->prepareDataProvider();
118
    }
119
120
    /**
121
     * Prepares the data provider that should return the requested collection of the models.
122
     * @return ActiveDataProvider
123
     */
124 6
    protected function prepareDataProvider()
125
    {
126 6
        $requestParams = Yii::$app->getRequest()->getBodyParams();
0 ignored issues
show
The method getBodyParams() does not exist on yii\console\Request. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

126
        $requestParams = Yii::$app->getRequest()->/** @scrutinizer ignore-call */ getBodyParams();
Loading history...
127 6
        if (empty($requestParams)) {
128 1
            $requestParams = Yii::$app->getRequest()->getQueryParams();
0 ignored issues
show
The method getQueryParams() does not exist on yii\console\Request. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

128
            $requestParams = Yii::$app->getRequest()->/** @scrutinizer ignore-call */ getQueryParams();
Loading history...
129
        }
130
131 6
        $filter = null;
132 6
        if ($this->dataFilter !== null) {
133
            $this->dataFilter = Yii::createObject($this->dataFilter);
0 ignored issues
show
$this->dataFilter of type yii\data\DataFilter is incompatible with the type array|callable|string expected by parameter $type of yii\BaseYii::createObject(). ( Ignorable by Annotation )

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

133
            $this->dataFilter = Yii::createObject(/** @scrutinizer ignore-type */ $this->dataFilter);
Loading history...
134
            if ($this->dataFilter->load($requestParams)) {
135
                $filter = $this->dataFilter->build();
136
                if ($filter === false) {
137
                    return $this->dataFilter;
138
                }
139
            }
140
        }
141
142 6
        if ($this->prepareDataProvider !== null) {
143
            return call_user_func($this->prepareDataProvider, $this, $filter);
144
        }
145
146
        /* @var $modelClass \yii\db\BaseActiveRecord */
147 6
        $modelClass = $this->modelClass;
148
149 6
        $query = $modelClass::find();
150 6
        if (!empty($filter)) {
151
            $query->andWhere($filter);
152
        }
153 6
        if (is_callable($this->prepareSearchQuery)) {
154 1
            $query = call_user_func($this->prepareSearchQuery, $query, $requestParams);
155
        }
156
157 6
        if (is_array($this->pagination)) {
158 4
            $pagination = ArrayHelper::merge(
159 4
                [
160 4
                    'params' => $requestParams,
161 4
                ],
162 4
                $this->pagination
163 4
            );
164
        } else {
165 2
            $pagination = $this->pagination;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->pagination can also be of type boolean. However, the property $pagination is declared as type array|false|yii\data\Pagination. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
166 2
            if ($this->pagination instanceof Pagination) {
167 1
                $pagination->params = $requestParams;
0 ignored issues
show
Documentation Bug introduced by
It seems like $requestParams can also be of type object. However, the property $params is declared as type array|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
168
            }
169
        }
170
171 6
        if (is_array($this->sort)) {
172 4
            $sort = ArrayHelper::merge(
173 4
                [
174 4
                    'params' => $requestParams,
175 4
                ],
176 4
                $this->sort
177 4
            );
178
        } else {
179 2
            $sort = $this->sort;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->sort can also be of type boolean. However, the property $sort is declared as type array|false|yii\data\Sort. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
180 2
            if ($this->sort instanceof Sort) {
181 1
                $sort->params = $requestParams;
0 ignored issues
show
Documentation Bug introduced by
It seems like $requestParams can also be of type object. However, the property $params is declared as type array|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
182
            }
183
        }
184
185 6
        return Yii::createObject([
186 6
            '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

186
            '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...
187 6
            'query' => $query,
188 6
            'pagination' => $pagination,
189 6
            'sort' => $sort,
190 6
        ]);
191
    }
192
}
193