[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Zend Framework (http://framework.zend.com/) 4 * 5 * @link http://github.com/zendframework/zf2 for the canonical source repository 6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 7 * @license http://framework.zend.com/license/new-bsd New BSD License 8 */ 9 10 namespace Zend\Stdlib\Hydrator; 11 12 use Traversable; 13 use Zend\Stdlib\Exception; 14 use Zend\Stdlib\ArrayUtils; 15 use Zend\Stdlib\Hydrator\Filter\FilterComposite; 16 use Zend\Stdlib\Hydrator\Filter\FilterProviderInterface; 17 use Zend\Stdlib\Hydrator\Filter\GetFilter; 18 use Zend\Stdlib\Hydrator\Filter\HasFilter; 19 use Zend\Stdlib\Hydrator\Filter\IsFilter; 20 use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter; 21 use Zend\Stdlib\Hydrator\Filter\OptionalParametersFilter; 22 use Zend\Stdlib\Hydrator\NamingStrategy\NamingStrategyInterface; 23 use Zend\Stdlib\Hydrator\NamingStrategy\UnderscoreNamingStrategy; 24 25 class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface 26 { 27 /** 28 * Holds the names of the methods used for hydration, indexed by class::property name, 29 * false if the hydration method is not callable/usable for hydration purposes 30 * 31 * @var string[]|bool[] 32 */ 33 private $hydrationMethodsCache = array(); 34 35 /** 36 * A map of extraction methods to property name to be used during extraction, indexed 37 * by class name and method name 38 * 39 * @var string[][] 40 */ 41 private $extractionMethodsCache = array(); 42 43 /** 44 * Flag defining whether array keys are underscore-separated (true) or camel case (false) 45 * 46 * @var bool 47 */ 48 protected $underscoreSeparatedKeys = true; 49 50 /** 51 * @var \Zend\Stdlib\Hydrator\Filter\FilterInterface 52 */ 53 private $callableMethodFilter; 54 55 /** 56 * Define if extract values will use camel case or name with underscore 57 * @param bool|array $underscoreSeparatedKeys 58 */ 59 public function __construct($underscoreSeparatedKeys = true) 60 { 61 parent::__construct(); 62 $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys); 63 64 $this->callableMethodFilter = new OptionalParametersFilter(); 65 66 $this->filterComposite->addFilter('is', new IsFilter()); 67 $this->filterComposite->addFilter('has', new HasFilter()); 68 $this->filterComposite->addFilter('get', new GetFilter()); 69 $this->filterComposite->addFilter('parameter', new OptionalParametersFilter(), FilterComposite::CONDITION_AND); 70 } 71 72 /** 73 * @param array|Traversable $options 74 * @return ClassMethods 75 * @throws Exception\InvalidArgumentException 76 */ 77 public function setOptions($options) 78 { 79 if ($options instanceof Traversable) { 80 $options = ArrayUtils::iteratorToArray($options); 81 } elseif (!is_array($options)) { 82 throw new Exception\InvalidArgumentException( 83 'The options parameter must be an array or a Traversable' 84 ); 85 } 86 if (isset($options['underscoreSeparatedKeys'])) { 87 $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']); 88 } 89 90 return $this; 91 } 92 93 /** 94 * @param bool $underscoreSeparatedKeys 95 * @return ClassMethods 96 */ 97 public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) 98 { 99 $this->underscoreSeparatedKeys = (bool) $underscoreSeparatedKeys; 100 101 if ($this->underscoreSeparatedKeys) { 102 $this->setNamingStrategy(new UnderscoreNamingStrategy); 103 } elseif ($this->getNamingStrategy() instanceof UnderscoreNamingStrategy) { 104 $this->removeNamingStrategy(); 105 } 106 107 return $this; 108 } 109 110 /** 111 * @return bool 112 */ 113 public function getUnderscoreSeparatedKeys() 114 { 115 return $this->underscoreSeparatedKeys; 116 } 117 118 /** 119 * Extract values from an object with class methods 120 * 121 * Extracts the getter/setter of the given $object. 122 * 123 * @param object $object 124 * @return array 125 * @throws Exception\BadMethodCallException for a non-object $object 126 */ 127 public function extract($object) 128 { 129 if (!is_object($object)) { 130 throw new Exception\BadMethodCallException(sprintf( 131 '%s expects the provided $object to be a PHP object)', 132 __METHOD__ 133 )); 134 } 135 136 $objectClass = get_class($object); 137 138 // reset the hydrator's hydrator's cache for this object, as the filter may be per-instance 139 if ($object instanceof FilterProviderInterface) { 140 $this->extractionMethodsCache[$objectClass] = null; 141 } 142 143 // pass 1 - finding out which properties can be extracted, with which methods (populate hydration cache) 144 if (! isset($this->extractionMethodsCache[$objectClass])) { 145 $this->extractionMethodsCache[$objectClass] = array(); 146 $filter = $this->filterComposite; 147 $methods = get_class_methods($object); 148 149 if ($object instanceof FilterProviderInterface) { 150 $filter = new FilterComposite( 151 array($object->getFilter()), 152 array(new MethodMatchFilter('getFilter')) 153 ); 154 } 155 156 foreach ($methods as $method) { 157 $methodFqn = $objectClass . '::' . $method; 158 159 if (! ($filter->filter($methodFqn) && $this->callableMethodFilter->filter($methodFqn))) { 160 continue; 161 } 162 163 $attribute = $method; 164 165 if (strpos($method, 'get') === 0) { 166 $attribute = substr($method, 3); 167 if (!property_exists($object, $attribute)) { 168 $attribute = lcfirst($attribute); 169 } 170 } 171 172 $this->extractionMethodsCache[$objectClass][$method] = $attribute; 173 } 174 } 175 176 $values = array(); 177 178 // pass 2 - actually extract data 179 foreach ($this->extractionMethodsCache[$objectClass] as $methodName => $attributeName) { 180 $realAttributeName = $this->extractName($attributeName, $object); 181 $values[$realAttributeName] = $this->extractValue($realAttributeName, $object->$methodName(), $object); 182 } 183 184 return $values; 185 } 186 187 /** 188 * Hydrate an object by populating getter/setter methods 189 * 190 * Hydrates an object by getter/setter methods of the object. 191 * 192 * @param array $data 193 * @param object $object 194 * @return object 195 * @throws Exception\BadMethodCallException for a non-object $object 196 */ 197 public function hydrate(array $data, $object) 198 { 199 if (!is_object($object)) { 200 throw new Exception\BadMethodCallException(sprintf( 201 '%s expects the provided $object to be a PHP object)', 202 __METHOD__ 203 )); 204 } 205 206 $objectClass = get_class($object); 207 208 foreach ($data as $property => $value) { 209 $propertyFqn = $objectClass . '::$' . $property; 210 211 if (! isset($this->hydrationMethodsCache[$propertyFqn])) { 212 $setterName = 'set' . ucfirst($this->hydrateName($property, $data)); 213 214 $this->hydrationMethodsCache[$propertyFqn] = is_callable(array($object, $setterName)) 215 ? $setterName 216 : false; 217 } 218 219 if ($this->hydrationMethodsCache[$propertyFqn]) { 220 $object->{$this->hydrationMethodsCache[$propertyFqn]}($this->hydrateValue($property, $value, $data)); 221 } 222 } 223 224 return $object; 225 } 226 227 /** 228 * {@inheritDoc} 229 */ 230 public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR) 231 { 232 $this->resetCaches(); 233 234 return parent::addFilter($name, $filter, $condition); 235 } 236 237 /** 238 * {@inheritDoc} 239 */ 240 public function removeFilter($name) 241 { 242 $this->resetCaches(); 243 244 return parent::removeFilter($name); 245 } 246 247 /** 248 * {@inheritDoc} 249 */ 250 public function setNamingStrategy(NamingStrategyInterface $strategy) 251 { 252 $this->resetCaches(); 253 254 return parent::setNamingStrategy($strategy); 255 } 256 257 /** 258 * {@inheritDoc} 259 */ 260 public function removeNamingStrategy() 261 { 262 $this->resetCaches(); 263 264 return parent::removeNamingStrategy(); 265 } 266 267 /** 268 * Reset all local hydration/extraction caches 269 */ 270 private function resetCaches() 271 { 272 $this->hydrationMethodsCache = $this->extractionMethodsCache = array(); 273 } 274 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |