Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. GetSetMethodNormalizer.php

class GetSetMethodNormalizer

Converts between objects with getter and setter methods and arrays.

The normalization process looks at all public methods and calls the ones which have a name starting with get and take no parameters. The result is a map from property names (method name stripped of the get prefix and converted to lower case) to property values. Property values are normalized through the serializer.

The denormalization first looks at the constructor of the given class to see if any of the parameters have the same name as one of the properties. The constructor is then called with all parameters or an exception is thrown if any required parameters were not present as properties. Then the denormalizer walks through the given map of property names to property values to see if a setter method exists for any of the properties. If a setter exists it is called with the property value. No automatic denormalization of the value takes place.

@author Nils Adermann <naderman@naderman.de> @author Kévin Dunglas <dunglas@gmail.com>

Hierarchy

  • class \Symfony\Component\Serializer\Normalizer\AbstractNormalizer implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface, \Symfony\Component\Serializer\Normalizer\DenormalizerInterface, \Symfony\Component\Serializer\SerializerAwareInterface uses \Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait, \Symfony\Component\Serializer\SerializerAwareTrait
    • class \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer extends \Symfony\Component\Serializer\Normalizer\AbstractNormalizer
      • class \Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer extends \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer

Expanded class hierarchy of GetSetMethodNormalizer

File

vendor/symfony/serializer/Normalizer/GetSetMethodNormalizer.php, line 38

Namespace

Symfony\Component\Serializer\Normalizer
View source
final class GetSetMethodNormalizer extends AbstractObjectNormalizer {
    private static $reflectionCache = [];
    private static array $setterAccessibleCache = [];
    public function getSupportedTypes(?string $format) : array {
        return [
            'object' => true,
        ];
    }
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool {
        return parent::supportsNormalization($data, $format) && $this->supports($data::class, true);
    }
    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool {
        return parent::supportsDenormalization($data, $type, $format) && $this->supports($type, false);
    }
    
    /**
     * Checks if the given class has any getter or setter method.
     */
    private function supports(string $class, bool $readAttributes) : bool {
        if ($this->classDiscriminatorResolver?->getMappingForClass($class)) {
            return true;
        }
        if (!isset(self::$reflectionCache[$class])) {
            self::$reflectionCache[$class] = new \ReflectionClass($class);
        }
        $reflection = self::$reflectionCache[$class];
        foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
            if ($readAttributes ? $this->isGetMethod($reflectionMethod) : $this->isSetMethod($reflectionMethod)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Checks if a method's name matches /^(get|is|has).+$/ and can be called non-statically without parameters.
     */
    private function isGetMethod(\ReflectionMethod $method) : bool {
        return !$method->isStatic() && !($method->getAttributes(Ignore::class) || $method->getAttributes(LegacyIgnore::class)) && !$method->getNumberOfRequiredParameters() && (2 < ($methodLength = \strlen($method->name)) && str_starts_with($method->name, 'is') && !ctype_lower($method->name[2]) || 3 < $methodLength && (str_starts_with($method->name, 'has') || str_starts_with($method->name, 'get')) && !ctype_lower($method->name[3]));
    }
    
    /**
     * Checks if a method's name matches /^set.+$/ and can be called non-statically with one parameter.
     */
    private function isSetMethod(\ReflectionMethod $method) : bool {
        return !$method->isStatic() && !$method->getAttributes(Ignore::class) && 0 < $method->getNumberOfParameters() && str_starts_with($method->name, 'set') && !ctype_lower($method->name[3]);
    }
    protected function extractAttributes(object $object, ?string $format = null, array $context = []) : array {
        $reflectionObject = new \ReflectionObject($object);
        $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);
        $attributes = [];
        foreach ($reflectionMethods as $method) {
            if (!$this->isGetMethod($method)) {
                continue;
            }
            $attributeName = lcfirst(substr($method->name, str_starts_with($method->name, 'is') ? 2 : 3));
            if ($this->isAllowedAttribute($object, $attributeName, $format, $context)) {
                $attributes[] = $attributeName;
            }
        }
        return $attributes;
    }
    protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []) : mixed {
        $getter = 'get' . $attribute;
        if (method_exists($object, $getter) && \is_callable([
            $object,
            $getter,
        ])) {
            return $object->{$getter}();
        }
        $isser = 'is' . $attribute;
        if (method_exists($object, $isser) && \is_callable([
            $object,
            $isser,
        ])) {
            return $object->{$isser}();
        }
        $haser = 'has' . $attribute;
        if (method_exists($object, $haser) && \is_callable([
            $object,
            $haser,
        ])) {
            return $object->{$haser}();
        }
        return null;
    }
    protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []) : void {
        $setter = 'set' . $attribute;
        $key = $object::class . ':' . $setter;
        if (!isset(self::$setterAccessibleCache[$key])) {
            self::$setterAccessibleCache[$key] = method_exists($object, $setter) && \is_callable([
                $object,
                $setter,
            ]) && !(new \ReflectionMethod($object, $setter))->isStatic();
        }
        if (self::$setterAccessibleCache[$key]) {
            $object->{$setter}($value);
        }
    }
    protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []) : bool {
        if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
            return false;
        }
        $class = \is_object($classOrObject) ? $classOrObject::class : $classOrObject;
        if (!isset(self::$reflectionCache[$class])) {
            self::$reflectionCache[$class] = new \ReflectionClass($class);
        }
        $reflection = self::$reflectionCache[$class];
        if ($context['_read_attributes'] ?? true) {
            foreach ([
                'get',
                'is',
                'has',
            ] as $getterPrefix) {
                $getter = $getterPrefix . $attribute;
                $reflectionMethod = $reflection->hasMethod($getter) ? $reflection->getMethod($getter) : null;
                if ($reflectionMethod && $this->isGetMethod($reflectionMethod)) {
                    return true;
                }
            }
            return false;
        }
        $setter = 'set' . $attribute;
        if ($reflection->hasMethod($setter) && $this->isSetMethod($reflection->getMethod($setter))) {
            return true;
        }
        $constructor = $reflection->getConstructor();
        if ($constructor && $constructor->isPublic()) {
            foreach ($constructor->getParameters() as $parameter) {
                if ($parameter->getName() === $attribute) {
                    return true;
                }
            }
        }
        return false;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
