summaryrefslogtreecommitdiff
path: root/lib/prado/framework/Data/SqlMap/Configuration/TResultProperty.php
blob: 0a4f8f11485d1e9fe8f49d146cf5526e46fd2f8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<?php
/**
 * TResultProperty class file.
 *
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 * @link https://github.com/pradosoft/prado
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
 * @package System.Data.SqlMap.Configuration
 */

/**
 * TResultProperty corresponds a <property> tags inside a <resultMap> tag.
 *
 * The {@link NullValue setNullValue()} attribute can be set to any valid
 * value (based on property type). The {@link NullValue setNullValue()} attribute
 * is used to specify an outgoing null value replacement. What this means is
 * that when a null value is detected in the result, the corresponding value of
 * the {@link NullValue getNullValue()} will be used instead.
 *
 * The {@link Select setSelect()} property is used to describe a relationship
 * between objects and to automatically load complex (i.e. user defined)
 * property types. The value of the {@link Select setSelect()} property must be
 * the name of another mapped statement. The value of the database
 * {@link Column setColumn()} that is defined in the same property element as
 * this statement attribute will be passed to the related mapped statement as
 * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified
 * with the {@link Select setSelect()} .
 *
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
 * @package System.Data.SqlMap.Configuration
 * @since 3.1
 */
class TResultProperty extends TComponent
{
	private $_nullValue;
	private $_propertyName;
	private $_columnName;
	private $_columnIndex=-1;
	private $_nestedResultMapName;
	private $_nestedResultMap;
	private $_valueType;
	private $_typeHandler;
	private $_isLazyLoad=false;
	private $_select;

	private $_hostResultMapID='inplicit internal mapping';

	const LIST_TYPE = 0;
	const ARRAY_TYPE = 1;

	/**
	 * Gets the containing result map ID.
	 * @param TResultMap containing result map.
	 */
	public function __construct($resultMap=null)
	{
		if($resultMap instanceof TResultMap)
			$this->_hostResultMapID = $resultMap->getID();
	}

	/**
	 * @return mixed null value replacement.
	 */
	public function getNullValue()
	{
		return $this->_nullValue;
	}

	/**
	 * @param mixed null value replacement.
	 */
	public function setNullValue($value)
	{
		$this->_nullValue = $value;
	}

	/**
	 * @return string name of a property of the result object that will be set to.
	 */
	public function getProperty()
	{
		return $this->_propertyName;
	}

	/**
	 * @param string name of a property of the result object that will be set to.
	 */
	public function setProperty($value)
	{
		$this->_propertyName = $value;
	}

	/**
	 * @return string name of the column in the result set from which the value
	 * will be used to populate the property.
	 */
	public function getColumn()
	{
		return $this->_columnName;
	}

	/**
	 * @param string name of the column in the result set from which the value
	 * will be used to populate the property.
	 */
	public function setColumn($value)
	{
		$this->_columnName = $value;
	}

	/**
	 * @return int index of the column in the ResultSet from which the value will
	 * be used to populate the object property
	 */
	public function getColumnIndex()
	{
		return $this->_columnIndex;
	}

	/**
	 * @param int index of the column in the ResultSet from which the value will
	 * be used to populate the object property
	 */
	public function setColumnIndex($value)
	{
		$this->_columnIndex = TPropertyValue::ensureInteger($value);
	}

	/**
	 * @return string ID of another <resultMap> used to fill the property.
	 */
	public function getResultMapping()
	{
		return $this->_nestedResultMapName;
	}

	/**
	 * @param string ID of another <resultMap> used to fill the property.
	 */
	public function setResultMapping($value)
	{
		$this->_nestedResultMapName = $value;
	}

	/**
	 * @return TResultMap nested result map.
	 */
	public function getNestedResultMap()
	{
		return $this->_nestedResultMap;
	}

	/**
	 * @param TResult nested result map.
	 */
	public function setNestedResultMap($value)
	{
		$this->_nestedResultMap = $value;
	}

	/**
	 * @return string property type of the object property to be set.
	 */
	public function getType()
	{
		return $this->_valueType;
	}

	/**
	 * @param string property type of the object property to be set.
	 */
	public function setType($value)
	{
		$this->_valueType = $value;
	}

	/**
	 * @return string custom type handler class name (may use namespace).
	 */
	public function getTypeHandler()
	{
		return $this->_typeHandler;
	}

	/**
	 * @param string custom type handler class name (may use namespace).
	 */
	public function setTypeHandler($value)
	{
		$this->_typeHandler = $value;
	}

	/**
	 * @return string name of another mapped statement
	 */
	public function getSelect()
	{
		return $this->_select;
	}

