|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009 Christopher Hlubek <hlubek@networkteam.com> 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * 00017 * This script is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * This copyright notice MUST APPEAR in all copies of the script! 00023 ***************************************************************/ 00024 00025 /** 00026 * Provides methods to call appropriate getter/setter on an object given the 00027 * property name. It does this following these rules: 00028 * - if the target object is an instance of ArrayAccess, it gets/sets the property 00029 * - if public getter/setter method exists, call it. 00030 * - if public property exists, return/set the value of it. 00031 * - else, throw exception 00032 * 00033 * @package Extbase 00034 * @subpackage Reflection 00035 * @version $Id: ObjectAccess.php 2149 2010-03-30 09:28:54Z jocrau $ 00036 */ 00037 class Tx_Extbase_Reflection_ObjectAccess { 00038 00039 const ACCESS_GET = 0; 00040 const ACCESS_SET = 1; 00041 const ACCESS_PUBLIC = 2; 00042 00043 /** 00044 * Get a property of a given object. 00045 * Tries to get the property the following ways: 00046 * - if the target is an array, and has this property, we call it. 00047 * - if public getter method exists, call it. 00048 * - if the target object is an instance of ArrayAccess, it gets the property 00049 * on it if it exists. 00050 * - if public property exists, return the value of it. 00051 * - else, throw exception 00052 * 00053 * @param mixed $subject Object or array to get the property from 00054 * @param string $propertyName name of the property to retrieve 00055 * @return object Value of the property. 00056 * @throws InvalidArgumentException in case $subject was not an object or $propertyName was not a string 00057 * @throws RuntimeException if the property was not accessible 00058 */ 00059 static public function getProperty($subject, $propertyName) { 00060 if (!is_object($subject) && !is_array($subject)) throw new InvalidArgumentException('$subject must be an object or array, ' . gettype($subject). ' given.', 1237301367); 00061 if (!is_string($propertyName)) throw new InvalidArgumentException('Given property name is not of type string.', 1231178303); 00062 00063 if (is_array($subject)) { 00064 if (array_key_exists($propertyName, $subject)) { 00065 return $subject[$propertyName]; 00066 } 00067 } else { 00068 if (is_callable(array($subject, 'get' . ucfirst($propertyName)))) { 00069 return call_user_func(array($subject, 'get' . ucfirst($propertyName))); 00070 } elseif (is_callable(array($subject, 'is' . ucfirst($propertyName)))) { 00071 return call_user_func(array($subject, 'is' . ucfirst($propertyName))); 00072 } elseif ($subject instanceof ArrayAccess && isset($subject[$propertyName])) { 00073 return $subject[$propertyName]; 00074 } elseif (array_key_exists($propertyName, get_object_vars($subject))) { 00075 return $subject->$propertyName; 00076 } 00077 } 00078 00079 throw new Tx_Extbase_Reflection_Exception_PropertyNotAccessibleException('The property "' . $propertyName . '" on the subject was not accessible.', 1263391473); 00080 } 00081 00082 /** 00083 * Gets a property path from a given object or array. 00084 * If propertyPath is "bla.blubb", then we first call getProperty($object, 'bla'), 00085 * and on the resulting object we call getProperty(..., 'blubb') 00086 * 00087 * @param mixed $subject Object or array to get the property path from 00088 * @param string $propertyPath 00089 * @return mixed Value of the property 00090 */ 00091 static public function getPropertyPath($subject, $propertyPath) { 00092 $propertyPathSegments = explode('.', $propertyPath); 00093 foreach ($propertyPathSegments as $pathSegment) { 00094 if (is_object($subject) && self::isPropertyGettable($subject, $pathSegment)) { 00095 $subject = self::getProperty($subject, $pathSegment); 00096 } elseif ((is_array($subject) || $subject instanceof ArrayAccess) && isset($subject[$pathSegment])) { 00097 $subject = $subject[$pathSegment]; 00098 } else { 00099 return NULL; 00100 } 00101 } 00102 return $subject; 00103 } 00104 00105 /** 00106 * Set a property for a given object. 00107 * Tries to set the property the following ways: 00108 * - if public setter method exists, call it. 00109 * - if public property exists, set it directly. 00110 * - if the target object is an instance of ArrayAccess, it sets the property 00111 * on it without checking if it existed. 00112 * - else, return FALSE 00113 * 00114 * @param object $object The target object 00115 * @param string $propertyName Name of the property to set 00116 * @param object $propertyValue Value of the property 00117 * @return void 00118 * @throws Tx_Extbase_Reflection_Exception if property was could not be set 00119 */ 00120 static public function setProperty(&$object, $propertyName, $propertyValue) { 00121 if (is_array($object)) { 00122 $object[$propertyName] = $propertyValue; 00123 return TRUE; 00124 } 00125 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1237301368); 00126 if (!is_string($propertyName)) throw new InvalidArgumentException('Given property name is not of type string.', 1231178878); 00127 00128 if (is_callable(array($object, $setterMethodName = self::buildSetterMethodName($propertyName)))) { 00129 call_user_func(array($object, $setterMethodName), $propertyValue); 00130 } elseif ($object instanceof ArrayAccess) { 00131 $object[$propertyName] = $propertyValue; 00132 } elseif (array_key_exists($propertyName, get_object_vars($object))) { 00133 $object->$propertyName = $propertyValue; 00134 } else { 00135 return FALSE; 00136 } 00137 return TRUE; 00138 } 00139 00140 /** 00141 * Returns an array of properties which can be get/set with the getProperty 00142 * and setProperty methods. 00143 * Includes the following properties: 00144 * - which can be set through a public setter method. 00145 * - public properties which can be directly set. 00146 * 00147 * @param object $object Object to receive property names for 00148 * @return array Array of all declared property names 00149 * @deprecated since Extbase 1.3.0; will be removed in Extbase 1.5.0. Please use getGettablePropertyNames() instead 00150 */ 00151 static public function getAccessiblePropertyNames($object) { 00152 t3lib_div::logDeprecatedFunction(); 00153 return self::getGettablePropertyNames($object); 00154 } 00155 00156 /** 00157 * Returns an array of properties which can be get with the getProperty() 00158 * method. 00159 * Includes the following properties: 00160 * - which can be get through a public getter method. 00161 * - public properties which can be directly get. 00162 * 00163 * @param object $object Object to receive property names for 00164 * @return array Array of all gettable property names 00165 * @author Sebastian Kurfürst <sebastian@typo3.org> 00166 * @author Karsten Dambekalns <karsten@typo3.org> 00167 */ 00168 static public function getGettablePropertyNames($object) { 00169 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1237301369); 00170 if ($object instanceof stdClass) { 00171 $declaredPropertyNames = array_keys(get_object_vars($object)); 00172 } else { 00173 $declaredPropertyNames = array_keys(get_class_vars(get_class($object))); 00174 } 00175 00176 foreach (get_class_methods($object) as $methodName) { 00177 if (is_callable(array($object, $methodName))) { 00178 if (substr($methodName, 0, 2) === 'is') { 00179 $declaredPropertyNames[] = strtolower(substr($methodName, 2, 1)) . (substr($methodName, 3)); 00180 } 00181 if (substr($methodName, 0, 3) === 'get') { 00182 $declaredPropertyNames[] = strtolower(substr($methodName, 3, 1)) . (substr($methodName, 4)); 00183 } 00184 } 00185 } 00186 00187 $propertyNames = array_unique($declaredPropertyNames); 00188 sort($propertyNames); 00189 return $propertyNames; 00190 } 00191 00192 /** 00193 * Returns an array of properties which can be set with the setProperty() 00194 * method. 00195 * Includes the following properties: 00196 * - which can be set through a public setter method. 00197 * - public properties which can be directly set. 00198 * 00199 * @param object $object Object to receive property names for 00200 * @return array Array of all settable property names 00201 * @author Karsten Dambekalns <karsten@typo3.org> 00202 */ 00203 static public function getSettablePropertyNames($object) { 00204 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1264022994); 00205 if ($object instanceof stdClass) { 00206 $declaredPropertyNames = array_keys(get_object_vars($object)); 00207 } else { 00208 $declaredPropertyNames = array_keys(get_class_vars(get_class($object))); 00209 } 00210 00211 foreach (get_class_methods($object) as $methodName) { 00212 if (substr($methodName, 0, 3) === 'set' && is_callable(array($object, $methodName))) { 00213 $declaredPropertyNames[] = strtolower(substr($methodName, 3, 1)) . (substr($methodName, 4)); 00214 } 00215 } 00216 00217 $propertyNames = array_unique($declaredPropertyNames); 00218 sort($propertyNames); 00219 return $propertyNames; 00220 } 00221 00222 /** 00223 * Get all properties (names and their current values) of the current 00224 * $object that are accessible through this class. 00225 * 00226 * @param object $object Object to get all properties from. 00227 * @return array Associative array of all properties. 00228 * @deprecated since Extbase 1.3.0; will be removed in Extbase 1.5.0. Please use getGettableProperties() instead 00229 */ 00230 static public function getAccessibleProperties($object) { 00231 t3lib_div::logDeprecatedFunction(); 00232 return self::getGettableProperties($object); 00233 } 00234 00235 /** 00236 * Get all properties (names and their current values) of the current 00237 * $object that are accessible through this class. 00238 * 00239 * @param object $object Object to get all properties from. 00240 * @return array Associative array of all properties. 00241 * @author Sebastian Kurfürst <sebastian@typo3.org> 00242 * @todo What to do with ArrayAccess 00243 */ 00244 static public function getGettableProperties($object) { 00245 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1237301370); 00246 $properties = array(); 00247 foreach (self::getGettablePropertyNames($object) as $propertyName) { 00248 $properties[$propertyName] = self::getProperty($object, $propertyName); 00249 } 00250 return $properties; 00251 } 00252 00253 00254 /** 00255 * Tells if the value of the specified property can be set by this Object Accessor. 00256 * 00257 * @param object $object Object containting the property 00258 * @param string $propertyName Name of the property to check 00259 * @return boolean 00260 * @author Robert Lemke <robert@typo3.org> 00261 */ 00262 static public function isPropertySettable($object, $propertyName) { 00263 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1259828920); 00264 if ($object instanceof stdClass && array_search($propertyName, array_keys(get_object_vars($object))) !== FALSE) { 00265 return TRUE; 00266 } elseif (array_search($propertyName, array_keys(get_class_vars(get_class($object)))) !== FALSE) { 00267 return TRUE; 00268 } 00269 return is_callable(array($object, self::buildSetterMethodName($propertyName))); 00270 } 00271 00272 /** 00273 * Tells if the value of the specified property can be retrieved by this Object Accessor. 00274 * 00275 * @param object $object Object containting the property 00276 * @param string $propertyName Name of the property to check 00277 * @return boolean 00278 */ 00279 static public function isPropertyGettable($object, $propertyName) { 00280 if (!is_object($object)) throw new InvalidArgumentException('$object must be an object, ' . gettype($object). ' given.', 1259828921); 00281 if ($object instanceof stdClass && array_search($propertyName, array_keys(get_object_vars($object))) !== FALSE) { 00282 return TRUE; 00283 } elseif (array_search($propertyName, array_keys(get_class_vars(get_class($object)))) !== FALSE) { 00284 return TRUE; 00285 } elseif ($object instanceof ArrayAccess && isset($object[$propertyName]) === TRUE) { 00286 return TRUE; 00287 } 00288 if (is_callable(array($object, 'get' . ucfirst($propertyName)))) return TRUE; 00289 return is_callable(array($object, 'is' . ucfirst($propertyName))); 00290 } 00291 00292 /** 00293 * Build the setter method name for a given property by capitalizing the 00294 * first letter of the property, and prepending it with "set". 00295 * 00296 * @param string $property Name of the property 00297 * @return string Name of the setter method name 00298 */ 00299 static protected function buildSetterMethodName($property) { 00300 return 'set' . ucfirst($property); 00301 } 00302 } 00303 00304 00305 ?>
1.8.0