Passed
Push — master ( 5e2b09...a39721 )
by Ben
09:28 queued 02:28
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::editView() 0 3 1
A PageManager::createFields() 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\Modules\Module;
11
use Thinktomorrow\Chief\Fields\Types\ImageField;
12
use Thinktomorrow\Chief\States\PageStatePresenter;
13
use Thinktomorrow\Chief\Concerns\Morphable\MorphableContract;
14
use Thinktomorrow\Chief\Fields\Fields;
15
use Thinktomorrow\Chief\Filters\Filters;
16
use Thinktomorrow\Chief\Management\Manager;
17
use Thinktomorrow\Chief\Fields\Types\TextField;
18
use Thinktomorrow\Chief\Fields\Types\InputField;
19
use Thinktomorrow\Chief\Management\AbstractManager;
20
use Thinktomorrow\Chief\Management\Assistants\ArchiveAssistant;
21
use Thinktomorrow\Chief\Management\Assistants\PublishAssistant;
22
use Thinktomorrow\Chief\Management\Assistants\UrlAssistant;
23
use Thinktomorrow\Chief\Management\Details\Details;
24
use Thinktomorrow\Chief\Pages\Application\DeletePage;
25
use Thinktomorrow\Chief\Management\Exceptions\DeleteAborted;
26
use Thinktomorrow\Chief\Management\Exceptions\NotAllowedManagerRoute;
27
use Thinktomorrow\Chief\Urls\UrlSlugFields;
28
29
class PageManager extends AbstractManager implements Manager
30
{
31
    /** @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...
32
    private $pageBuilderField;
33
34
    protected $assistants = [
35
        'url'     => UrlAssistant::class,
36
        'archive' => ArchiveAssistant::class,
37
        'publish' => PublishAssistant::class,
38
    ];
39
40
    public function can($verb): bool
41 97
    {
42
        try {
43 97
            $this->authorize($verb);
44 97
45
            return parent::can($verb);
46 88
        } catch (NotAllowedManagerRoute $e) {
47
            return false;
48
        }
49 88
    }
50
51 87
    /**
52 3
     * @param $verb
53 3
     * @throws NotAllowedManagerRoute
54
     */
55
    private function authorize($verb)
56
    {
57
        $permission = 'update-page';
58
59
        if (in_array($verb, ['index', 'show'])) {
60
            $permission = 'view-page';
61 88
        } elseif (in_array($verb, ['create', 'store'])) {
62
            $permission = 'create-page';
63 88
        } elseif (in_array($verb, ['delete'])) {
64
            $permission = 'delete-page';
65 88
        }
66 24
67 70
        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

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

85
            /** @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...
86
                ->validation('required-fallback-locale|max:200', [], [
87 49
                    'trans.' . config('app.fallback_locale', 'nl') . '.title' => 'title',
88
                ])
89 49
                ->label('De titel van je ' . $this->model->labelSingular ?? 'pagina')
90 49
                ->description('Dit is de titel die zal worden getoond in de overzichten en modules.')
91 49
                ->tag('general'),
92 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

92
            /** @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...
93 49
                ->translatable($this->model->availableLocales())
94
                ->label('Zoekmachine titel')
95 49
                ->tag('seo'),
96 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

96
            /** @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...
97 49
                ->translatable($this->model->availableLocales())
98 49
                ->label('Zoekmachine omschrijving')
99 49
                ->description('omschrijving van de pagina zoals in search engines (o.a. google) wordt weergegeven.')
100 49
                ->tag('seo'),
101 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

101
            /** @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...
102 49
                ->validation('max:250')
103 49
                ->translatable($this->model->availableLocales())
104 49
                ->label('Zoekmachine sleutelwoorden')
105 49
                ->description('sleutelwoorden van de pagina waarop in search engines (o.a google) gezocht kan worden.')
106 49
                ->tag('seo'),
107 49
            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

107
            /** @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...
108 49
                ->translatable($this->model->availableLocales())
109 49
                ->label('Zoekmachine foto')
110 49
                ->description('foto die bij het delen van deze pagina getoond wordt. De ideale afmetingen zijn 1200px breed op 627px hoog.')
111 49
                ->tag('seo')
112 49
        );
113
    }
114
115
    public static function filters(): Filters
116 3
    {
117
        return new Filters([
118 3
            PublishedFilter::class,
119 3
        ]);
120
    }
121
122
    private function pageBuilderField()
123 49
    {
124
        if ($this->pageBuilderField) {
125 49
            return $this->pageBuilderField;
126 42
        }
127
128
        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...
129 49
    }
130
131
    public function createView(): string
132 3
    {
133
        return 'chief::back.pages._partials._createform';
134 3
    }
135
136 1
    public function editView(): string
137 1
    {
138
        return 'chief::back.pages._partials._editform';
139
    }
140
141 2
    public function createFields(): Fields
142 2
    {
143 2
        return $this->fields()->keyed('title');
144 2
    }
145
146 2
    public function saveCreateFields(Request $request): void
147
    {
148
        // Store the morph_key upon creation
149 2
        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...
150 1
            $this->model->morph_key = $this->model->morphKey();
151
        }
152
153 2
        parent::saveFields($request, $this->createFields()->merge($this->fieldsWithAssistantFields()->keyed('url-slugs')));
154
    }
155
156 90
    public function details(): Details
157
    {
158
        // For existing model
159 90
        if ($this->hasExistingModel()) {
160 69
            return parent::details()
161 69
                ->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...
162 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

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

209
                $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...
210 44
                    return null;
211
                }, $translation);
212 44
                continue;
213 44
            }
214 43
215
            $trans[$locale] = $this->addDefaultShortDescription($translation);
216
        }
217
218 2
        // Merge with request...
219 2
        return $request->merge(['trans' => $trans]);
220 2
    }
221
222
    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

222
    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...
223 43
    {
224
        Audit::activity()
225
            ->performedOn($this->model)
226
            ->log('created');
227 44
    }
228
229
    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

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