	/**
	 * The select property is used to describe a relationship between objects
	 * and to automatically load complex (i.e. user defined) property types.
	 * @param string name of another mapped statement.
	 */
	public function setSelect($value)
	{
		$this->_select = $value;
	}

	/**
	 * @return boolean indicate whether or not the select statement's results should be lazy loaded
	 */
	public function getLazyLoad()
	{
		return $this->_isLazyLoad;
	}

	/**
	 * @param boolean indicate whether or not the select statement's results should be lazy loaded
	 */
	public function setLazyLoad($value)
	{
		$this->_isLazyLoad = TPropertyValue::ensureBoolean($value,false);
	}

	/**
	 * Gets the value for the current property, converts to applicable type if necessary.
	 * @param TSqlMapTypeHandlerRegistry type handler registry
	 * @param array result row
	 * @return mixed property value.
	 */
	public function getPropertyValue($registry,$row)
	{
		$value = null;
		$index = $this->getColumnIndex();
		$name = $this->getColumn();
		if($index > 0 && isset($row[$index]))
			$value = $this->getTypedValue($registry,$row[$index]);
		else if(isset($row[$name]))
			$value = $this->getTypedValue($registry,$row[$name]);
		if(($value===null) && ($this->getNullValue()!==null))
			$value = $this->getTypedValue($registry,$this->getNullValue());
		return $value;
	}

	/**
	 * @param TSqlMapTypeHandlerRegistry type handler registry
	 * @param mixed raw property value
	 * @return mixed property value casted to specific type.
	 */
	protected function getTypedValue($registry,$value)
	{
		if(($handler = $this->createTypeHandler($registry))!==null)
			return $handler->getResult($value);
		else
			return $registry->convertToType($this->getType(), $value);
	}

	/**
	 * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}.
	 * @param TSqlMapTypeHandlerRegistry type handler registry
	 * @return TSqlMapTypeHandler type handler.
	 */
	protected function createTypeHandler($registry)
	{
		$type=$this->getTypeHandler() ? $this->getTypeHandler() : $this->getType();
		$handler=$registry->getTypeHandler($type);
		if($handler===null && $this->getTypeHandler())
			$handler = Prado::createComponent($type);
		return $handler;
	}

	/**
	 * Determines if the type is an instance of ArrayAccess, TList or an array.
	 * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE
	 */
	protected function getPropertyValueType()
	{
		if(class_exists($type = $this->getType(), false)) //NO force autoloading
		{
			if($type==='TList')
				return self::LIST_TYPE;
			$class = new ReflectionClass($type);
			if($class->isSubclassOf('TList'))
				return self::LIST_TYPE;
			if($class->implementsInterface('ArrayAccess'))
				return self::ARRAY_TYPE;
		}
		if(strtolower($type) == 'array')
			return self::ARRAY_TYPE;
	}

	/**
	 * Returns true if the result property {@link Type getType()} is of TList type
	 * or that the actual result object is an instance of TList.
	 * @param object result object
	 * @return boolean true if the result object is an instance of TList
	 */
	public function instanceOfListType($target)
	{
		if($this->getType()===null)
			return  TPropertyAccess::get($target,$this->getProperty()) instanceof TList;
		return $this->getPropertyValueType() == self::LIST_TYPE;
	}

	/**
	 * Returns true if the result property {@link Type getType()} is of ArrayAccess
	 * or that the actual result object is an array or implements ArrayAccess
	 * @param object result object
	 * @return boolean true if the result object is an instance of ArrayAccess or is an array.
	 */
	public function instanceOfArrayType($target)
	{
		if($this->getType()===null)
		{
			$prop = TPropertyAccess::get($target,$this->getProperty());
			if(is_object($prop))
				return $prop instanceof ArrayAccess;
			return is_array($prop);
		}
		return $this->getPropertyValueType() == self::ARRAY_TYPE;
	}

	public function __sleep()
	{
		$exprops = array(); $cn = 'TResultProperty';
		if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue";
		if ($this->_propertyName===null) $exprops[] = "\0$cn\0_propertyNama";
		if ($this->_columnName===null) $exprops[] = "\0$cn\0_columnName";
		if ($this->_columnIndex==-1) $exprops[] = "\0$cn\0_columnIndex";
		if ($this->_nestedResultMapName===null) $exprops[] = "\0$cn\0_nestedResultMapName";
		if ($this->_nestedResultMap===null) $exprops[] = "\0$cn\0_nestedResultMap";
		if ($this->_valueType===null) $exprops[] = "\0$cn\0_valueType";
		if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler";
		if ($this->_isLazyLoad===false) $exprops[] = "\0$cn\0_isLazyLoad";
		if ($this->_select===null) $exprops[] = "\0$cn\0_select";
		return array_diff(parent::__sleep(),$exprops);
	}
}