Passed
Push — master ( c92e71...89beee )
by Jonathan
25:53
created

ListController::buildContentQuery()   C

Complexity

Conditions 12
Paths 31

Size

Total Lines 55
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 29
c 1
b 0
f 0
nc 31
nop 0
dl 0
loc 55
rs 6.9666

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 Uccello\Core\Http\Controllers\Core;
4
5
use Schema;
0 ignored issues
show
Bug introduced by
The type Schema 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...
6
use Illuminate\Http\Request;
0 ignored issues
show
Bug introduced by
The type Illuminate\Http\Request 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...
7
use Spatie\Searchable\Search;
0 ignored issues
show
Bug introduced by
The type Spatie\Searchable\Search 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...
8
use Uccello\Core\Models\Domain;
9
use Uccello\Core\Models\Module;
10
use Uccello\Core\Facades\Uccello;
11
use Uccello\Core\Models\Relatedlist;
12
use Uccello\Core\Models\Filter;
13
14
class ListController extends Controller
15
{
16
    protected $viewName = 'list.main';
17
18
    /**
19
     * Check user permissions
20
     */
21
    protected function checkPermissions()
22
    {
23
        $this->middleware('uccello.permissions:retrieve');
24
    }
25
26
    /**
27
     * @inheritDoc
28
     */
29
    public function process(?Domain $domain, Module $module, Request $request)
30
    {
31
        // Pre-process
32
        $this->preProcess($domain, $module, $request);
33
34
        // Selected filter
35
        if ($request->input('filter')) {
36
            $selectedFilterId = $request->input('filter');
37
            $selectedFilter = Filter::find($selectedFilterId);
38
        }
39
40
        if (empty($selectedFilter)) { // For example if the given filter does not exist
41
            $selectedFilter = $module->filters()->where('type', 'list')->first();
42
            $selectedFilterId = $selectedFilter->id;
43
        }
44
45
        // Get datatable columns
46
        $datatableColumns = Uccello::getDatatableColumns($module, $selectedFilterId);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $selectedFilterId does not seem to be defined for all execution paths leading up to this point.
Loading history...
47
48
        // Get filters
49
        $filters = Filter::where('module_id', $module->id)
50
            ->where('type', 'list')
51
            ->get();
52
53
        // Order by
54
        $filterOrderBy = (array) $selectedFilter->order_by;
55
56
        return $this->autoView(compact('datatableColumns', 'filters', 'selectedFilter', 'filterOrderBy'));
57
    }
58
59
    /**
60
     * Display a listing of the resources.
61
     * The result is formated differently if it is a classic query or one requested by datatable.
62
     * Filter on domain if domain_id column exists.
63
     * @param  \Uccello\Core\Models\Domain|null $domain
64
     * @param  \Uccello\Core\Models\Module $module
65
     * @param  \Illuminate\Http\Request $request
66
     * @return \Illuminate\Http\Response
0 ignored issues
show
Bug introduced by
The type Illuminate\Http\Response 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...
67
     */
68
    public function processForContent(?Domain $domain, Module $module, Request $request)
69
    {
70
        $length = (int)$request->get('length') ?? env('UCCELLO_ITEMS_PER_PAGE', 15);
0 ignored issues
show
Bug introduced by
The function env was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

70
        $length = (int)$request->get('length') ?? /** @scrutinizer ignore-call */ env('UCCELLO_ITEMS_PER_PAGE', 15);
Loading history...
71
72
        $recordId = $request->get('id');
73
        $relatedListId = $request->get('relatedlist');
74
        $action = $request->get('action');
75
76
        // Pre-process
77
        $this->preProcess($domain, $module, $request, false);
78
79
        // Get model model class
80
        $modelClass = $module->model_class;
81
82
        // Check if the class exists
83
        if (!class_exists($modelClass)) {
84
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
85
        }
86
87
        // Build query
88
        $query = $this->buildContentQuery();
89
90
        // Limit the number maximum of items per page
91
        $maxItemsPerPage = env('UCCELLO_MAX_ITEMS_PER_PAGE', 100);
92
        if ($length > $maxItemsPerPage) {
93
            $length = $maxItemsPerPage;
94
        }
95
96
        // If the query is for a related list, add conditions
97
        if ($relatedListId && $action !== 'select') {
98
            // Get related list
99
            $relatedList = Relatedlist::find($relatedListId);
100
101
            if ($relatedList && $relatedList->method) {
102
                // Related list method
103
                $method = $relatedList->method;
104
105
                // Update query
106
                $model = new $modelClass;
107
                $records = $model->$method($relatedList, $recordId, $query)->paginate($length);
108
            }
109
        } elseif ($relatedListId && $action === 'select') {
110
            // Get related list
111
            $relatedList = Relatedlist::find($relatedListId);
112
113
            if ($relatedList && $relatedList->method) {
114
                // Related list method
115
                $method = $relatedList->method;
116
                $recordIdsMethod = $method . 'RecordIds';
117
118
                // Get related records ids
119
                $model = new $modelClass;
120
                $filteredRecordIds = $model->$recordIdsMethod($relatedList, $recordId);
121
122
                // Add the record id itself to be filtered
123
                if ($relatedList->module_id === $relatedList->related_module_id && !empty($recordId) && !$filteredRecordIds->contains($recordId)) {
124
                    $filteredRecordIds[] = (int)$recordId;
125
                }
126
127
                // Make the quer
128
                $records = $query->whereNotIn($model->getKeyName(), $filteredRecordIds)->paginate($length);
129
            }
130
        } else {
131
            // Paginate results
132
            $records = $query->paginate($length);
133
        }
134
135
        $records->getCollection()->transform(function ($record) use ($domain, $module) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $records does not seem to be defined for all execution paths leading up to this point.
Loading history...
136
            foreach ($module->fields as $field) {
137
                // If a special template exists, use it. Else use the generic template
138
                $uitype = uitype($field->uitype_id);
139
                $uitypeViewName = sprintf('uitypes.list.%s', $uitype->name);
140
                $uitypeFallbackView = 'uccello::modules.default.uitypes.list.text';
141
                $uitypeViewToInclude = uccello()->view($uitype->package, $module, $uitypeViewName, $uitypeFallbackView);
0 ignored issues
show
Bug introduced by
Are you sure the usage of uccello() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
142
                $record->{$field->name.'_html'} = view()->make($uitypeViewToInclude, compact('domain', 'module', 'record', 'field'))->render();
0 ignored issues
show
Bug introduced by
The function view was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

142
                $record->{$field->name.'_html'} = /** @scrutinizer ignore-call */ view()->make($uitypeViewToInclude, compact('domain', 'module', 'record', 'field'))->render();
Loading history...
143
            }
144
145
            return $record;
146
        });
147
148
        return $records;
149
    }
