Passed
Push — master ( 45be64...e3c02a )
by Peter
02:31
created

Page::addClasses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Website\Form\Factory;
6
7
use AbterPhp\Admin\Form\Factory\Base;
8
use AbterPhp\Framework\Constant\Html5;
9
use AbterPhp\Framework\Constant\Session;
10
use AbterPhp\Framework\Form\Component\Option;
11
use AbterPhp\Framework\Form\Container\CheckboxGroup;
12
use AbterPhp\Framework\Form\Container\FormGroup;
13
use AbterPhp\Framework\Form\Container\Hideable;
14
use AbterPhp\Framework\Form\Element\Input;
15
use AbterPhp\Framework\Form\Element\Select;
16
use AbterPhp\Framework\Form\Element\Textarea;
17
use AbterPhp\Framework\Form\Extra\DefaultButtons;
18
use AbterPhp\Framework\Form\Extra\Help;
19
use AbterPhp\Framework\Form\IForm;
20
use AbterPhp\Framework\Form\Label\Countable;
21
use AbterPhp\Framework\Form\Label\Label;
22
use AbterPhp\Framework\Html\Component;
23
use AbterPhp\Framework\Html\Component\Button;
24
use AbterPhp\Framework\I18n\ITranslator;
25
use AbterPhp\Website\Constant\Authorization;
26
use AbterPhp\Website\Domain\Entities\Page as Entity;
27
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...
28
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...
29
use AbterPhp\Website\Form\Factory\Page\Assets as AssetsFactory;
30
use AbterPhp\Website\Form\Factory\Page\Meta as MetaFactory;
31
use AbterPhp\Website\Orm\PageCategoryRepo;
32
use AbterPhp\Website\Orm\PageLayoutRepo;
33
use Casbin\Enforcer;
34
use Opulence\Orm\IEntity;
35
use Opulence\Sessions\ISession;
36
37
/**
38
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
39
 */
