Passed
Push — master ( f6fb5e...281f71 )
by Peter
02:15
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
            ->addIdentifier($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($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 addTitle(Entity $entity): Page
139
    {
140
        $input = new Input('title', 'title', $entity->getTitle());
141
        $label = new Label('title', 'website:pageTitle');
142
143
        $this->form[] = new FormGroup($input, $label, null, [], [Html5::ATTR_CLASS => FormGroup::CLASS_REQUIRED]);
144
145
        return $this;
146
    }
147
148
    /**
149
     * @param Entity $entity
150
     *
151
     * @return $this
152
     */
153
    protected function addIdentifier(Entity $entity): Page
154
    {
155
        $input = new Input(
156
            'identifier',
157
            'identifier',
158
            $entity->getIdentifier(),
159
            [],
160
            [Html5::ATTR_CLASS => 'semi-auto']
161
        );
162
        $label = new Label('identifier', 'website:pageIdentifier');
163
        $help  = new Help('website:pageIdentifierHelp');
164
165
        $this->form[] = new FormGroup($input, $label, $help);
166
167
        return $this;
168
    }
169
170
    /**
171
     * @param Entity $entity
172
     *
173
     * @return $this
174
     */
175
    protected function addDescription(Entity $entity): Page
176
    {
177
        $input = new Textarea('description', 'description', $entity->getMeta()->getDescription());
178
        $label = new Countable('description', 'website:pageDescription', Countable::DEFAULT_SIZE);
179
        $help  = new Help('website:pageDescriptionHelp');
180
181
        $this->form[] = new FormGroup(
182
            $input,
183
            $label,
184
            $help,
185
            [],
186
            [Html5::ATTR_CLASS => FormGroup::CLASS_COUNTABLE]
187
        );
188
189
        return $this;
190
    }
191
192
    /**
193
     * @param Entity $entity
194
     *
195
     * @return $this
196
     */
197
    protected function addMeta(Entity $entity): Page
198
    {
199
        $hideable = new Hideable($this->translator->translate('website:pageMetaBtn'));
200
        foreach ($this->metaFactory->create($entity) as $component) {
201
            $hideable[] = $component;
202
        }
203
204
        $this->form[] = $hideable;
205
206
        return $this;
207
    }
208
209
    /**
210
     * @param Entity $entity
211
     *
212
     * @return $this
213
     */
214
    protected function addLead(Entity $entity): Page
215
    {
216
        $attribs = [Html5::ATTR_ROWS => '10'];
217
        $input   = new Textarea('lead', 'lead', $entity->getLead(), [], $attribs);
218
        $label   = new Label('lead', 'website:pageLead');
219
        $help    = new Help('website:pageLeadHelp');
220
221
        $this->form[] = new FormGroup($input, $label, $help);
222
223
        return $this;
224
    }
225
226
    /**
227
     * @param Entity $entity
228
     *
229
     * @return $this
230
     */
231
    protected function addBody(Entity $entity): Page
232
    {
233
        $attribs = [Html5::ATTR_CLASS => 'wysiwyg', Html5::ATTR_ROWS => '15'];
234
        $input   = new Textarea('body', 'body', $entity->getBody(), [], $attribs);
235
        $label   = new Label('body', 'website:pageBody');
236
237
        $this->form[] = new FormGroup($input, $label);
238
239
        return $this;
240
    }
241
242
    /**
243
     * @param Entity $entity
244
     *
245
     * @return $this
246
     */
247
    protected function addCategoryId(Entity $entity): Page
248
    {
249
        $allCategories = $this->getAllCategories();
250
        $categoryId    = $entity->getCategory() ? $entity->getCategory()->getId() : null;
251
252
        $options = $this->createCategoryIdOptions($allCategories, $categoryId);
253
254
        $this->form[] = new FormGroup(
255
            $this->createCategoryIdSelect($options),
256
            $this->createCategoryIdLabel()
257
        );
258
259
        return $this;
260
    }
261
262
    /**
263
     * @param Option[] $options
264
     *
265
     * @return Select
266
     */
267
    protected function createCategoryIdSelect(array $options): Select
268
    {
269
        $select = new Select('category_id', 'category_id');
270
271
        foreach ($options as $option) {
272
            $select[] = $option;
273
        }
274
275
        return $select;
276
    }
277
278
    /**
279
     * @return Label
280
     */
281
    protected function createCategoryIdLabel(): Label
282
    {
283
        return new Label('category_id', 'website:pageCategoryIdLabel');
284
    }
285
286
    /**
287
     * @return PageCategory[]
288
     */
289
    protected function getAllCategories(): array
290
    {
291
        return $this->categoryRepo->getAll();
292
    }
293
294
    /**
295
     * @param PageCategory[] $allCategories
296
     * @param string|null    $categoryId
297
     *
298
     * @return Option[]
299
     */
300
    protected function createCategoryIdOptions(array $allCategories, ?string $categoryId): array
301
    {
302
        $options   = [];
303
        $options[] = new Option('', 'framework:none', false);
304
        foreach ($allCategories as $category) {
305
            $isSelected = $category->getId() === $categoryId;
306
            $options[]  = new Option($category->getId(), $category->getName(), $isSelected);
307
        }
308
309
        return $options;
310
    }
311
312
    /**
313
     * @param Entity $entity
314
     *
315
     * @return $this
316
     */
317
    protected function addLayoutId(Entity $entity): Page
318
    {
319
        $allLayouts = $this->getAllLayouts();
320
        $layoutId   = $entity->getLayoutId();
321
322
        $options = $this->createLayoutIdOptions($allLayouts, $layoutId);
323
324
        $this->form[] = new FormGroup(
325
            $this->createLayoutIdSelect($options),
326
            $this->createLayoutIdLabel()
327
        );
328
329
        return $this;
330
    }
331
332
    /**
333
     * @return PageLayout[]
334
     */
335
    protected function getAllLayouts(): array
336
    {
337
        return $this->layoutRepo->getAll();
338
    }
339
340
    /**
341
     * @param PageLayout[] $allLayouts
342
     * @param string|null  $layoutId
343
     *
344
     * @return Option[]
345
     */
346
    protected function createLayoutIdOptions(array $allLayouts, ?string $layoutId): array
347
    {
348
        $options   = [];
349
        $options[] = new Option('', 'framework:none', false);
350
        foreach ($allLayouts as $layout) {
351
            $isSelected = $layout->getId() === $layoutId;
352
            $options[]  = new Option($layout->getId(), $layout->getName(), $isSelected);
353
        }
354
355
        return $options;
356
    }
357
358
    /**
359
     * @param Option[] $options
360
     *
361
     * @return Select
362
     */
363
    protected function createLayoutIdSelect(array $options): Select
364
    {
365
        $select = new Select('layout_id', 'layout_id');
366
367
        foreach ($options as $option) {
368
            $select[] = $option;
369
        }
370
371
        return $select;
372
    }
373
374
    /**
375
     * @return Label
376
     */
377
    protected function createLayoutIdLabel(): Label
378
    {
379
        return new Label('layout_id', 'website:pageLayoutIdLabel');
380
    }
381
382
    /**
383
     * @param Entity $entity
384
     * @param bool   $advancedAllowed
385
     *
386
     * @return Page
387
     */
388
    protected function addLayout(Entity $entity, bool $advancedAllowed): Page
389
    {
390
        if (!$advancedAllowed) {
391
            return $this->addLayoutHidden($entity);
392
        }
393
394
        return $this->addLayoutTextarea($entity);
395
    }
396
397
    /**
398
     * @param Entity $entity
399
     *
400
     * @return $this
401
     */
402
    protected function addLayoutHidden(Entity $entity): Page
403
    {
404
        $attribs      = [Html5::ATTR_TYPE => Input::TYPE_HIDDEN];
405
        $this->form[] = new Input('layout', 'layout', $entity->getLayout(), [], $attribs);
406
407
        return $this;
408
    }
409
410
    /**
411
     * @param Entity $entity
412
     *
413
     * @return $this
414
     */
415
    protected function addLayoutTextarea(Entity $entity): Page
416
    {
417
        $input = new Textarea('layout', 'layout', $entity->getLayout(), [], [Html5::ATTR_ROWS => '15']);
418
        $label = new Label('layout', 'website:pageLayoutLabel');
419
420
        $this->form[] = new FormGroup($input, $label, null, [], [Html5::ATTR_ID => 'layout-div']);
421
422
        return $this;
423
    }
424
425
    /**
426
     * @param Entity $entity
427
     * @param bool   $advancedAllowed
428
     *
429
     * @return $this
430
     */
431
    protected function addAssets(Entity $entity, bool $advancedAllowed): Page
432
    {
433
        if (!$advancedAllowed) {
434
            return $this;
435
        }
436
437
        $nodes = $this->assetsFactory->create($entity);
438
        if (empty($nodes)) {
439
            return $this;
440
        }
441
442
        $container = new Hideable($this->translator->translate('website:pageAssetsBtn'));
443
        foreach ($nodes as $node) {
444
            $container[] = $node;
445
        }
446
447
        $this->form[] = $container;
448
449
        return $this;
450
    }
451
452
    /**
453
     * @param Entity $entity
454
     *
455
     * @return $this
456
     */
457
    protected function addIsDraft(Entity $entity): Page
458
    {
459
        $attributes = [Html5::ATTR_TYPE => Input::TYPE_CHECKBOX];
460
        if ($entity->isDraft()) {
461
            $attributes[Html5::ATTR_CHECKED] = null;
462
        }
463
        $input = new Input(
464
            'is_draft',
465
            'is_draft',
466
            '1',
467
            [],
468
            $attributes
469
        );
470
        $label = new Label('is_draft', 'website:pageIsDraft');
471
        $help  = new Component('website:pageIsDraft');
472
473
        $this->form[] = new CheckboxGroup($input, $label, $help, [], [Html5::ATTR_ID => 'is-draft-container']);
474
475
        return $this;
476
    }
477
478
    /**
479
     * @param string $showUrl
480
     *
481
     * @return Base
482
     */
483
    protected function addCustomButtons(string $showUrl): Base
484
    {
485
        $buttons = new DefaultButtons();
486
487
        $this->addPublishAndEdit($buttons);
488
489
        $buttons
490
            ->addSaveAndBack()
491
            ->addBackToGrid($showUrl);
492
493
        $this->addSaveAsDraftAndBack($buttons);
494
495
        $buttons->addSaveAndEdit()->addSaveAndCreate();
496
497
        $this->form[] = $buttons;
498
499
        return $this;
500
    }
501
502
503
    /**
504
     * @param DefaultButtons $buttons
505
     *
506
     * @return DefaultButtons
507
     */
508
    public function addPublishAndEdit(DefaultButtons $buttons): DefaultButtons
509
    {
510
        $attributes = [
511
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
512
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
513
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
514
            Html5::ATTR_ID    => [static::BTN_ID_PUBLISH],
515
        ];
516
517
        $buttons[] = new Button(
518
            static::BTN_CONTENT_PUBLISH_AND_EDIT,
519
            [Button::INTENT_SUCCESS, Button::INTENT_FORM, Button::INTENT_LARGE, Button::INTENT_HIDDEN],
520
            $attributes
521
        );
522
523
        return $buttons;
524
    }
525
526
    /**
527
     * @param DefaultButtons $buttons
528
     *
529
     * @return DefaultButtons
530
     */
531
    public function addSaveAsDraftAndBack(DefaultButtons $buttons): DefaultButtons
532
    {
533
        $attributes = [
534
            Html5::ATTR_NAME  => [DefaultButtons::BTN_NAME_NEXT],
535
            Html5::ATTR_TYPE  => [Button::TYPE_SUBMIT],
536
            Html5::ATTR_VALUE => [DefaultButtons::BTN_VALUE_NEXT_EDIT],
537
            Html5::ATTR_ID    => [static::BTN_ID_DRAFT],
538
        ];
539
540
        $buttons[] = new Button(
541
            static::BTN_CONTENT_SAVE_AS_DRAFT_AND_EDIT,
542
            [Button::INTENT_WARNING, Button::INTENT_FORM, Button::INTENT_HIDDEN],
543
            $attributes
544
        );
545
546
        return $buttons;
547
    }
548
}
549