Passed
Push — master ( df08cc...276b2d )
by Peter
02:35
created

Page::addPublishAndEdit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 16
rs 9.9332
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Website\Form\Factory;
6
7
use AbterPhp\Framework\Constant\Html5;
8
use AbterPhp\Framework\Constant\Session;
9
use AbterPhp\Framework\Form\Component\Option;
10
use AbterPhp\Framework\Form\Container\CheckboxGroup;
11
use AbterPhp\Framework\Form\Container\FormGroup;
12
use AbterPhp\Framework\Form\Container\Hideable;
13
use AbterPhp\Framework\Form\Element\Input;
14
use AbterPhp\Framework\Form\Element\Select;
15
use AbterPhp\Framework\Form\Element\Textarea;
16
use AbterPhp\Framework\Form\Extra\DefaultButtons;
17
use AbterPhp\Framework\Form\Extra\Help;
18
use AbterPhp\Framework\Form\Factory\Base;
19
use AbterPhp\Framework\Form\Factory\IFormFactory;
20
use AbterPhp\Framework\Form\IForm;
21
use AbterPhp\Framework\Form\Label\Countable;
22
use AbterPhp\Framework\Form\Label\Label;
23
use AbterPhp\Framework\Html\Component;
24
use AbterPhp\Framework\Html\Component\Button;
25
use AbterPhp\Framework\I18n\ITranslator;
26
use AbterPhp\Website\Constant\Authorization;
27
use AbterPhp\Website\Domain\Entities\Page as Entity;
28
use AbterPhp\Website\Domain\Entities\PageCategory;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, AbterPhp\Website\Form\Factory\PageCategory. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
29
use AbterPhp\Website\Domain\Entities\PageLayout;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, AbterPhp\Website\Form\Factory\PageLayout. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
30
use AbterPhp\Website\Form\Factory\Page\Assets as AssetsFactory;
31
use AbterPhp\Website\Form\Factory\Page\Meta as MetaFactory;
32
use AbterPhp\Website\Orm\PageCategoryRepo;
33
use AbterPhp\Website\Orm\PageLayoutRepo;
34
use Casbin\Enforcer;
35
use Opulence\Orm\IEntity;
36
use Opulence\Sessions\ISession;
37
38
class Page extends Base
39
{
40
    const BTN_CONTENT_PUBLISH_AND_EDIT       = 'website:publishAndEdit';
41
    const BTN_CONTENT_SAVE_AS_DRAFT_AND_EDIT = 'website:saveAsDraftAndEdit';
42
43
    const BTN_ID_DRAFT   = 'draft-btn';
44
    const BTN_ID_PUBLISH = 'publish-btn';
45
46
    /** @var PageCategoryRepo */
47
    protected $categoryRepo;
48
49
    /** @var PageLayoutRepo */
50
    protected $layoutRepo;
51
52
    /** @var MetaFactory */
53
    protected $metaFactory;
54
55
    /** @var AssetsFactory */
56
    protected $assetsFactory;
57
58
    /** @var Enforcer */
59
    protected $enforcer;
60
61
    /**
62
     * Page constructor.
63
     *
64
     * @param ISession         $session
65
     * @param ITranslator      $translator
66
     * @param PageCategoryRepo $categoryRepo
67
     * @param PageLayoutRepo   $layoutRepo
68
     * @param MetaFactory      $metaFactory
69
     * @param AssetsFactory    $assetsFactory
70
     * @param Enforcer         $enforcer
71
     */
72
    public function __construct(
73
        ISession $session,
74
        ITranslator $translator,
75
        PageCategoryRepo $categoryRepo,
76
        PageLayoutRepo $layoutRepo,
77
        MetaFactory $metaFactory,
78
        AssetsFactory $assetsFactory,
79
        Enforcer $enforcer
80
    ) {
81
        parent::__construct($session, $translator);
82
83
        $this->categoryRepo  = $categoryRepo;
84
        $this->layoutRepo    = $layoutRepo;
85
        $this->metaFactory   = $metaFactory;
86
        $this->assetsFactory = $assetsFactory;
87
        $this->enforcer      = $enforcer;
88
    }
89
90
    /**
91
     * @param string       $action
92
     * @param string       $method
93
     * @param string       $showUrl
94
     * @param IEntity|null $entity
95
     *
96
     * @return IForm
97
     */
98
    public function create(string $action, string $method, string $showUrl, ?IEntity $entity = null): IForm
99
    {
100
        if (!($entity instanceof Entity)) {
101
            throw new \InvalidArgumentException(IFormFactory::ERR_MSG_ENTITY_MISSING);
102
        }
103
104
        $username        = $this->session->get(Session::USERNAME);
105
        $advancedAllowed = $this->enforcer->enforce(
106
            $username,
107
            Authorization::RESOURCE_PAGES,
108
            Authorization::ROLE_PAGES_ADVANCED_WRITE
109
        );
110
111
        $this->createForm($action, $method)
112
            ->addDefaultElements()
113
            ->addIdentifier($entity)
114
            ->addTitle($entity)
115
            ->addDescription($entity)
116
            ->addMeta($entity)
117
            ->addLead($entity)
118
            ->addBody($entity)
119
            ->addCategoryId($entity)
120
            ->addLayoutId($entity)
121
            ->addLayout($entity, $advancedAllowed)
122
            ->addAssets($entity, $advancedAllowed)
123
            ->addIsDraft($entity)
124
            ->addCustomButtons($entity, $showUrl);
125
126
        $form = $this->form;
127
128
        $this->form = null;
129
130
        return $form;
131
    }
132
133
    /**
134
     * @param Entity $entity
135
     *
136
     * @return $this
137
     */
138
    protected function addIdentifier(Entity $entity): Page
139
    {
140
        $input = new Input('identifier', 'identifier', $entity->getIdentifier());
141
        $label = new Label('title', 'website:pageIdentifier');
142
143
        $this->form[] = new FormGroup($input, $label);
144
145
        return $this;
146
    }
147
148
    /**
149
     * @param Entity $entity
150
     *
151
     * @return $this
152
     */
153
    protected function addTitle(Entity $entity): Page
154
    {
155
        $input = new Input('title', 'title', $entity->getTitle());
156
        $label = new Label('title', 'website:pageTitle');
157
158
        $this->form[] = new FormGroup($input, $label);
159
160
        return $this;
161
    }
162
163
    /**
164
     * @param Entity $entity
165
     *
166
     * @return $this
167
     */
168
    protected function addDescription(Entity $entity): Page
169
    {
170
        $input = new Textarea('description', 'description', $entity->getMeta()->getDescription());
171
        $label = new Countable('description', 'website:pageDescription', Countable::DEFAULT_SIZE);
172
        $help  = new Help('website:pageDescriptionHelp');
173
174
        $this->form[] = new FormGroup(
175
            $input,
176
            $label,
177
            $help,
178
            [],
179
            [Html5::ATTR_CLASS => FormGroup::CLASS_COUNTABLE]
180
        );
181
182
        return $this;
183
    }
184
185
    /**
186
     * @param Entity $entity
187
     *
188
     * @return $this
189
     */
190
    protected function addMeta(Entity $entity): Page
191
    {
192
        $hideable = new Hideable($this->translator->translate('website:pageMetaBtn'));
193
        foreach ($this->metaFactory->create($entity) as $component) {
194
            $hideable[] = $component;
195
        }
196
197
        $this->form[] = $hideable;
198
199
        return $this;
200
    }
201
202
    /**
203
     * @param Entity $entity
204
     *
205
     * @return $this
206
     */
207
    protected function addLead(Entity $entity): Page
208
    {
209
        $attribs = [Html5::ATTR_ROWS => '10'];
210
        $input   = new Textarea('lead', 'lead', $entity->getLead(), [], $attribs);
211
        $label   = new Label('lead', 'website:pageLead');
212
        $help    = new Help('website:pageLeadHelp');
213
214
        $this->form[] = new FormGroup($input, $label, $help);
215
216
        return $this;
217
    }
218
219
    /**
220
     * @param Entity $entity
221
     *
222
     * @return $this
223
     */
224
    protected function addBody(Entity $entity): Page
225
    {
226
        $attribs = [Html5::ATTR_CLASS => 'wysiwyg', Html5::ATTR_ROWS => '15'];
227
        $input   = new Textarea('body', 'body', $entity->getBody(), [], $attribs);
228
        $label   = new Label('body', 'website:pageBody');
229
230
        $this->form[] = new FormGroup($input, $label);
231
232
        return $this;
233
    }
234
235
    /**
236
     * @param Entity $entity
237
     *
238
     * @return $this
239
     */
240
    protected function addCategoryId(Entity $entity): Page
241
    {
242
        $allCategories = $this->getAllCategories();
243
        $categoryId    = $entity->getCategory() ? $entity->getCategory()->getId() : null;
244
245
        $options = $this->createCategoryIdOptions($allCategories, $categoryId);
246
247
        $this->form[] = new FormGroup(
248
            $this->createCategoryIdSelect($options),
249
            $this->createCategoryIdLabel()
250
        );
251
252
        return $this;
253
    }
254
255
    /**
256
     * @param Option[] $options
257
     *
258
     * @return Select
259
     */
260
    protected function createCategoryIdSelect(array $options): Select
261
    {
262
        $select = new Select('category_id', 'category_id');
263
264
        foreach ($options as $option) {
265
            $select[] = $option;
266
        }
267
268
        return $select;
269
    }
270
271
    /**
272
     * @return Label
273
     */
274
    protected function createCategoryIdLabel(): Label
275
    {
276
        return new Label('category_id', 'website:pageCategoryIdLabel');
277
    }
278
279
    /**
280
     * @return PageCategory[]
281
     */
282
    protected function getAllCategories(): array
283
    {
284
        return $this->categoryRepo->getAll();
285
    }
286
287
    /**
288
     * @param PageCategory[] $allCategories
289
     * @param string|null    $categoryId
290
     *
291
     * @return Option[]
292
     */
293
    protected function createCategoryIdOptions(array $allCategories, ?string $categoryId): array
294
    {
295
        $options   = [];
296
        $options[] = new Option('', 'framework:none', false);
297
        foreach ($allCategories as $category) {
298
            $isSelected = $category->getId() === $categoryId;
299
            $options[]  = new Option($category->getId(), $category->getIdentifier(), $isSelected);
300
        }
301
302
        return $options;
303
    }
304
305
    /**
306
     * @param Entity $entity
307
     *
308
     * @return $this
309
     */
310
    protected function addLayoutId(Entity $entity): Page
311
    {
312
        $allLayouts = $this->getAllLayouts();
313
        $layoutId   = $entity->getLayoutId();
314
315
        $options = $this->createLayoutIdOptions($allLayouts, $layoutId);
316
317
        $this->form[] = new FormGroup(
318
            $this->createLayoutIdSelect($options),
319
            $this->createLayoutIdLabel()
320
        );
321
322
        return $this;
323
    }
324
325
    /**
326
     * @return PageLayout[]
327
     */
328
    protected function getAllLayouts(): array
329
    {
330
        return $this->layoutRepo->getAll();
331
    }
332
333
    /**
334
     * @param PageLayout[] $allLayouts
335
     * @param string|null  $layoutId
336
     *
337
     * @return Option[]
338
     */
339
    protected function createLayoutIdOptions(array $allLayouts, ?string $layoutId): array
340
    {
341
        $options   = [];
342
        $options[] = new Option('', 'framework:none', false);
343
        foreach ($allLayouts as $layout) {
344
            $content    = $layout->getIdentifier();
345
            $isSelected = $layout->getId() === $layoutId;
346
            $options[]  = new Option($layout->getId(), $content, $isSelected);
347
        }
348
349
        return $options;
350
    }
351
352
    /**
353
     * @param Option[] $options
354
     *
355
     * @return Select
356
     */
357
    protected function createLayoutIdSelect(array $options): Select
358
    {
359
        $select = new Select('layout_id', 'layout_id');
360
361
        foreach ($options as $option) {
362
            $select[] = $option;
363
        }
364
365
        return $select;
366
    }
367
368
    /**
369
     * @return Label
370
     */
371
    protected function createLayoutIdLabel(): Label
372
    {
373
        return new Label('layout_id', 'website:pageLayoutIdLabel');
374
    }
375
376
    /**
377
     * @param Entity $entity
378
     * @param bool   $advancedAllowed
379
     *
380
     * @return Page
381
     */
382
    protected function addLayout(Entity $entity, bool $advancedAllowed): Page
383
    {
384
        if (!$advancedAllowed) {
385
            return $this->addLayoutHidden($entity);
386
        }
387
388
        return $this->addLayoutTextarea($entity);
389
    }
390
391
    /**
392
     * @param Entity $entity
393
     *
394
     * @return $this
395
     */
396
    protected function addLayoutHidden(Entity $entity): Page
397
    {
398
        $attribs      = [Html5::ATTR_TYPE => Input::TYPE_HIDDEN];
399
        $this->form[] = new Input('layout', 'layout', $entity->getLayout(), [], $attribs);
400
401
        return $this;
402
    }
403
404
    /**
405
     * @param Entity $entity
406
     *
407
     * @return $this
408
     */
409
    protected function addLayoutTextarea(Entity $entity): Page
410
    {
411
        $input = new Textarea('layout', 'layout', $entity->getLayout(), [], [Html5::ATTR_ROWS => '15']);
412
        $label = new Label('layout', 'website:pageLayoutLabel');
413
414
        $this->form[] = new FormGroup($input, $label, null, [], [Html5::ATTR_ID => 'layout-div']);
415
416
        return $this;
417
    }
418
419
    /**
420
     * @param Entity $entity
421
     * @param bool   $advancedAllowed
422
     *
423
     * @return $this
424
     */
425
    protected function addAssets(Entity $entity, bool $advancedAllowed): Page
426
    {
427
        if (!$advancedAllowed) {
428
            return $this;
429
        }
430
431
        $hideable = new Hideable($this->translator->translate('website:pageAssetsBtn'));
432
433
        $nodes = $this->assetsFactory->create($entity);
434
        foreach ($nodes as $node) {
435
            $hideable[] = $node;
436
        }
437
438
        $this->form[] = $hideable;
439
440
        return $this;
441
    }
442
443
    /**
444
     * @param Entity $entity
445
     *
446
     * @return $this
447
     */
448
    protected function addIsDraft(Entity $entity): Page
449
    {
450
        $attributes = [Html5::ATTR_TYPE => Input::TYPE_CHECKBOX];
451
        if ($entity->isDraft()) {
452
            $attributes[Html5::ATTR_CHECKED] = null;
453
        }
454
        $input = new Input(
455
            'is_draft',
456
            'is_draft',
457
            '1',
458
            [],
459
            $attributes
460
        );
461
        $label = new Label('is_draft', 'website:pageIsDraft');
462
        $help  = new Component('website:pageIsDraft');
463
464
        $this->form[] = new CheckboxGroup($input, $label, $help, [], [Html5::ATTR_ID => 'is-draft-container']);
465
466
        return $this;
467
    }
468
469
    /**
470
     * @param Entity $entity
471
     * @param string $showUrl
472
     *
473
     * @return Base
474
     */
475
    protected function addCustomButtons(Entity $entity, string $showUrl): Base
0 ignored issues
show
Unused Code introduced by
The parameter $entity 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

475
    protected function addCustomButtons(/** @scrutinizer ignore-unused */ Entity $entity, string $showUrl): Base

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...
476
    {
477
        $buttons = new DefaultButtons();
478
479
        $this->addPublishAndEdit($buttons);
480
481
        $buttons
482
            ->addSaveAndBack()
483
            ->addBackToGrid($showUrl);
484
485
        $this->addSaveAsDraftAndBack($buttons);
486
487
        $buttons->addSaveAndEdit()->addSaveAndCreate();
488
489
        $this->form[] = $buttons;
490
491
        return $this;
492
    }
493
494
495
    /**
496
     * @param DefaultButtons $buttons
497
     *
498
     * @return DefaultButtons
499
     */
500
    public function addPublishAndEdit(DefaultButtons $buttons): DefaultButtons
501
    {
502
        $attributes = [
503
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
504
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
505
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
506
            Html5::ATTR_ID    => [static::BTN_ID_PUBLISH],
507
        ];
508
509
        $buttons[] = new Button(
510
            static::BTN_CONTENT_PUBLISH_AND_EDIT,
511
            [Button::INTENT_SUCCESS, Button::INTENT_FORM, Button::INTENT_LARGE, Button::INTENT_HIDDEN],
512
            $attributes
513
        );
514
515
        return $buttons;
516
    }
517
518
    /**
519
     * @param DefaultButtons $buttons
520
     *
521
     * @return DefaultButtons
522
     */
523
    public function addSaveAsDraftAndBack(DefaultButtons $buttons): DefaultButtons
524
    {
525
        $attributes = [
526
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
527
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
528
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
529
            Html5::ATTR_ID    => [static::BTN_ID_DRAFT],
530
        ];
531
532
        $buttons[] = new Button(
533
            static::BTN_CONTENT_SAVE_AS_DRAFT_AND_EDIT,
534
            [Button::INTENT_WARNING, Button::INTENT_FORM, Button::INTENT_HIDDEN],
535
            $attributes
536
        );
537
538
        return $buttons;
539
    }
540
}
541