Completed
Pull Request — master (#274)
by
unknown
63:55 queued 33:13
created

AbstractManager   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Test Coverage

Coverage 95.89%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 29
eloc 66
c 2
b 0
f 0
dl 0
loc 222
ccs 70
cts 73
cp 0.9589
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A findManaged() 0 7 1
A manage() 0 5 1
A updateRequest() 0 3 1
A hasExistingModel() 0 3 2
A fieldsWithAssistantFields() 0 13 3
A guard() 0 7 2
A route() 0 21 2
A storeRequest() 0 3 1
A validateConstraints() 0 4 2
A can() 0 3 1
A delete() 0 3 1
A model() 0 3 1
A filters() 0 3 1
A findAllManaged() 0 21 4
A fieldArrangement() 0 3 1
A fields() 0 3 1
A existingModel() 0 7 2
A requestContainsTranslations() 0 3 1
1
<?php
2
3
namespace Thinktomorrow\Chief\Management;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Collection;
7
use Thinktomorrow\Chief\Concerns\Translatable\TranslatableCommand;
8
use Thinktomorrow\Chief\Fields\FieldArrangement;
9
use Thinktomorrow\Chief\Fields\Fields;
10
use Thinktomorrow\Chief\Fields\RenderingFields;
11
use Thinktomorrow\Chief\Fields\SavingFields;
12
use Thinktomorrow\Chief\Filters\Filters;
13
use Thinktomorrow\Chief\Management\Assistants\AssistedManager;
14
use Thinktomorrow\Chief\Management\Details\HasDetails;
15
use Thinktomorrow\Chief\Management\Details\HasSections;
16
use Thinktomorrow\Chief\Management\Exceptions\NonExistingRecord;
17
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
18
19
abstract class AbstractManager
20
{
21
    use RenderingFields,
0 ignored issues
show
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...
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...
Bug introduced by
The trait Thinktomorrow\Chief\Fields\SavingFields requires the property $key which is not provided by Thinktomorrow\Chief\Management\AbstractManager.
Loading history...
22
        SavingFields,
23
        HasDetails,
24
        HasSections,
25
        ManagesMedia,
26
        ManagesPagebuilder,
27
        TranslatableCommand,
28
        AssistedManager;
29
30
    protected $translation_columns = [];
31
32
    protected $model;
33
34
    /** @var Register */
35
    protected $registration;
36
37 149
    public function __construct(Registration $registration)
38
    {
39 149
        $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...
40
41
        // Upon instantiation, a general model is set that doesn't point to a persisted record.
42 149
        $this->manage(app($this->registration->model()));
43
44
        // Check if key and model are present since the model should be set by the manager itself
45 149
        $this->validateConstraints();
46 149
    }
47
48 149
    public function manage($model): Manager
49
    {
50 149
        $this->model = $model;
51
52 149
        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...
53
    }
54
55 85
    public function findManaged($id): Manager
56
    {
57 85
        $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

57
        /** @scrutinizer ignore-call */ 
58
        $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...
58
59 85
        $modelInstance = $model::where('id', $id)->withoutGlobalScopes()->first();
60
61 85
        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

61
        return (new static(/** @scrutinizer ignore-type */ $this->registration))->manage($modelInstance);
Loading history...
62
    }
63
64 1
    public function findAllManaged($apply_filters = false): Collection
65
    {
66 1
        $model = $this->registration->model();
67
68 1
        $builder = (new $model)->query();
69
70 1
        if ($apply_filters) {
71 1
            $this->filters()->apply($builder);
72
        }
73
74 1
        if ($this->isAssistedBy('publish')) {
75 1
            $builder->orderBy('published', 'DESC');
76
        }
77
78
        // if model has no timestamps, updated_at doesn't exist
79 1
        if ($this->model()->timestamps) {
80 1
            $builder->orderBy('updated_at', 'DESC');
81
        }
82
83
        return $builder->get()->map(function ($model) {
84 1
            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

84
            return (new static(/** @scrutinizer ignore-type */ $this->registration))->manage($model);
Loading history...
85 1
        });
86
    }
87
88 90
    public function model()
89
    {
90 90
        return $this->model;
91
    }
92
93 94
    public function hasExistingModel(): bool
94
    {
95 94
        return ($this->model && $this->model->exists);
96
    }
97
98
    /**
99
     * If the model exists return it otherwise
100
     * throws a nonExistingRecord exception;
101
     *
102
     * @throws NonExistingRecord
103
     */
104 94
    protected function existingModel()
105
    {
106 94
        if (!$this->hasExistingModel()) {
107 1
            throw new NonExistingRecord('Model does not exist yet but is expected.');
108
        }
109
110 93
        return $this->model;
111
    }
112
113
    /**
114
     * Determine which actions should be available for this
115
     * manager and their respective routed urls.
116
     *
117
     * @param $verb
118
     * @return null|string
119
     * @throws NonExistingRecord
120
     */
121 117
    public function route($verb): ?string
122
    {
123
        $routes = [
124 117
            '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

124
            '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...
125 117
            'create'  => route('chief.back.managers.create', [$this->registration->key()]),
126 117
            'store'   => route('chief.back.managers.store', [$this->registration->key()]),
127
        ];
128
129 117
        if (array_key_exists($verb, $routes)) {
130 68
            return $routes[$verb] ?? null;
131
        }
132
133
        //These routes expect the model to be persisted in the database
134
        $modelRoutes = [
135 94
            'edit'    => route('chief.back.managers.edit', [$this->registration->key(), $this->existingModel()->id]),
136 93
            'update'  => route('chief.back.managers.update', [$this->registration->key(), $this->existingModel()->id]),
137 93
            'delete'  => route('chief.back.managers.delete', [$this->registration->key(), $this->existingModel()->id]),
138 93
            'upload'  => route('chief.back.managers.media.upload', [$this->registration->key(), $this->existingModel()->id]),
139
        ];
140
141 93
        return $modelRoutes[$verb] ?? null;
142
    }
143
144 121
    public function can($verb): bool
145
    {
146 121
        return !is_null($this->route($verb));
147
    }
148
149 107
    public function guard($verb): Manager
150
    {
151 107
        if (! $this->can($verb)) {
152 1
            NotAllowedManagerRoute::notAllowedVerb($verb, $this);
153
        }
154
155 106
        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...
156
    }
157
158 83
    public function fields(): Fields
159
    {
160 83
        return new Fields();
161
    }
162
163
    /**
164
     * Enrich the manager fields with any of the assistant specified fields
165
     *
166
     * @return Fields
167
     * @throws \Exception
168
     */
169 101
    public function fieldsWithAssistantFields(): Fields
170
    {
171 101
        $fields = $this->fields();
172
173 101
        foreach ($this->assistants() as $assistant) {
174 77
            if (! method_exists($assistant, 'fields')) {
175 75
                continue;
176
            }
177
178 77
            $fields = $fields->merge($assistant->fields());
179
        }
180
181 101
        return $fields;
182
    }
183
184
    /**
185
     * This determines the arrangement of the manageable fields
186
     * on the create and edit forms. By default, all fields
187
     * are presented in their order of appearance
188
     *
189
     * @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...
190
     * @return FieldArrangement
191
     * @throws \Exception
192
     */
193 3
    public function fieldArrangement($key = null): FieldArrangement
194
    {
195 3
        return new FieldArrangement($this->fieldsWithAssistantFields());
196
    }
197
198 1
    public function delete()
199
    {
200 1
        $this->model->delete();
201 1
    }
202
203
    public static function filters(): Filters
204
    {
205
        return new Filters();
206
    }
207
208
    /**
209
     * This method can be used to manipulate the store request payload
210
     * before being passed to the storing / updating the models.
211
     *
212
     * @param Request $request
213
     * @return Request
214
     */
215 24
    public function storeRequest(Request $request): Request
216
    {
217 24
        return $request;
218
    }
219
220
    /**
221
     * This method can be used to manipulate the update request payload
222
     * before being passed to the storing / updating the models.
223
     *
224
     * @param Request $request
225
     * @return Request
226
     */
227 22
    public function updateRequest(Request $request): Request
228
    {
229 22
        return $request;
230
    }
231
232 77
    protected function requestContainsTranslations(Request $request): bool
233
    {
234 77
        return $request->has('trans');
235
    }
236
237 149
    protected function validateConstraints()
238
    {
239 149
        if (!$this->model) {
240
            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.');
241
        }
242 149
    }
243
}
244