Control::addWidget()   B
last analyzed

Complexity

Conditions 8
Paths 40

Size

Total Lines 53
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 0
cts 22
cp 0
rs 7.1199
c 0
b 0
f 0
cc 8
eloc 24
nc 40
nop 4
crap 72

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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) {
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...
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) {
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...
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) {
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...
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');
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...
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
			/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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);
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...
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) {
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...
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