Scaffolding::breadcrumbs()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 10
ccs 0
cts 0
cp 0
crap 6
rs 10
1
<?php
2
3
namespace Terranet\Administrator;
4
5
use DaveJamesMiller\Breadcrumbs\BreadcrumbsManager;
6
use Illuminate\Database\Eloquent\Model;
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Eloquent\Model 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 Illuminate\Http\Request;
8
use Illuminate\Support\Arr;
9
use Terranet\Administrator\Contracts\ActionsManager as ActionsManagerContract;
10
use Terranet\Administrator\Contracts\AutoTranslatable;
11
use Terranet\Administrator\Contracts\Filter as FiltersManagerContract;
12
use Terranet\Administrator\Contracts\Module;
13
use Terranet\Administrator\Contracts\Module\Filtrable;
14
use Terranet\Administrator\Contracts\Module\Sortable;
15
use Terranet\Administrator\Contracts\Services\Finder as FinderContract;
16
use Terranet\Administrator\Contracts\Services\TemplateProvider;
17
use Terranet\Administrator\Requests\UpdateRequest;
18
use Terranet\Administrator\Services\Breadcrumbs;
19
use Terranet\Administrator\Services\CrudActions;
20
use Terranet\Administrator\Services\Finder;
21
use Terranet\Administrator\Services\Saver;
22
use Terranet\Administrator\Services\Sorter;
23
use Terranet\Administrator\Services\Template;
24
use Terranet\Administrator\Traits\AutoTranslatesInstances;
25
use Terranet\Administrator\Traits\Module\AllowsNavigation;
26
use Terranet\Administrator\Traits\Module\HasColumns;
27
28
class Scaffolding implements Module, AutoTranslatable
29
{
30
    use AllowsNavigation, HasColumns, AutoTranslatesInstances;
31
32
    const PAGE_INDEX = 'index';
33
    const PAGE_VIEW = 'view';
34
    const PAGE_EDIT = 'edit';
35
36
    /**
37
     * The module Eloquent model class.
38
     *
39
     * @return string
40
     */
41
    protected $model;
42
43
    /**
44
     * Breadcrumbs provider.
45
     *
46
     * @var Breadcrumbs
47
     */
48
    protected $breadcrumbs = Breadcrumbs::class;
49
50
    /**
51
     * Service layer responsible for searching items.
52
     *
53
     * @var FinderContract
54
     */
55
    protected $finder = Finder::class;
56
57
    /**
58
     * Service layer responsible for persisting request.
59
     *
60
     * @var Contracts\Services\Saver
61
     */
62
    protected $saver = Saver::class;
63
64
    /**
65
     * Actions manager class.
66
     *
67
     * @var \Terranet\Administrator\Contracts\Services\CrudActions
68
     */
69
    protected $actions = CrudActions::class;
70
71
    /**
72
     * View templates provider.
73
     *
74
     * @var TemplateProvider
75
     */
76
    protected $template = Template::class;
77
78
    /**
79
     * Include or not columns of Date type in index listing.
80
     *
81
     * @var bool
82
     */
83
    protected $includeDateColumns;
84
85
    /**
86
     * Global ACL Manager.
87
     *
88
     * @var mixed null
89
     */
90
    protected $guard;
91
92
    /** @var array */
93
    protected static $methods = [];
94
95
    /** @var Request */
96
    protected $request;
97
98
    /**
99
     * Scaffolding constructor.
100
     *
101
     * @param  AdminRequest  $request
102
     */
103
    public function __construct(AdminRequest $request)
104
    {
105
        if (null === $this->includeDateColumns) {
106
            $this->includeDateColumns = $this->defaultIncludeDateColumnsValue();
107
        }
108
109
        $this->request = $request;
110
    }
111
112
    /**
113
     * @param $method
114
     * @param $arguments
115
     * @return null|mixed
116
     */
117
    public function __call($method, $arguments)
118
    {
119
        // Call user-defined method if exists.
120
        if ($closure = Arr::get(static::$methods, $method)) {
121
            return \call_user_func_array($closure, $arguments);
122
        }
123
124
        return null;
125
    }
126
127
    /**
128
     * Extend functionality by adding new methods.
129
     *
130
     * @param $name
131
     * @param $closure
132
     * @throws Exception
133
     */
134
    public static function addMethod($name, $closure)
135
    {
136
        if (!(new static())->hasMethod($name)) {
0 ignored issues
show
Bug introduced by
The call to Terranet\Administrator\Scaffolding::__construct() has too few arguments starting with request. ( Ignorable by Annotation )

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

136
        if (!(/** @scrutinizer ignore-call */ new static())->hasMethod($name)) {

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
137
            static::$methods[$name] = $closure;
138
        }
139
    }
140
141
    /**
142
     * Disable Actions column totally for Readonly Resources.
143
     *
144
     * @return bool
145
     */
146
    public function readonly()
147
    {
148
        return false;
149
    }
150
151
    /**
152
     * Check if method exists.
153
     *
154
     * @param $name
155
     * @return bool
156
     */
157
    public function hasMethod($name)
158
    {
159
        return method_exists($this, $name) || Arr::has(static::$methods, $name);
160
    }
161
162
    /**
163
     * The module Templates manager.
164
     *
165
     * @return string
166
     */
167
    protected function templateClassName(): string
168
    {
169
        if (class_exists($file = $this->getQualifiedClassNameOfType('Templates'))) {
170
            return $file;
171
        }
172
173
        return $this->template;
174
    }
175
176
    public function template(): TemplateProvider
177
    {
178
        return once(function () {
179
            // check for resource template
180
            $handler = $this->templateClassName();
181
            $handler = new $handler();
182
183
            if (!$handler instanceof TemplateProvider) {
184
                throw new Exception('Templates handler must implement '.TemplateProvider::class.' contract');
185
            }
186
187
            return $handler;
188
        });
189
    }
190
191
    /**
192
     * @return Model
193
     * @throws \Exception
194
     */
195
    public function model()
196
    {
197
        static $model = null;
198
199
        if (null === $model && ($class = $this->getModelClass())) {
200
            $model = new $class();
201
        }
202
203
        return $model;
204
    }
205
206
    /**
207
     * @param $model
208
     * @return $this
209
     */
210
    public function setModel($model)
211
    {
212
        $this->model = $model;
213
214
        return $this;
215
    }
216
217
    /**
218
     * @return Request
219
     */
220
    public function request()
221
    {
222
        return $this->request;
223
    }
224
225
    /**
226
     * Define the class responsive for fetching items.
227
     *
228
     * @return string
229
     */
230
    protected function finderClassName(): string
231
    {
232
        if (class_exists($file = $this->getQualifiedClassNameOfType('Finders'))) {
233
            return $file;
234
        }
235
236
        return $this->finder;
237
    }
238
239
    /**
240
     * @return mixed
241
     */
242
    public function finder(): FinderContract
243
    {
244
        $className = $this->finderClassName();
245
246
        return once(function () use ($className) {
247
            $this->columns();
248
249
            return new $className($this);
250
        });
251
    }
252
253
    /**
254
     * Filters & Scopes manager.
255
     *
256
     * @return Filter
257
     */
258
    public function filter(): FiltersManagerContract
259
    {
260
        $filters = $scopes = null;
261
262
        if ($this instanceof Filtrable) {
263
            $filters = $this->filters();
0 ignored issues
show
Bug introduced by
The method filters() does not exist on Terranet\Administrator\Scaffolding. Since you implemented __call, 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

263
            /** @scrutinizer ignore-call */ 
264
            $filters = $this->filters();
Loading history...
264
            $scopes = $this->scopes();
0 ignored issues
show
Bug introduced by
The method scopes() does not exist on Terranet\Administrator\Scaffolding. Since you implemented __call, 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

264
            /** @scrutinizer ignore-call */ 
265
            $scopes = $this->scopes();
Loading history...
265
        }
266
267
        return new Filter($this->request(), $filters, $scopes);
268
    }
269
270
    /**
271
     * @return Sorter
272
     */
273
    public function sortableManager(): Sorter
274
    {
275
        return once(function () {
276
            return new Sorter(
277
                $this instanceof Sortable ? $this->sortable() : [],
0 ignored issues
show
Bug introduced by
It seems like $this instanceof Terrane...s->sortable() : array() can also be of type null; however, parameter $sortable of Terranet\Administrator\S...s\Sorter::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

277
                /** @scrutinizer ignore-type */ $this instanceof Sortable ? $this->sortable() : [],
Loading history...
Bug introduced by
The method sortable() does not exist on Terranet\Administrator\Scaffolding. Since you implemented __call, 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

277
                $this instanceof Sortable ? $this->/** @scrutinizer ignore-call */ sortable() : [],
Loading history...
278
                method_exists($this, 'sortDirection') ? $this->sortDirection() : 'desc'
0 ignored issues
show
Bug introduced by
It seems like method_exists($this, 'so...ortDirection() : 'desc' can also be of type null; however, parameter $sortDir of Terranet\Administrator\S...s\Sorter::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

278
                /** @scrutinizer ignore-type */ method_exists($this, 'sortDirection') ? $this->sortDirection() : 'desc'
Loading history...
Bug introduced by
The method sortDirection() does not exist on Terranet\Administrator\Scaffolding. Since you implemented __call, 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

278
                method_exists($this, 'sortDirection') ? $this->/** @scrutinizer ignore-call */ sortDirection() : 'desc'
Loading history...
279
            );
280
        });
281
    }
282
283
    /**
284
     * Define the class responsive for persisting items.
285
     *
286
     * @return string
287
     */
288
    protected function saverClassName(): string
289
    {
290
        if (class_exists($file = $this->getQualifiedClassNameOfType('Savers'))) {
291
            return $file;
292
        }
293
294
        return $this->saver;
295
    }
296
297
    /**
298
     * Define the class responsive for persisting items.
299
     *
300
     * @param  Model  $eloquent
301
     * @param  UpdateRequest  $request
302
     * @return Contracts\Services\Saver
303
     * @throws Exception
304
     */
305
    public function saver(Model $eloquent, UpdateRequest $request): Contracts\Services\Saver
306
    {
307
        $className = $this->saverClassName();
308
        $instance = new $className($eloquent, $request);
309
310
        if (!$instance instanceof Contracts\Services\Saver) {
311
            throw new Exception('Saver must implement '.Saver::class.' contract');
312
        }
313
314
        return $instance;
315
    }
316
317
    /**
318
     * Breadcrumbs provider
319
     * First parse Module doc block for provider declaration.
320
     *
321
     * @return mixed
322
     */
323
    public function breadcrumbsClassName()
324
    {
325
        if (class_exists($file = $this->getQualifiedClassNameOfType('Breadcrumbs'))) {
326
            return $file;
327
        }
328
329
        return $this->breadcrumbs;
330
    }
331
332
    /**
333
     * Breadcrumbs service.
334
     *
335
     * @return Breadcrumbs
336
     * @throws Exception
337
     */
338
    public function breadcrumbs(): Breadcrumbs
339
    {
340
        if (!class_exists(BreadcrumbsManager::class)) {
341
            throw new Exception('Please install `davejamesmiller/laravel-breadcrumbs:^5.2` package.');
342
        }
343
344
        $provider = $this->breadcrumbsClassName();
345
346
        return new $provider(
347
            app(BreadcrumbsManager::class), $this
0 ignored issues
show
Bug introduced by
The function app 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

347
            /** @scrutinizer ignore-call */ 
348
            app(BreadcrumbsManager::class), $this
Loading history...
348
        );
349
    }
350
351
    /**
352
     * Define the Actions provider - object responsive for
353
     * CRUD operations, Export, etc...
354
     * as like as checks action permissions.
355
     *
356
     * @return mixed
357
     */
358
    public function actionsClassName()
359
    {
360
        if (class_exists($file = $this->getQualifiedClassNameOfType('Actions'))) {
361
            return $file;
362
        }
363
364
        return $this->actions;
365
    }
366
367
    /**
368
     * @return ActionsManager
369
     * @throws Exception
370
     */
371
    public function actions(): ActionsManagerContract
372
    {
373
        $handler = $this->actionsClassName();
374
        $handler = new $handler($this, $this->request());
375
376
        if (!$handler instanceof CrudActions) {
377
            throw new Exception('Actions handler must implement '.CrudActions::class.' contract');
378
        }
379
380
        return new ActionsManager($handler, $this);
381
    }
382
383
    /**
384
     * The module Eloquent model.
385
     *
386
     * @return mixed
387
     * @throws \Exception
388
     */
389
    protected function getModelClass()
390
    {
391
        return $this->model;
392
    }
393
394
    /**
395
     * Get the full path to class of special type.
396
     *
397
     * @param $type
398
     * @return string
399
     */
400
    protected function getQualifiedClassNameOfType($type)
401
    {
402
        return app()->getNamespace()."Http\\Terranet\\Administrator\\{$type}\\".class_basename($this);
0 ignored issues
show
Bug introduced by
The function app 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

402
        return /** @scrutinizer ignore-call */ app()->getNamespace()."Http\\Terranet\\Administrator\\{$type}\\".class_basename($this);
Loading history...
403
    }
404
405
    /**
406
     * @return mixed
407
     */
408
    protected function defaultIncludeDateColumnsValue()
409
    {
410
        return config(
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

410
        return /** @scrutinizer ignore-call */ config(
Loading history...
411
            "administrator.grid.timestamps.{$this->url()}",
412
            config('administrator.grid.timestamps.enabled')
413
        );
414
    }
415
}
416