1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Control.php |
4
|
|
|
* |
5
|
|
|
* @copyright Vice v copyright.php |
6
|
|
|
* @license https://www.ipublikuj.eu |
7
|
|
|
* @author Adam Kadlec <[email protected]> |
8
|
|
|
* @package iPublikuj:Widgets! |
9
|
|
|
* @subpackage Components |
10
|
|
|
* @since 1.0.0 |
11
|
|
|
* |
12
|
|
|
* @date 24.07.13 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
declare(strict_types = 1); |
16
|
|
|
|
17
|
|
|
namespace IPub\Widgets\Components; |
18
|
|
|
|
19
|
|
|
use Nette\Application; |
20
|
|
|
use Nette\Bridges; |
21
|
|
|
use Nette\ComponentModel; |
22
|
|
|
use Nette\Localization; |
23
|
|
|
use Nette\Utils; |
24
|
|
|
|
25
|
|
|
use IPub\Widgets\Application\UI; |
26
|
|
|
use IPub\Widgets\Decorators; |
27
|
|
|
use IPub\Widgets\Entities; |
28
|
|
|
use IPub\Widgets\Exceptions; |
29
|
|
|
use IPub\Widgets\Managers; |
30
|
|
|
use IPub\Widgets\Widgets; |
31
|
|
|
use Tracy\Debugger; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Widgets container control definition |
35
|
|
|
* |
36
|
|
|
* @package iPublikuj:Widgets! |
37
|
|
|
* @subpackage Components |
38
|
|
|
* |
39
|
|
|
* @author Adam Kadlec <[email protected]> |
40
|
|
|
* |
41
|
|
|
* @method onAttached(Application\UI\Control $component) |
42
|
|
|
* |
43
|
|
|
* @property Application\UI\ITemplate $template |
44
|
|
|
*/ |
45
|
1 |
|
class Control extends UI\BaseControl |
46
|
|
|
{ |
47
|
|
|
/** |
48
|
|
|
* @var array |
49
|
|
|
*/ |
50
|
|
|
public $onAttached = []; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var Managers\WidgetsManager |
54
|
|
|
*/ |
55
|
|
|
protected $widgetsManager; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @var Managers\DecoratorsManager |
59
|
|
|
*/ |
60
|
|
|
protected $decoratorsManager; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @var Managers\FiltersManager |
64
|
|
|
*/ |
65
|
|
|
protected $filtersManager; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @var string |
69
|
|
|
*/ |
70
|
|
|
protected $position; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @var Decorators\IFactory |
74
|
|
|
*/ |
75
|
|
|
protected $decorator; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @var string |
79
|
|
|
*/ |
80
|
|
|
protected $group = 'default'; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @param string $position |
84
|
|
|
* @param Managers\WidgetsManager $widgetsManager |
85
|
|
|
* @param Managers\DecoratorsManager $decoratorsManager |
86
|
|
|
* @param Managers\FiltersManager $filtersManager |
87
|
|
|
* @param ComponentModel\IContainer|NULL $parent |
88
|
|
|
* @param string|NULL $name |
89
|
|
|
*/ |
90
|
|
|
public function __construct( |
91
|
|
|
string $position = 'default', |
92
|
|
|
Managers\WidgetsManager $widgetsManager, |
93
|
|
|
Managers\DecoratorsManager $decoratorsManager, |
94
|
|
|
Managers\FiltersManager $filtersManager, |
95
|
|
|
?ComponentModel\IContainer $parent = NULL, |
96
|
|
|
?string $name = NULL |
97
|
|
|
) { |
98
|
|
|
parent::__construct($parent, $name); |
99
|
|
|
|
100
|
|
|
// Store info about widgets position |
101
|
|
|
$this->position = $position; |
102
|
|
|
|
103
|
|
|
// Extension managers |
104
|
|
|
$this->widgetsManager = $widgetsManager; |
105
|
|
|
$this->decoratorsManager = $decoratorsManager; |
106
|
|
|
$this->filtersManager = $filtersManager; |
107
|
|
|
|
108
|
|
|
// Register widgets container |
109
|
|
|
$this->addComponent(new ComponentModel\Container, 'widgets'); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Attach component to presenter |
114
|
|
|
* |
115
|
|
|
* @param Application\UI\Presenter $presenter |
116
|
|
|
* |
117
|
|
|
* @throws Exceptions\DecoratorNotRegisteredException |
118
|
|
|
*/ |
119
|
|
|
protected function attached($presenter) : void |
120
|
|
|
{ |
121
|
|
|
parent::attached($presenter); |
122
|
|
|
|
123
|
|
|
if (!$presenter instanceof Application\UI\Presenter) { |
|
|
|
|
124
|
|
|
return; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
// Register default raw widget decorator |
128
|
|
|
$this->setDecorator('widgets.decorator.raw'); |
129
|
|
|
|
130
|
|
|
// Call attached event |
131
|
|
|
$this->onAttached($this); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Render widgets in selected position |
136
|
|
|
*/ |
137
|
|
|
public function render() : void |
138
|
|
|
{ |
139
|
|
|
foreach (func_get_args() as $arg) { |
140
|
|
|
// Check if decorator name is provided |
141
|
|
|
if (is_string($arg)) { |
142
|
|
|
$this->setDecorator($arg); |
143
|
|
|
|
144
|
|
|
} elseif (is_array($arg)) { |
145
|
|
|
if (array_key_exists('group', $arg)) { |
146
|
|
|
$this->setGroup($arg['group']); |
147
|
|
|
|
148
|
|
|
} elseif (array_key_exists('decorator', $arg)) { |
149
|
|
|
$this->setDecorator($arg['decorator']); |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// Check if control has template |
155
|
|
|
if ($this->template instanceof Bridges\ApplicationLatte\Template) { |
|
|
|
|
156
|
|
|
$widgets = $this->getWidgets(); |
157
|
|
|
|
158
|
|
|
// Assign vars to template |
159
|
|
|
$this->template->add('widgets', $widgets !== NULL ? $widgets : []); |
160
|
|
|
|
161
|
|
|
// Check if translator is available |
162
|
|
|
if ($this->getTranslator() instanceof Localization\ITranslator) { |
|
|
|
|
163
|
|
|
$this->template->setTranslator($this->getTranslator()); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
// If template was not defined before... |
167
|
|
|
if ($this->template->getFile() === NULL) { |
168
|
|
|
// Get component actual dir |
169
|
|
|
$dir = dirname($this->getReflection()->getFileName()); |
170
|
|
|
|
171
|
|
|
// ...try to get base component template file |
172
|
|
|
$templateFile = $this->templateFile !== NULL && is_file($this->templateFile) ? $this->templateFile : $dir . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'default.latte'; |
173
|
|
|
$this->template->setFile($templateFile); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
// Render component template |
177
|
|
|
$this->template->render(); |
178
|
|
|
|
179
|
|
|
} else { |
180
|
|
|
throw new Exceptions\InvalidStateException('Widgets container control is without template.'); |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Set widgets outer decorator |
186
|
|
|
* |
187
|
|
|
* @param string $decorator |
188
|
|
|
* |
189
|
|
|
* @return void |
190
|
|
|
* |
191
|
|
|
* @throws Exceptions\DecoratorNotRegisteredException |
192
|
|
|
*/ |
193
|
|
|
public function setDecorator(string $decorator) : void |
194
|
|
|
{ |
195
|
|
|
// Try to find decorator factory |
196
|
|
|
if ($factory = $this->decoratorsManager->get($decorator)) { |
197
|
|
|
// Check if some decorator is registered... |
198
|
|
|
if ($component = $this->getComponent('decorator', FALSE)) { |
199
|
|
|
// ... if yes, remove it |
200
|
|
|
$this->removeComponent($component); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
// Register decorator component |
204
|
|
|
$this->addComponent($factory->create(), 'decorator'); |
|
|
|
|
205
|
|
|
|
206
|
|
|
} else { |
207
|
|
|
throw new Exceptions\DecoratorNotRegisteredException(sprintf('Widgets decorator: "%s" is not registered.', $decorator)); |
208
|
|
|
} |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Set widgets group |
213
|
|
|
* |
214
|
|
|
* @param string $group |
215
|
|
|
* |
216
|
|
|
* @return void |
217
|
|
|
*/ |
218
|
|
|
public function setGroup(string $group) : void |
219
|
|
|
{ |
220
|
|
|
$this->group = $group; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Get widgets group |
225
|
|
|
* |
226
|
|
|
* @return string |
227
|
|
|
*/ |
228
|
|
|
public function getGroup() : string |
229
|
|
|
{ |
230
|
|
|
return $this->group; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Get all registered widgets in position |
235
|
|
|
* |
236
|
|
|
* @return \Iterator|NULL |
237
|
|
|
*/ |
238
|
|
|
public function getWidgets() : ?\Iterator |
239
|
|
|
{ |
240
|
|
|
if ( |
241
|
|
|
($container = $this->getComponent('widgets')->getComponent($this->group, FALSE)) |
242
|
|
|
&& ($positionContainer = $container->getComponent($this->position, FALSE)) |
243
|
|
|
&& ($widgets = $positionContainer->getComponents()) |
244
|
|
|
) { |
245
|
|
|
/* |
|
|
|
|
246
|
|
|
// Apply widgets filters |
247
|
|
|
foreach ($this->filtersManager as $filter) { |
248
|
|
|
$widgets = $filter->create($widgets, [ |
249
|
|
|
'access' => TRUE, |
250
|
|
|
'active' => TRUE, |
251
|
|
|
'status' => 1, |
252
|
|
|
]); |
253
|
|
|
} |
254
|
|
|
*/ |
255
|
|
|
|
256
|
|
|
return $widgets; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
return NULL; |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* Add widget to container |
264
|
|
|
* |
265
|
|
|
* @param string|Widgets\IFactory $name |
266
|
|
|
* @param array $data |
267
|
|
|
* @param string|NULL $group |
268
|
|
|
* @param string|NULL $position |
269
|
|
|
* |
270
|
|
|
* @return Widgets\IWidget |
271
|
|
|
* |
272
|
|
|
* @throws Exceptions\WidgetNotRegisteredException |
273
|
|
|
* @throws Exceptions\InvalidStateException |
274
|
|
|
*/ |
275
|
|
|
public function addWidget($name, array $data = [], string $group = NULL, string $position = NULL) : Widgets\IWidget |
276
|
|
|
{ |
277
|
|
|
if ($position === NULL) { |
278
|
|
|
$position = $this->position; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
if ($group === NULL) { |
282
|
|
|
$group = $this->group; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
// Prepare widget settings data |
286
|
|
|
$data = $this->createData($data); |
287
|
|
|
|
288
|
|
|
if (is_string($name)) { |
289
|
|
|
if (!$factory = $this->widgetsManager->get($name, $group)) { |
290
|
|
|
throw new Exceptions\WidgetNotRegisteredException(sprintf('Widget of type "%s" in group "%s" is not registered.', $name, $group)); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
} elseif (!$name instanceof Widgets\IFactory) { |
294
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Provided service is not valid widgets factory service. Instance of IPub\Widgets\Widgets\IFactory expected, instance of %s provided', get_class($name))); |
295
|
|
|
|
296
|
|
|
} else { |
297
|
|
|
$factory = $name; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** @var ComponentModel\Container $container */ |
301
|
|
|
$container = $this->getComponent('widgets')->getComponent($group, FALSE); |
302
|
|
|
|
303
|
|
|
if (!$container) { |
304
|
|
|
$this->getComponent('widgets')->addComponent(new ComponentModel\Container, $group); |
305
|
|
|
|
306
|
|
|
/** @var ComponentModel\Container $container */ |
307
|
|
|
$container = $this->getComponent('widgets')->getComponent($group); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** @var ComponentModel\Container $positionContainer */ |
311
|
|
|
$positionContainer = $container->getComponent($position, FALSE); |
312
|
|
|
|
313
|
|
|
if (!$positionContainer) { |
314
|
|
|
$container->addComponent(new ComponentModel\Container, $position); |
315
|
|
|
|
316
|
|
|
/** @var ComponentModel\Container $positionContainer */ |
317
|
|
|
$positionContainer = $container->getComponent($position); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
// Create component |
321
|
|
|
$widget = $factory->create($data); |
|
|
|
|
322
|
|
|
|
323
|
|
|
// Add widget component to container/position |
324
|
|
|
$positionContainer->addComponent($widget, ($widget->getName() . spl_object_hash($data))); |
325
|
|
|
|
326
|
|
|
return $widget; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* Convert data to object |
331
|
|
|
* |
332
|
|
|
* @param mixed $data |
333
|
|
|
* |
334
|
|
|
* @return Entities\IData |
335
|
|
|
* |
336
|
|
|
* @throws Exceptions\InvalidStateException |
337
|
|
|
*/ |
338
|
|
|
private function createData($data) : Entities\IData |
339
|
|
|
{ |
340
|
|
|
// Data are in required object |
341
|
|
|
if ($data instanceof Entities\IData) { |
342
|
|
|
return $data; |
343
|
|
|
|
344
|
|
|
// or data are in array |
345
|
|
|
} elseif (is_array($data)) { |
346
|
|
|
// Create new data object |
347
|
|
|
return (new Entities\Data($data)); |
348
|
|
|
|
349
|
|
|
// or data are in ArrayHash object |
350
|
|
|
} elseif ($data instanceof Utils\ArrayHash) { |
|
|
|
|
351
|
|
|
// Create new data object |
352
|
|
|
return (new Entities\Data((array) $data)); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
throw new Exceptions\InvalidStateException('Widget data could not be converted to data entity.'); |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* @param string $name |
360
|
|
|
* @param mixed $args |
361
|
|
|
* |
362
|
|
|
* @return mixed |
363
|
|
|
* |
364
|
|
|
* @throws Exceptions\DecoratorNotRegisteredException |
365
|
|
|
*/ |
366
|
|
|
public function __call($name, $args) |
367
|
|
|
{ |
368
|
|
|
if (Utils\Strings::startsWith($name, 'render')) { |
369
|
|
|
// Get decorator name |
370
|
|
|
if ($decoratorName = Utils\Strings::capitalize(Utils\Strings::substring($name, 6))) { |
371
|
|
|
// Set widget decorator |
372
|
|
|
$this->setDecorator($decoratorName); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// Call component rendering |
376
|
|
|
$this->render(); |
377
|
|
|
|
378
|
|
|
} else { |
379
|
|
|
return parent::__call($name, $args); |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.