Passed
Push — master ( 1b176b...61854e )
by Jonathan
15:21
created

ListController::isDisplayingTrash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Uccello\Core\Http\Controllers\Core;
4
5
use Schema;
6
use Illuminate\Http\Request;
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...
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)  // Module
50
            ->where('type', 'list')                         // Type (list)
51
            ->where(function ($query) use($domain) {        // Domain
52
                $query->whereNull('domain_id')
53
                    ->orWhere('domain_id', $domain->getKey());
54
            })
55
            ->where(function ($query) {                     // User
56
                $query->where('is_public', true)
57
                    ->orWhere(function ($query) {
58
                        $query->where('is_public', false)
59
                            ->where('user_id', '=', auth()->id());
60
                    })
61
                    ->orWhere(function ($query) {
62
                        $query->where('is_public', false)
63
                            ->whereNull('user_id');
64
                    });
65
            })
66
            ->orderBy('order')
67
            ->get();
68
69
        // Order
70
        $filterOrder = (array) $selectedFilter->order;
71
72
        // See descendants
73
        $seeDescendants = request()->session()->get('descendants');
74
75
        // Use soft deleting
76
        $usesSoftDeleting = $this->isModuleUsingSoftDeleting();
77
78
        // Check if we want to display trash data
79
        $displayTrash = $this->isDisplayingTrash();
80
81
        return $this->autoView(compact(
82
            'datatableColumns',
83
            'filters',
84
            'selectedFilter',
85
            'filterOrder',
86
            'seeDescendants',
87
            'usesSoftDeleting',
88
            'displayTrash'
89
        ));
90
    }
91
92
    /**
93
     * Display a listing of the resources.
94
     * The result is formated differently if it is a classic query or one requested by datatable.
95
     * Filter on domain if domain_id column exists.
96
     * @param  \Uccello\Core\Models\Domain|null $domain
97
     * @param  \Uccello\Core\Models\Module $module
98
     * @param  \Illuminate\Http\Request $request
99
     * @return \Illuminate\Http\Response
100
     */
101
    public function processForContent(?Domain $domain, Module $module, Request $request)
102
    {
103
        $length = (int)$request->get('length') ?? env('UCCELLO_ITEMS_PER_PAGE', 15);
104
105
        $recordId = $request->get('id');
106
        $relatedListId = $request->get('relatedlist');
107
        $action = $request->get('action');
108
109
        if ($request->has('descendants') && $request->get('descendants') !== $request->session()->get('descendants')) {
110
            $request->session()->put('descendants', $request->get('descendants'));
111
        }
112
113
        // Pre-process
114
        $this->preProcess($domain, $module, $request, false);
115
116
        // Get model model class
117
        $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...
118
119
        // Check if the class exists
120
        if (!class_exists($modelClass)) {
121
            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...
122
        }
123
124
        // Build query
125
        $query = $this->buildContentQuery();
126
127
        // Limit the number maximum of items per page
128
        $maxItemsPerPage = env('UCCELLO_MAX_ITEMS_PER_PAGE', 100);
129
        if ($length > $maxItemsPerPage) {
130
            $length = $maxItemsPerPage;
131
        }
132
133
        // If the query is for a related list, add conditions
134
        if ($relatedListId && $action !== 'select') {
135
            // Get related list
136
            $relatedList = Relatedlist::find($relatedListId);
137
138
            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...
139
                // Related list method
140
                $method = $relatedList->method;
141
142
                // Update query
143
                $model = new $modelClass;
144
                $records = $model->$method($relatedList, $recordId, $query)->paginate($length);
145
            }
146
        } elseif ($relatedListId && $action === 'select') {
147
            // Get related list
148
            $relatedList = Relatedlist::find($relatedListId);
149
150
            if ($relatedList && $relatedList->method) {
151
                // Related list method
152
                $method = $relatedList->method;
153
                $recordIdsMethod = $method . 'RecordIds';
154
155
                // Get related records ids
156
                $model = new $modelClass;
157
                $filteredRecordIds = $model->$recordIdsMethod($relatedList, $recordId);
158
159
                // Add the record id itself to be filtered
160
                if ($relatedList->module_id === $relatedList->related_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...
Bug introduced by
The property module_id does not exist on Uccello\Core\Models\Relatedlist. Did you mean module?
Loading history...
161
                    $filteredRecordIds[] = (int)$recordId;
162
                }
163
164
                // Make the quer
165
                $records = $query->whereNotIn($model->getKeyName(), $filteredRecordIds)->paginate($length);
166
            }
167
        } else {
168
            // Paginate results
169
            $records = $query->paginate($length);
170
        }
171
172
        $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...
173
            foreach ($module->fields as $field) {
174
                // If a special template exists, use it. Else use the generic template
175
                $uitype = uitype($field->uitype_id);
176
                $uitypeViewName = sprintf('uitypes.list.%s', $uitype->name);
177
                $uitypeFallbackView = 'uccello::modules.default.uitypes.list.text';
178
                $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...
179
                $record->{$field->name.'_html'} = view()->make($uitypeViewToInclude, compact('domain', 'module', 'record', 'field'))->render();
180
            }
181
182
            // Add primary key name and value
183
            $record->__primaryKey = $record->getKey();
184
            $record->__primaryKeyName = $record->getKeyName();
