Completed
Push — master ( e52e2c...9baf6c )
by Oleg
08:13
created

Builder::forget()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
crap 2
1
<?php
2
namespace Malezha\Menu\Entity;
3
4
use Illuminate\Contracts\Config\Repository;
5
use Illuminate\Contracts\Container\Container;
6
use Illuminate\Contracts\View\Factory as ViewFactory;
7
use Malezha\Menu\Contracts\Attributes as AttributesContract;
8
use Malezha\Menu\Contracts\Builder as BuilderContract;
9
use Malezha\Menu\Contracts\Group;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Malezha\Menu\Entity\Group.

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...
10
use Malezha\Menu\Contracts\HasAttributes as HasAttributesContract;
11
use Malezha\Menu\Contracts\Item;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Malezha\Menu\Entity\Item.

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...
12
use Malezha\Menu\Contracts\Link;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Malezha\Menu\Entity\Link.

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...
13
use Malezha\Menu\Traits\HasAttributes;
14
15
/**
16
 * Class Builder
17
 * @package Malezha\Menu\Entity
18
 */
19
class Builder implements BuilderContract
20
{
21
    use HasAttributes;
22
23
    /**
24
     * @var Container
25
     */
26
    protected $container;
27
28
    /**
29
     * @var array
30
     */
31
    protected $items;
32
33
    /**
34
     * @var string
35
     */
36
    protected $name;
37
38
    /**
39
     * @var string
40
     */
41
    protected $type;
42
43
    /**
44
     * @var AttributesContract
45
     */
46
    protected $activeAttributes;
47
48
    /**
49
     * @param Container $container
50
     * @param string $name
51
     * @param string $type
52
     * @param array $attributes
53
     * @param array $activeAttributes
54
     */
55 14
    public function __construct(Container $container, $name, $type = self::UL, $attributes = [], $activeAttributes = [])
56
    {
57 14
        $this->container = $container;
58 14
        $this->name = $name;
59 14
        $this->type = $type;
60 14
        $this->attributes = $this->container->make(AttributesContract::class, ['attributes' => $attributes]);
61 14
        $this->items = [];
62 14
        $this->activeAttributes = $this->container->make(AttributesContract::class, ['attributes' => $activeAttributes]);
63 14
    }
64
65
    /**
66
     * @param string $name
67
     * @param \Closure $itemCallable
68
     * @param \Closure $menuCallable
69
     * @return Group
70
     */
71 2
    public function group($name, \Closure $itemCallable, \Closure $menuCallable)
72
    {
73 2
        $item = $this->container->make(Item::class, [
74 2
            'builder' => $this,
75 2
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => []]),
76 2
            'link' => $this->container->make(Link::class, [
77 2
                'title' => $name,
78 2
                'attributes' => $this->container->make(AttributesContract::class, ['attributes' => []]),
79 2
            ]),
80 2
            'request' => $this->container->make('request'),
81 2
        ]);
82 2
        call_user_func($itemCallable, $item);
83
84 2
        $menu = $this->container->make(BuilderContract::class, [
85 2
            'container' => $this->container, 
86 2
            'name' => $name,
87 2
            'activeAttributes' => $this->activeAttributes()->all(),
88 2
        ]);
89 2
        call_user_func($menuCallable, $menu);
90
91 2
        $group = $this->container->make(Group::class, [
92 2
            'menu' => $menu,
93 2
            'item' => $item,
94 2
        ]);
95 2
        $this->items[$name] = $group;
96
97 2
        return $group;
98
    }
99
100
    /**
101
     * @param string $name
102
     * @param string $title
103
     * @param string $url
104
     * @param array $attributes
105
     * @param array $linkAttributes
106
     * @param \Closure|null $callback
107
     * @return Item
108
     */
109 6
    public function add($name, $title, $url, $attributes = [], $linkAttributes = [], $callback = null)
110
    {
111 6
        $link = $this->container->make(Link::class, [
112 6
            'title' => $title,
113 6
            'url' => $url,
114 6
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => $linkAttributes]),
115 6
        ]);
116
        
117 6
        $item = $this->container->make(Item::class, [
118 6
            'builder' => $this,
119 6
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => $attributes]),
120 6
            'link' => $link,
121 6
            'request' => $this->container->make('request'),
122 6
        ]);
123
124 6
        if (is_callable($callback)) {
125 2
            call_user_func($callback, $item);
126 2
        }
127
128 6
        $this->items[$name] = $item;
129
130 6
        return $item;
131
    }
132
133
    /**
134
     * @param string $name
135
     * @return bool
136
     */
137 4
    public function has($name)
138
    {
139 4
        return array_key_exists($name, $this->items);
140
    }
141
142
    /**
143
     * @param string $name
144
     * @param mixed|null $default
145
     * @return Item|Group|null
146
     */
147 2
    public function get($name, $default = null)
148
    {
149 2
        if ($this->has($name)) {
150 2
            return $this->items[$name];
151
        }
152
        return $default;
153
    }
154
155
    /**
156
     * @return array
157
     */
158 3
    public function all()
159
    {
160 3
        return $this->items;
161
    }
162
163
    /**
164
     * @param string $name
165
     */
166 2
    public function forget($name)
167
    {
168 1
        if ($this->has($name)) {
169 2
            unset($this->items[$name]);
170 1
        }
171 1
    }
172
173
    /**
174
     * @return string
175
     */
176 3
    public function getType()
177
    {
178 3
        return $this->type;
179
    }
180
181
    /**
182
     * @param string $type
183
     */
184 1
    public function setType($type)
185
    {
186 1
        $this->type = (string)$type;
187 1
    }
188
189
    /**
190
     * @param string|null $view
191
     * @return string
192
     */
193 2
    public function render($view = null)
194
    {
195
        /** @var Repository $config */
196 2
        $config = $this->container->make('config');
197
        
198 2
        $view = (empty($view)) ? $config->get('menu.view') : $view;
199 2
        $minify = $config->get('menu.minify', false);
200
        
201
        /* @var ViewFactory $viewFactory */
202 2
        $viewFactory = $this->container->make(ViewFactory::class);
203
204 2
        $rendered = $viewFactory->make($view, [
205 2
            'menu' => $this,
206 2
            'renderView' => $view,
207 2
        ])->render();
208
        
209 2
        if ($minify) {
210 2
            $rendered = $this->minifyHtmlOutput($rendered);
211 2
        }
212
        
213 2
        return $rendered;
214
    }
215
216
    /**
217
     * @param \Closure|null $callback
218
     * @return Attributes|mixed
219
     */
220 6
    public function activeAttributes($callback = null)
221
    {
222 6
        if (is_callable($callback)) {
223 1
            return call_user_func($callback, $this->activeAttributes);
224
        }
225
226 6
        return $this->activeAttributes;
227
    }
228
229
    /**
230
     * @param $html
231
     * @return mixed
232
     */
233 2
    protected function minifyHtmlOutput($html)
234
    {
235
        $search = array(
236 2
            '/\>[^\S]+/s',  // strip whitespaces after tags, except space
237 2
            '/[^\S]+\</s',  // strip whitespaces before tags, except space
238
            '/(\s)+/s'       // shorten multiple whitespace sequences
239 2
        );
240
241
        $replace = array(
242 2
            '>',
243 2
            '<',
244
            '\\1'
245 2
        );
246
247 2
        return preg_replace($search, $replace, $html);
248
    }
249
}