Completed
Pull Request — master (#334)
by Philippe
70:05 queued 37:24
created

AbstractManager::delete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Thinktomorrow\Chief\Management;
4
5
use Illuminate\Contracts\Pagination\Paginator;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Http\Request;
8
use Thinktomorrow\Chief\Concerns\Translatable\TranslatableCommand;
9
use Thinktomorrow\Chief\Fields\FieldArrangement;
10
use Thinktomorrow\Chief\Fields\Fields;
11
use Thinktomorrow\Chief\Fields\RenderingFields;
12
use Thinktomorrow\Chief\Fields\SavingFields;
13
use Thinktomorrow\Chief\Filters\Filters;
14
use Thinktomorrow\Chief\Management\Assistants\AssistedManager;
15
use Thinktomorrow\Chief\Management\Details\HasDetails;
16
use Thinktomorrow\Chief\Management\Details\HasSections;
17
use Thinktomorrow\Chief\Management\Exceptions\NonExistingRecord;
18
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
19
20
abstract class AbstractManager
21
{
22
    use RenderingFields,
0 ignored issues
show
Bug introduced by
The trait Thinktomorrow\Chief\Fields\SavingFields requires the property $key which is not provided by Thinktomorrow\Chief\Management\AbstractManager.
Loading history...
introduced by
The trait Thinktomorrow\Chief\Management\ManagesPagebuilder requires some properties which are not provided by Thinktomorrow\Chief\Management\AbstractManager: $trans, $slug, $page_id, $id
Loading history...
introduced by
The trait Thinktomorrow\Chief\Management\Details\HasDetails requires some properties which are not provided by Thinktomorrow\Chief\Management\AbstractManager: $labelPlural, $id, $labelSingular, $title
Loading history...
23
        SavingFields,
24
        HasDetails,
25
        HasSections,
26
        ManagesMedia,
27
        ManagesPagebuilder,
28
        TranslatableCommand,
29
        AssistedManager;
30
31
    protected $translation_columns = [];
32
33
    protected $model;
34
35
    /** @var Register */
36
    protected $registration;
37
38
    protected $pageCount                 = 20;
39
    protected $paginated                 = true;
40
    protected static $bootedTraitMethods = [];
41
42 167
    public function __construct(Registration $registration)
43
    {
44 167
        $this->registration = $registration;
0 ignored issues
show
Documentation Bug introduced by
It seems like $registration of type Thinktomorrow\Chief\Management\Registration is incompatible with the declared type Thinktomorrow\Chief\Management\Register of property $registration.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
45
46
        // Upon instantiation, a general model is set that doesn't point to a persisted record.
47 167
        $this->manage(app($this->registration->model()));
48
49
        // Check if key and model are present since the model should be set by the manager itself
50 167
        $this->validateConstraints();
51
52 167
        static::bootTraitMethods();
53 167
    }
54
55 167
    public function manage($model): Manager
56
    {
57 167
        $this->model = $model;
58
59 167
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Thinktomorrow\Chief\Management\AbstractManager which is incompatible with the type-hinted return Thinktomorrow\Chief\Management\Manager.
Loading history...
60
    }
61
62 96
    public function findManaged($id): Manager
63
    {
64 96
        $model = $this->registration->model();
0 ignored issues
show
Bug introduced by
The method model() does not exist on Thinktomorrow\Chief\Management\Register. ( Ignorable by Annotation )

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

64
        /** @scrutinizer ignore-call */ 
65
        $model = $this->registration->model();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
66 96
        $modelInstance = $model::where('id', $id)->withoutGlobalScopes()->first();
67
68 96
        return (new static($this->registration))->manage($modelInstance);
0 ignored issues
show
Bug introduced by
$this->registration of type Thinktomorrow\Chief\Management\Register is incompatible with the type Thinktomorrow\Chief\Management\Registration expected by parameter $registration of Thinktomorrow\Chief\Mana...tManager::__construct(). ( Ignorable by Annotation )

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

68
        return (new static(/** @scrutinizer ignore-type */ $this->registration))->manage($modelInstance);
Loading history...
69
    }
70
71 6
    public function indexCollection()
72
    {
73 6
        $model = $this->registration->model();
74
75 6
        $builder = (new $model)->query();
76
77 6
        $this->filters()->apply($builder);
78
79 6
        $builder = $this->indexBuilder($builder);
80
81 6
        $builder = $this->indexSorting($builder);
82
83 6
        if ($this->paginated) {
84 6
            return $this->indexPagination($builder);
85
        }
86
87
        return $builder->get()->map(function ($model) {
88
            return (new static($this->registration))->manage($model);
0 ignored issues
show
Bug introduced by
$this->registration of type Thinktomorrow\Chief\Management\Register is incompatible with the type Thinktomorrow\Chief\Management\Registration expected by parameter $registration of Thinktomorrow\Chief\Mana...tManager::__construct(). ( Ignorable by Annotation )

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

88
            return (new static(/** @scrutinizer ignore-type */ $this->registration))->manage($model);
Loading history...
89
        });
90
    }
91
92 6
    protected function indexBuilder(Builder $builder): Builder
93
    {
94 6
        return $builder;
95
    }
96
97 6
    protected function indexSorting(Builder $builder): Builder
98
    {
99 6
        if ($this->isAssistedBy('publish')) {
100 3
            $builder->orderBy('published', 'DESC');
101
        }
102
103
        // if model has no timestamps, updated_at doesn't exist
104 6
        if ($this->model()->timestamps) {
105 6
            $builder->orderBy('updated_at', 'DESC');
106
        }
107
108 6
        return $builder;
109
    }
110
111 6
    protected function indexPagination($builder): Paginator
112
    {
113 6
        $paginator = $builder->paginate($this->pageCount);
114
115
        $modifiedCollection = $builder->paginate($this->pageCount)->getCollection()->transform(function ($model) {
116 4
            return (new static($this->registration))->manage($model);
0 ignored issues
show
Bug introduced by
$this->registration of type Thinktomorrow\Chief\Management\Register is incompatible with the type Thinktomorrow\Chief\Management\Registration expected by parameter $registration of Thinktomorrow\Chief\Mana...tManager::__construct(). ( Ignorable by Annotation )

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

116
            return (new static(/** @scrutinizer ignore-type */ $this->registration))->manage($model);
Loading history...
117 6
        });
118
119 6
        return $paginator->setCollection($modifiedCollection);
120
    }
121
122 105
    public function model()
123
    {
124 105
        return $this->model;
125
    }
126
127 105
    public function hasExistingModel(): bool
128
    {
129 105
        return ($this->model && $this->model->exists);
130
    }
131
132
    /**
133
     * If the model exists return it otherwise
134
     * throws a nonExistingRecord exception;
135
     *
136
     * @throws NonExistingRecord
137
     */
138 105
    protected function existingModel()
139
    {
140 105
        if (!$this->hasExistingModel()) {
141 1
            throw new NonExistingRecord('Model does not exist yet but is expected.');
142
        }
143
144 104
        return $this->model;
145
    }
146
147
    /**
148
     * Determine which actions should be available for this
149
     * manager and their respective routed urls.
150
     *
151
     * @param $verb
152
     * @return null|string
153
     * @throws NonExistingRecord
154
     */
155 128
    public function route($verb): ?string
156
    {
157
        $routes = [
158 128
            'index'   => route('chief.back.managers.index', [$this->registration->key()]),
0 ignored issues
show
Bug introduced by
The method key() does not exist on Thinktomorrow\Chief\Management\Register. ( Ignorable by Annotation )

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

158
            'index'   => route('chief.back.managers.index', [$this->registration->/** @scrutinizer ignore-call */ key()]),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159 128
            'create'  => route('chief.back.managers.create', [$this->registration->key()]),
160 128
            'store'   => route('chief.back.managers.store', [$this->registration->key()]),
161
        ];
162
163 128
        if (array_key_exists($verb, $routes)) {
164 74
            return $routes[$verb] ?? null;
165
        }
166
167
        //These routes expect the model to be persisted in the database
168
        $modelRoutes = [
169 105
            'edit'    => route('chief.back.managers.edit', [$this->registration->key(), $this->existingModel()->id]),
170 104
            'update'  => route('chief.back.managers.update', [$this->registration->key(), $this->existingModel()->id]),
171 104
            'delete'  => route('chief.back.managers.delete', [$this->registration->key(), $this->existingModel()->id]),
172 104
            'upload'  => route('chief.back.managers.media.upload', [$this->registration->key(), $this->existingModel()->id]),
173
        ];
174
175 104
        return $modelRoutes[$verb] ?? null;
176
    }
177
178 138
    public function can($verb): bool
179
    {
180 138
        foreach (static::$bootedTraitMethods['can'] as $method) {
181 8
            if (!method_exists($this, $method)) {
182
                continue;
183
            }
184 8
            $this->$method($verb);
185
        }
186
187 134
        return !is_null($this->route($verb));
188
    }
189
190 124
    public function guard($verb): Manager
191
    {
192 124
        if (! $this->can($verb)) {
193 5
            NotAllowedManagerRoute::notAllowedVerb($verb, $this);
194
        }
195
196 119
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Thinktomorrow\Chief\Management\AbstractManager which is incompatible with the type-hinted return Thinktomorrow\Chief\Management\Manager.
Loading history...
197
    }
198
199 87
    public function fields(): Fields
200
    {
201 87
        return new Fields();
202
    }
203
204
    /**
205
     * Enrich the manager fields with any of the assistant specified fields
206
     *
207
     * @return Fields
208
     * @throws \Exception
209
     */
210 110
    public function fieldsWithAssistantFields(): Fields
211
    {
212 110
        $fields = $this->fields();
213
214 110
        foreach ($this->assistants() as $assistant) {
215 84
            if (! method_exists($assistant, 'fields')) {
216 82
                continue;
217
            }
218
219 84
            $fields = $fields->merge($assistant->fields());
220
        }
221
222 110
        return $fields;
223
    }
224
225
    /**
226
     * This determines the arrangement of the manageable fields
227
     * on the create and edit forms. By default, all fields
228
     * are presented in their order of appearance
229
     *
230
     * @param null $key pinpoint to a specific field arrangement e.g. for create page.
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $key is correct as it would always require null to be passed?
Loading history...
231
     * @return FieldArrangement
232
     * @throws \Exception
233
     */
234 3
    public function fieldArrangement($key = null): FieldArrangement
235
    {
236 3
        return new FieldArrangement($this->fieldsWithAssistantFields());
237
    }
238
239 1
    public function delete()
240
    {
241 1
        $this->model->delete();
0 ignored issues
show
Bug introduced by
The method delete() does not exist on Illuminate\Contracts\Foundation\Application. ( Ignorable by Annotation )

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

241
        $this->model->/** @scrutinizer ignore-call */ 
242
                      delete();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
242 1
    }
243
244 3
    public static function filters(): Filters
245
    {
246 3
        return new Filters();
247
    }
248
249
    /**
250
     * This method can be used to manipulate the store request payload
251
     * before being passed to the storing / updating the models.
252
     *
253
     * @param Request $request
254
     * @return Request
255
     */
256 26
    public function storeRequest(Request $request): Request
257
    {
258 26
        return $request;
259
    }
260
261
    /**
262
     * This method can be used to manipulate the update request payload
263
     * before being passed to the storing / updating the models.
264
     *
265
     * @param Request $request
266
     * @return Request
267
     */
268 24
    public function updateRequest(Request $request): Request
269
    {
270 24
        return $request;
271
    }
272
273 83
    protected function requestContainsTranslations(Request $request): bool
274
    {
275 83
        return $request->has('trans');
276
    }
277
278 167
    protected function validateConstraints()
279
    {
280 167
        if (!$this->model) {
281
            throw new \DomainException('Model class should be set for this manager. Please set the model property default via the constructor or by extending the setupDefaults method.');
282
        }
283 167
    }
284
285 167
    public static function bootTraitMethods()
286
    {
287 167
        $class = static::class;
288
289
        $methods = [
290 167
            'can'
291
        ];
292
293 167
        foreach ($methods as $baseMethod) {
294 167
            static::$bootedTraitMethods[$baseMethod] = [];
295
296 167
            foreach (class_uses_recursive($class) as $trait) {
297 167
                $method = class_basename($trait) . ucfirst($baseMethod);
298
299 167
                if (method_exists($class, $method) && ! in_array($method, static::$bootedTraitMethods[$baseMethod])) {
300 167
                    static::$bootedTraitMethods[$baseMethod][] = lcfirst($method);
301
                }
302
            }
303
        }
304 167
    }
305
}
306