Passed
Push — master ( f812d5...20cedb )
by Adam
02:03
created

Control   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 330
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 1.18%

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 8
dl 0
loc 330
ccs 1
cts 85
cp 0.0118
rs 8.2857
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 21 1
A attached() 0 14 2
C render() 0 44 11
A setDecorator() 0 17 3
A setGroup() 0 4 1
A getGroup() 0 4 1
B getWidgets() 0 21 5
C addWidget() 0 49 8
A createData() 0 19 4
A __call() 0 16 3
1
<?php
2
/**
3
 * Control.php
4
 *
5
 * @copyright      Vice v copyright.php
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec https://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\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
32
/**
33
 * Widgets container control definition
34
 *
35
 * @package        iPublikuj:Widgets!
36
 * @subpackage     Components
37
 *                 
38
 * @author         Adam Kadlec <[email protected]>
39
 *
40
 * @method onAttached(Application\UI\Control $component)
41
 *
42
 * @property Application\UI\ITemplate $template
43
 */
44 1
class Control extends UI\BaseControl
45
{
46
	/**
47
	 * @var array
48
	 */
49
	public $onAttached = [];
50
51
	/**
52
	 * @var Managers\WidgetsManager
53
	 */
54
	protected $widgetsManager;
55
56
	/**
57
	 * @var Managers\DecoratorsManager
58
	 */
59
	protected $decoratorsManager;
60
61
	/**
62
	 * @var Managers\FiltersManager
63
	 */
64
	protected $filtersManager;
65
66
	/**
67
	 * @var string
68
	 */
69
	protected $position;
70
71
	/**
72
	 * @var Decorators\IFactory
73
	 */
74
	protected $decorator;
75
76
	/**
77
	 * @var string
78
	 */
79
	protected $group = 'default';
80
81
	/**
82
	 * @param string $position
83
	 * @param Managers\WidgetsManager $widgetsManager
84
	 * @param Managers\DecoratorsManager $decoratorsManager
85
	 * @param Managers\FiltersManager $filtersManager
86
	 * @param ComponentModel\IContainer|NULL $parent
87
	 * @param string|NULL $name
88
	 */
89
	public function __construct(
90
		string $position = 'default',
91
		Managers\WidgetsManager $widgetsManager,
92
		Managers\DecoratorsManager $decoratorsManager,
93
		Managers\FiltersManager $filtersManager,
94
		?ComponentModel\IContainer $parent = NULL,
95
		?string $name = NULL
96
	) {
97
		parent::__construct($parent, $name);
98
99
		// Store info about widgets position
100
		$this->position = $position;
101
102
		// Extension managers
103
		$this->widgetsManager = $widgetsManager;
104
		$this->decoratorsManager = $decoratorsManager;
105
		$this->filtersManager = $filtersManager;
106
107
		// Register widgets container
108
		$this->addComponent(new ComponentModel\Container(), 'widgets');
109
	}
110
111
	/**
112
	 * Attach component to presenter
113
	 *
114
	 * @param Application\UI\Presenter $presenter
115
	 *
116
	 * @throws Exceptions\DecoratorNotRegisteredException
117
	 */
118
	protected function attached($presenter) : void
119
	{
120
		parent::attached($presenter);
121
122
		if (!$presenter instanceof Application\UI\Presenter) {
0 ignored issues
show
Bug introduced by
The class Nette\Application\UI\Presenter does not exist. Did you forget a USE statement, or did you not list all dependencies?

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 the composer.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 or require-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 ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
123
			return;
124
		}
125
126
		// Register default raw widget decorator
127
		$this->setDecorator('widgets.decorator.raw');
128
129
		// Call attached event
130
		$this->onAttached($this);
131
	}
132
133
	/**
134
	 * Render widgets in selected position
135
	 */
136
	public function render() : void
137
	{
138
		foreach (func_get_args() as $arg) {
139
			// Check if decorator name is provided
140
			if (is_string($arg)) {
141
				$this->setDecorator($arg);
142
143
			} elseif (is_array($arg)) {
144
				if (array_key_exists('group', $arg)) {
145
					$this->setGroup($arg['group']);
146
147
				} elseif (array_key_exists('decorator', $arg)) {
148
					$this->setDecorator($arg['decorator']);
149
				}
150
			}
151
		}
152
153
		// Check if control has template
154
		if ($this->template instanceof Bridges\ApplicationLatte\Template) {
0 ignored issues
show
Bug introduced by
The class Nette\Bridges\ApplicationLatte\Template does not exist. Did you forget a USE statement, or did you not list all dependencies?

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 the composer.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 or require-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 ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
155
			// Assign vars to template
156
			$this->template->add('widgets', $this->getWidgets());
157
158
			// Check if translator is available
159
			if ($this->getTranslator() instanceof Localization\ITranslator) {
0 ignored issues
show
Bug introduced by
The class Nette\Localization\ITranslator does not exist. Did you forget a USE statement, or did you not list all dependencies?

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 the composer.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 or require-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 ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
160
				$this->template->setTranslator($this->getTranslator());
161
			}
162
163
			// If template was not defined before...
164
			if ($this->template->getFile() === NULL) {
165
				// Get component actual dir
166
				$dir = dirname($this->getReflection()->getFileName());
167
168
				// ...try to get base component template file
169
				$templateFile = $this->templateFile !== NULL && is_file($this->templateFile) ? $this->templateFile : $dir . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'default.latte';
170
				$this->template->setFile($templateFile);
171
			}
172
173
			// Render component template
174
			$this->template->render();
175
176
		} else {
177
			throw new Exceptions\InvalidStateException('Widgets container control is without template.');
178
		}
179
	}
180
181
	/**
182
	 * Set widgets outer decorator
183
	 *
184
	 * @param string $decorator
185
	 *
186
	 * @return void
187
	 *
188
	 * @throws Exceptions\DecoratorNotRegisteredException
189
	 */
190
	public function setDecorator(string $decorator) : void
191
	{
192
		// Try to find decorator factory
193
		if ($factory = $this->decoratorsManager->get($decorator)) {
194
			// Check if some decorator is registered...
195
			if ($component = $this->getComponent('decorator', FALSE)) {
196
				// ... if yes, remove it
197
				$this->removeComponent($component);
198
			}
199
200
			// Register decorator component
201
			$this->addComponent($factory->create(), 'decorator');
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<IPub\Widgets\Decorators\IFactory>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
202
203
		} else {
204
			throw new Exceptions\DecoratorNotRegisteredException(sprintf('Widgets decorator: "%s" is not registered.', $decorator));
205
		}
206
	}
207
208
	/**
209
	 * Set widgets group
210
	 *
211
	 * @param string $group
212
	 *
213
	 * @return void
214
	 */
215
	public function setGroup(string $group) : void
216
	{
217
		$this->group = $group;
218
	}
219
220
	/**
221
	 * Get widgets group
222
	 *
223
	 * @return string
224
	 */
225
	public function getGroup() : string
226
	{
227
		return $this->group;
228
	}
229
230
	/**
231
	 * Get all registered widgets in position
232
	 *
233
	 * @return array
234
	 */
235
	public function getWidgets() : array
236
	{
237
		if (
238
			($container = $this->getComponent('widgets')->getComponent($this->group, FALSE))
239
			&& ($positionContainer = $container->getComponent($this->position, FALSE))
240
			&& ($widgets = $positionContainer->getComponents())
241
		) {
242
			// Apply widgets filters
243
			foreach ($this->filtersManager as $filter) {
244
					$widgets = $filter->create($widgets, [
245
						'access' => TRUE,
246
						'active' => TRUE,
247
						'status' => 1,
248
					]);
249
			}
250
251
			return $widgets;
252
		}
253
254
		return [];
255
	}
256
257
	/**
258
	 * Add widget to container
259
	 *
260
	 * @param string|Widgets\IFactory $name
261
	 * @param array $data
262
	 * @param string|NULL $group
263
	 * @param string|NULL $position
264
	 *
265
	 * @return Widgets\IWidget
266
	 *
267
	 * @throws Exceptions\WidgetNotRegisteredException
268
	 * @throws Exceptions\InvalidStateException
269
	 */
270
	public function addWidget($name, array $data = [], string $group = NULL, string $position = NULL) : Widgets\IWidget
271
	{
272
		if ($position === NULL) {
273
			$position = $this->position;
274
		}
275
276
		if ($group === NULL) {
277
			$group = $this->group;
278
		}
279
280
		// Prepare widget settings data
281
		$data = $this->createData($data);
282
283
		if (is_string($name)) {
284
			if (!$factory = $this->widgetsManager->get($name, $group)) {
285
				throw new Exceptions\WidgetNotRegisteredException(sprintf('Widget of type "%s" in group "%s" is not registered.', $name, $group));
286
			}
287
288
		} elseif (!$name instanceof Widgets\IFactory) {
289
			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)));
