Completed
Push — master ( ad329f...099915 )
by Fabio
05:37
created

TResultProperty::setColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * TResultProperty class file.
4
 *
5
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6
 * @link https://github.com/pradosoft/prado
7
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
8
 * @package Prado\Data\SqlMap\Configuration
9
 */
10
11
namespace Prado\Data\SqlMap\Configuration;
12
13
use Prado\Collections\TList;
14
use Prado\Data\SqlMap\DataMapper\TPropertyAccess;
15
use Prado\Prado;
16
use Prado\TPropertyValue;
17
use ReflectionClass;
18
19
/**
20
 * TResultProperty corresponds a <property> tags inside a <resultMap> tag.
21
 *
22
 * The {@link NullValue setNullValue()} attribute can be set to any valid
23
 * value (based on property type). The {@link NullValue setNullValue()} attribute
24
 * is used to specify an outgoing null value replacement. What this means is
25
 * that when a null value is detected in the result, the corresponding value of
26
 * the {@link NullValue getNullValue()} will be used instead.
27
 *
28
 * The {@link Select setSelect()} property is used to describe a relationship
29
 * between objects and to automatically load complex (i.e. user defined)
30
 * property types. The value of the {@link Select setSelect()} property must be
31
 * the name of another mapped statement. The value of the database
32
 * {@link Column setColumn()} that is defined in the same property element as
33
 * this statement attribute will be passed to the related mapped statement as
34
 * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified
35
 * with the {@link Select setSelect()} .
36
 *
37
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
38
 * @package Prado\Data\SqlMap\Configuration
39
 * @since 3.1
40
 */
