RequestCriteria::apply()   F
last analyzed

Complexity

Conditions 37
Paths 432

Size

Total Lines 154
Code Lines 98

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 37
eloc 98
nc 432
nop 2
dl 0
loc 154
rs 0.7887
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Yeelight\Repositories\Criteria;
4
5
use Illuminate\Support\Facades\Request;
6
use Prettus\Repository\Contracts\RepositoryInterface;
7
8
/**
9
 * Class RequestCriteria
10
 *
11
 * @category Yeelight
12
 *
13
 * @package Yeelight\Repositories\Criteria
14
 *
15
 * @author Sheldon Lee <[email protected]>
16
 *
17
 * @license https://opensource.org/licenses/MIT MIT
18
 *
19
 * @link https://www.yeelight.com
20
 */
21
class RequestCriteria extends \Prettus\Repository\Criteria\RequestCriteria
22
{
23
    /**
24
     * Apply criteria in query repository.
25
     *
26
     * @param Builder|Model       $model
0 ignored issues
show
Bug introduced by
The type Yeelight\Repositories\Criteria\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type Yeelight\Repositories\Criteria\Builder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
     * @param RepositoryInterface $repository
28
     *
29
     * @throws \Exception
30
     *
31
     * @return mixed
32
     */
33
    public function apply($model, RepositoryInterface $repository)
34
    {
35
        $fieldsSearchable = $repository->getFieldsSearchable();
36
        list($querySearch, $querySearchFields) = $this->parserQueryToSearch($fieldsSearchable);
37
        $search = $this->request->get(config('repository.criteria.params.search', 'search'), $querySearch);
38
        $searchFields = $this->request->get(config('repository.criteria.params.searchFields', 'searchFields'), $querySearchFields);
39
        $filter = $this->request->get(config('repository.criteria.params.filter', 'filter'), null);
40
        $orderBy = $this->request->get(config('repository.criteria.params.orderBy', 'orderBy'), null);
41
        $sortedBy = $this->request->get(config('repository.criteria.params.sortedBy', 'sortedBy'), 'asc');
42
        $with = $this->request->get(config('repository.criteria.params.with', 'with'), null);
43
        $sortedBy = !empty($sortedBy) ? $sortedBy : 'asc';
44
45
        if ($search && is_array($fieldsSearchable) && count($fieldsSearchable)) {
46
            $searchFields = is_array($searchFields) || is_null($searchFields) ? $searchFields : explode(';', $searchFields);
47
            $fields = $this->parserFieldsSearch($fieldsSearchable, $searchFields);
48
            $isFirstField = true;
49
            $searchData = $this->parserSearchData($search);
50
            $search = $this->parserSearchValue($search);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $search is correct as $this->parserSearchValue($search) targeting Prettus\Repository\Crite...ia::parserSearchValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
51
            $modelForceAndWhere = method_exists($repository, 'getIsSearchableForceAndWhere') ? $repository->getIsSearchableForceAndWhere() : false;
52
53
            $model = $model->where(function ($query) use ($fields, $search, $searchData, $isFirstField, $modelForceAndWhere) {
54
                /* @var Builder $query */
55
56
                foreach ($fields as $field => $condition) {
57
                    if (is_numeric($field)) {
58
                        $field = $condition;
59
                        $condition = '=';
60
                    }
61
62
                    $value = null;
63
64
                    $condition = trim(strtolower($condition));
65
66
                    if (isset($searchData[$field])) {
67
                        if ($condition == 'like_raw') {
68
                            $condition = 'like';
69
                            $value = $searchData[$field];
70
                        } elseif ($condition == 'like_safe') {
71
                            $condition = 'like';
72
                            if (str_contains_ascii_only($searchData[$field])) {
73
                                $value = "%{$searchData[$field]}%";
74
                            } else {
75
                                $value = null;
76
                            }
77
                        } else {
78
                            $value = ($condition == 'like' || $condition == 'ilike') ? "%{$searchData[$field]}%" : $searchData[$field];
79
                        }
80
                    } else {
81
                        if (!is_null($search)) {
82
                            if ($condition == 'like_raw') {
83
                                $condition = 'like';
84
                                $value = $searchData[$field];
85
                            } elseif ($condition == 'like_safe') {
86
                                $condition = 'like';
87
                                if (str_contains_ascii_only($search)) {
88
                                    $value = "%{$search}%";
89
                                } else {
90
                                    $value = null;
91
                                }
92
                            } else {
93
                                $value = ($condition == 'like' || $condition == 'ilike') ? "%{$search}%" : $search;
94
                            }
95
                        }
96
                    }
97
98
                    $relation = null;
99
                    if (stripos($field, '.')) {
100
                        $explode = explode('.', $field);
101
                        $field = array_pop($explode);
102
                        $relation = implode('.', $explode);
103
                    }
104
                    $modelTableName = $query->getModel()->getTable();
105
                    if ($isFirstField || $modelForceAndWhere) {
106
                        if (!is_null($value)) {
107
                            if (!is_null($relation)) {
108
                                $query->whereHas($relation, function ($query) use ($field, $condition, $value) {
109
                                    $query->where($field, $condition, $value);
110
                                });
111
                            } else {
112
                                $query->where($modelTableName.'.'.$field, $condition, $value);
113
                            }
114
                            $isFirstField = false;
115
                        }
116
                    } else {
117
                        if (!is_null($value)) {
118
                            if (!is_null($relation)) {
119
                                $query->orWhereHas($relation, function ($query) use ($field, $condition, $value) {
120
                                    $query->where($field, $condition, $value);
121
                                });
122
                            } else {
123
                                $query->orWhere($modelTableName.'.'.$field, $condition, $value);
124
                            }
125
                        }
126
                    }
127
                }
128
            });
129
        }
130
131
        if (isset($orderBy) && !empty($orderBy)) {
132
            $split = explode('|', $orderBy);
133
            if (count($split) > 1) {
134
                /*
135
                 * ex.
136
                 * products|description -> join products on current_table.product_id = products.id order by description
137
                 *
138
                 * products:custom_id|products.description -> join products on current_table.custom_id = products.id order
139
                 * by products.description (in case both tables have same column name)
140
                 */
141
                $table = $model->getModel()->getTable();
142
                $sortTable = $split[0];
143
                $sortColumn = $split[1];
144
145
                $split = explode(':', $sortTable);
146
                if (count($split) > 1) {
147
                    $sortTable = $split[0];
148
                    $keyName = $table.'.'.$split[1];
149
                } else {
150
                    /*
151
                     * If you do not define which column to use as a joining column on current table, it will
152
                     * use a singular of a join table appended with _id
153
                     *
154
                     * ex.
155
                     * products -> product_id
156
                     */
157
                    $prefix = rtrim($sortTable, 's');
158
                    $keyName = $table.'.'.$prefix.'_id';
159
                }
160
161
                $model = $model
162
                    ->leftJoin($sortTable, $keyName, '=', $sortTable.'.id')
163
                    ->orderBy($sortColumn, $sortedBy)
164
                    ->addSelect($table.'.*');
165
            } else {
166
                $model = $model->orderBy($orderBy, $sortedBy);
167
            }
168
        }
169
170
        if (isset($filter) && !empty($filter)) {
171
            if (is_string($filter)) {
172
                $filter = explode(';', $filter);
173
            }
174
175
            $model = $model->select($filter);
176
        }
177
178
        if ($with) {
179
            $with = explode(';', $with);
180
            $model = $model->with($with);
181
        }
182
183
        $this->request->offsetUnset(config('repository.criteria.params.search', 'search'));
184
        $this->request->offsetUnset(config('repository.criteria.params.searchFields', 'searchFields'));
185
186
        return $model;
187
    }
188
189
    protected function parserFieldsSearch(array $fields = [], array $searchFields = null)
190
    {
191
        if (!is_null($searchFields) && count($searchFields)) {
192
            $acceptedConditions = config('repository.criteria.acceptedConditions', [
193
                '=',
194
                'like',
195
                'like_raw',
196
            ]);
197
            $originalFields = $fields;
198
            $fields = [];
199
200
            foreach ($searchFields as $index => $field) {
201
                $field_parts = explode(':', $field);
202
                $temporaryIndex = array_search($field_parts[0], $originalFields);
203
204
                if (count($field_parts) == 2) {
205
                    if (in_array($field_parts[1], $acceptedConditions)) {
206
                        unset($originalFields[$temporaryIndex]);
207
                        $field = $field_parts[0];
208
                        $condition = $field_parts[1];
209
                        $originalFields[$field] = $condition;
210
                        $searchFields[$index] = $field;
211
                    }
212
                }
213
            }
214
215
            foreach ($originalFields as $field => $condition) {
216
                if (is_numeric($field)) {
217
                    $field = $condition;
218
                    $condition = '=';
219
                }
220
                if (in_array($field, $searchFields)) {
221
                    $fields[$field] = $condition;
222
                }
223
            }
224
225
            if (count($fields) == 0) {
226
                throw new \Exception(trans('repository::criteria.fields_not_accepted', ['field' => implode(',', $searchFields)]));
227
            }
228
        }
229
230
        return $fields;
231
    }
232
233
    /**
234
     * Parser query to Search String.
235
     *
236
     * @param $columns
237
     *
238
     * @return string
239
     */
240
    protected function parserQueryToSearch($columns)
241
    {
242
        /** @var \Illuminate\Http\Request $request * */
243
        $request = Request::instance();
244
245
        $query = $request->query();
246
        $search = '';
247
        $searchFields = '';
248
249
        foreach ($columns as $index => $column) {
250
            if (is_int($index)) {
251
                $index = $column;
252
                $column = '=';
253
            }
254
            if (isset($query[$index]) && !empty($query[$index])) {
255
                $search .= $index.':'.$query[$index].';';
256
                $searchFields .= $index.':'.$column.';';
257
            }
258
        }
259
260
        return [rtrim($search, ';'), rtrim($searchFields, ';')];
0 ignored issues
show
Bug Best Practice introduced by
The expression return array(rtrim($sear...im($searchFields, ';')) returns the type array<integer,string> which is incompatible with the documented return type string.
Loading history...
261
    }
262
}
263