Completed
Push — master ( 38e886...df2920 )
by Oleg
04:55
created

Builder::has()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
namespace Malezha\Menu\Entity;
3
4
use Illuminate\Contracts\Container\Container;
5
use Malezha\Menu\Contracts\Attributes as AttributesContract;
6
use Malezha\Menu\Contracts\Builder as BuilderContract;
7
use Malezha\Menu\Contracts\Group as GroupContract;
8
use Malezha\Menu\Contracts\Item as ItemContract;
9
use Malezha\Menu\Contracts\Link as LinkContract;
10
use Malezha\Menu\Contracts\MenuRender;
11
use Malezha\Menu\Traits\HasAttributes;
12
13
/**
14
 * Class Builder
15
 * @package Malezha\Menu\Entity
16
 */
17
class Builder implements BuilderContract
18
{
19
    use HasAttributes;
20
21
    /**
22
     * @var Container
23
     */
24
    protected $container;
25
26
    /**
27
     * @var array
28
     */
29
    protected $items;
30
31
    /**
32
     * @var string
33
     */
34
    protected $name;
35
36
    /**
37
     * @var string
38
     */
39
    protected $type;
40
41
    /**
42
     * @var AttributesContract
43
     */
44
    protected $activeAttributes;
45
46
    /**
47
     * @var MenuRender
48
     */
49
    protected $viewFactory;
50
51
    /**
52
     * @var array
53
     */
54
    protected $config;
55
56
    /**
57
     * @var string
58
     */
59
    protected $view = null;
60
    
61
    /**
62
     * Builder constructor.
63
     *
64
     * @param Container $container
65
     * @param string $name
66
     * @param AttributesContract $attributes
67
     * @param AttributesContract $activeAttributes
68
     * @param string $type
69
     * @param string $view
70
     */
71 21
    public function __construct(Container $container, $name, AttributesContract $attributes,
72
                                AttributesContract $activeAttributes, $type = self::UL, $view = null)
73
    {
74 21
        $this->container = $container;
75 21
        $this->name = $name;
76 21
        $this->type = $type;
77 21
        $this->attributes = $attributes;
78 21
        $this->items = [];
79 21
        $this->activeAttributes = $activeAttributes;
80 21
        $this->viewFactory = $this->container->make(MenuRender::class);
81 21
        $this->config = $this->container->make('config')->get('menu');
82
        try {
83 21
            $this->setView($view);
84 21
        } catch (\Exception $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
85 21
    }
86
87
    /**
88
     * Make sub menu
89
     *
90
     * @param string $name
91
     * @param \Closure $itemCallable
92
     * @param \Closure $menuCallable
93
     * @return mixed
94
     */
95 5
    public function group($name, \Closure $itemCallable, \Closure $menuCallable)
96
    {
97 5
        $item = $this->container->make(ItemContract::class, [
98 5
            'builder' => $this,
99 5
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => []]),
100 5
            'link' => $this->container->make(LinkContract::class, [
101 5
                'title' => $name,
102 5
                'attributes' => $this->container->make(AttributesContract::class, ['attributes' => []]),
103 5
            ]),
104 5
            'request' => $this->container->make('request'),
105 5
        ]);
106 5
        call_user_func($itemCallable, $item);
107
108 5
        $menu = $this->container->make(BuilderContract::class, [
109 5
            'container' => $this->container, 
110 5
            'name' => $name,
111 5
            'activeAttributes' => $this->activeAttributes(),
112 5
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => []]),
113 5
            'view' => $this->getView(),
114 5
        ]);
115 5
        call_user_func($menuCallable, $menu);
116
117 5
        $group = $this->container->make(GroupContract::class, [
118 5
            'menu' => $menu,
119 5
            'item' => $item,
120 5
        ]);
121 5
        $this->items[$name] = $group;
122
123 5
        return $group;
124
    }
125
126
    /**
127
     * Add new element
128
     *
129
     * @param string $name
130
     * @param string $title
131
     * @param string $url
132
     * @param array $attributes
133
     * @param array $linkAttributes
134
     * @param \Closure|null $callback
135
     * @return ItemContract
136
     */
137 13
    public function add($name, $title, $url, $attributes = [], $linkAttributes = [], $callback = null)
138
    {
139 13
        $link = $this->container->make(LinkContract::class, [
140 13
            'title' => $title,
141 13
            'url' => $url,
142 13
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => $linkAttributes]),
143 13
        ]);
144
        
145 13
        $item = $this->container->make(ItemContract::class, [
146 13
            'builder' => $this,
147 13
            'attributes' => $this->container->make(AttributesContract::class, ['attributes' => $attributes]),
148 13
            'link' => $link,
149 13
            'request' => $this->container->make('request'),
150 13
        ]);
