1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Control.php |
4
|
|
|
* |
5
|
|
|
* @copyright Vice v copyright.php |
6
|
|
|
* @license http://www.ipublikuj.eu |
7
|
|
|
* @author Adam Kadlec http://www.ipublikuj.eu |
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; |
20
|
|
|
use Nette\Application; |
21
|
|
|
use Nette\ComponentModel; |
22
|
|
|
use Nette\Localization; |
23
|
|
|
use Nette\Utils; |
24
|
|
|
|
25
|
|
|
use IPub; |
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 IPub\Widgets\Application\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 $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) |
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() |
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
|
|
|
} |
145
|
|
|
|
146
|
|
|
// Check if control has template |
147
|
|
|
if ($this->template instanceof Nette\Bridges\ApplicationLatte\Template) { |
148
|
|
|
// Assign vars to template |
149
|
|
|
$this->template->add('widgets', $this->getWidgets()); |
150
|
|
|
|
151
|
|
|
// Check if translator is available |
152
|
|
|
if ($this->getTranslator() instanceof Localization\ITranslator) { |
153
|
|
|
$this->template->setTranslator($this->getTranslator()); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
// If template was not defined before... |
157
|
|
View Code Duplication |
if ($this->template->getFile() === NULL) { |
|
|
|
|
158
|
|
|
// Get component actual dir |
159
|
|
|
$dir = dirname($this->getReflection()->getFileName()); |
160
|
|
|
|
161
|
|
|
// ...try to get base component template file |
162
|
|
|
$templateFile = $this->templateFile !== NULL && is_file($this->templateFile) ? $this->templateFile : $dir . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'default.latte'; |
163
|
|
|
$this->template->setFile($templateFile); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
// Render component template |
167
|
|
|
$this->template->render(); |
168
|
|
|
|
169
|
|
|
} else { |
170
|
|
|
throw new Exceptions\InvalidStateException('Widgets container control is without template.'); |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Set widgets outer decorator |
176
|
|
|
* |
177
|
|
|
* @param string $decorator |
178
|
|
|
* |
179
|
|
|
* @throws Exceptions\DecoratorNotRegisteredException |
180
|
|
|
*/ |
181
|
|
|
public function setDecorator(string $decorator) |
182
|
|
|
{ |
183
|
|
|
// Try to find decorator factory |
184
|
|
|
if ($factory = $this->decoratorsManager->get($decorator)) { |
185
|
|
|
// Check if some decorator is registered... |
186
|
|
|
if ($component = $this->getComponent('decorator', FALSE)) { |
187
|
|
|
// ... if yes, remove it |
188
|
|
|
$this->removeComponent($component); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
// Register decorator component |
192
|
|
|
$this->addComponent($factory->create(), 'decorator'); |
|
|
|
|
193
|
|
|
|
194
|
|
|
} else { |
195
|
|
|
throw new Exceptions\DecoratorNotRegisteredException(sprintf('Widgets decorator: "%s" is not registered.', $decorator)); |
196
|
|
|
} |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Set widgets group |
201
|
|
|
* |
202
|
|
|
* @param string $group |
203
|
|
|
*/ |
204
|
|
|
public function setGroup(string $group) |
205
|
|
|
{ |
206
|
|
|
$this->group = $group; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Get widgets group |
211
|
|
|
* |
212
|
|
|
* @return string |
213
|
|
|
*/ |
214
|
|
|
public function getGroup() : string |
215
|
|
|
{ |
216
|
|
|
return $this->group; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Get all registered widgets in position |
221
|
|
|
* |
222
|
|
|
* @return array |
223
|
|
|
*/ |
224
|
|
|
public function getWidgets() |
225
|
|
|
{ |
226
|
|
|
if ( |
227
|
|
|
($container = $this->getComponent('widgets')->getComponent($this->group, FALSE)) |
|
|
|
|
228
|
|
|
&& ($positionContainer = $container->getComponent($this->position, FALSE)) |
229
|
|
|
&& ($widgets = $positionContainer->getComponents()) |
230
|
|
|
) { |
231
|
|
|
// Apply widgets filters |
232
|
|
|
foreach ($this->filtersManager as $filter) { |
233
|
|
|
$widgets = $filter->create($widgets, [ |
234
|
|
|
'access' => TRUE, |
235
|
|
|
'active' => TRUE, |
236
|
|
|
'status' => 1, |
237
|
|
|
]); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
return $widgets; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
return []; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Add widget to container |
248
|
|
|
* |
249
|
|
|
* @param string $name |
250
|
|
|
* @param array $data |
251
|
|
|
* @param string|NULL $group |
252
|
|
|
* @param string|NULL $position |
253
|
|
|
* |
254
|
|
|
* @throws Exceptions\WidgetNotRegisteredException |
255
|
|
|
* @throws Exceptions\InvalidStateException |
256
|
|
|
*/ |
257
|
|
|
public function addWidget(string $name, array $data = [], string $group = NULL, string $position = NULL) |
258
|
|
|
{ |
259
|
|
|
if ($position === NULL) { |
260
|
|
|
$position = $this->position; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
if ($group === NULL) { |
264
|
|
|
$group = $this->group; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
// Prepare widget settings data |
268
|
|
|
$data = $this->createData($data); |
269
|
|
|
|
270
|
|
|
if (!$factory = $this->widgetsManager->get($name, $group)) { |
271
|
|
|
throw new Exceptions\WidgetNotRegisteredException(sprintf('Widget of type "%s" in group "%s" is not registered.', $name, $group)); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
// Check container exist |
275
|
|
|
$container = $this->getComponent('widgets')->getComponent($group, FALSE); |
|
|
|
|
276
|
|
|
|
277
|
|
|
if (!$container) { |
278
|
|
|
$this->getComponent('widgets')->addComponent(new Nette\ComponentModel\Container, $group); |
|
|
|
|
279
|
|
|
$container = $this->getComponent('widgets')->getComponent($group); |
|
|
|
|
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
// Check container exist |
283
|
|
|
$positionContainer = $container->getComponent($position, FALSE); |
284
|
|
|
|
285
|
|
|
if (!$positionContainer) { |
286
|
|
|
$container->addComponent(new Nette\ComponentModel\Container, $position); |
287
|
|
|
$positionContainer = $container->getComponent($position); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
// Create component |
291
|
|
|
$widget = $factory->create($data); |
|
|
|
|
292
|
|
|
|
293
|
|
|
// Add widget component to container/position |
294
|
|
|
$positionContainer->addComponent($widget, ($widget->getName() . spl_object_hash($data))); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Convert data to object |
299
|
|
|
* |
300
|
|
|
* @param mixed $data |
301
|
|
|
* |
302
|
|
|
* @return Entities\IData |
303
|
|
|
* |
304
|
|
|
* @throws Exceptions\InvalidStateException |
305
|
|
|
*/ |
306
|
|
|
private function createData($data) : Entities\IData |
307
|
|
|
{ |
308
|
|
|
// Data are in required object |
309
|
|
|
if ($data instanceof Entities\IData) { |
310
|
|
|
return $data; |
311
|
|
|
|
312
|
|
|
// or data are in array |
313
|
|
|
} elseif (is_array($data)) { |
314
|
|
|
// Create new data object |
315
|
|
|
return (new Entities\Data($data)); |
316
|
|
|
|
317
|
|
|
// or data are in ArrayHash object |
318
|
|
|
} elseif ($data instanceof Utils\ArrayHash) { |
319
|
|
|
// Create new data object |
320
|
|
|
return (new Entities\Data((array) $data)); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
throw new Exceptions\InvalidStateException('Widget data could not be converted to data entity.'); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* @param string $name |
328
|
|
|
* @param mixed $args |
329
|
|
|
* |
330
|
|
|
* @return mixed |
331
|
|
|
* |
332
|
|
|
* @throws Exceptions\DecoratorNotRegisteredException |
333
|
|
|
*/ |
334
|
|
|
public function __call($name, $args) |
335
|
|
|
{ |
336
|
|
|
if (Utils\Strings::startsWith($name, 'render')) { |
337
|
|
|
// Get decorator name |
338
|
|
|
if ($decoratorName = Utils\Strings::capitalize(Utils\Strings::substring($name, 6))) { |
339
|
|
|
// Set widget decorator |
340
|
|
|
$this->setDecorator($decoratorName); |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
// Call component rendering |
344
|
|
|
$this->render(); |
345
|
|
|
|
346
|
|
|
} else { |
347
|
|
|
return parent::__call($name, $args); |
348
|
|
|
} |
349
|
|
|
} |
350
|
|
|
} |
351
|
|
|
|
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.