Completed
Push — master ( d823f0...07497a )
by Jonathan
68:17
created

ListController::buildContentQuery()   B

Complexity

Conditions 10
Paths 21

Size

Total Lines 48
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 24
nc 21
nop 0
dl 0
loc 48
rs 7.6666
c 0
b 0
f 0

How to fix   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;
6
use DB;
7
use Illuminate\Http\Request;
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...
Bug introduced by
The method getDatatableColumns() does not exist on Uccello\Core\Facades\Uccello. Since you implemented __callStatic, 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

46
        /** @scrutinizer ignore-call */ 
47
        $datatableColumns = Uccello::getDatatableColumns($module, $selectedFilterId);
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
61
    /**
62
     * Display a listing of the resources.
63
     * The result is formated differently if it is a classic query or one requested by datatable.
64
     * Filter on domain if domain_id column exists.
65
     * @param  \Uccello\Core\Models\Domain|null $domain
66
     * @param  \Uccello\Core\Models\Module $module
67
     * @param  \Illuminate\Http\Request $request
68
     * @return \Illuminate\Http\Response
69
     */
70
    public function processForContent(?Domain $domain, Module $module, Request $request)
71
    {
72
        $length = (int)$request->get('length') ?? env('UCCELLO_ITEMS_PER_PAGE', 15);
73
74
        $recordId = $request->get('id');
75
        $relatedListId = $request->get('relatedlist');
76
        $action = $request->get('action');
77
78
        // Pre-process
79
        $this->preProcess($domain, $module, $request);
80
81
        // Get model model class
82
        $modelClass = $module->model_class;
0 ignored issues
show
Bug introduced by
The property model_class does not seem to exist on Uccello\Core\Models\Module. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
83
84
        // Check if the class exists
85
        if (!class_exists($modelClass)) {
86
            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...
87
        }
88
89
        // Build query
90
        $query = $this->buildContentQuery();
91
92
        // Limit the number maximum of items per page
93
        $maxItemsPerPage = env('UCCELLO_MAX_ITEMS_PER_PAGE', 100);
94
        if ($length > $maxItemsPerPage) {
95
            $length = $maxItemsPerPage;
96
        }
97
98
        // If the query is for a related list, add conditions
99
        if ($relatedListId && $action !== 'select') {
100
            // Get related list
101
            $relatedList = Relatedlist::find($relatedListId);
102
103
            if ($relatedList && $relatedList->method) {
0 ignored issues
show
Bug introduced by
The property method does not seem to exist on Uccello\Core\Models\Relatedlist. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
104
                // Related list method
105
                $method = $relatedList->method;
106
107
                // Update query
108
                $model = new $modelClass;
109
                $records = $model->$method($relatedList, $recordId, $query, 0, $length);
110
            }
111
        } elseif ($relatedListId && $action === 'select') {
112
            // Get related list
113
            $relatedList = Relatedlist::find($relatedListId);
114
115
            if ($relatedList && $relatedList->method) {
116
                // Related list method
117
                $method = $relatedList->method;
118
                $recordIdsMethod = $method . 'RecordIds';
119
120
                // Get related records ids
121
                $model = new $modelClass;
122
                $filteredRecordIds = $model->$recordIdsMethod($relatedList, $recordId);
123
124
                // Add the record id itself to be filtered
125
                if ($relatedList->related_module_id === $module->id && !empty($recordId) && !$filteredRecordIds->contains($recordId)) {
0 ignored issues
show
Bug introduced by
The property related_module_id does not exist on Uccello\Core\Models\Relatedlist. Did you mean module?
Loading history...
126
                    $filteredRecordIds[] = (int)$recordId;
127
                }
128
129
                // Make the quer
130
                $records = $query->whereNotIn($model->getKeyName(), $filteredRecordIds)->paginate($length);
131
            }
132
        } else {
133
            // Paginate results
134
            $records = $query->paginate($length);
135
        }
136
137
        $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...
138
            foreach ($module->fields as $field) {
139
                // If a special template exists, use it. Else use the generic template
140
                $uitypeViewName = sprintf('uitypes.list.%s', $field->uitype->name);
141
                $uitypeFallbackView = 'uccello::modules.default.uitypes.list.text';
142
                $uitypeViewToInclude = uccello()->view($field->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...
143
                $record->{$field->name.'_html'} = view()->make($uitypeViewToInclude, compact('domain', 'module', 'record', 'field'))->render();
144
            }
145
146
            return $record;
147
        });
148
149
        return $records;
150
    }
151
152
    /**
153
     * Autocomplete a listing of the resources.
154
     * The result is formated differently if it is a classic query or one requested by datatable.
155
     * Filter on domain if domain_id column exists.
156
     * @param  \Uccello\Core\Models\Domain|null $domain
157
     * @param  \Uccello\Core\Models\Module $module
158
     * @param  \Illuminate\Http\Request $request
159
     * @return \Illuminate\Http\Response
160
     */
161
    public function processForAutocomplete(?Domain $domain, Module $module, Request $request)
162
    {
163
        // If we don't use multi domains, find the first one
164
        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...
165
            $domain = Domain::first();
0 ignored issues
show
Unused Code introduced by
The assignment to $domain is dead and can be removed.
Loading history...
166
        }
