Passed
Push — ft/pagefield ( db2ad6...f2722b )
by Ben
10:27
created

PageManager::fieldArrangement()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 12
c 2
b 0
f 1
dl 0
loc 22
ccs 12
cts 12
cp 1
rs 9.8666
cc 3
nc 3
nop 1
crap 3

3 Methods

Rating   Name   Duplication   Size   Complexity  
A PageManager::createFields() 0 3 1
A PageManager::editView() 0 3 1
A PageManager::createView() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Thinktomorrow\Chief\Pages;
6
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Str;
9
use Thinktomorrow\Chief\Audit\Audit;
10
use Thinktomorrow\Chief\Fields\Types\HtmlField;
11
use Thinktomorrow\Chief\Fields\Types\SelectField;
12
use Thinktomorrow\Chief\Fragments\FragmentField;
13
use Thinktomorrow\Chief\Fragments\Fragments;
0 ignored issues
show
Bug introduced by
The type Thinktomorrow\Chief\Fragments\Fragments 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...
14
use Thinktomorrow\Chief\Modules\Module;
15
use Thinktomorrow\Chief\Fields\Types\ImageField;
16
use Thinktomorrow\Chief\States\PageStatePresenter;
17
use Thinktomorrow\Chief\Concerns\Morphable\MorphableContract;
18
use Thinktomorrow\Chief\Fields\Fields;
19
use Thinktomorrow\Chief\Filters\Filters;
20
use Thinktomorrow\Chief\Management\Manager;
21
use Thinktomorrow\Chief\Fields\Types\TextField;
22
use Thinktomorrow\Chief\Fields\Types\InputField;
23
use Thinktomorrow\Chief\Management\AbstractManager;
24
use Thinktomorrow\Chief\Management\Assistants\ArchiveAssistant;
25
use Thinktomorrow\Chief\Management\Assistants\PublishAssistant;
26
use Thinktomorrow\Chief\Management\Assistants\UrlAssistant;
27
use Thinktomorrow\Chief\Management\Details\Details;
28
use Thinktomorrow\Chief\Pages\Application\DeletePage;
29
use Thinktomorrow\Chief\Management\Exceptions\DeleteAborted;
30
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
31
use Thinktomorrow\Chief\Urls\UrlSlugFields;
32
33
class PageManager extends AbstractManager implements Manager
34
{
35
    /** @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...
36
    private $pageBuilderField;
37
38
    protected $assistants = [
39
        'url'     => UrlAssistant::class,
40
        'archive' => ArchiveAssistant::class,
41
        'publish' => PublishAssistant::class,
42
    ];
43 118
44
    public function can($verb): bool
45
    {
46 118
        try {
47
            $this->authorize($verb);
48 117
49 3
            return parent::can($verb);
50 3
        } catch (NotAllowedManagerRoute $e) {
51
            return false;
52
        }
53
    }
54
55
    /**
56
     * @param $verb
57
     * @throws NotAllowedManagerRoute
58 118
     */
59
    private function authorize($verb)
60 118
    {
61
        $permission = 'update-page';
62 118
63 25
        if (in_array($verb, ['index', 'show'])) {
64 100
            $permission = 'view-page';
65 22
        } elseif (in_array($verb, ['create', 'store'])) {
66 95
            $permission = 'create-page';
67 11
        } elseif (in_array($verb, ['delete'])) {
68
            $permission = 'delete-page';
69
        }
70 118
71 1
        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

71
        if (!auth()->guard('chief')->user()->/** @scrutinizer ignore-call */ hasPermissionTo($permission)) {
Loading history...
72
            throw NotAllowedManagerRoute::notAllowedPermission($permission, $this);
73 117
        }
74
    }
75
76
    /**
77
     * The set of fields that should be manageable for a certain model.
78
     *
79
     * Additionally, you should:
80
     * 1. Make sure to setup the proper migrations and
81
     * 2. For a translatable field you should add this field to the $translatedAttributes property of the model as well.
82
     *
83
     * @return Fields
84 49
     */
85
    public function fields(): Fields
86 49
    {
87 49
        return parent::fields()->add(
88 49
            $this->pageBuilderField(),
89 49
            InputField::make('title')->translatable($this->model->availableLocales())
0 ignored issues
show
Deprecated Code introduced by
The function Thinktomorrow\Chief\Fiel...ctField::translatable() has been deprecated: use locales(array $locales) instead ( Ignorable by Annotation )

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

89
            /** @scrutinizer ignore-deprecated */ InputField::make('title')->translatable($this->model->availableLocales())

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
90 49
                ->validation('required-fallback-locale|max:200', [], [
91
                    'trans.' . config('app.fallback_locale', 'nl') . '.title' => 'title',
92 49
                ])
93 49
                ->label('Intern label')
94 49
                ->description('Dit is de benaming die zal worden getoond in de admin selectie velden.')
95 49
                ->tag('general'),
96 49
            InputField::make('seo_title')
0 ignored issues
show
Deprecated Code introduced by
The function Thinktomorrow\Chief\Fiel...ctField::translatable() has been deprecated: use locales(array $locales) instead ( Ignorable by Annotation )

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

96
            /** @scrutinizer ignore-deprecated */ InputField::make('seo_title')

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
97 49
                ->translatable($this->model->availableLocales())
98 49
                ->label('Zoekmachine titel')
99 49
                ->tag('seo'),
100 49
            TextField::make('seo_description')
0 ignored issues
show
Deprecated Code introduced by
The function Thinktomorrow\Chief\Fiel...ctField::translatable() has been deprecated: use locales(array $locales) instead ( Ignorable by Annotation )

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

100
            /** @scrutinizer ignore-deprecated */ TextField::make('seo_description')

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
101 49
                ->translatable($this->model->availableLocales())
102 49
                ->label('Zoekmachine omschrijving')
103 49
                ->description('omschrijving van de pagina zoals in search engines (o.a. google) wordt weergegeven.')
104 49
                ->tag('seo'),
105 49
            InputField::make('seo_keywords')
0 ignored issues
show
Deprecated Code introduced by
The function Thinktomorrow\Chief\Fiel...ctField::translatable() has been deprecated: use locales(array $locales) instead ( Ignorable by Annotation )

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

105
            /** @scrutinizer ignore-deprecated */ InputField::make('seo_keywords')

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
106 49
                ->validation('max:250')
107 49
                ->translatable($this->model->availableLocales())
108 49
                ->label('Zoekmachine sleutelwoorden')
109 49
                ->description('sleutelwoorden van de pagina waarop in search engines (o.a google) gezocht kan worden.')
110
                ->tag('seo'),
111
            ImageField::make('seo_image')
0 ignored issues
show
Deprecated Code introduced by
The function Thinktomorrow\Chief\Fiel...ctField::translatable() has been deprecated: use locales(array $locales) instead ( Ignorable by Annotation )

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

111
            /** @scrutinizer ignore-deprecated */ ImageField::make('seo_image')

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
112
                ->translatable($this->model->availableLocales())
113 3
                ->label('Zoekmachine foto')
114
                ->description('foto die bij het delen van deze pagina getoond wordt. De ideale afmetingen zijn 1200px breed op 627px hoog.')
115 3
                ->tag('seo')
116 3
        );
117
    }
118
119
    public static function filters(): Filters
120 49
    {
121
        return new Filters([
122 49
            PublishedFilter::class,
123 40
        ]);
124
    }
125
126 49
    private function pageBuilderField()
127
    {
128
        if ($this->pageBuilderField) {
129 4
            return $this->pageBuilderField;
130
        }
131 4
132
        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...
133 1
    }
134 1
135
    public function createView(): string
136
    {
137
        return 'chief::back.pages._partials._createform';
138 3
    }
139 3
140 3
    public function editView(): string
141 3
    {
142
        return 'chief::back.pages._partials._editform';
143 3
    }
144
145
    public function createFields(): Fields
146 3
    {
147 1
        return $this->fields()->keyed('title');
148
    }
149
150 3
    public function saveCreateFields(Request $request): void
151
    {
152
        // Store the morph_key upon creation
153 108
        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...
154
            $this->model->morph_key = $this->model->morphKey();
155
        }
156 108
157 87
        parent::saveFields($request, $this->createFields()->merge($this->fieldsWithAssistantFields()->keyed('url-slugs')));
158 87
    }
