annotate vendor/symfony/serializer/Normalizer/GetSetMethodNormalizer.php @ 8:50b0d041100e

Further files for download
author Chris Cannam
date Mon, 05 Feb 2018 10:56:40 +0000
parents 4c8ae668cc8c
children 1fec387a4317
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Serializer\Normalizer;
Chris@0 13
Chris@0 14 /**
Chris@0 15 * Converts between objects with getter and setter methods and arrays.
Chris@0 16 *
Chris@0 17 * The normalization process looks at all public methods and calls the ones
Chris@0 18 * which have a name starting with get and take no parameters. The result is a
Chris@0 19 * map from property names (method name stripped of the get prefix and converted
Chris@0 20 * to lower case) to property values. Property values are normalized through the
Chris@0 21 * serializer.
Chris@0 22 *
Chris@0 23 * The denormalization first looks at the constructor of the given class to see
Chris@0 24 * if any of the parameters have the same name as one of the properties. The
Chris@0 25 * constructor is then called with all parameters or an exception is thrown if
Chris@0 26 * any required parameters were not present as properties. Then the denormalizer
Chris@0 27 * walks through the given map of property names to property values to see if a
Chris@0 28 * setter method exists for any of the properties. If a setter exists it is
Chris@0 29 * called with the property value. No automatic denormalization of the value
Chris@0 30 * takes place.
Chris@0 31 *
Chris@0 32 * @author Nils Adermann <naderman@naderman.de>
Chris@0 33 * @author Kévin Dunglas <dunglas@gmail.com>
Chris@0 34 */
Chris@0 35 class GetSetMethodNormalizer extends AbstractObjectNormalizer
Chris@0 36 {
Chris@0 37 private static $setterAccessibleCache = array();
Chris@0 38
Chris@0 39 /**
Chris@0 40 * {@inheritdoc}
Chris@0 41 */
Chris@0 42 public function supportsNormalization($data, $format = null)
Chris@0 43 {
Chris@0 44 return parent::supportsNormalization($data, $format) && $this->supports(get_class($data));
Chris@0 45 }
Chris@0 46
Chris@0 47 /**
Chris@0 48 * {@inheritdoc}
Chris@0 49 */
Chris@0 50 public function supportsDenormalization($data, $type, $format = null)
Chris@0 51 {
Chris@0 52 return parent::supportsDenormalization($data, $type, $format) && $this->supports($type);
Chris@0 53 }
Chris@0 54
Chris@0 55 /**
Chris@0 56 * Checks if the given class has any get{Property} method.
Chris@0 57 *
Chris@0 58 * @param string $class
Chris@0 59 *
Chris@0 60 * @return bool
Chris@0 61 */
Chris@0 62 private function supports($class)
Chris@0 63 {
Chris@0 64 $class = new \ReflectionClass($class);
Chris@0 65 $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
Chris@0 66 foreach ($methods as $method) {
Chris@0 67 if ($this->isGetMethod($method)) {
Chris@0 68 return true;
Chris@0 69 }
Chris@0 70 }
Chris@0 71
Chris@0 72 return false;
Chris@0 73 }
Chris@0 74
Chris@0 75 /**
Chris@0 76 * Checks if a method's name is get.* or is.*, and can be called without parameters.
Chris@0 77 *
Chris@0 78 * @param \ReflectionMethod $method the method to check
Chris@0 79 *
Chris@0 80 * @return bool whether the method is a getter or boolean getter
Chris@0 81 */
Chris@0 82 private function isGetMethod(\ReflectionMethod $method)
Chris@0 83 {
Chris@0 84 $methodLength = strlen($method->name);
Chris@0 85
Chris@0 86 return
Chris@0 87 !$method->isStatic() &&
Chris@0 88 (
Chris@0 89 ((0 === strpos($method->name, 'get') && 3 < $methodLength) ||
Chris@0 90 (0 === strpos($method->name, 'is') && 2 < $methodLength)) &&
Chris@0 91 0 === $method->getNumberOfRequiredParameters()
Chris@0 92 )
Chris@0 93 ;
Chris@0 94 }
Chris@0 95
Chris@0 96 /**
Chris@0 97 * {@inheritdoc}
Chris@0 98 */
Chris@0 99 protected function extractAttributes($object, $format = null, array $context = array())
Chris@0 100 {
Chris@0 101 $reflectionObject = new \ReflectionObject($object);
Chris@0 102 $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);
Chris@0 103
Chris@0 104 $attributes = array();
Chris@0 105 foreach ($reflectionMethods as $method) {
Chris@0 106 if (!$this->isGetMethod($method)) {
Chris@0 107 continue;
Chris@0 108 }
Chris@0 109
Chris@0 110 $attributeName = lcfirst(substr($method->name, 0 === strpos($method->name, 'is') ? 2 : 3));
Chris@0 111
Chris@0 112 if ($this->isAllowedAttribute($object, $attributeName)) {
Chris@0 113 $attributes[] = $attributeName;
Chris@0 114 }
Chris@0 115 }
Chris@0 116
Chris@0 117 return $attributes;
Chris@0 118 }
Chris@0 119
Chris@0 120 /**
Chris@0 121 * {@inheritdoc}
Chris@0 122 */
Chris@0 123 protected function getAttributeValue($object, $attribute, $format = null, array $context = array())
Chris@0 124 {
Chris@0 125 $ucfirsted = ucfirst($attribute);
Chris@0 126
Chris@0 127 $getter = 'get'.$ucfirsted;
Chris@0 128 if (is_callable(array($object, $getter))) {
Chris@0 129 return $object->$getter();
Chris@0 130 }
Chris@0 131
Chris@0 132 $isser = 'is'.$ucfirsted;
Chris@0 133 if (is_callable(array($object, $isser))) {
Chris@0 134 return $object->$isser();
Chris@0 135 }
Chris@0 136 }
Chris@0 137
Chris@0 138 /**
Chris@0 139 * {@inheritdoc}
Chris@0 140 */
Chris@0 141 protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = array())
Chris@0 142 {
Chris@0 143 $setter = 'set'.ucfirst($attribute);
Chris@0 144 $key = get_class($object).':'.$setter;
Chris@0 145
Chris@0 146 if (!isset(self::$setterAccessibleCache[$key])) {
Chris@0 147 self::$setterAccessibleCache[$key] = is_callable(array($object, $setter)) && !(new \ReflectionMethod($object, $setter))->isStatic();
Chris@0 148 }
Chris@0 149
Chris@0 150 if (self::$setterAccessibleCache[$key]) {
Chris@0 151 $object->$setter($value);
Chris@0 152 }
Chris@0 153 }
Chris@0 154 }