151
152 13
        if (is_callable($callback)) {
153 4
            call_user_func($callback, $item);
154 4
        }
155
156 13
        $this->items[$name] = $item;
157
158 13
        return $item;
159
    }
160
161
    /**
162
     * Check exits by name
163
     *
164
     * @param string $name
165
     * @return bool
166
     */
167 5
    public function has($name)
168
    {
169 5
        return array_key_exists($name, $this->items);
170
    }
171
172
    /**
173
     * Get element or sub menu by name
174
     *
175
     * @param string $name
176
     * @param mixed|null $default
177
     * @return ItemContract|GroupContract|null
178
     */
179 3
    public function get($name, $default = null)
180
    {
181 3
        if ($this->has($name)) {
182 3
            return $this->items[$name];
183
        }
184 1
        return $default;
185
    }
186
187
    /**
188
     * Get all elements and sub menus
189
     *
190
     * @return array
191
     */
192 7
    public function all()
193
    {
194 7
        return $this->items;
195
    }
196
197
    /**
198
     * Delete element
199
     *
200
     * @param string $name
201
     */
202 1
    public function forget($name)
203
    {
204 1
        if ($this->has($name)) {
205 1
            unset($this->items[$name]);
206 1
        }
207 1
    }
208
209
    /**
210
     * Get menu type: UL or OL
211
     *
212
     * @return string
213
     */
214 7
    public function getType()
215
    {
216 7
        return $this->type;
217
    }
218
219
    /**
220
     * Set menu type. You can use constants at this interface
221
     *
222
     * @param string $type
223
     */
224 1
    public function setType($type)
225
    {
226 1
        $this->type = (string) $type;
227 1
    }
228
229
    /**
230
     * Render menu to html
231
     *
232
     * @param string|null $renderView
233
     * @return string
234
     */
235 6
    public function render($renderView = null)
236
    {
237 6
        $view = $this->getRenderView($renderView);
238
239 6
        $minify = $this->config['minify'];
240
241 6
        $rendered = $this->viewFactory->make($view)->with([
242 6
            'menu' => $this,
243 6
            'renderView' => $renderView,
244 6
        ])->render();
245
        
246 6
        if ($minify) {
247 6
            $rendered = $this->minifyHtmlOutput($rendered);
248 6
        }
249
        
250 6
        return $rendered;
251
    }
252
253
    /**
254
     * Get active attributes object.
255
     * If send \Closure option as parameter then returned callback result.
256
     *
257
     * @param \Closure|null $callback
258
     * @return AttributesContract|mixed
259
     */
260 9
    public function activeAttributes($callback = null)
261
    {
262 9
        if (is_callable($callback)) {
263 1
            return call_user_func($callback, $this->activeAttributes);
264
        }
265
266 9
        return $this->activeAttributes;
267
    }
268
269
    /**
270
     * Get render view
271
     *
272
     * @return string
273
     */
274 5
    public function getView()
275
    {
276 5
        return $this->view;
277
    }
278
279
    /**
280
     * Set render view
281
     *
282
     * @param string $view
283
     * @throws \Exception
284
     */
285 21
    public function setView($view)
286
    {
287 21
        if (!$this->viewFactory->exists($view)) {
288 21
            throw new \Exception('View not found');
289
        }
290
        
291 1
        $this->view = $view;
292 1
    }
293
294
    /**
295
     * Minify html
296
     *
297
     * @param string $html
298
     * @return string
299
     */
300 6
    protected function minifyHtmlOutput($html)
301
    {
302
        $search = array(
303 6
            '/\>[^\S]+/s', // strip whitespaces after tags, except space
304 6
            '/[^\S]+\</s', // strip whitespaces before tags, except space
305
            '/(\s)+/s'       // shorten multiple whitespace sequences
306 6
        );
307
308
        $replace = array(
309 6
            '>',
310 6
            '<',
311
            '\\1'
312 6
        );
313
314 6
        return preg_replace($search, $replace, $html);
315
    }
316
317
    /**
318
     * Get view for render
319
     * 
320
     * @param string $view
321
     * @return string
322
     */
323 6
    protected function getRenderView($view = null)
324
    {
325 6
        $renderView = $this->config['view'];
326
        
327 6
        if (!empty($this->view)) {
328 1
            $renderView = $this->view;
329 1
        }
330
        
331 6
        if (!empty($view) && $this->viewFactory->exists($view)) {
332 1
            $renderView = $view;
333 1
        }
334
        
335 6
        return $renderView;
336
    }
337
}