Passed
Push — ft/states ( 728e57...af2f8a )
by Ben
08:47
created

PageManager::__construct()   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
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace Thinktomorrow\Chief\Pages;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Str;
7
use Thinktomorrow\Chief\Audit\Audit;
8
use Thinktomorrow\Chief\Modules\Module;
9
use Thinktomorrow\Chief\States\PageStatePresenter;
10
use Thinktomorrow\Chief\Concerns\Morphable\MorphableContract;
11
use Thinktomorrow\Chief\Fields\Fields;
12
use Thinktomorrow\Chief\Filters\Filters;
13
use Thinktomorrow\Chief\Fields\FieldsTab;
14
use Thinktomorrow\Chief\Management\Manager;
15
use Thinktomorrow\Chief\Fields\Types\TextField;
16
use Thinktomorrow\Chief\Fields\FieldArrangement;
17
use Thinktomorrow\Chief\Fields\Types\InputField;
18
use Thinktomorrow\Chief\Fields\Types\MediaField;
19
use Thinktomorrow\Chief\Management\Registration;
20
use Thinktomorrow\Chief\Fields\RemainingFieldsTab;
21
use Thinktomorrow\Chief\Management\AbstractManager;
22
use Thinktomorrow\Chief\Management\Assistants\ArchiveAssistant;
23
use Thinktomorrow\Chief\Management\Assistants\PublishAssistant;
24
use Thinktomorrow\Chief\Management\Assistants\UrlAssistant;
25
use Thinktomorrow\Chief\Management\Details\Details;
26
use Thinktomorrow\Chief\Pages\Application\DeletePage;
27
use Thinktomorrow\Chief\Management\Exceptions\DeleteAborted;
28
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
29
use Thinktomorrow\Chief\Urls\UrlSlugFields;
30
31
class PageManager extends AbstractManager implements Manager
32
{
33
    /** @var PageBuilderField */
0 ignored issues
show
Bug introduced by
The type Thinktomorrow\Chief\Pages\PageBuilderField 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...
34
    private $pageBuilderField;
35
36
    protected $assistants = [
37
        'url'     => UrlAssistant::class,
38
        'archive' => ArchiveAssistant::class,
39
        'publish' => PublishAssistant::class,
40
    ];
41
42 110
    public function can($verb): bool
43
    {
44 110
        try {
45 110
            $this->authorize($verb);
46
47 94
            return parent::can($verb);
48
        } catch (NotAllowedManagerRoute $e) {
49
            return false;
50 94
        }
51
    }
52 93
53 3
    /**
54 3
     * @param $verb
55
     * @throws NotAllowedManagerRoute
56
     */
57
    private function authorize($verb)
58
    {
59
        $permission = 'update-page';
60
61
        if (in_array($verb, ['index','show'])) {
62 94
            $permission = 'view-page';
63
        } elseif (in_array($verb, ['create','store'])) {
64 94
            $permission = 'create-page';
65
        } elseif (in_array($verb, ['delete'])) {
66 94
            $permission = 'delete-page';
67 24
        }
68 76
69 22
        if (! auth()->guard('chief')->user()->hasPermissionTo($permission)) {
0 ignored issues
show
Bug introduced by
The method hasPermissionTo() does not exist on Illuminate\Contracts\Auth\Authenticatable. It seems like you code against a sub-type of Illuminate\Contracts\Auth\Authenticatable such as Illuminate\Foundation\Auth\User. ( Ignorable by Annotation )

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

69
        if (! auth()->guard('chief')->user()->/** @scrutinizer ignore-call */ hasPermissionTo($permission)) {
Loading history...
70 71
            throw NotAllowedManagerRoute::notAllowedPermission($permission, $this);
71 12
        }
72
    }
73
74 94
    /**
75 1
     * The set of fields that should be manageable for a certain model.
76
     *
77 93
     * Additionally, you should:
78
     * 1. Make sure to setup the proper migrations and
79
     * 2. For a translatable field you should add this field to the $translatedAttributes property of the model as well.
80
     *
81
     * @return Fields
82
     */
83
    public function fields(): Fields
84
    {
85
        return parent::fields()->add(
86
            $this->pageBuilderField(),
87
            InputField::make('title')->translatable($this->model->availableLocales())
0 ignored issues
show
Bug introduced by
It seems like Thinktomorrow\Chief\Fiel...erzichten en modules.') can also be of type null; however, parameter $fields of Thinktomorrow\Chief\Fields\Fields::add() does only seem to accept Thinktomorrow\Chief\Fields\Types\Field, 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

87
            /** @scrutinizer ignore-type */ InputField::make('title')->translatable($this->model->availableLocales())
Loading history...
88 49
                                     ->validation('required-fallback-locale|max:200', [], [
89
                                         'trans.'.config('app.fallback_locale', 'nl').'.title' => 'title',
90 49
                                     ])
91 49
                                     ->label('De titel van je '.$this->model->labelSingular ?? 'pagina')
0 ignored issues
show
Bug introduced by
The method label() does not exist on Thinktomorrow\Chief\Fields\Types\InputField. 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

91
                                     ->/** @scrutinizer ignore-call */ label('De titel van je '.$this->model->labelSingular ?? 'pagina')
Loading history...
92 49
                                     ->description('Dit is de titel die zal worden getoond in de overzichten en modules.'),
0 ignored issues
show
Bug introduced by
The method description() does not exist on Thinktomorrow\Chief\Fields\Types\InputField. 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

92
                                     ->/** @scrutinizer ignore-call */ description('Dit is de titel die zal worden getoond in de overzichten en modules.'),
Loading history...
93 49
            InputField::make('seo_title')
94 49
                ->translatable($this->model->availableLocales())
95
                ->label('Zoekmachine titel'),
96 49
            TextField::make('seo_description')
97 49
                ->translatable($this->model->availableLocales())
98 49
                ->label('Zoekmachine omschrijving')
0 ignored issues
show
Bug introduced by
The method label() does not exist on Thinktomorrow\Chief\Fields\Types\TextField. 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

98
                ->/** @scrutinizer ignore-call */ label('Zoekmachine omschrijving')
Loading history...
99 49
                ->description('omschrijving van de pagina zoals in search engines (o.a. google) wordt weergegeven.'),
0 ignored issues
show
Bug introduced by
The method description() does not exist on Thinktomorrow\Chief\Fields\Types\TextField. 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

99
                ->/** @scrutinizer ignore-call */ description('omschrijving van de pagina zoals in search engines (o.a. google) wordt weergegeven.'),
Loading history...
100 49
            InputField::make('seo_keywords')
101 49
                ->validation('max:250')
102 49
                ->translatable($this->model->availableLocales())
103 49
                ->label('Zoekmachine sleutelwoorden')
104 49
                ->description('sleutelwoorden van de pagina waarop in search engines (o.a google) gezocht kan worden.'),
105 49
            MediaField::make('seo_image')
106 49
                ->translatable($this->model->availableLocales())
107 49
                ->label('Zoekmachine foto')
0 ignored issues
show
Bug introduced by
The method label() does not exist on Thinktomorrow\Chief\Fields\Types\MediaField. 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

107
                ->/** @scrutinizer ignore-call */ label('Zoekmachine foto')
Loading history...
108 49
                ->description('foto die bij het delen van deze pagina getoond wordt. De ideale afmetingen zijn 1200px breed op 627px hoog.')
0 ignored issues
show
Bug introduced by
The method description() does not exist on Thinktomorrow\Chief\Fields\Types\MediaField. 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

108
                ->/** @scrutinizer ignore-call */ description('foto die bij het delen van deze pagina getoond wordt. De ideale afmetingen zijn 1200px breed op 627px hoog.')
Loading history...
109 49
        );
110 49
    }
111 49
112 49
    public static function filters(): Filters
113 49
    {
114
        return new Filters([
115
            PublishedFilter::class
116
        ]);
117 3
    }
118
119 3
    private function pageBuilderField()
120 3
    {
121
        if ($this->pageBuilderField) {
122
            return $this->pageBuilderField;
123
        }
124 49
125
        return $this->pageBuilderField = $this->createPagebuilderField();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createPagebuilderField() of type Thinktomorrow\Chief\Fields\Types\PagebuilderField is incompatible with the declared type Thinktomorrow\Chief\Pages\PageBuilderField of property $pageBuilderField.

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...
126 49
    }
127 42
128
    public function fieldArrangement($key = null): FieldArrangement
129
    {
130 49
        if ($key == 'create') {
131
            return new FieldArrangement($this->fieldsWithAssistantFields()->filterBy(function ($field) {
132
                return in_array($field->key, ['title']);
133 3
            }));
134
        }
135 3
136
        $tabs = [
137 1
            new FieldsTab('pagina', ['sections']),
138 1
            new RemainingFieldsTab('algemeen'),
139
            new FieldsTab('url', ['url-slugs'], 'chief::back.pages._partials.url', [
140
                'redirects' =>  UrlSlugFields::redirectsFromModel($this->model),
141
            ]),
142 2
            new FieldsTab('seo', ['seo_title', 'seo_description', 'seo_keywords', 'seo_image']),
143 2
        ];
144 2
145 2
        if (Module::anyAvailableForCreation()) {
146
            array_splice($tabs, 1, 0, [new FieldsTab('modules', [], 'chief::back.pages._partials.modules')]);
147 2
        }
148
149
        return new FieldArrangement($this->fieldsWithAssistantFields(), $tabs);
150 2
    }
151 1
152
    public function details(): Details
153
    {
154 2
        // For existing model
155
        if ($this->model && $this->model->id) {
156
            return parent::details()
157 98
                ->set('title', $this->model->title ? ucfirst($this->model->title) : '')
158
                ->set('intro', PageStatePresenter::fromModel($this->model)->label())
159
                ->set('context', '');
160 98
        }
161 77
162 77
        return parent::details();
163 77
    }
164 77
165
    public function saveFields(Request $request)
166
    {
167 26
        // Store the morph_key upon creation
168
        if ($this->model instanceof MorphableContract && ! $this->model->morph_key) {
0 ignored issues
show
Bug introduced by
Accessing morph_key on the interface Thinktomorrow\Chief\Conc...hable\MorphableContract suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
169
            $this->model->morph_key = $this->model->morphKey();
170 59
        }
171
172
        parent::saveFields($request);
173 59
    }
174 16
175
    public function delete()
176
    {
177 59
        $this->guard('delete');
178 57
179
        if (request()->get('deleteconfirmation') !== 'DELETE') {
180 9
            throw new DeleteAborted();
181
        }
182 9
183
        app(DeletePage::class)->handle($this->model->id);
184 9
    }
185 3
186
    public function storeRequest(Request $request): Request
187
    {
188 6
        $trans = [];
189 6
        $urls = $request->get('url-slugs', []);
190
191 18
        foreach ($request->get('trans', []) as $locale => $translation) {
192
            if (is_array_empty($translation)) {
193 18
                continue;
194 18
            }
195
196 18
            $trans[$locale] = $this->addDefaultShortDescription($translation);
197 17
198 1
            // Automatically add an url for this locale based on the given title
199
            if (!isset($urls[$locale]) && isset($translation['title'])) {
200
                $urls[$locale] = Str::slug($translation['title']);
201 17
            }
202
        }
203
204 17
        // Merge with request...
205 17
        return $request->merge(['trans' => $trans, 'url-slugs' => $urls]);
206
    }
207
208
    public function updateRequest(Request $request): Request
209
    {
210 18
        $trans = [];
211
        foreach ($request->get('trans', []) as $locale => $translation) {
212
            if (is_array_empty($translation)) {
213 48
214
                // Nullify all values
215 48
                $trans[$locale] = array_map(function ($value) {
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

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

215
                $trans[$locale] = array_map(function (/** @scrutinizer ignore-unused */ $value) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
216 48
                    return null;
217 47
                }, $translation);
218
                continue;
219
            }
220
221 2
            $trans[$locale] = $this->addDefaultShortDescription($translation);
222 2
        }
223 2
224
        // Merge with request...
225
        return $request->merge(['trans' => $trans]);
226 47
    }
227
228
    public function afterStore($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

228
    public function afterStore(/** @scrutinizer ignore-unused */ $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
229
    {
230 48
        Audit::activity()
231
            ->performedOn($this->model)
232
            ->log('created');
233 16
    }
234
235 16
    public function afterUpdate($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

235
    public function afterUpdate(/** @scrutinizer ignore-unused */ $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
236 16
    {
237 16
        Audit::activity()
238 16
            ->performedOn($this->model)
239
            ->log('edited');
240 44
    }
241
242 44
    /**
243 44
     * @param array $translation
244 44
     * @return array
245 44
     */
246
    private function addDefaultShortDescription(array $translation): array
247
    {
248
        if (isset($translation['content'])) {
249
            $translation['short'] = $translation['short'] ?? teaser($translation['content'], 100);
250
        }
251 61
252
        return $translation;
253 61
    }
254
}
255