Primary   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 84
c 3
b 0
f 0
dl 0
loc 196
rs 10
wmc 26

9 Methods

Rating   Name   Duplication   Size   Complexity  
A decorateUserBlockContainer() 0 9 4
A decorateGeneralContainer() 0 11 4
A handleItems() 0 11 4
A decorateDropdown() 0 10 2
A init() 0 11 1
A decorateUserBlock() 0 25 5
A handleButtons() 0 10 4
A __construct() 0 3 1
A decorateNavigation() 0 15 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\PropellerAdmin\Decorator\Navigation;
6
7
use AbterPhp\Framework\Constant\Html5;
8
use AbterPhp\Framework\Decorator\Decorator;
9
use AbterPhp\Framework\Decorator\Rule;
10
use AbterPhp\Framework\Html\Component;
11
use AbterPhp\Framework\Html\ICollection;
12
use AbterPhp\Framework\Html\INode;
13
use AbterPhp\Framework\Html\ITag;
14
use AbterPhp\Framework\Html\Tag;
15
use AbterPhp\Framework\Navigation\Dropdown;
16
use AbterPhp\Framework\Navigation\Item;
17
use AbterPhp\Framework\Navigation\Navigation;
18
use AbterPhp\Framework\Navigation\UserBlock;
19
use Opulence\Routing\Urls\UrlGenerator;
20
21
class Primary extends Decorator
22
{
23
    const PRIMARY_PREFIX_CLASS    = 'pmd-sidebar-overlay';
24
    const PRIMARY_CONTAINER_CLASS = 'pmd-sidebar sidebar-default pmd-sidebar-slide-push pmd-sidebar-left pmd-sidebar-open bg-fill-darkblue sidebar-with-icons nav pmd-sidebar-nav'; // nolint
25
    const PRIMARY_CLASS           = 'nav pmd-sidebar-nav';
26
27
    const USER_BLOCK_ITEM_CLASS = 'dropdown pmd-dropdown pmd-user-info visible-xs visible-md visible-sm visible-lg';
28
29
    const USER_BLOCK_CLASS         = 'btn-user dropdown-toggle media';
30
    const USER_BLOCK_ARIA_EXPANDED = 'false';
31
    const USER_BLOCK_DATA_TOGGLE   = 'dropdown';
32
    const USER_BLOCK_DATA_SIDEBAR  = 'true';
33
34
    const USER_BLOCK_MEDIA_LEFT_CLASS  = 'media-left';
35
    const USER_BLOCK_MEDIA_BODY_CLASS  = 'media-body media-middle';
36
    const USER_BLOCK_MEDIA_RIGHT_CLASS = 'media-right media-middle';
37
38
    const USER_BLOCK_MEDIA_RIGHT_ICON_CLASS = 'dic-more-vert dic';
39
40
    const DROPDOWN_WRAPPER_CLASS   = 'pmd-dropdown-menu-container';
41
    const DROPDOWN_PREFIX_CLASS    = 'pmd-dropdown-menu-bg';
42
    const DROPDOWN_CLASS           = 'dropdown-menu';
43
    const DROPDOWN_CONTAINER_CLASS = 'dropdown pmd-dropdown openable nav-open';
44
45
    const HEADER_WEIGHT = -100000;
46
47
    const ATTR_ARIA_EXPANDED = 'aria-expanded';
48
    const ATTR_DATA_TOGGLE   = 'data-toggle';
49
    const ATTR_DATA_SIDEBAR  = 'data-sidebar';
50
51
    /** @var UrlGenerator */
52
    protected $urlGenerator;
53
54
    /**
55
     * Primary constructor.
56
     *
57
     * @param UrlGenerator $urlGenerator
58
     */
59
    public function __construct(UrlGenerator $urlGenerator)
60
    {
61
        $this->urlGenerator = $urlGenerator;
62
    }
63
64
    /**
65
     * @return $this
66
     */
67
    public function init(): Decorator
68
    {
69
        $this->rules[] = new Rule(
70
            [Navigation::INTENT_PRIMARY],
71
            Navigation::class,
72
            [static::PRIMARY_CLASS],
73
            [],
74
            [$this, 'decorateNavigation']
75
        );
76
77
        return $this;
78
    }
79
80
    /**
81
     * @param Navigation $navigation
82
     */
83
    public function decorateNavigation(Navigation $navigation)
84
    {
85
        // Setup navigation properly
86
        $navigation->setPrefix(new Component(null, [], [Html5::ATTR_CLASS => static::PRIMARY_PREFIX_CLASS]));
87
88
        $wrapperAttribs = [
89
            Html5::ATTR_CLASS => static::PRIMARY_CONTAINER_CLASS,
90
            Html5::ATTR_ROLE  => [Navigation::ROLE_NAVIGATION],
91
        ];
92
        $navigation->setWrapper(new Component(null, [], $wrapperAttribs, Html5::TAG_ASIDE));
93
94
        $nodes = $navigation->getNodes();
95
96
        $this->handleButtons(...$nodes);
97
        $this->handleItems(...$nodes);
98
    }
99
100
    /**
101
     * @param INode ...$items
102
     */
103
    protected function handleButtons(INode ...$items)
104
    {
105
        foreach ($items as $item) {
106
            if (!($item instanceof Item)) {
107
                continue;
108
            }
109
110
            /** @var Component\Button $button */
111
            foreach ($item->collect(Component\Button::class) as $button) {
112
                $button->unsetAttributeValue(Html5::ATTR_CLASS, 'btn');
113
            }
114
        }
115
    }
116
117
    /**
118
     * @param INode ...$items
119
     */
120
    protected function handleItems(INode ...$items)
121
    {
122
        foreach ($items as $item) {
123
            if (!($item instanceof Item)) {
124
                continue;
125
            }
126
127
            if ($item->hasIntent(UserBlock::class)) {
128
                $this->decorateUserBlockContainer($item);
129
            } else {
130
                $this->decorateGeneralContainer($item);
131
            }
132
        }
133
    }
134
135
    /**
136
     * @param Item $item
137
     */
138
    protected function decorateGeneralContainer(Item $item)
139
    {
140
        if (!$item->hasIntent(Item::INTENT_DROPDOWN)) {
141
            return;
142
        }
143
144
        $item->appendToClass(static::DROPDOWN_CONTAINER_CLASS);
145
146
        foreach ($item as $subItem) {
147
            if ($subItem instanceof Dropdown) {
148
                $this->decorateDropdown($subItem);
149
            }
150
        }
151
    }
152
153
    /**
154
     * @param Item $item
155
     */
156
    protected function decorateUserBlockContainer(Item $item)
157
    {
158
        $item->appendToClass(static::USER_BLOCK_ITEM_CLASS);
159
160
        foreach ($item as $subItem) {
161
            if ($subItem instanceof UserBlock) {
162
                $this->decorateUserBlock($subItem);
163
            } elseif ($subItem instanceof Dropdown) {
164
                $this->decorateDropdown($subItem);
165
            }
166
        }
167
    }
168
169
    /**
170
     * @suppress PhanUndeclaredMethod
171
     *
172
     * @param UserBlock $userBlock
173
     */
174
    protected function decorateUserBlock(UserBlock $userBlock)
175
    {
176
        $userBlock->appendToClass(static::USER_BLOCK_CLASS)
177
            ->setAttribute(static::ATTR_ARIA_EXPANDED, static::USER_BLOCK_ARIA_EXPANDED)
178
            ->setAttribute(static::ATTR_DATA_SIDEBAR, static::USER_BLOCK_DATA_SIDEBAR)
179
            ->setAttribute(static::ATTR_DATA_TOGGLE, static::USER_BLOCK_DATA_TOGGLE);
180
181
        $left  = $userBlock->getMediaLeft();
182
        $body  = $userBlock->getMediaBody();
183
        $right = $userBlock->getMediaRight();
184
185
        if ($left instanceof ITag) {
186
            $left->appendToClass(static::USER_BLOCK_MEDIA_LEFT_CLASS);
187
        }
188
        if ($body instanceof ITag) {
189
            $body->appendToClass(static::USER_BLOCK_MEDIA_BODY_CLASS);
190
        }
191
        if ($right instanceof ITag) {
192
            $right->appendToClass(static::USER_BLOCK_MEDIA_RIGHT_CLASS);
193
            if ($right instanceof ICollection) {
194
                $right[] = new Tag(
195
                    null,
196
                    [],
197
                    [Html5::ATTR_CLASS => static::USER_BLOCK_MEDIA_RIGHT_ICON_CLASS],
198
                    Html5::TAG_I
199
                );
200
            }
201
        }
202
    }
203
204
    /**
205
     * @param Dropdown $dropdown
206
     */
207
    protected function decorateDropdown(Dropdown $dropdown)
208
    {
209
        $dropdown->appendToClass(static::DROPDOWN_CLASS);
210
211
        if ($dropdown->getWrapper()) {
212
            $dropdown->getWrapper()->appendToClass(static::DROPDOWN_WRAPPER_CLASS);
213
        }
214
215
        $prefix   = $dropdown->getPrefix();
216
        $prefix[] = new Tag(null, [], [Html5::ATTR_CLASS => static::DROPDOWN_PREFIX_CLASS], Html5::TAG_DIV);
217
    }
218
}
219