AbstractNormalizer::$defaultContext protected property
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES public constant If ATTRIBUTES are specified, and the source has fields that are not part of that list,
either ignore those attributes (true) or throw an ExtraAttributesException (false).
AbstractNormalizer::applyCallbacks final protected function
AbstractNormalizer::applyFilterBool final protected function
AbstractNormalizer::ATTRIBUTES public constant Limit (de)normalize to the specified names.
AbstractNormalizer::CALLBACKS public constant Hashmap of field name =&gt; callable to (de)normalize this field.
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER public constant Handler to call when a circular reference has been detected.
AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT public constant How many loops of circular reference to allow while normalizing.
AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT_COUNTERS protected constant @internal
AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS public constant Hashmap of default values for constructor arguments.
AbstractNormalizer::FILTER_BOOL public constant Flag to control whether a non-boolean value should be filtered using the
filter_var function with the {\FILTER_VALIDATE_BOOL filter before casting it to a boolean.
AbstractNormalizer::getAllowedAttributes protected function Gets attributes to normalize using groups. 1
AbstractNormalizer::getAttributeDenormalizationContext protected function Computes the denormalization context merged with current one. Metadata always wins over global context, as more specific.
AbstractNormalizer::getAttributeMetadata protected function @internal
AbstractNormalizer::getAttributeNormalizationContext protected function Computes the normalization context merged with current one. Metadata always wins over global context, as more specific.
AbstractNormalizer::getConstructor protected function Returns the method to use to construct an object. This method must be either
the object constructor or static.
AbstractNormalizer::getGroups protected function
AbstractNormalizer::GROUPS public constant Only (de)normalize attributes that are in the specified groups.
AbstractNormalizer::handleCircularReference protected function Handles a circular reference.
AbstractNormalizer::IGNORED_ATTRIBUTES public constant Skip the specified attributes when normalizing an object tree.
AbstractNormalizer::isCircularReference protected function Detects if the configured circular reference limit is reached.
AbstractNormalizer::OBJECT_TO_POPULATE public constant Instead of creating a new instance of an object, update the specified object.
AbstractNormalizer::prepareForDenormalization protected function Normalizes the given data to an array. It&#039;s particularly useful during
the denormalization process.
AbstractNormalizer::REQUIRE_ALL_PROPERTIES public constant Require all properties to be listed in the input instead of falling
back to null for nullable ones.
AbstractNormalizer::validateCallbackContext final protected function Validate callbacks set in context.
AbstractObjectNormalizer::$attributesCache private property
AbstractObjectNormalizer::$classDiscriminatorResolver protected property
AbstractObjectNormalizer::$objectClassResolver private property 1
AbstractObjectNormalizer::$typeCache private property
AbstractObjectNormalizer::createChildContext protected function Overwritten to update the cache key for the child. Overrides AbstractNormalizer::createChildContext
AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE public constant Flag to tell the denormalizer to also populate existing objects on
attributes of the main object.
AbstractObjectNormalizer::denormalize public function Denormalizes data back into an object of the given class. Overrides DenormalizerInterface::denormalize
AbstractObjectNormalizer::denormalizeParameter protected function @internal Overrides AbstractNormalizer::denormalizeParameter
AbstractObjectNormalizer::DEPTH_KEY_PATTERN public constant How to track the current depth in the context.
AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT public constant While denormalizing, we can verify that type matches.
AbstractObjectNormalizer::ENABLE_MAX_DEPTH public constant Set to true to respect the max depth metadata on fields.
AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY public constant Specify which context key are not relevant to determine which attributes
of an object to (de)normalize.
AbstractObjectNormalizer::getAttributes protected function Gets and caches attributes for the given object, format and context.
AbstractObjectNormalizer::getCacheKey private function Builds the cache key for the attributes cache.
AbstractObjectNormalizer::getMappedClass private function
AbstractObjectNormalizer::getNestedAttributes private function Returns all attributes with a SerializedPath attribute and the respective path.
AbstractObjectNormalizer::getPropertyType private function BC layer for PropertyTypeExtractorInterface::getTypes().
Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0).
AbstractObjectNormalizer::getType private function
AbstractObjectNormalizer::instantiateObject protected function Instantiates an object using constructor parameters when needed. Overrides AbstractNormalizer::instantiateObject
AbstractObjectNormalizer::isMaxDepthReached private function Is the max depth reached for the given attribute?
AbstractObjectNormalizer::isUninitializedValueError private function This error may occur when specific object normalizer implementation gets attribute value
by accessing a public uninitialized property or by calling a method accessing such property.
AbstractObjectNormalizer::MAX_DEPTH_HANDLER public constant Callback to allow to set a value for an attribute when the max depth has
been reached.
AbstractObjectNormalizer::normalize public function Normalizes data into a set of arrays/scalars. Overrides NormalizerInterface::normalize
AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS public constant Flag to control whether an empty object should be kept as an object (in
JSON: {}) or converted to a list (in JSON: []).
AbstractObjectNormalizer::removeNestedValue private function
AbstractObjectNormalizer::SKIP_NULL_VALUES public constant Flag to control whether fields with the value `null` should be output
when normalizing or omitted.
AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES public constant Flag to control whether uninitialized PHP&gt;=7.4 typed class properties
should be excluded when normalizing.
AbstractObjectNormalizer::updateData private function Sets an attribute and apply the name converter if necessary.
AbstractObjectNormalizer::validateAndDenormalize private function Validates the submitted data and denormalizes it.
AbstractObjectNormalizer::validateAndDenormalizeLegacy private function Validates the submitted data and denormalizes it.
AbstractObjectNormalizer::__construct public function Sets the {@link ClassMetadataFactoryInterface} to use. Overrides AbstractNormalizer::__construct 2
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS public constant
GetSetMethodNormalizer::$reflectionCache private static property
GetSetMethodNormalizer::$setterAccessibleCache private static property
GetSetMethodNormalizer::extractAttributes protected function Extracts attributes to normalize from the class of the given object, format and context. Overrides AbstractObjectNormalizer::extractAttributes
GetSetMethodNormalizer::getAttributeValue protected function Gets the attribute value. Overrides AbstractObjectNormalizer::getAttributeValue
GetSetMethodNormalizer::getSupportedTypes public function Returns the types potentially supported by this normalizer. Overrides NormalizerInterface::getSupportedTypes
GetSetMethodNormalizer::isAllowedAttribute protected function Is this attribute allowed? Overrides AbstractNormalizer::isAllowedAttribute
GetSetMethodNormalizer::isGetMethod private function Checks if a method&#039;s name matches /^(get|is|has).+$/ and can be called non-statically without parameters.
GetSetMethodNormalizer::isSetMethod private function Checks if a method&#039;s name matches /^set.+$/ and can be called non-statically with one parameter.
GetSetMethodNormalizer::setAttributeValue protected function Overrides AbstractObjectNormalizer::setAttributeValue
GetSetMethodNormalizer::supports private function Checks if the given class has any getter or setter method.
GetSetMethodNormalizer::supportsDenormalization public function Checks whether the given class is supported for denormalization by this normalizer. Overrides AbstractObjectNormalizer::supportsDenormalization
GetSetMethodNormalizer::supportsNormalization public function Checks whether the given class is supported for normalization by this normalizer. Overrides AbstractObjectNormalizer::supportsNormalization
ObjectToPopulateTrait::extractObjectToPopulate protected function Extract the `object_to_populate` field from the context if it exists
and is an instance of the provided $class.
SerializerAwareTrait::$serializer protected property
SerializerAwareTrait::setSerializer public function
RSS feed
Powered by Drupal