150
151
    /**
152
     * Autocomplete a listing of the resources.
153
     * The result is formated differently if it is a classic query or one requested by datatable.
154
     * Filter on domain if domain_id column exists.
155
     * @param  \Uccello\Core\Models\Domain|null $domain
156
     * @param  \Uccello\Core\Models\Module $module
157
     * @param  \Illuminate\Http\Request $request
158
     * @return \Illuminate\Http\Response
159
     */
160
    public function processForAutocomplete(?Domain $domain, Module $module, Request $request)
161
    {
162
        // If we don't use multi domains, find the first one
163
        if (!uccello()->useMultiDomains()) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of uccello() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
164
            $domain = Domain::first();
0 ignored issues
show
Unused Code introduced by
The assignment to $domain is dead and can be removed.
Loading history...
165
        }
166
167
        // Query
168
        $q = $request->get('q');
169
        // Model class
170
        $modelClass = $module->model_class;
171
172
        $results = collect();
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

172
        $results = /** @scrutinizer ignore-call */ collect();
Loading history...
173
        if (method_exists($modelClass, 'getSearchResult') && property_exists($modelClass, 'searchableColumns')) {
174
            $searchResults = new Search();
175
            $searchResults->registerModel($modelClass, (array) (new $modelClass)->searchableColumns);
176
            $results = $searchResults->search($q)->take(config('uccello.max_results.autocomplete', 10));
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

176
            $results = $searchResults->search($q)->take(/** @scrutinizer ignore-call */ config('uccello.max_results.autocomplete', 10));
Loading history...
177
        }
178
179
        return $results;
180
    }
181
182
    /**
183
     * Save list filter into database
184
     *
185
     * @param \Uccello\Core\Models\Domain|null $domain
186
     * @param \Uccello\Core\Models\Module $module
187
     * @param \Illuminate\Http\Request $request
188
     * @return \Illuminate\Http\Response
189
     */
190
    public function saveFilter(?Domain $domain, Module $module, Request $request)