167
168
        // Query
169
        $q = $request->get('q');
170
171
        // Model class
172
        $modelClass = $module->model_class;
0 ignored issues
show
Bug introduced by
The property model_class does not seem to exist on Uccello\Core\Models\Module. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
173
174
        if ($q) {
175
            DB::statement("SET SESSION sql_mode = ''");
176
            $query = $modelClass::search($q);
177
        } else {
178
            $query = $modelClass::query();
179
        }
180
181
        return $query->paginate(10);
182
    }
183
184
    /**
185
     * Save list filter into database
186
     *
187
     * @param \Uccello\Core\Models\Domain|null $domain
188
     * @param \Uccello\Core\Models\Module $module
189
     * @param \Illuminate\Http\Request $request
190
     * @return \Illuminate\Http\Response
191
     */
192
    public function saveFilter(?Domain $domain, Module $module, Request $request)
193
    {
194
        $saveOrder = $request->input('save_order');
195
        $savePageLength = $request->input('save_page_length');
196
197
        // Optional data
198
        $data = [];
199
        if ($savePageLength) {
200
            $data["length"] = $request->input('page_length');
201
        }
202
203
        $filter = Filter::firstOrNew([
204
            'domain_id' => $domain->id,
205
            'module_id' => $module->id,
206
            'user_id' => auth()->id(),
207
            'name' => $request->input('name'),
208
            'type' => $request->input('type')
209
        ]);
210
        $filter->columns = $request->input('columns');
0 ignored issues
show
Bug introduced by
The property columns does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
211
        $filter->conditions = $request->input('conditions') ?? null;
0 ignored issues
show
Bug introduced by
The property conditions does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
212
        $filter->order_by = $saveOrder ? $request->input('order') : null;
0 ignored issues
show
Bug introduced by
The property order_by does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
213
        $filter->is_default = $request->input('default');
0 ignored issues
show
Bug introduced by
The property is_default does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
214
        $filter->is_public = $request->input('public');
0 ignored issues
show
Bug introduced by
The property is_public does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
215
        $filter->data = !empty($data) ? $data : null;
0 ignored issues
show
Bug introduced by
The property data does not seem to exist on Uccello\Core\Models\Filter. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
216
        $filter->save();
217
218
        return $filter;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $filter returns the type Uccello\Core\Models\Filter which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
219
    }
220
221
    /**
222
     * Retrieve a filter by its id and delete it
223
     *
224
     * @param \Uccello\Core\Models\Domain|null $domain
225
     * @param \Uccello\Core\Models\Module $module
226
     * @param \Illuminate\Http\Request $request
227
     * @return \Illuminate\Http\Response
228
     */
229
    public function deleteFilter(?Domain $domain, Module $module, Request $request)
230
    {
231
        // Retrieve filter by id
232
        $filterId = $request->input('id');
233
        $filter = Filter::find($filterId);
234
235
        if ($filter) {
236
            if ($filter->readOnly) {
237
                // Response
238
                $success = false;
239
                $message = uctrans('error.filter.read_only', $module);
240
            } else {
241
                // Delete
242
                $filter->delete();
243
244
                // Response
245
                $success = true;
246
                $message = uctrans('success.filter.deleted', $module);
247
            }
248
        } else {
249
            // Response
250
            $success = false;
251
            $message = uctrans('error.filter.not_found', $module);
252
        }
253
254
        return [
255
            'success' => $success,
256
            'message' => $message
257
        ];
258
    }
259
260
    /**
261
     * Build query for retrieving content
262
     *
263
     * @return \Illuminate\Database\Eloquent\Builder;
264
     */
265
    protected function buildContentQuery()
266
    {
267
        $order = $this->request->get('order');
268
        $columns = $this->request->get('columns');
269
270
        $domain = $this->domain;
271
        $module = $this->module;
272
273
         // Get model model class
274
         $modelClass = $module->model_class;
0 ignored issues
show
Bug introduced by
The property model_class does not seem to exist on Uccello\Core\Models\Module. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
275
276
         // Check if the class exists
277
         if (!class_exists($modelClass)) {
278
             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...
279
         }
280
281
        // Filter on domain if column exists
282
        if (Schema::hasColumn((new $modelClass)->getTable(), 'domain_id')) {
283
            $query = $modelClass::where('domain_id', $domain->id);
284
        } else {
285
            $query = $modelClass::query();
286
        }
287
288
        // Search by column
289
        foreach ($columns as $fieldName => $column) {
290
            if (!empty($column[ "search" ])) {
291
                $searchValue = $column[ "search" ];
292
            } else {
293
                $searchValue = null;
294
            }
295
296
            // Get field by name and search by field column
297
            $field = $module->getField($fieldName);
298
            if (isset($searchValue) && !is_null($field)) {
299
                $query = $field->uitype->addConditionToSearchQuery($query, $field, $searchValue);
300
            }
301
        }
302
303
        // Order results
304
        if (!empty($order)) {
305
            foreach ($order as $fieldColumn => $value) {
306
                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 289. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
307
                    $query = $query->orderBy($fieldColumn, $value);
308
                }
309
            }
310
        }
311
312
        return $query;
313
    }
314
}
315