[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/zendframework/zend-stdlib/src/Hydrator/ -> ClassMethods.php (source)

   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  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1