Passed
Push — master ( 72cb54...ce8977 )
by Philippe
02:38 queued 14s
created

PageManager::updateRequest()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 18
ccs 9
cts 9
cp 1
rs 9.9666
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Thinktomorrow\Chief\Pages;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Http\Request;
7
use Thinktomorrow\Chief\Audit\Audit;
8
use Thinktomorrow\Chief\Fields\Fields;
9
use Thinktomorrow\Chief\Modules\Module;
10
use Thinktomorrow\Chief\Filters\Filters;
11
use Thinktomorrow\Chief\Fields\FieldsTab;
12
use Thinktomorrow\Chief\Management\Manager;
13
use Thinktomorrow\Chief\Urls\UrlSlugFields;
14
use Thinktomorrow\Chief\Fields\Types\TextField;
15
use Thinktomorrow\Chief\Fields\FieldArrangement;
16
use Thinktomorrow\Chief\Fields\Types\InputField;
17
use Thinktomorrow\Chief\Fields\Types\MediaField;
18
use Thinktomorrow\Chief\Management\Registration;
19
use Thinktomorrow\Chief\Fields\RemainingFieldsTab;
20
use Thinktomorrow\Chief\Management\AbstractManager;
21
use Thinktomorrow\Chief\Management\Details\Details;
22
use Thinktomorrow\Chief\Pages\Application\DeletePage;
23
use Thinktomorrow\Chief\Management\Assistants\UrlAssistant;
24
use Thinktomorrow\Chief\Management\Exceptions\DeleteAborted;
25
use Thinktomorrow\Chief\Concerns\Morphable\MorphableContract;
26
use Thinktomorrow\Chief\Management\Assistants\ArchiveAssistant;
27
use Thinktomorrow\Chief\Management\Assistants\PublishAssistant;
28
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
29
30
class PageManager extends AbstractManager implements Manager
31
{
32
    /** @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...
33
    private $pageBuilderField;
34
35
    protected $assistants = [
36
        'url'     => UrlAssistant::class,
37
        'archive' => ArchiveAssistant::class,
38
        'publish' => PublishAssistant::class,
39
    ];
40
41 91
    public function __construct(Registration $registration)
42
    {
43 91
        parent::__construct($registration);
44 91
    }
45
46 83
    public function can($verb): bool
47
    {
48
        try {
49 83
            $this->authorize($verb);
50
51 82
            return parent::can($verb);
52 3
        } catch (NotAllowedManagerRoute $e) {
53 3
            return false;
54
        }
55
    }
56
57
    /**
58
     * @param $verb
59
     * @throws NotAllowedManagerRoute
60
     */
61 83
    private function authorize($verb)
62
    {
63 83
        $permission = 'update-page';
64
65 83
        if (in_array($verb, ['index','show'])) {
66 23
            $permission = 'view-page';
67 65
        } elseif (in_array($verb, ['create','store'])) {
68 22
            $permission = 'create-page';
69 60
        } elseif (in_array($verb, ['delete'])) {
70 6
            $permission = 'delete-page';
71
        }
72
        
73 83
        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

73
        if (! auth()->guard('chief')->user()->/** @scrutinizer ignore-call */ hasPermissionTo($permission)) {
Loading history...
74 1
            throw NotAllowedManagerRoute::notAllowedPermission($permission, $this);
75
        }
76 82
    }
77
78
    /**
79
     * The set of fields that should be manageable for a certain model.
80
     *
81
     * Additionally, you should:
82
     * 1. Make sure to setup the proper migrations and
83
     * 2. For a translatable field you should add this field to the $translatedAttributes property of the model as well.
84
     *
85
     * @return Fields
86
     */
87 49
    public function fields(): Fields
88
    {
89 49
        return parent::fields()->add(
90 49
            $this->pageBuilderField(),
91 49
            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

91
            /** @scrutinizer ignore-type */ InputField::make('title')->translatable($this->model->availableLocales())
Loading history...
92 49
                                     ->validation('required-fallback-locale|max:200', [], [
93 49
                                         'trans.'.config('app.fallback_locale', 'nl').'.title' => 'title',
94
                                     ])
95 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

95
                                     ->/** @scrutinizer ignore-call */ label('De titel van je '.$this->model->labelSingular ?? 'pagina')
Loading history...
96 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

96
                                     ->/** @scrutinizer ignore-call */ description('Dit is de titel die zal worden getoond in de overzichten en modules.'),
Loading history...
97 49
            InputField::make('seo_title')
98 49
                ->translatable($this->model->availableLocales())
99 49
                ->label('Zoekmachine titel'),
100 49
            TextField::make('seo_description')
101 49
                ->translatable($this->model->availableLocales())
102 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

102
                ->/** @scrutinizer ignore-call */ label('Zoekmachine omschrijving')
Loading history...
103 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

103
                ->/** @scrutinizer ignore-call */ description('omschrijving van de pagina zoals in search engines (o.a. google) wordt weergegeven.'),
Loading history...
104 49
            InputField::make('seo_keywords')
105 49
                ->validation('max:250')
106 49
                ->translatable($this->model->availableLocales())
107 49
                ->label('Zoekmachine sleutelwoorden')
108 49
                ->description('sleutelwoorden van de pagina waarop in search engines (o.a google) gezocht kan worden.'),
109 49
            MediaField::make('seo_image')
110 49
                ->translatable($this->model->availableLocales())
111 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

111
                ->/** @scrutinizer ignore-call */ label('Zoekmachine foto')
Loading history...
112 49
                ->description('foto die bij het delen van deze pagina getoont word. (afmeting: 1200x627px)')
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

112
                ->/** @scrutinizer ignore-call */ description('foto die bij het delen van deze pagina getoont word. (afmeting: 1200x627px)')
Loading history...
113
        );
114
    }
115
116 3
    public static function filters(): Filters
117
    {
118 3
        return new Filters([
119 3
            PublishedFilter::class
120
        ]);
121
    }
122
123 49
    private function pageBuilderField()
124
    {
125 49
        if ($this->pageBuilderField) {
126 42
            return $this->pageBuilderField;
127
        }
128
129 49
        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...
130
    }
131
132 2
    public function fieldArrangement($key = null): FieldArrangement
133
    {
134 2
        if ($key == 'create') {
135
            return new FieldArrangement($this->fieldsWithAssistantFields()->filterBy(function ($field) {
136 1
                return in_array($field->key, ['title']);
137 1
            }));
138
        }
139
140
        $tabs = [
141 1
            new FieldsTab('pagina', ['sections']),
142 1
            new RemainingFieldsTab('algemeen'),
143 1
            new FieldsTab('url', ['url-slugs'], 'chief::back.pages._partials.url', [
144 1
                'redirects' =>  UrlSlugFields::redirectsFromModel($this->model),
145
            ]),
146 1
            new FieldsTab('seo', ['seo_title', 'seo_description', 'seo_keywords', 'seo_image']),
147
        ];
148 1
        if (Module::atLeastOneRegistered()) {
149 1
            array_splice($tabs, 1, 0, [new FieldsTab('modules', [], 'chief::back.pages._partials.modules')]);
150
        }
151
152 1
        return new FieldArrangement($this->fieldsWithAssistantFields(), $tabs);
153
    }
154
155 85
    public function details(): Details
156
    {
157
        // For existing model
158 85
        if ($this->model->id) {
159 64
            return parent::details()
160 64
                ->set('title', ucfirst($this->model->title))
161 64
                ->set('intro', 'Aangepast ' . $this->model->updated_at->format('d/m/Y H:i'))
162 64
                ->set('context', '<span class="inline-xs stack-s">' . $this->assistant('publish')->publicationStatusAsLabel() . '</span>');
0 ignored issues
show
Bug introduced by
The method publicationStatusAsLabel() does not exist on Thinktomorrow\Chief\Mana...nt\Assistants\Assistant. It seems like you code against a sub-type of Thinktomorrow\Chief\Mana...nt\Assistants\Assistant such as Thinktomorrow\Chief\Mana...stants\PublishAssistant. ( Ignorable by Annotation )

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

162
                ->set('context', '<span class="inline-xs stack-s">' . $this->assistant('publish')->/** @scrutinizer ignore-call */ publicationStatusAsLabel() . '</span>');
Loading history...
163
        }
164
165 25
        return parent::details();
166
    }
167
168 51
    public function saveFields(Request $request)
169
    {
170
        // Store the morph_key upon creation
171 51
        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...
172 16
            $this->model->morph_key = $this->model->morphKey();
173
        }
174
175 51
        parent::saveFields($request);
176 51
    }