191
    {
192
        $saveOrder = $request->input('save_order');
193
        $savePageLength = $request->input('save_page_length');
194
195
        // Optional data
196
        $data = [];
197
        if ($savePageLength) {
198
            $data["length"] = $request->input('page_length');
199
        }
200
201
        $filter = Filter::firstOrNew([
202
            'domain_id' => $domain->id,
203
            'module_id' => $module->id,
204
            'user_id' => auth()->id(),
0 ignored issues
show
Bug introduced by
The function auth was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

204
            'user_id' => /** @scrutinizer ignore-call */ auth()->id(),
Loading history...
205
            'name' => $request->input('name'),
206
            'type' => $request->input('type')
207
        ]);
208
        $filter->columns = $request->input('columns');
209
        $filter->conditions = $request->input('conditions') ?? null;
210
        $filter->order_by = $saveOrder ? $request->input('order') : null;
211
        $filter->is_default = $request->input('default');
212
        $filter->is_public = $request->input('public');
213
        $filter->data = !empty($data) ? $data : null;
214
        $filter->save();
215
216
        return $filter;
217
    }
218
219
    /**
220
     * Retrieve a filter by its id and delete it
221
     *
222
     * @param \Uccello\Core\Models\Domain|null $domain
223
     * @param \Uccello\Core\Models\Module $module
224
     * @param \Illuminate\Http\Request $request
225
     * @return \Illuminate\Http\Response
226
     */
227
    public function deleteFilter(?Domain $domain, Module $module, Request $request)
228
    {
229
        // Retrieve filter by id
230
        $filterId = $request->input('id');
231
        $filter = Filter::find($filterId);
232
233
        if ($filter) {
234
            if ($filter->readOnly) {
235
                // Response
236
                $success = false;
237
                $message = uctrans('error.filter.read_only', $module);
238
            } else {
239
                // Delete
240
                $filter->delete();
241
242
                // Response
243
                $success = true;
244
                $message = uctrans('success.filter.deleted', $module);
245
            }
246
        } else {
247
            // Response
248
            $success = false;
249
            $message = uctrans('error.filter.not_found', $module);
250
        }
251
252
        return [
253
            'success' => $success,
254
            'message' => $message
255
        ];
256
    }
257
258
    /**
259
     * Build query for retrieving content
260
     *
261
     * @return \Illuminate\Database\Eloquent\Builder;
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Eloquent\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...
262
     */
263
    protected function buildContentQuery()
264
    {
265
        $order = $this->request->get('order');
266
        $columns = $this->request->get('columns');
267
268
        $domain = $this->domain;
269
        $module = $this->module;
270
271
         // Get model model class
272
         $modelClass = $module->model_class;
273
274
         // Check if the class exists
275
         if (!class_exists($modelClass)) {
276
             return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Illuminate\Database\Eloquent\Builder.
Loading history...
277
         }
278
279
        // Filter on domain if column exists
280
        if (Schema::hasColumn((new $modelClass)->getTable(), 'domain_id')) {
281
            // Activate transversal view if the user is allowed
282
            if (auth()->user()->canSeeDescendantsRecords($domain) && request('descendants')) {
0 ignored issues
show
Bug introduced by
The function auth was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

282
            if (/** @scrutinizer ignore-call */ auth()->user()->canSeeDescendantsRecords($domain) && request('descendants')) {
Loading history...
Bug introduced by
The function request was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

282
            if (auth()->user()->canSeeDescendantsRecords($domain) && /** @scrutinizer ignore-call */ request('descendants')) {
Loading history...
283
                $domainsIds = $domain->findDescendants()->pluck('id');
284
                $query = $modelClass::whereIn('domain_id', $domainsIds);
285
            } else {
286
                $query = $modelClass::where('domain_id', $domain->id);
287
            }
288
        } else {
289
            $query = $modelClass::query();
290
        }
291
292
        // Search by column
293
        foreach ($columns as $fieldName => $column) {
294
            if (!empty($column[ "search" ])) {
295
                $searchValue = $column[ "search" ];
296
            } else {
297
                $searchValue = null;
298
            }
299
300
            // Get field by name and search by field column
301
            $field = $module->getField($fieldName);
302
            if (isset($searchValue) && !is_null($field)) {
303
                $uitype = uitype($field->uitype_id);
304
                $query = $uitype->addConditionToSearchQuery($query, $field, $searchValue);
305
            }
306
        }
307
308
        // Order results
309
        if (!empty($order)) {
310
            foreach ($order as $fieldColumn => $value) {
311
                if (!is_null($field)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $field seems to be defined by a foreach iteration on line 293. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
312
                    $query = $query->orderBy($fieldColumn, $value);
313
                }
314
            }
315
        }
316
317
        return $query;
318
    }
319
}
320