Passed
Push — master ( 47e8e4...d5adc1 )
by Fabio
04:41
created

TBehaviorParameterLoader::attachModuleBehaviors()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 14
rs 9.9666
1
<?php
2
3
/**
4
 * TBehaviorParameterLoader class file.
5
 *
6
 * @author Brad Anderson <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 */
10
11
namespace Prado\Util\Behaviors;
12
13
use Prado\Exceptions\TConfigurationException;
14
use Prado\Prado;
15
use Prado\TComponent;
16
use Prado\TPropertyValue;
17
18
/**
19
 * TBehaviorParameterLoader class.
20
 *
21
 * TBehaviorParameterLoader implements attaching Behaviors from Parameters
22
 * before any work has been done.  Here is an example of how to attach a behavior
23
 * via parameter within an application.xml:
24
 * <code>
25
 * <application id="prado-app">
26
 *		<parameters>
27
 *		<parameter id="pagethemebehaviorloader" class="Prado\Util\Behaviors\TBehaviorParameterLoader" BehaviorName="testBehavior" BehaviorClass="Prado\Util\Behaviors\TParameterizeBehavior" Priority="10" AttachToClass="Prado\Web\UI\TPage" Parameter="ThemeName" Property="Theme" DefaultValue="America/Los Angeles" />
28
 *		<parameters>
29
 * 	  ...
30
 * </code>
31
 *
32
 * TBehaviorParameterLoader can be used in parameters to load behaviors through the
33
 * application configuration parameters, {@link TParameterModule}, as well in each
34
 * folder through the config.xml/php files.
35
 *
36
 * @author Brad Anderson <[email protected]>
37
 * @package Prado\Util\Behaviors
38
 * @since 4.2.0
39
 */