40
class Page extends Base
41
{
42
    const BTN_CONTENT_PUBLISH_AND_EDIT       = 'website:publishAndEdit';
43
    const BTN_CONTENT_SAVE_AS_DRAFT_AND_EDIT = 'website:saveAsDraftAndEdit';
44
45
    const BTN_ID_DRAFT   = 'draft-btn';
46
    const BTN_ID_PUBLISH = 'publish-btn';
47
48
    /** @var PageCategoryRepo */
49
    protected $categoryRepo;
50
51
    /** @var PageLayoutRepo */
52
    protected $layoutRepo;
53
54
    /** @var MetaFactory */
55
    protected $metaFactory;
56
57
    /** @var AssetsFactory */
58
    protected $assetsFactory;
59
60
    /** @var Enforcer */
61
    protected $enforcer;
62
63
    /**
64
     * Page constructor.
65
     *
66
     * @param ISession         $session
67
     * @param ITranslator      $translator
68
     * @param PageCategoryRepo $categoryRepo
69
     * @param PageLayoutRepo   $layoutRepo
70
     * @param MetaFactory      $metaFactory
71
     * @param AssetsFactory    $assetsFactory
72
     * @param Enforcer         $enforcer
73
     */
74
    public function __construct(
75
        ISession $session,
76
        ITranslator $translator,
77
        PageCategoryRepo $categoryRepo,
78
        PageLayoutRepo $layoutRepo,
79
        MetaFactory $metaFactory,
80
        AssetsFactory $assetsFactory,
81
        Enforcer $enforcer
82
    ) {
83
        parent::__construct($session, $translator);
84
85
        $this->categoryRepo  = $categoryRepo;
86
        $this->layoutRepo    = $layoutRepo;
87
        $this->metaFactory   = $metaFactory;
88
        $this->assetsFactory = $assetsFactory;
89
        $this->enforcer      = $enforcer;
90
    }
91
92
    /**
93
     * @param string       $action
94
     * @param string       $method
95
     * @param string       $showUrl
96
     * @param IEntity|null $entity
97
     *
98
     * @return IForm
99
     */
100
    public function create(string $action, string $method, string $showUrl, ?IEntity $entity = null): IForm
101
    {
102
        assert($entity instanceof Entity, new \InvalidArgumentException());
103
104
        $username        = $this->session->get(Session::USERNAME);
105
        $advancedAllowed = $this->enforcer->enforce(
106
            $username,
107
            Authorization::RESOURCE_PAGES,
108
            Authorization::ROLE_ADVANCED_WRITE
109
        );
110
111
        $this->createForm($action, $method)
112
            ->addDefaultElements()
113
            ->addTitle($entity)
114
            ->addClasses($entity)
115
            ->addIdentifier($entity)
116
            ->addDescription($entity)
117
            ->addMeta($entity)
118
            ->addLead($entity)
119
            ->addBody($entity)
120
            ->addCategoryId($entity)
121
            ->addLayoutId($entity)
122
            ->addLayout($entity, $advancedAllowed)
123
            ->addAssets($entity, $advancedAllowed)
124
            ->addIsDraft($entity)
125
            ->addCustomButtons($showUrl);
126
127
        $form = $this->form;
128
129
        $this->form = null;
130
131
        return $form;
132
    }
133
134
    /**
135
     * @param Entity $entity
136
     *
137
     * @return $this
138
     */
139
    protected function addTitle(Entity $entity): Page
140
    {
141
        $input = new Input('title', 'title', $entity->getTitle());
142
        $label = new Label('title', 'website:pageTitle');
143
144
        $this->form[] = new FormGroup($input, $label, null, [], [Html5::ATTR_CLASS => FormGroup::CLASS_REQUIRED]);
145
146
        return $this;
147
    }
148
149
    /**
150
     * @param Entity $entity
151
     *
152
     * @return $this
153
     */
154
    protected function addClasses(Entity $entity): Page
155
    {
156
        $input = new Input('classes', 'classes', $entity->getClasses());
157
        $label = new Label('classes', 'website:pageClasses');
158
        $help  = new Help('website:pageClassesHelp');
159
160
        $this->form[] = new FormGroup($input, $label, $help);
161
162
        return $this;
163
    }
164
165
    /**
166
     * @param Entity $entity
167
     *
168
     * @return $this
169
     */
170
    protected function addIdentifier(Entity $entity): Page
171
    {
172
        $input = new Input(
173
            'identifier',
174
            'identifier',
175
            $entity->getIdentifier(),
176
            [],
177
            [Html5::ATTR_CLASS => 'semi-auto']
178
        );
179
        $label = new Label('identifier', 'website:pageIdentifier');
180
        $help  = new Help('website:pageIdentifierHelp');
181
182
        $this->form[] = new FormGroup($input, $label, $help);
183
184
        return $this;
185
    }
186
187
    /**
188
     * @param Entity $entity
189
     *
190
     * @return $this
191
     */
192
    protected function addDescription(Entity $entity): Page
193
    {
194
        $input = new Textarea('description', 'description', $entity->getMeta()->getDescription());
195
        $label = new Countable('description', 'website:pageDescription', Countable::DEFAULT_SIZE);
196
        $help  = new Help('website:pageDescriptionHelp');
197
198
        $this->form[] = new FormGroup(
199
            $input,
200
            $label,
201
            $help,
202
            [],
203
            [Html5::ATTR_CLASS => FormGroup::CLASS_COUNTABLE]
204
        );
205
206
        return $this;
207
    }
208
209
    /**
210
     * @param Entity $entity
211
     *
212
     * @return $this
213
     */
214
    protected function addMeta(Entity $entity): Page
215
    {
216
        $hideable = new Hideable($this->translator->translate('website:pageMetaBtn'));
217
        foreach ($this->metaFactory->create($entity) as $component) {
218
            $hideable[] = $component;
219
        }
220
221
        $this->form[] = $hideable;
222
223
        return $this;
224
    }
225
226
    /**
227
     * @param Entity $entity
228
     *
229
     * @return $this
230
     */
231
    protected function addLead(Entity $entity): Page
232
    {
233
        $attribs = [Html5::ATTR_ROWS => '10'];
234
        $input   = new Textarea('lead', 'lead', $entity->getLead(), [], $attribs);
235
        $label   = new Label('lead', 'website:pageLead');
236
        $help    = new Help('website:pageLeadHelp');
237
238
        $this->form[] = new FormGroup($input, $label, $help);
239
240
        return $this;
241
    }
242
243
    /**
244
     * @param Entity $entity
245
     *
246
     * @return $this
247
     */
248
    protected function addBody(Entity $entity): Page
249
    {
250
        $attribs = [Html5::ATTR_CLASS => 'wysiwyg', Html5::ATTR_ROWS => '15'];
251
        $input   = new Textarea('body', 'body', $entity->getBody(), [], $attribs);
252
        $label   = new Label('body', 'website:pageBody');
253
254
        $this->form[] = new FormGroup($input, $label);
255
256
        return $this;
257
    }
258
259
    /**
260
     * @param Entity $entity
261
     *
262
     * @return $this
263
     */
264
    protected function addCategoryId(Entity $entity): Page
265
    {
266
        $allCategories = $this->getAllCategories();
267
        $categoryId    = $entity->getCategory() ? $entity->getCategory()->getId() : null;
268
269
        $options = $this->createCategoryIdOptions($allCategories, $categoryId);
270
271
        $this->form[] = new FormGroup(
272
            $this->createCategoryIdSelect($options),
273
            $this->createCategoryIdLabel()
274
        );
275
276
        return $this;
277
    }
278
279
    /**
280
     * @param Option[] $options
281
     *
282
     * @return Select
283
     */
284
    protected function createCategoryIdSelect(array $options): Select
285
    {
286
        $select = new Select('category_id', 'category_id');
287
288
        foreach ($options as $option) {
289
            $select[] = $option;
290
        }
291
292
        return $select;
293
    }
294
295
    /**
296
     * @return Label
297
     */
298
    protected function createCategoryIdLabel(): Label
299
    {
300
        return new Label('category_id', 'website:pageCategoryIdLabel');
301
    }
302
303
    /**
304
     * @return PageCategory[]
305
     */
306
    protected function getAllCategories(): array
307
    {
308
        return $this->categoryRepo->getAll();
309
    }
310
311
    /**
312
     * @param PageCategory[] $allCategories
313
     * @param string|null    $categoryId
314
     *
315
     * @return Option[]
316
     */
317
    protected function createCategoryIdOptions(array $allCategories, ?string $categoryId): array
318
    {
319
        $options   = [];
320
        $options[] = new Option('', 'framework:none', false);
321
        foreach ($allCategories as $category) {
322
            $isSelected = $category->getId() === $categoryId;
323
            $options[]  = new Option($category->getId(), $category->getName(), $isSelected);
324
        }
325
326
        return $options;
327
    }
328
329
    /**
330
     * @param Entity $entity
331
     *
332
     * @return $this
333
     */
334
    protected function addLayoutId(Entity $entity): Page
335
    {
336
        $allLayouts = $this->getAllLayouts();
337
        $layoutId   = $entity->getLayoutId();
338
339
        $options = $this->createLayoutIdOptions($allLayouts, $layoutId);
340
341
        $this->form[] = new FormGroup(
342
            $this->createLayoutIdSelect($options),
343
            $this->createLayoutIdLabel()
344
        );
345
346
        return $this;
347
    }
348
349
    /**
350
     * @return PageLayout[]
351
     */
352
    protected function getAllLayouts(): array
353
    {
354
        return $this->layoutRepo->getAll();
355
    }
356
357
    /**
358
     * @param PageLayout[] $allLayouts
359
     * @param string|null  $layoutId
360
     *
361
     * @return Option[]
362
     */
363
    protected function createLayoutIdOptions(array $allLayouts, ?string $layoutId): array
364
    {
365
        $options   = [];
366
        $options[] = new Option('', 'framework:none', false);
367
        foreach ($allLayouts as $layout) {
368
            $isSelected = $layout->getId() === $layoutId;
369
            $options[]  = new Option($layout->getId(), $layout->getName(), $isSelected);
370
        }
371
372
        return $options;
373
    }
374
375
    /**
376
     * @param Option[] $options
377
     *
378
     * @return Select
379
     */
380
    protected function createLayoutIdSelect(array $options): Select
381
    {
382
        $select = new Select('layout_id', 'layout_id');
383
384
        foreach ($options as $option) {
385
            $select[] = $option;
386
        }
387
388
        return $select;
389
    }
390
391
    /**
392
     * @return Label
393
     */
394
    protected function createLayoutIdLabel(): Label
395
    {
396
        return new Label('layout_id', 'website:pageLayoutIdLabel');
397
    }
398
399
    /**
400
     * @param Entity $entity
401
     * @param bool   $advancedAllowed
402
     *
403
     * @return Page
404
     */
405
    protected function addLayout(Entity $entity, bool $advancedAllowed): Page
406
    {
407
        if (!$advancedAllowed) {
408
            return $this->addLayoutHidden($entity);
409
        }
410
411
        return $this->addLayoutTextarea($entity);
412
    }
413
414
    /**
415
     * @param Entity $entity
416
     *
417
     * @return $this
418
     */
419
    protected function addLayoutHidden(Entity $entity): Page
420
    {
421
        $attribs      = [Html5::ATTR_TYPE => Input::TYPE_HIDDEN];
422
        $this->form[] = new Input('layout', 'layout', $entity->getLayout(), [], $attribs);
423
424
        return $this;
425
    }
426
427
    /**
428
     * @param Entity $entity
429
     *
430
     * @return $this
431
     */
432
    protected function addLayoutTextarea(Entity $entity): Page
433
    {
434
        $input = new Textarea('layout', 'layout', $entity->getLayout(), [], [Html5::ATTR_ROWS => '15']);
435
        $label = new Label('layout', 'website:pageLayoutLabel');
436
437
        $this->form[] = new FormGroup($input, $label, null, [], [Html5::ATTR_ID => 'layout-div']);
438
439
        return $this;
440
    }
441
442
    /**
443
     * @param Entity $entity
444
     * @param bool   $advancedAllowed
445
     *
446
     * @return $this
447
     */
448
    protected function addAssets(Entity $entity, bool $advancedAllowed): Page
449
    {
450
        if (!$advancedAllowed) {
451
            return $this;
452
        }
453
454
        $nodes = $this->assetsFactory->create($entity);
455
        if (empty($nodes)) {
456
            return $this;
457
        }
458
459
        $container = new Hideable($this->translator->translate('website:pageAssetsBtn'));
460
        foreach ($nodes as $node) {
461
            $container[] = $node;
462
        }
463
464
        $this->form[] = $container;
465
466
        return $this;
467
    }
468
469
    /**
470
     * @param Entity $entity
471
     *
472
     * @return $this
473
     */
474
    protected function addIsDraft(Entity $entity): Page
475
    {
476
        $attributes = [Html5::ATTR_TYPE => Input::TYPE_CHECKBOX];
477
        if ($entity->isDraft()) {
478
            $attributes[Html5::ATTR_CHECKED] = null;
479
        }
480
        $input = new Input(
481
            'is_draft',
482
            'is_draft',
483
            '1',
484
            [],
485
            $attributes
486
        );
487
        $label = new Label('is_draft', 'website:pageIsDraft');
488
        $help  = new Component('website:pageIsDraft');
489
490
        $this->form[] = new CheckboxGroup($input, $label, $help, [], [Html5::ATTR_ID => 'is-draft-container']);
491
492
        return $this;
493
    }
494
495
    /**
496
     * @param string $showUrl
497
     *
498
     * @return Base
499
     */
500
    protected function addCustomButtons(string $showUrl): Base
501
    {
502
        $buttons = new DefaultButtons();
503
504
        $this->addPublishAndEdit($buttons);
505
506
        $buttons
507
            ->addSaveAndBack()
508
            ->addBackToGrid($showUrl);
509
510
        $this->addSaveAsDraftAndBack($buttons);
511
512
        $buttons->addSaveAndEdit()->addSaveAndCreate();
513
514
        $this->form[] = $buttons;
515
516
        return $this;
517
    }
518
519
520
    /**
521
     * @param DefaultButtons $buttons
522
     *
523
     * @return DefaultButtons
524
     */
525
    public function addPublishAndEdit(DefaultButtons $buttons): DefaultButtons
526
    {
527
        $attributes = [
528
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
529
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
530
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
531
            Html5::ATTR_ID    => [static::BTN_ID_PUBLISH],
532
        ];
533
534
        $buttons[] = new Button(
535
            static::BTN_CONTENT_PUBLISH_AND_EDIT,
536
            [Button::INTENT_SUCCESS, Button::INTENT_FORM, Button::INTENT_LARGE, Button::INTENT_HIDDEN],
537
            $attributes
538
        );
539
540
        return $buttons;
541
    }
542
543
    /**
544
     * @param DefaultButtons $buttons
545
     *
546
     * @return DefaultButtons
547
     */
548
    public function addSaveAsDraftAndBack(DefaultButtons $buttons): DefaultButtons
549
    {
550
        $attributes = [
551
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
552
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
553
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
554
            Html5::ATTR_ID    => [static::BTN_ID_DRAFT],
555
        ];
556
557
        $buttons[] = new Button(
558
            static::BTN_CONTENT_SAVE_AS_DRAFT_AND_EDIT,
559
            [Button::INTENT_WARNING, Button::INTENT_FORM, Button::INTENT_HIDDEN],
560
            $attributes
561
        );
562
563
        return $buttons;
564
    }
565
}
566