RequestCriteria   B
last analyzed

Complexity

Total Complexity 46

Size/Duplication

Total Lines 235
Duplicated Lines 8.94 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 21
loc 235
ccs 0
cts 164
cp 0
rs 8.3999
c 0
b 0
f 0
wmc 46
lcom 1
cbo 1

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
C apply() 21 79 21
C parserSearchData() 0 30 7
C parserSearchValue() 0 23 7
C parserFieldsSearch() 0 60 10

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like RequestCriteria often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RequestCriteria, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * This file is part of the Laravel Platfourm package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Longman\Platfourm\Repository\Criteria;
12
13
use Longman\Platfourm\Contracts\Repository\Criteria;
14
use Longman\Platfourm\Contracts\Repository\Repository;
15
16
/**
17
 * Class RequestCriteria.
18
 */
19
class RequestCriteria implements Criteria
20
{
21
    /**
22
     * @var \Illuminate\Http\Request
23
     */
24
    protected $request;
25
26
    protected $sortBy;
27
28
    protected $fields;
29
30
    protected $search;
31
32
    protected $searchFields;
33
34
    public function __construct($sortBy, $fields, $search, $searchFields)
35
    {
36
        $this->request      = app('request');
37
        $this->sortBy       = $sortBy;
38
        $this->fields       = $fields;
39
        $this->search       = $search;
40
        $this->searchFields = $searchFields;
41
    }
42
43
    /**
44
     * Apply criteria in query repository.
45
     *
46
     * @param             $model
47
     * @param  Repository $repository
48
     * @return mixed
49
     */
50
    public function apply($model, Repository $repository)
51
    {
52
        $searchableFields = $model->getSearchableFields();
53
        $filterableFields = $model->getFilterableFields();
54
        $sortableFields   = $model->getSortableFields();
55
        $requestFields    = $this->request->all();
56
57
        $sortBy = $this->sortBy;
58
        $fields = $this->fields;
59
60
        $search       = $this->search;
61
        $searchFields = $this->searchFields;
62
        $searchFields = !empty($searchFields) ? explode(',', $searchFields) : $searchableFields;
63
64 View Code Duplication
        if ($search && $searchableFields) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
65
            $model = $model->where(function ($query) use ($requestFields, $searchableFields, $searchFields, $search) {
66
67
                $isFirstField = true;
68
69
                foreach ($searchFields as $field) {
70
                    if (!in_array($field, $searchableFields)) {
71
                        continue;
72
                    }
73
74
                    $value = "%{$search}%";
75
76
                    if ($isFirstField && !is_null($value)) {
77
                        $query->where($field, 'like', $value);
78
                        $isFirstField = false;
79
                    } elseif (!is_null($value)) {
80
                        $query->orWhere($field, 'like', $value);
81
                    }
82
                }
83
            });
84
        }
85
86
        if ($filterableFields) {
87
            $model = $model->where(function ($query) use ($requestFields, $filterableFields) {
88
89
                foreach ($filterableFields as $field => $condition) {
90
                    if (!isset($requestFields[$field])) {
91
                        continue;
92
                    }
93
94
                    $value = $requestFields[$field];
95
                    if (!is_null($value)) {
96
                        $query->where($field, $condition, $value);
97
                    }
98
                }
99
            });
100
        }
101
102
        if (!empty($sortBy)) {
103
            $sortBy = explode(',', $sortBy);
104
            foreach ($sortBy as $sortItem) {
105
                $sortEx    = explode(':', $sortItem);
106
                $sortField = isset($sortEx[0]) ? trim($sortEx[0]) : '';
107
                $sortDir   = isset($sortEx[1]) ? trim($sortEx[1]) : 'asc';
108
                if (!in_array($sortField, $sortableFields)) {
109
                    continue;
110
                }
111
                if (!in_array($sortDir, ['asc', 'desc'])) {
112
                    $sortDir = 'asc';
113
                }
114
115
                $model = $model->orderBy($sortField, $sortDir);
116
            }
117
        }
118
119
        if (!empty($fields)) {
120
            if (is_string($fields)) {
121
                $fields = explode(',', $fields);
122
            }
123
124
            $model = $model->select($fields);
125
        }
126
127
        return $model;
128
    }
129
130
    /**
131
     * @param  $search
132
     * @return array
133
     */
134
    protected function parserSearchData($search)
135
    {
136
137
        if (is_array($search)) {
138
            foreach ($search as $key => $value) {
139
                if (empty($value)) {
140
                    unset($search[$key]);
141
                }
142
            }
143
144
            return $search;
145
        }
146
147
        $searchData = [];
148
149
        if (stripos($search, ':')) {
150
            $fields = explode(';', $search);
151
152
            foreach ($fields as $row) {
153
                try {
154
                    list($field, $value) = explode(':', $row);
155
                    $searchData[$field] = $value;
156
                } catch (\Exception $e) {
157
                    //Surround offset error
158
                }
159
            }
160
        }
161
162
        return $searchData;
163
    }
164
165
    /**
166
     * @param  $search
167
     * @return null
168
     */
169
    protected function parserSearchValue($search)
170
    {
171
172
        if (is_array($search)) {
173
            return isset($search['q']) ? $search['q'] : null;
174
        }
175
176
        if (stripos($search, ';') || stripos($search, ':')) {
177
            $values = explode(';', $search);
178
179
            foreach ($values as $value) {
180
                $s = explode(':', $value);
181
182
                if (count($s) == 1) {
183
                    return $s[0];
184
                }
185
            }
186
187
            return;
188
        }
189
190
        return $search;
191
    }
192
193
    protected function parserFieldsSearch(array $fields = [], array $searchFields = null)
194
    {
195
196
        if (!is_null($searchFields) && count($searchFields)) {
197
            $acceptedConditions = config('database.criteria.acceptedConditions', [
198
                '=',
199
                '>',
200
                '>=',
201
                '<',
202
                '<=',
203
                '!=',
204
                '<>',
205
                'like',
206
                'not like',
207
                'between',
208
                'not between',
209
                'in',
210
                'not in',
211
                'null',
212
                'not null'
213
            ]);
214
            $originalFields     = $fields;
215
            $fields             = [];
216
217
            foreach ($searchFields as $index => $field) {
218
                $field_parts = explode(':', $field);
219
                $_index      = array_search($field_parts[0], $originalFields);
220
221
                if (count($field_parts) == 2) {
222
                    if (in_array($field_parts[1], $acceptedConditions)) {
223
                        unset($originalFields[$_index]);
224
                        $field                  = $field_parts[0];
225
                        $condition              = $field_parts[1];
226
                        $originalFields[$field] = $condition;
227
                        $searchFields[$index]   = $field;
228
                    }
229
                }
230
            }
231
232
            foreach ($originalFields as $field => $condition) {
233
                if (is_numeric($field)) {
234
                    $field     = $condition;
235
                    $condition = '=';
236
                }
237
238
                if (in_array($field, $searchFields)) {
239
                    $fields[$field] = $condition;
240
                }
241
            }
242
243
            if (count($fields) == 0) {
244
                throw new \Exception(trans(
245
                    'database::criteria.fields_not_accepted',
246
                    ['field' => implode(',', $searchFields)]
247
                ));
248
            }
249
        }
250
251
        return $fields;
252
    }
253
}
254