|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* BB's Zend Framework 2 Components |
|
4
|
|
|
* |
|
5
|
|
|
* UI Components |
|
6
|
|
|
* |
|
7
|
|
|
* @package [MyApplication] |
|
8
|
|
|
* @subpackage BB's Zend Framework 2 Components |
|
9
|
|
|
* @subpackage UI Components |
|
10
|
|
|
* @author Björn Bartels <[email protected]> |
|
11
|
|
|
* @link https://gitlab.bjoernbartels.earth/groups/zf2 |
|
12
|
|
|
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
|
13
|
|
|
* @copyright copyright (c) 2016 Björn Bartels <[email protected]> |
|
14
|
|
|
*/ |
|
15
|
|
|
|
|
16
|
|
|
namespace UIComponents\View\Helper; |
|
17
|
|
|
|
|
18
|
|
|
use Zend\ServiceManager\ServiceLocatorAwareInterface; |
|
19
|
|
|
use Zend\View\Exception; |
|
20
|
|
|
use Zend\View\Renderer\RendererInterface as Renderer; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Proxy helper for retrieving navigational helpers and forwarding calls |
|
24
|
|
|
*/ |
|
25
|
|
|
class AbstractProxyHelper extends AbstractHelper |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* View helper namespace |
|
29
|
|
|
* |
|
30
|
|
|
* @var string |
|
31
|
|
|
*/ |
|
32
|
|
|
const NS = 'UIComponents\View\Helper\Components'; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Default proxy to use in {@link render()} |
|
36
|
|
|
* |
|
37
|
|
|
* @var string |
|
38
|
|
|
*/ |
|
39
|
|
|
protected $defaultProxy = 'element'; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* Indicates whether or not a given helper has been injected |
|
43
|
|
|
* |
|
44
|
|
|
* @var array |
|
45
|
|
|
*/ |
|
46
|
|
|
protected $injected = []; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* Whether ACL should be injected when proxying |
|
50
|
|
|
* |
|
51
|
|
|
* @var bool |
|
52
|
|
|
*/ |
|
53
|
|
|
protected $injectAcl = true; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* Whether container should be injected when proxying |
|
57
|
|
|
* |
|
58
|
|
|
* @var bool |
|
59
|
|
|
*/ |
|
60
|
|
|
protected $injectContainer = true; |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* Whether translator should be injected when proxying |
|
64
|
|
|
* |
|
65
|
|
|
* @var bool |
|
66
|
|
|
*/ |
|
67
|
|
|
protected $injectTranslator = true; |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* @var Navigation\PluginManager |
|
71
|
|
|
*/ |
|
72
|
|
|
protected $plugins; |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* AbstractContainer to operate on by default |
|
76
|
|
|
* |
|
77
|
|
|
* @var Navigation\AbstractContainer|Navigation\Navigation|\Zend\Navigation\AbstractContainer |
|
78
|
|
|
*/ |
|
79
|
|
|
protected $container; |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Helper entry point |
|
83
|
|
|
* |
|
84
|
|
|
* @param array $options option to operate on |
|
85
|
|
|
* @return Components |
|
86
|
|
|
*/ |
|
87
|
|
View Code Duplication |
public function __invoke($options = array()) |
|
|
|
|
|
|
88
|
|
|
{ |
|
89
|
|
|
if (isset($options['container']) && null !== $options['container']) { |
|
90
|
|
|
$this->setContainer($options['container']); |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
return ($this); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Magic overload: Proxy to other navigation helpers or the container |
|
98
|
|
|
* |
|
99
|
|
|
* Examples of usage from a view script or layout: |
|
100
|
|
|
* <code> |
|
101
|
|
|
* echo $this->Components()->Widget(...); |
|
102
|
|
|
* </code> |
|
103
|
|
|
* |
|
104
|
|
|
* @param string $method helper name or method name in container |
|
105
|
|
|
* @param array $arguments [optional] arguments to pass |
|
106
|
|
|
* @throws \Zend\View\Exception\ExceptionInterface if proxying to a helper, and the |
|
107
|
|
|
* helper is not an instance of the |
|
108
|
|
|
* interface specified in |
|
109
|
|
|
* {@link findHelper()} |
|
110
|
|
|
* @throws \Zend\View\Exception\ExceptionInterface if method does not exist in container |
|
111
|
|
|
* @return mixed returns what the proxied call returns |
|
112
|
|
|
*/ |
|
113
|
|
|
public function __call($method, array $arguments = []) |
|
114
|
|
|
{ |
|
115
|
|
|
// check if call should proxy to another helper |
|
116
|
|
|
$helper = $this->findHelper($method, false); |
|
117
|
|
|
if ($helper) { |
|
118
|
|
|
//if ($helper instanceof ServiceLocatorAwareInterface && $this->getServiceLocator()) { |
|
119
|
|
|
if (method_exists($helper, "setServiceLocator") && $this->getServiceLocator()) { |
|
120
|
|
|
$helper->setServiceLocator($this->getServiceLocator()); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
if (method_exists($helper, "setTranslator") && $this->getTranslator()) { |
|
124
|
|
|
$helper->setTranslator($this->getTranslator()); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
return call_user_func_array($helper, $arguments); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
// default behaviour: proxy call to container |
|
131
|
|
|
return parent::__call($method, $arguments); |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Sets navigation container the helper operates on by default |
|
136
|
|
|
* |
|
137
|
|
|
* Implements {@link HelperInterface::setContainer()}. |
|
138
|
|
|
* |
|
139
|
|
|
* @param string|Navigation\AbstractContainer $container Default is null, meaning container will be reset. |
|
140
|
|
|
* @return AbstractHelper |
|
141
|
|
|
*/ |
|
142
|
|
|
public function setContainer($container = null) |
|
143
|
|
|
{ |
|
144
|
|
|
$this->parseContainer($container); |
|
145
|
|
|
$this->container = $container; |
|
|
|
|
|
|
146
|
|
|
|
|
147
|
|
|
return $this; |
|
|
|
|
|
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Returns the navigation container helper operates on by default |
|
152
|
|
|
* |
|
153
|
|
|
* Implements {@link HelperInterface::getContainer()}. |
|
154
|
|
|
* |
|
155
|
|
|
* If no container is set, a new container will be instantiated and |
|
156
|
|
|
* stored in the helper. |
|
157
|
|
|
* |
|
158
|
|
|
* @return Navigation\AbstractContainer|\Zend\Navigation\AbstractContainer navigation container |
|
159
|
|
|
*/ |
|
160
|
|
|
public function getContainer() |
|
161
|
|
|
{ |
|
162
|
|
|
if (null === $this->container) { |
|
163
|
|
|
$this->container = new \UIComponents\Navigation\Navigation(); |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
|
|
return $this->container; |
|
|
|
|
|
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Renders helper |
|
171
|
|
|
* |
|
172
|
|
|
* @param AbstractContainer $container |
|
173
|
|
|
* @return string |
|
174
|
|
|
* @throws Exception\RuntimeException |
|
175
|
|
|
*/ |
|
176
|
|
|
public function render($container = null) |
|
177
|
|
|
{ |
|
178
|
|
|
return ''; |
|
179
|
|
|
//return $this->findHelper($this->getDefaultProxy())->render($container); |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
/** |
|
183
|
|
|
* Returns the helper matching $proxy |
|
184
|
|
|
* |
|
185
|
|
|
* The helper must implement the interface |
|
186
|
|
|
* {@link UIComponents\View\Helper\Components\HelperInterface}. |
|
187
|
|
|
* |
|
188
|
|
|
* @param string $proxy helper name |
|
189
|
|
|
* @param bool $strict [optional] whether exceptions should be |
|
190
|
|
|
* thrown if something goes |
|
191
|
|
|
* wrong. Default is true. |
|
192
|
|
|
* @throws Exception\RuntimeException if $strict is true and helper cannot be found |
|
193
|
|
|
* @return boolean|\UIComponents\View\Helper\Components\HelperInterface helper instance |
|
194
|
|
|
*/ |
|
195
|
|
|
public function findHelper($proxy, $strict = true) |
|
196
|
|
|
{ |
|
197
|
|
|
$plugins = $this->getPluginManager(); |
|
198
|
|
|
if (!$plugins->has($proxy)) { |
|
199
|
|
|
if ($strict) { |
|
200
|
|
|
throw new Exception\RuntimeException(sprintf( |
|
201
|
|
|
'Failed to find plugin for %s', |
|
202
|
|
|
$proxy |
|
203
|
|
|
)); |
|
204
|
|
|
} |
|
205
|
|
|
return false; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
$helper = $plugins->get($proxy); |
|
209
|
|
|
|
|
210
|
|
|
if ($helper && ($helper instanceof \Zend\View\Helper\Navigation\Menu)) { |
|
211
|
|
|
|
|
212
|
|
|
$container = $this->getContainer(); |
|
213
|
|
|
$hash = spl_object_hash($container) . spl_object_hash($helper); |
|
214
|
|
|
if (!isset($this->injected[$hash])) { |
|
215
|
|
|
$helper->setContainer(); |
|
216
|
|
|
$this->inject($helper); |
|
217
|
|
|
$this->injected[$hash] = true; |
|
218
|
|
|
} else { |
|
219
|
|
|
if ($this->getInjectContainer()) { |
|
220
|
|
|
$helper->setContainer($container); |
|
221
|
|
|
} |
|
222
|
|
|
} |
|
223
|
|
|
|
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
return $helper; |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Injects container, ACL, and translator to the given $helper if this |
|
231
|
|
|
* helper is configured to do so |
|
232
|
|
|
* |
|
233
|
|
|
* @param \Zend\View\Helper\AbstractHelper $helper helper instance |
|
234
|
|
|
* @return void |
|
235
|
|
|
*/ |
|
236
|
|
|
protected function inject(\Zend\View\Helper\AbstractHelper $helper) |
|
237
|
|
|
{ |
|
238
|
|
|
if ( |
|
239
|
|
|
($helper instanceof \UIComponents\View\Helper\AbstractHelper) || |
|
240
|
|
|
($helper instanceof \UIComponents\View\Helper\Navigation\Menu) |
|
241
|
|
|
) { |
|
242
|
|
|
if ($this->getInjectContainer() && !$helper->hasContainer()) { |
|
243
|
|
|
$helper->setContainer($this->getContainer()); |
|
|
|
|
|
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
if ($this->getInjectAcl()) { |
|
247
|
|
|
if (!$helper->hasAcl()) { |
|
248
|
|
|
$helper->setAcl($this->getAcl()); |
|
249
|
|
|
} |
|
250
|
|
|
if (!$helper->hasRole()) { |
|
251
|
|
|
$helper->setRole($this->getRole()); |
|
252
|
|
|
} |
|
253
|
|
|
} |
|
254
|
|
|
if ($this->getInjectTranslator() && !$helper->hasTranslator()) { |
|
255
|
|
|
$helper->setTranslator( |
|
256
|
|
|
$this->getTranslator(), |
|
257
|
|
|
$this->getTranslatorTextDomain() |
|
258
|
|
|
); |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
/** |
|
264
|
|
|
* Sets the default proxy to use in {@link render()} |
|
265
|
|
|
* |
|
266
|
|
|
* @param string $proxy default proxy |
|
267
|
|
|
* @return Bootstrap |
|
268
|
|
|
*/ |
|
269
|
|
|
public function setDefaultProxy($proxy) |
|
270
|
|
|
{ |
|
271
|
|
|
$this->defaultProxy = (string) $proxy; |
|
272
|
|
|
return $this; |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
/** |
|
276
|
|
|
* Returns the default proxy to use in {@link render()} |
|
277
|
|
|
* |
|
278
|
|
|
* @return string |
|
279
|
|
|
*/ |
|
280
|
|
|
public function getDefaultProxy() |
|
281
|
|
|
{ |
|
282
|
|
|
return $this->defaultProxy; |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
/** |
|
286
|
|
|
* Sets whether container should be injected when proxying |
|
287
|
|
|
* |
|
288
|
|
|
* @param bool $injectContainer |
|
289
|
|
|
* @return Bootstrap |
|
290
|
|
|
*/ |
|
291
|
|
|
public function setInjectContainer($injectContainer = true) |
|
292
|
|
|
{ |
|
293
|
|
|
$this->injectContainer = (bool) $injectContainer; |
|
294
|
|
|
return $this; |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
/** |
|
298
|
|
|
* Returns whether container should be injected when proxying |
|
299
|
|
|
* |
|
300
|
|
|
* @return bool |
|
301
|
|
|
*/ |
|
302
|
|
|
public function getInjectContainer() |
|
303
|
|
|
{ |
|
304
|
|
|
return $this->injectContainer; |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
/** |
|
308
|
|
|
* Sets whether ACL should be injected when proxying |
|
309
|
|
|
* |
|
310
|
|
|
* @param bool $injectAcl |
|
311
|
|
|
* @return NavigBootstrapation |
|
312
|
|
|
*/ |
|
313
|
|
|
public function setInjectAcl($injectAcl = true) |
|
314
|
|
|
{ |
|
315
|
|
|
$this->injectAcl = (bool) $injectAcl; |
|
316
|
|
|
return $this; |
|
317
|
|
|
} |
|
318
|
|
|
|
|
319
|
|
|
/** |
|
320
|
|
|
* Returns whether ACL should be injected when proxying |
|
321
|
|
|
* |
|
322
|
|
|
* @return bool |
|
323
|
|
|
*/ |
|
324
|
|
|
public function getInjectAcl() |
|
325
|
|
|
{ |
|
326
|
|
|
return $this->injectAcl; |
|
327
|
|
|
} |
|
328
|
|
|
|
|
329
|
|
|
/** |
|
330
|
|
|
* Sets whether translator should be injected when proxying |
|
331
|
|
|
* |
|
332
|
|
|
* @param bool $injectTranslator |
|
333
|
|
|
* @return Bootstrap |
|
334
|
|
|
*/ |
|
335
|
|
|
public function setInjectTranslator($injectTranslator = true) |
|
336
|
|
|
{ |
|
337
|
|
|
$this->injectTranslator = (bool) $injectTranslator; |
|
338
|
|
|
return $this; |
|
339
|
|
|
} |
|
340
|
|
|
|
|
341
|
|
|
/** |
|
342
|
|
|
* Returns whether translator should be injected when proxying |
|
343
|
|
|
* |
|
344
|
|
|
* @return bool |
|
345
|
|
|
*/ |
|
346
|
|
|
public function getInjectTranslator() |
|
347
|
|
|
{ |
|
348
|
|
|
return $this->injectTranslator; |
|
349
|
|
|
} |
|
350
|
|
|
|
|
351
|
|
|
/** |
|
352
|
|
|
* Set manager for retrieving navigation helpers |
|
353
|
|
|
* |
|
354
|
|
|
* @param Components\PluginManager $plugins |
|
355
|
|
|
* @return Components |
|
356
|
|
|
*/ |
|
357
|
|
|
public function setPluginManager(AbstractPluginManager $plugins) |
|
358
|
|
|
{ |
|
359
|
|
|
$renderer = $this->getView(); |
|
360
|
|
|
if ($renderer) { |
|
361
|
|
|
$plugins->setRenderer($renderer); |
|
362
|
|
|
} |
|
363
|
|
|
$this->plugins = $plugins; |
|
|
|
|
|
|
364
|
|
|
|
|
365
|
|
|
return $this; |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
/** |
|
369
|
|
|
* Retrieve plugin loader for navigation helpers |
|
370
|
|
|
* |
|
371
|
|
|
* Lazy-loads an instance of Navigation\HelperLoader if none currently |
|
372
|
|
|
* registered. |
|
373
|
|
|
* |
|
374
|
|
|
* @return Components\PluginManager |
|
375
|
|
|
*/ |
|
376
|
|
|
public function getPluginManager() |
|
377
|
|
|
{ |
|
378
|
|
|
if (null === $this->plugins) { |
|
379
|
|
|
$this->setPluginManager(new Components\PluginManager()); |
|
380
|
|
|
} |
|
381
|
|
|
|
|
382
|
|
|
return $this->plugins; |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
|
|
/** |
|
386
|
|
|
* Set the View object |
|
387
|
|
|
* |
|
388
|
|
|
* @param Renderer $view |
|
389
|
|
|
* @return self |
|
390
|
|
|
*/ |
|
391
|
|
|
public function setView(Renderer $view) |
|
392
|
|
|
{ |
|
393
|
|
|
parent::setView($view); |
|
394
|
|
|
if ($view && $this->plugins) { |
|
395
|
|
|
$this->plugins->setRenderer($view); |
|
396
|
|
|
} |
|
397
|
|
|
return $this; |
|
398
|
|
|
} |
|
399
|
|
|
} |
|
400
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.