185
186
            return $record;
187
        });
188
189
        return $records;
190
    }
191
192
    /**
193
     * Autocomplete a listing of the resources.
194
     * The result is formated differently if it is a classic query or one requested by datatable.
195
     * Filter on domain if domain_id column exists.
196
     * @param  \Uccello\Core\Models\Domain|null $domain
197
     * @param  \Uccello\Core\Models\Module $module
198
     * @param  \Illuminate\Http\Request $request
199
     * @return \Illuminate\Http\Response
200
     */
201
    public function processForAutocomplete(?Domain $domain, Module $module, Request $request)
202
    {
203
        // If we don't use multi domains, find the first one
204
        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...
205
            $domain = Domain::first();
0 ignored issues
show
Unused Code introduced by
The assignment to $domain is dead and can be removed.
Loading history...
206
        }
207
208
        // Query
209
        $q = $request->get('q');
210
        // Model class
211
        $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...
212
213
        $results = collect();
214
        if (method_exists($modelClass, 'getSearchResult') && property_exists($modelClass, 'searchableColumns')) {
215
            $searchResults = new Search();
216
            $searchResults->registerModel($modelClass, (array) (new $modelClass)->searchableColumns);
217
            $results = $searchResults->search($q)->take(config('uccello.max_results.autocomplete', 10));
218
        }
219
220
        return $results;
221
    }
222
223
    /**
224
     * Save list filter into database
225
     *
226
     * @param \Uccello\Core\Models\Domain|null $domain
227
     * @param \Uccello\Core\Models\Module $module
228
     * @param \Illuminate\Http\Request $request
229
     * @return \Illuminate\Http\Response
230
     */
231
    public function saveFilter(?Domain $domain, Module $module, Request $request)
232
    {
233
        $saveOrder = $request->input('save_order');
234
        $savePageLength = $request->input('save_page_length');
235
236
        // Optional data
237
        $data = [];
238
        if ($savePageLength) {
239
            $data["length"] = $request->input('page_length');
240
        }
241
242
        $filter = Filter::firstOrNew([
243
            'domain_id' => $domain->id,
244
            'module_id' => $module->id,
245
            'user_id' => auth()->id(),
246
            'name' => $request->input('name'),
247
            'type' => $request->input('type')
248
        ]);
249
        $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...
250
        $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...
251
        $filter->order = $saveOrder ? $request->input('order') : null;
0 ignored issues
show
Bug introduced by
The property order 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...
252
        $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...
253
        $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...
254
        $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...
255
        $filter->save();
256
257
        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...
258
    }
259
260
    /**
261
     * Retrieve a filter by its id and delete it
262
     *
263
     * @param \Uccello\Core\Models\Domain|null $domain
264
     * @param \Uccello\Core\Models\Module $module
265
     * @param \Illuminate\Http\Request $request
266
     * @return \Illuminate\Http\Response
267
     */
268
    public function deleteFilter(?Domain $domain, Module $module, Request $request)
269
    {
270
        // Retrieve filter by id
271
        $filterId = $request->input('id');
272
        $filter = Filter::find($filterId);
273
274
        if ($filter) {
275
            if ($filter->readOnly) {
276
                // Response
277
                $success = false;
278
                $message = uctrans('error.filter.read_only', $module);
279
            } else {
280
                // Delete
281
                $filter->delete();
282
283
                // Response
284
                $success = true;
285
                $message = uctrans('success.filter.deleted', $module);
286
            }
287
        } else {
288
            // Response
289
            $success = false;
290
            $message = uctrans('error.filter.not_found', $module);
291
        }
292
293
        return [
294
            'success' => $success,
295
            'message' => $message
296
        ];
297
    }
298
299
    /**
300
     * Check if the model class link to the module is using soft deleting.
301
     *
302
     * @return boolean
303
     */
304
    protected function isModuleUsingSoftDeleting()
305
    {
306
        return in_array(
307
            \Illuminate\Database\Eloquent\SoftDeletes::class,
308
            array_keys((new \ReflectionClass($this->module->model_class))->getTraits())
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...
309
        );
310
    }
311
312
    /**
313
     * Check if we want to display trash data
314
     *
315
     * @return boolean
316
     */
317
    protected function isDisplayingTrash()
318
    {
319
        return $this->isModuleUsingSoftDeleting() && $this->request->get('filter') === 'trash';
320
    }
321
322
    /**
323
     * Build query for retrieving content
324
     *
325
     * @return \Illuminate\Database\Eloquent\Builder;
326
     */
327
    protected function buildContentQuery()
328
    {
329
        $filter = [
330
            'order' => $this->request->get('order'),
331
            'columns' => $this->request->get('columns'),
332
        ];
333
334
        // Get model model class
335
        $modelClass = $this->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...
336
337
        // Check if the class exists
338
        if (!class_exists($modelClass) || !method_exists($modelClass, 'scopeInDomain')) {
339
            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...
340
        }
341
342
        // Filter on domain if column exists
343
        $query = $modelClass::inDomain($this->domain, $this->request->session()->get('descendants'))
344
                            ->filterBy($filter);
345
346
        // Display trash if filter is selected
347
        if ($this->isDisplayingTrash()) {
348
            $query = $query->onlyTrashed();
349
        }
350
351
        return $query;
352
    }
353
}
354