159 87
160 87
    public function details(): Details
161
    {
162
        // For existing model
163 27
        if ($this->hasExistingModel()) {
164
            return parent::details()
165
                ->set('title', $this->existingModel()->title ? ucfirst($this->existingModel()->title) : '')
0 ignored issues
show
Bug introduced by
Accessing title on the interface Thinktomorrow\Chief\Management\ManagedModel suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
166 69
                ->set('intro', PageStatePresenter::fromModel($this->existingModel())->label())
0 ignored issues
show
Bug introduced by
$this->existingModel() of type Thinktomorrow\Chief\Management\ManagedModel is incompatible with the type Thinktomorrow\Chief\States\State\StatefulContract expected by parameter $model of Thinktomorrow\Chief\Stat...ePresenter::fromModel(). ( Ignorable by Annotation )

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

166
                ->set('intro', PageStatePresenter::fromModel(/** @scrutinizer ignore-type */ $this->existingModel())->label())
Loading history...
167
                ->set('context', '');
168
        }
169 69
170 16
        return parent::details();
171
    }
172
173 69
    public function delete()
174 67
    {
175
        $this->guard('delete');
176 8
177
        if (request()->get('deleteconfirmation') !== 'DELETE') {
178 8
            throw new DeleteAborted();
179
        }
180 8
181 2
        app(DeletePage::class)->handle($this->model->id);
182
    }
183
184 6
    public function storeRequest(Request $request): Request
185 6
    {
186
        $trans = [];
187 18
        $urls = $request->input('url-slugs', []);
188
189 18
        foreach ($request->input('trans', []) as $locale => $translation) {
190 18
            if (is_array_empty($translation)) {
191
                continue;
192 18
            }
193 17
194 1
            $trans[$locale] = $this->addDefaultShortDescription($translation);
195
196
            // Automatically add an url for this locale based on the given title
197 17
            if (!isset($urls[$locale]) && isset($translation['title'])) {
198
                $urls[$locale] = Str::slug($translation['title']);
199
            }
200 17
        }
201 17
202
        // Merge with request...
203
        return $request->merge(['trans' => $trans, 'url-slugs' => $urls]);
204
    }
205
206 18
    public function updateRequest(Request $request): Request
207
    {
208
        $trans = [];
209 71
        foreach ($request->input('trans', []) as $locale => $translation) {
210
            if (is_array_empty($translation)) {
211 71
212 71
                // Nullify all values
213 65
                $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

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

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

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