summaryrefslogtreecommitdiff
path: root/framework/Data/SqlMap/DataMapper/TPropertyAccess.php
blob: d5956d9dfd241de19d3be0e24042789a2c7ef924 (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
<?php
/**
 * TPropertyAccess class file.
 *
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005-2014 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @package Prado\Data\SqlMap\DataMapper
 */

namespace Prado\Data\SqlMap\DataMapper;

/**
 * TPropertyAccess class provides dot notation stype property access and setting.
 *
 * Access object's properties (and subproperties) using dot path notation.
 * The following are equivalent.
 * <code>
 * echo $obj->property1;
 * echo $obj->getProperty1();
 * echo $obj['property1']; //$obj may be an array or object
 * echo TPropertyAccess($obj, 'property1');
 * </code>
 *
 * Setting a property value.
 * <code>
 * $obj1->propert1 = 'hello';
 * $obj->setProperty('hello');
 * $obj['property1'] = 'hello'; //$obj may be an array or object
 * TPropertyAccess($obj, 'property1', 'hello');
 * </code>
 *
 * Subproperties are supported using the dot notation. E.g.
 * <code>
 * echo $obj->property1->property2->property3
 * echo TPropertyAccess::get($obj, 'property1.property2.property3');
 * </code>
 *
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
 * @package Prado\Data\SqlMap\DataMapper
 * @since 3.1
 */
class TPropertyAccess
{
	/**
	 * Gets the property value.
	 * @param mixed object or path.
	 * @param string property path.
	 * @return mixed property value.
	 * @throws TInvalidDataValueException if property path is invalid.
	 */
	public static function get($object,$path)
	{
		if(!is_array($object) && !is_object($object))
			return $object;
		$properties = explode('.', $path);
		foreach($properties as $prop)
		{
			if(is_array($object) || $object instanceof ArrayAccess)
			{
				if(array_key_exists($prop, $object))
					$object = $object[$prop];
				else
					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
			}
			else if(is_object($object))
			{
				$getter = 'get'.$prop;
				if(method_exists($object, $getter) && is_callable(array($object, $getter)))
					$object = $object->{$getter}();
				else if(in_array($prop, array_keys(get_object_vars($object))))
					$object = $object->{$prop};
				elseif(method_exists($object, '__get') && is_callable(array($object, '__get')))
					$object = $object->{$prop};
				else
					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
			}
			else
				throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
		}
		return $object;
	}

	/**
	 * @param mixed object or array
	 * @param string property path.
	 * @return boolean true if property path is valid
	 */
	public static function has($object, $path)
	{
		if(!is_array($object) && !is_object($object))
			return false;
		$properties = explode('.', $path);
		foreach($properties as $prop)
		{
			if(is_array($object) || $object instanceof ArrayAccess)
			{
				if(array_key_exists($prop, $object))
					$object = $object[$prop];
				else
					return false;
			}
			else if(is_object($object))
			{
				$getter = 'get'.$prop;
				if(method_exists($object, $getter) && is_callable(array($object, $getter)))
					$object = $object->{$getter}();
				else if(in_array($prop, array_keys(get_object_vars($object))))
					$object = $object->{$prop};
				elseif(method_exists($object, '__get') && is_callable(array($object, '__get')))
					$object = $object->{$prop};
				else
					return false;
			}
			else
				return false;
		}
		return true;
	}

	/**
	 * Sets the property value.
	 * @param mixed object or array
	 * @param string property path.
	 * @param mixed new property value.
	 * @throws TInvalidDataValueException if property path is invalid.
	 */
	public static function set(&$originalObject, $path, $value)
	{
		$properties = explode('.', $path);
		$prop = array_pop($properties);
		if(count($properties) > 0)
			$object = self::get($originalObject, implode('.',$properties));
		else
			$object = &$originalObject;

		if(is_array($object) || $object instanceof ArrayAccess)
		{
			$object[$prop] = $value;
		}
		else if(is_object($object))
		{
			$setter = 'set'.$prop;
			if (method_exists($object, $setter) && is_callable(array($object, $setter)))
				$object->{$setter}($value);
			else
				$object->{$prop} = $value;
		}
		else
			throw new TInvalidPropertyException('sqlmap_invalid_property_type',$path);
	}

}