41
class TResultProperty extends \Prado\TComponent
42
{
43
	private $_nullValue;
44
	private $_propertyName;
45
	private $_columnName;
46
	private $_columnIndex = -1;
47
	private $_nestedResultMapName;
48
	private $_nestedResultMap;
49
	private $_valueType;
50
	private $_typeHandler;
51
	private $_isLazyLoad = false;
52
	private $_select;
53
54
	private $_hostResultMapID = 'inplicit internal mapping';
55
56
	const LIST_TYPE = 0;
57
	const ARRAY_TYPE = 1;
58
59
	/**
60
	 * Gets the containing result map ID.
61
	 * @param TResultMap $resultMap containing result map.
62
	 */
63 23
	public function __construct($resultMap = null)
64
	{
65 23
		if ($resultMap instanceof TResultMap) {
66
			$this->_hostResultMapID = $resultMap->getID();
67
		}
68 23
	}
69
70
	/**
71
	 * @return mixed null value replacement.
72
	 */
73 33
	public function getNullValue()
74
	{
75 33
		return $this->_nullValue;
76
	}
77
78
	/**
79
	 * @param mixed $value null value replacement.
80
	 */
81
	public function setNullValue($value)
82
	{
83
		$this->_nullValue = $value;
84
	}
85
86
	/**
87
	 * @return string name of a property of the result object that will be set to.
88
	 */
89 69
	public function getProperty()
90
	{
91 69
		return $this->_propertyName;
92
	}
93
94
	/**
95
	 * @param string $value name of a property of the result object that will be set to.
96
	 */
97
	public function setProperty($value)
98
	{
99
		$this->_propertyName = $value;
100
	}
101
102
	/**
103
	 * @return string name of the column in the result set from which the value
104
	 * will be used to populate the property.
105
	 */
106 83
	public function getColumn()
107
	{
108 83
		return $this->_columnName;
109
	}
110
111
	/**
112
	 * @param string $value name of the column in the result set from which the value
113
	 * will be used to populate the property.
114
	 */
115 23
	public function setColumn($value)
116
	{
117 23
		$this->_columnName = $value;
118 23
	}
119
120
	/**
121
	 * @return int index of the column in the ResultSet from which the value will
122
	 * be used to populate the object property
123
	 */
124 83
	public function getColumnIndex()
125
	{
126 83
		return $this->_columnIndex;
127
	}
128
129
	/**
130
	 * @param int $value index of the column in the ResultSet from which the value will
131
	 * be used to populate the object property
132
	 */
133 23
	public function setColumnIndex($value)
134
	{
135 23
		$this->_columnIndex = TPropertyValue::ensureInteger($value);
136 23
	}
137
138
	/**
139
	 * @return string ID of another <resultMap> used to fill the property.
140
	 */
141 1
	public function getResultMapping()
142
	{
143 1
		return $this->_nestedResultMapName;
144
	}
145
146
	/**
147
	 * @param string $value ID of another <resultMap> used to fill the property.
148
	 */
149
	public function setResultMapping($value)
150
	{
151
		$this->_nestedResultMapName = $value;
152
	}
153
154
	/**
155
	 * @return TResultMap nested result map.
156
	 */
157 61
	public function getNestedResultMap()
158
	{
159 61
		return $this->_nestedResultMap;
160
	}
161
162
	/**
163
	 * @param TResult $value nested result map.
164
	 */
165
	public function setNestedResultMap($value)
166
	{
167
		$this->_nestedResultMap = $value;
168
	}
169
170
	/**
171
	 * @return string property type of the object property to be set.
172
	 */
173 83
	public function getType()
174
	{
175 83
		return $this->_valueType;
176
	}
177
178
	/**
179
	 * @param string $value property type of the object property to be set.
180
	 */
181 30
	public function setType($value)
182
	{
183 30
		$this->_valueType = $value;
184 30
	}
185
186
	/**
187
	 * @return string custom type handler class name (may use namespace).
188
	 */
189 83
	public function getTypeHandler()
190
	{
191 83
		return $this->_typeHandler;
192
	}
193
194
	/**
195
	 * @param string $value custom type handler class name (may use namespace).
196
	 */
197
	public function setTypeHandler($value)
198
	{
199
		$this->_typeHandler = $value;
200
	}
201
202
	/**
203
	 * @return string name of another mapped statement
204
	 */
205 61
	public function getSelect()
206
	{
207 61
		return $this->_select;
208
	}
209
210
	/**
211
	 * The select property is used to describe a relationship between objects
212
	 * and to automatically load complex (i.e. user defined) property types.
213
	 * @param string $value name of another mapped statement.
214
	 */
215
	public function setSelect($value)
216
	{
217
		$this->_select = $value;
218
	}
219
220
	/**
221
	 * @return bool indicate whether or not the select statement's results should be lazy loaded
222
	 */
223 10
	public function getLazyLoad()
224
	{
225 10
		return $this->_isLazyLoad;
226
	}
227
228
	/**
229
	 * @param bool $value indicate whether or not the select statement's results should be lazy loaded
230
	 */
231
	public function setLazyLoad($value)
232
	{
233
		$this->_isLazyLoad = TPropertyValue::ensureBoolean($value, false);
234
	}
235
236
	/**
237
	 * Gets the value for the current property, converts to applicable type if necessary.
238
	 * @param TSqlMapTypeHandlerRegistry $registry type handler registry
239
	 * @param array $row result row
240
	 * @return mixed property value.
241
	 */
242 83
	public function getPropertyValue($registry, $row)
243
	{
244 83
		$value = null;
245 83
		$index = $this->getColumnIndex();
246 83
		$name = $this->getColumn();
247 83
		if ($index > 0 && isset($row[$index])) {
248
			$value = $this->getTypedValue($registry, $row[$index]);
249 83
		} elseif (isset($row[$name])) {
250 82
			$value = $this->getTypedValue($registry, $row[$name]);
251
		}
252 83
		if (($value === null) && ($this->getNullValue() !== null)) {
253 18
			$value = $this->getTypedValue($registry, $this->getNullValue());
254
		}
255 83
		return $value;
256
	}
257
258
	/**
259
	 * @param TSqlMapTypeHandlerRegistry $registry type handler registry
260
	 * @param mixed $value raw property value
261
	 * @return mixed property value casted to specific type.
262
	 */
263 83
	protected function getTypedValue($registry, $value)
264
	{
265 83
		if (($handler = $this->createTypeHandler($registry)) !== null) {
266 41
			return $handler->getResult($value);
267
		} else {
268 83
			return $registry->convertToType($this->getType(), $value);
269
		}
270
	}
271
272
	/**
273
	 * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}.
274
	 * @param TSqlMapTypeHandlerRegistry $registry type handler registry
275
	 * @return TSqlMapTypeHandler type handler.
276
	 */
277 83
	protected function createTypeHandler($registry)
278
	{
279 83
		$type = $this->getTypeHandler() ? $this->getTypeHandler() : $this->getType();
280 83
		$handler = $registry->getTypeHandler($type);
281 83
		if ($handler === null && $this->getTypeHandler()) {
282 19
			$handler = Prado::createComponent($type);
283
		}
284 83
		return $handler;
285
	}
286
287
	/**
288
	 * Determines if the type is an instance of \ArrayAccess, TList or an array.
289
	 * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE
290
	 */
291 4
	protected function getPropertyValueType()
292
	{
293 4
		if (class_exists($type = $this->getType(), false)) { //NO force autoloading
294 3
			if ($type === 'TList') {
295 3
				return self::LIST_TYPE;
296
			}
297
			$class = new ReflectionClass($type);
298
			if ($class->isSubclassOf('TList')) {
299
				return self::LIST_TYPE;
300
			}
301
			if ($class->implementsInterface('ArrayAccess')) {
302
				return self::ARRAY_TYPE;
303
			}
304
		}
305 1
		if (strtolower($type) == 'array') {
306
			return self::ARRAY_TYPE;
307
		}
308 1
	}
309
310
	/**
311
	 * Returns true if the result property {@link Type getType()} is of TList type
312
	 * or that the actual result object is an instance of TList.
313
	 * @param object $target result object
314
	 * @return bool true if the result object is an instance of TList
315
	 */
316 14
	public function instanceOfListType($target)
317
	{
318 14
		if ($this->getType() === null) {
319 10
			return  TPropertyAccess::get($target, $this->getProperty()) instanceof TList;
320
		}
321 4
		return $this->getPropertyValueType() == self::LIST_TYPE;
322
	}
323
324
	/**
325
	 * Returns true if the result property {@link Type getType()} is of \ArrayAccess
326
	 * or that the actual result object is an array or implements \ArrayAccess
327
	 * @param object $target result object
328
	 * @return bool true if the result object is an instance of \ArrayAccess or is an array.
329
	 */
330 7
	public function instanceOfArrayType($target)
331
	{
332 7
		if ($this->getType() === null) {
333 7
			$prop = TPropertyAccess::get($target, $this->getProperty());
334 7
			if (is_object($prop)) {
335 2
				return $prop instanceof \ArrayAccess;
336
			}
337 5
			return is_array($prop);
338
		}
339
		return $this->getPropertyValueType() == self::ARRAY_TYPE;
340
	}
341
342
	public function __sleep()
343
	{
344
		$exprops = [];
345
		$cn = 'TResultProperty';
346
		if ($this->_nullValue === null) {
347
			$exprops[] = "\0$cn\0_nullValue";
348
		}
349
		if ($this->_propertyName === null) {
350
			$exprops[] = "\0$cn\0_propertyNama";
351
		}
352
		if ($this->_columnName === null) {
353
			$exprops[] = "\0$cn\0_columnName";
354
		}
355
		if ($this->_columnIndex == -1) {
356
			$exprops[] = "\0$cn\0_columnIndex";
357
		}
358
		if ($this->_nestedResultMapName === null) {
359
			$exprops[] = "\0$cn\0_nestedResultMapName";
360
		}
361
		if ($this->_nestedResultMap === null) {
362
			$exprops[] = "\0$cn\0_nestedResultMap";
363
		}
364
		if ($this->_valueType === null) {
365
			$exprops[] = "\0$cn\0_valueType";
366
		}
367
		if ($this->_typeHandler === null) {
368
			$exprops[] = "\0$cn\0_typeHandler";
369
		}
370
		if ($this->_isLazyLoad === false) {
371
			$exprops[] = "\0$cn\0_isLazyLoad";
372
		}
373
		if ($this->_select === null) {
374
			$exprops[] = "\0$cn\0_select";
375
		}
376
		return array_diff(parent::__sleep(), $exprops);
377
	}
378
}
379