177
178 6
    public function delete()
179
    {
180 6
        if (request()->get('deleteconfirmation') !== 'DELETE') {
181 1
            throw new DeleteAborted();
182
        }
183
184 5
        app(DeletePage::class)->handle($this->model->id);
185 5
    }
186
187 18
    public function storeRequest(Request $request): Request
188
    {
189 18
        $trans = [];
190 18
        $urls = $request->get('url-slugs', []);
191
192 18
        foreach ($request->get('trans', []) as $locale => $translation) {
193 17
            if (is_array_empty($translation)) {
194 1
                continue;
195
            }
196
197 17
            $trans[$locale] = $this->addDefaultShortDescription($translation);
198
199
            // Automatically add an url for this locale based on the given title
200 17
            if (!isset($urls[$locale]) && isset($translation['title'])) {
201 17
                $urls[$locale] = Str::slug($translation['title']);
202
            }
203
        }
204
205
        // Merge with request...
206 18
        return $request->merge(['trans' => $trans, 'url-slugs' => $urls]);
207
    }
208
209 40
    public function updateRequest(Request $request): Request
210
    {
211 40
        $trans = [];
212 40
        foreach ($request->get('trans', []) as $locale => $translation) {
213 39
            if (is_array_empty($translation)) {
214
215
                // Nullify all values
216
                $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

216
                $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...
217 2
                    return null;
218 2
                }, $translation);
219 2
                continue;
220
            }
221
222 39
            $trans[$locale] = $this->addDefaultShortDescription($translation);
223
        }
224
225
        // Merge with request...
226 40
        return $request->merge(['trans' => $trans]);
227
    }
228
229 16
    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

229
    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...
230
    {
231 16
        Audit::activity()
232 16
            ->performedOn($this->model)
233 16
            ->log('created');
234 16
    }
235
236 38
    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

236
    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...
237
    {
238 38
        Audit::activity()
239 38
            ->performedOn($this->model)
240 38
            ->log('edited');
241 38
    }
242
243
    /**
244
     * @param array $translation
245
     * @return array
246
     */
247 53
    private function addDefaultShortDescription(array $translation): array
248
    {
249 53
        if (isset($translation['content'])) {
250 1
            $translation['short'] = $translation['short'] ?? teaser($translation['content'], 100);
251
        }
252
253 53
        return $translation;
254
    }
255
}
256