Passed
Push — master ( 0f9eb8...340202 )
by Jonathan
24:22
created

ListController::buildContentQuery()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 20
rs 9.9666
cc 3
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)
50
            ->where('type', 'list')
51
            ->get();
52
53
        // Order by
54
        $filterOrderBy = (array) $selectedFilter->order;
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
67
     */
68
    public function processForContent(?Domain $domain, Module $module, Request $request)
69
    {
70
        $length = (int)$request->get('length') ?? env('UCCELLO_ITEMS_PER_PAGE', 15);
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;
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...
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) {
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...
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)) {
0 ignored issues
show
Bug introduced by
The property module_id does not exist on Uccello\Core\Models\Relatedlist. Did you mean module?
Loading history...
Bug introduced by
The property related_module_id does not exist on Uccello\Core\Models\Relatedlist. Did you mean module?
Loading history...
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();
143
            }
144
145
            // Add primary key name and value
146
            $record->__primaryKey = $record->getKey();
147
            $record->__primaryKeyName = $record->getKeyName();
148
149
            return $record;
150
        });
151
152
        return $records;
153
    }
154
155
    /**
156
     * Autocomplete a listing of the resources.
157
     * The result is formated differently if it is a classic query or one requested by datatable.
158
     * Filter on domain if domain_id column exists.
159
     * @param  \Uccello\Core\Models\Domain|null $domain
160
     * @param  \Uccello\Core\Models\Module $module
161
     * @param  \Illuminate\Http\Request $request
162
     * @return \Illuminate\Http\Response
163
     */
164
    public function processForAutocomplete(?Domain $domain, Module $module, Request $request)
165
    {
166
        // If we don't use multi domains, find the first one
167
        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...
168
            $domain = Domain::first();
0 ignored issues
show
Unused Code introduced by
The assignment to $domain is dead and can be removed.
Loading history...
169
        }
170
171
        // Query
172
        $q = $request->get('q');
173
        // Model class
174
        $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...
175
176
        $results = collect();
177
        if (method_exists($modelClass, 'getSearchResult') && property_exists($modelClass, 'searchableColumns')) {
178
            $searchResults = new Search();
179
            $searchResults->registerModel($modelClass, (array) (new $modelClass)->searchableColumns);
180
            $results = $searchResults->search($q)->take(config('uccello.max_results.autocomplete', 10));
181
        }
182
183
        return $results;
184
    }
185
186
    /**
187
     * Save list filter into database
188
     *
189
     * @param \Uccello\Core\Models\Domain|null $domain
190
     * @param \Uccello\Core\Models\Module $module
191
     * @param \Illuminate\Http\Request $request
192
     * @return \Illuminate\Http\Response
193
     */
194
    public function saveFilter(?Domain $domain, Module $module, Request $request)
195
    {
196
        $saveOrder = $request->input('save_order');
197
        $savePageLength = $request->input('save_page_length');
198
199
        // Optional data
200
        $data = [];
201
        if ($savePageLength) {
202
            $data["length"] = $request->input('page_length');
203
        }
204
205
        $filter = Filter::firstOrNew([
206
            'domain_id' => $domain->id,
207
            'module_id' => $module->id,
208
            'user_id' => auth()->id(),
209
            'name' => $request->input('name'),
210
            'type' => $request->input('type')
211
        ]);
212
        $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...
213
        $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...
214
        $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...
215
        $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...
216
        $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...
217
        $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...
218
        $filter->save();
219
220
        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...
221
    }
222
223
    /**
224
     * Retrieve a filter by its id and delete it
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 deleteFilter(?Domain $domain, Module $module, Request $request)
232
    {
233
        // Retrieve filter by id
234
        $filterId = $request->input('id');
235
        $filter = Filter::find($filterId);
236
237
        if ($filter) {
238
            if ($filter->readOnly) {
239
                // Response
240
                $success = false;
241
                $message = uctrans('error.filter.read_only', $module);
242
            } else {
243
                // Delete
244
                $filter->delete();
245
246
                // Response
247
                $success = true;
248
                $message = uctrans('success.filter.deleted', $module);
249
            }
250
        } else {
251
            // Response
252
            $success = false;
253
            $message = uctrans('error.filter.not_found', $module);
254
        }
255
256
        return [
257
            'success' => $success,
258
            'message' => $message
259
        ];
260
    }
261
262
    /**
263
     * Build query for retrieving content
264
     *
265
     * @return \Illuminate\Database\Eloquent\Builder;
266
     */
267
    protected function buildContentQuery()
268
    {
269
        $filter = [
270
            'order' => $this->request->get('order'),
271
            'columns' => $this->request->get('columns'),
272
        ];
273
274
        // Get model model class
275
        $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...
276
277
        // Check if the class exists
278
        if (!class_exists($modelClass) || !method_exists($modelClass, 'scopeInDomain')) {
279
            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...
280
        }
281
282
        // Filter on domain if column exists
283
        $query = $modelClass::inDomain($this->domain, $this->request->get('descendants'))
284
                            ->filterBy($filter);
285
286
        return $query;
287
    }
288
}
289