40
41
class TBehaviorParameterLoader extends TComponent
42
{
43
	/** @var string name of the behavior attaching to the owner */
44
	private $_behaviorName;
45
	
46
	/** @var string class of the behavior attaching to the owner */
47
	private $_behaviorClass;
48
	
49
	/** @var numeric priority of the behavior attaching to the owner */
0 ignored issues
show
Bug introduced by
The type Prado\Util\Behaviors\numeric was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
	private $_priority;
51
	
52
	/** @var string what object to attach the behavior */
53
	private $_attachto;
54
	
55
	/** @var string what class to attach the behavior */
56
	private $_attachtoclass;
57
	
58
	/** @var array<string, string> additional properties to feed the behavior */
59
	private $_properties = [];
60
	
61
	/** @var array<string, array<properties>> the list of behaviors to attach to the page */
62
	private static $_pageBehaviors = [];
63
	
64
	/** @var array<string, array<behaviors> the list of behaviors to attach to the page */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array<behaviors> at position 7 could not be parsed: Expected '>' at position 7, but found '>'.
Loading history...
65
	private static $_moduleBehaviors = [];
66
	
67
	/**
68
	 * Install the behavior via dynamic event dyInit, called after a parameter
69
	 * class is loaded in TParameterModule or TApplication configurations.
70
	 * @param null|mixed $config for Parameters this is null.
71
	 */
72
	public function dyInit($config)
73
	{
74
		if (!$this->_behaviorName) {
75
			throw new TConfigurationException('behaviorparameterloader_no_behavior_name');
76
		}
77
		if (!$this->_behaviorClass) {
78
			throw new TConfigurationException('behaviorparameterloader_no_behavior_class');
79
		}
80
		
81
		if ($this->_attachto === null && $this->_attachtoclass === null) {
82
			throw new TConfigurationException('behaviorparameterloader_attachto_class_required');
83
		} elseif ($this->_attachto !== null && $this->_attachtoclass !== null) {
84
			throw new TConfigurationException('behaviorparameterloader_attachto_and_class_only_one');
85
		}
86
		$this->_properties['class'] = $this->_behaviorClass;
87
		if ($this->_attachtoclass) {
88
			TComponent::attachClassBehavior($this->_behaviorName, $this->_properties, $this->_attachtoclass, $this->_priority);
0 ignored issues
show
Bug introduced by
$this->_properties of type array<string,string> is incompatible with the type object|string expected by parameter $behavior of Prado\TComponent::attachClassBehavior(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

88
			TComponent::attachClassBehavior($this->_behaviorName, /** @scrutinizer ignore-type */ $this->_properties, $this->_attachtoclass, $this->_priority);
Loading history...
89
		} else {
90
			if (strtolower($this->_attachto) == "page") {
91
				if (!count(self::$_pageBehaviors)) {
92
					Prado::getApplication()->onBeginRequest[] = [$this, 'attachTPageServiceHandler'];
0 ignored issues
show
Bug Best Practice introduced by
The property onBeginRequest does not exist on Prado\TApplication. Since you implemented __get, consider adding a @property annotation.
Loading history...
93
				}
94
				self::$_pageBehaviors[$this->_behaviorName] = $this->_properties;
95
				return;
96
			} elseif (strncasecmp(strtolower($this->_attachto), 'module:', 7) === 0) {
97
				if (!count(self::$_moduleBehaviors)) {
98
					Prado::getApplication()->attachEventHandler('onInitComplete', [$this, 'attachModulesBehaviors'], -20);
0 ignored issues
show
Bug introduced by
-20 of type integer is incompatible with the type Prado\numeric|null expected by parameter $priority of Prado\TComponent::attachEventHandler(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
					Prado::getApplication()->attachEventHandler('onInitComplete', [$this, 'attachModulesBehaviors'], /** @scrutinizer ignore-type */ -20);
Loading history...
99
				}
100
				$moduleid = trim(substr($this->_attachto, 7));
101
				if (!$moduleid) {
102
					throw new TConfigurationException('behaviorparameterloader_moduleid_required', $moduleid);
103
				}
104
				self::$_moduleBehaviors[$moduleid] = self::$_moduleBehaviors[$moduleid] ?? [];
105
				self::$_moduleBehaviors[$moduleid][$this->_behaviorName] = $this->_properties;
106
				return;
107
			} elseif (strtolower($this->_attachto) == "application") {
108
				$owner = Prado::getApplication();
109
			} else {
110
				$owner = Prado::getApplication()->getSubProperty($this->_attachto);
111
			}
112
			$priority = $this->_properties['priority'] ?? null;
0 ignored issues
show
Unused Code introduced by
The assignment to $priority is dead and can be removed.
Loading history...
113
			unset($this->_properties['priority']);
114
			if (!$owner) {
115
				throw new TConfigurationException('behaviorparameterloader_behaviorowner_required', $this->_attachto);
116
			}
117
			$owner->attachBehavior($this->_behaviorName, $this->_properties, $this->_priority);
118
		}
119
	}
120
	
121
	/**
122
	 * TApplication::onBeginRequest Handler that adds {@link attachTPageBehaviors} to
123
	 * TPageService::onPreRunPage. In turn, this attaches {@link attachTPageBehaviors}
124
	 * to TPageService to then adds the page behaviors.
125
	 * @param object $sender the object that raised the event
126
	 * @param mixed $param parameter of the event
127
	 */
128
	public function attachTPageServiceHandler($sender, $param)
129
	{
130
		$service = Prado::getApplication()->getService();
131
		if ($service->isa('Prado\\Web\\Services\\TPageService')) {
0 ignored issues
show
Bug introduced by
The method isa() does not exist on Prado\IService. Since it exists in all sub-types, consider adding an abstract or default implementation to Prado\IService. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

131
		if ($service->/** @scrutinizer ignore-call */ isa('Prado\\Web\\Services\\TPageService')) {
Loading history...
132
			$service->attachEventHandler('onPreRunPage', [$this, 'attachTPageBehaviors'], -20);
0 ignored issues
show
Bug introduced by
The method attachEventHandler() does not exist on Prado\IService. Since it exists in all sub-types, consider adding an abstract or default implementation to Prado\IService. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

132
			$service->/** @scrutinizer ignore-call */ 
133
             attachEventHandler('onPreRunPage', [$this, 'attachTPageBehaviors'], -20);
Loading history...
133
		}
134
	}
135
	
136
	/**
137
	 * This method attaches page behaviors to the TPage handling the TPageService::OnPreInitPage event.
138
	 * @param object $sender the object that raised the event
139
	 * @param Prado\Web\UI\TPage $page the page being initialized
0 ignored issues
show
Bug introduced by
The type Prado\Prado\Web\UI\TPage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
140
	 */
141
	public function attachModuleBehaviors($sender, $page)
142
	{
143
		foreach (self::$_moduleBehaviors as $id => $behaviors) {
144
			$owner = Prado::getApplication()->getModule($id);
145
			if (!$owner) {
146
				throw new TConfigurationException('behaviorparameterloader_behaviormodule_not_found', $id);
147
			}
148
			foreach ($behaviors as $name => $properties) {
149
				$priority = $properties['priority'] ?? null;
150
				unset($properties['priority']);
151
				$owner->attachBehavior($name, $properties, $priority);
0 ignored issues
show
Bug introduced by
The method attachBehavior() does not exist on Prado\IModule. Since it exists in all sub-types, consider adding an abstract or default implementation to Prado\IModule. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
				$owner->/** @scrutinizer ignore-call */ 
152
            attachBehavior($name, $properties, $priority);
Loading history...
152
			}
153
		}
154
		self::$_moduleBehaviors = [];
155
	}
156
	
157
	/**
158
	 * This method attaches page behaviors to the TPage handling the TPageService::OnPreInitPage event.
159
	 * @param object $sender the object that raised the event
160
	 * @param Prado\Web\UI\TPage $page the page being initialized
161
	 */
162
	public function attachTPageBehaviors($sender, $page)
163
	{
164
		foreach (self::$_pageBehaviors as $name => $properties) {
165
			$priority = $properties['priority'] ?? null;
166
			unset($properties['priority']);
167
			$page->attachBehavior($name, $properties, $priority);
168
		}
169
		self::$_pageBehaviors = [];
170
	}
171
	
172
	/**
173
	 * This resets the module and page behavior cache data.
174
	 */
175
	public function reset()
176
	{
177
		if ($this->_attachtoclass) {
178
			TComponent::detachClassBehavior($this->_behaviorName, $this->_attachtoclass);
179
		}
180
		Prado::getApplication()->detachEventHandler('onInitComplete', [$this, 'attachModulesBehaviors']);
181
		Prado::getApplication()->detachEventHandler('onBeginRequest', [$this, 'attachTPageServiceHandler']);
182
		self::$_moduleBehaviors = [];
183
		self::$_pageBehaviors = [];
184
		
185
		$this->_behaviorName = null;
186
		$this->_behaviorClass = null;
187
		$this->_priority = null;
188
		$this->_attachto = null;
189
		$this->_attachtoclass = null;
190
		$this->_properties = [];
191
	}
192
	
193
	/**
194
	 * gets the name of the attaching behavior.
195
	 * @return string the name of the attaching behavior.
196
	 */
197
	public function getBehaviorName()
198
	{
199
		return $this->_behaviorName;
200
	}
201
	
202
	/**
203
	 * sets the name of the attaching behavior.
204
	 * @param string $name the name of the attaching behavior.
205
	 */
206
	public function setBehaviorName($name)
207
	{
208
		$this->_behaviorName = TPropertyValue::ensureString($name);
209
	}
210
	
211
	/**
212
	 * gets the class of the attaching behavior.
213
	 * @return string the class of the attaching behavior.
214
	 */
215
	public function getBehaviorClass()
216
	{
217
		return $this->_behaviorClass;
218
	}
219
	
220
	/**
221
	 * sets the class of the attaching behavior.
222
	 * @param string $className the class of the attaching behavior.
223
	 */
224
	public function setBehaviorClass($className)
225
	{
226
		$this->_behaviorClass = TPropertyValue::ensureString($className);
227
	}
228
	
229
	/**
230
	 * gets the priority of the attaching behavior.
231
	 * @return numeric the priority of the attaching behavior.
232
	 */
233
	public function getPriority()
234
	{
235
		return $this->_priority;
236
	}
237
	
238
	/**
239
	 * sets the priority of the attaching behavior.
240
	 * @param numeric $priority the priority of the attaching behavior.
241
	 */
242
	public function setPriority($priority)
243
	{
244
		$this->_priority = TPropertyValue::ensureFloat($priority);
0 ignored issues
show
Documentation Bug introduced by
It seems like Prado\TPropertyValue::ensureFloat($priority) of type double is incompatible with the declared type Prado\Util\Behaviors\numeric of property $_priority.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
245
	}
246
	
247
	/**
248
	 * gets the AttachTo value.
249
	 * @return string the AttachTo value.
250
	 */
251
	public function getAttachTo()
252
	{
253
		return $this->_attachto;
254
	}
255
	
256
	/**
257
	 * Sets the AttachTo property.
258
	 * @param string $attachto the new AttachTo value.
259
	 */
260
	public function setAttachTo($attachto)
261
	{
262
		$this->_attachto = TPropertyValue::ensureString($attachto);
263
	}
264
	
265
	/**
266
	 * gets the AttachToClass value.
267
	 * @return string the AttachToClass value.
268
	 */
269
	public function getAttachToClass()
270
	{
271
		return $this->_attachtoclass;
272
	}
273
	
274
	/**
275
	 * Sets the AttachToClass property.
276
	 * @param string $attachto the new AttachToClass value.
277
	 */
278
	public function setAttachToClass($attachto)
279
	{
280
		$this->_attachtoclass = TPropertyValue::ensureString($attachto);
281
	}
282
	
283
	/**
284
	 * gets the Additional Properties of the behavior.
285
	 * @return array additional behaviors for the behavior class.
286
	 */
287
	public function getProperties()
288
	{
289
		return $this->_properties;
290
	}
291
	
292
	/**
293
	 * magic method for storing the properties for the behavior. If there is no
294
	 * set Property then it stores the property to set on the behavior.
295
	 * @param string $name name of the property being set.
296
	 * @param string $value value of the property being set.
297
	 */
298
	public function __set($name, $value)
299
	{
300
		if (method_exists($this, $setter = 'set' . $name)) {
301
			return $this->$setter($value);
302
		} else {
303
			$this->_properties[$name] = $value;
304
		}
305
	}
306
}
307