290
291
		} else {
292
			$factory = $name;
293
		}
294
295
		// Check container exist
296
		$container = $this->getComponent('widgets')->getComponent($group, FALSE);
297
298
		if (!$container) {
299
			$this->getComponent('widgets')->addComponent(new ComponentModel\Container, $group);
300
			$container = $this->getComponent('widgets')->getComponent($group);
301
		}
302
303
		// Check container exist
304
		$positionContainer = $container->getComponent($position, FALSE);
305
306
		if (!$positionContainer) {
307
			$container->addComponent(new ComponentModel\Container, $position);
308
			$positionContainer = $container->getComponent($position);
309
		}
310
311
		// Create component
312
		$widget = $factory->create($data);
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<IPub\Widgets\Widgets\IFactory>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
313
314
		// Add widget component to container/position
315
		$positionContainer->addComponent($widget, ($widget->getName() . spl_object_hash($data)));
316
317
		return $widget;
318
	}
319
320
	/**
321
	 * Convert data to object
322
	 *
323
	 * @param mixed $data
324
	 *
325
	 * @return Entities\IData
326
	 *
327
	 * @throws Exceptions\InvalidStateException
328
	 */
329
	private function createData($data) : Entities\IData
330
	{
331
		// Data are in required object
332
		if ($data instanceof Entities\IData) {
333
			return $data;
334
335
		// or data are in array
336
		} elseif (is_array($data)) {
337
			// Create new data object
338
			return (new Entities\Data($data));
339
340
		// or data are in ArrayHash object
341
		} elseif ($data instanceof Utils\ArrayHash) {
0 ignored issues
show
Bug introduced by
The class Nette\Utils\ArrayHash does not exist. Did you forget a USE statement, or did you not list all dependencies?

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 the composer.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 or require-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 ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
342
			// Create new data object
343
			return (new Entities\Data((array) $data));
344
		}
345
346
		throw new Exceptions\InvalidStateException('Widget data could not be converted to data entity.');
347
	}
348
349
	/**
350
	 * @param string $name
351
	 * @param mixed $args
352
	 *
353
	 * @return mixed
354
	 *
355
	 * @throws Exceptions\DecoratorNotRegisteredException
356
	 */
357
	public function __call($name, $args)
358
	{
359
		if (Utils\Strings::startsWith($name, 'render')) {
360
			// Get decorator name
361
			if ($decoratorName = Utils\Strings::capitalize(Utils\Strings::substring($name, 6))) {
362
				// Set widget decorator
363
				$this->setDecorator($decoratorName);
364
			}
365
366
			// Call component rendering
367
			$this->render();
368
369
		} else {
370
			return parent::__call($name, $args);
371
		}
372
	}
373
}
374