Passed
Push — master ( ebf7d2...a00973 )
by Peter
03:48
created

Primary::decorateUserBlockContainer()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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