vendor/symfony/property-info/Extractor/ReflectionExtractor.php line 86
<?php/** This file is part of the Symfony package.** (c) Fabien Potencier <fabien@symfony.com>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace Symfony\Component\PropertyInfo\Extractor;use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;use Symfony\Component\PropertyInfo\PropertyReadInfo;use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;use Symfony\Component\PropertyInfo\PropertyWriteInfo;use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;use Symfony\Component\PropertyInfo\Type;use Symfony\Component\String\Inflector\EnglishInflector;use Symfony\Component\String\Inflector\InflectorInterface;/*** Extracts data using the reflection API.** @author Kévin Dunglas <dunglas@gmail.com>** @final*/class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface, PropertyInitializableExtractorInterface, PropertyReadInfoExtractorInterface, PropertyWriteInfoExtractorInterface, ConstructorArgumentTypeExtractorInterface{/*** @internal*/public static array $defaultMutatorPrefixes = ['add', 'remove', 'set'];/*** @internal*/public static array $defaultAccessorPrefixes = ['get', 'is', 'has', 'can'];/*** @internal*/public static array $defaultArrayMutatorPrefixes = ['add', 'remove'];public const ALLOW_PRIVATE = 1;public const ALLOW_PROTECTED = 2;public const ALLOW_PUBLIC = 4;/** @var int Allow none of the magic methods */public const DISALLOW_MAGIC_METHODS = 0;/** @var int Allow magic __get methods */public const ALLOW_MAGIC_GET = 1 << 0;/** @var int Allow magic __set methods */public const ALLOW_MAGIC_SET = 1 << 1;/** @var int Allow magic __call methods */public const ALLOW_MAGIC_CALL = 1 << 2;private const MAP_TYPES = ['integer' => Type::BUILTIN_TYPE_INT,'boolean' => Type::BUILTIN_TYPE_BOOL,'double' => Type::BUILTIN_TYPE_FLOAT,];private $mutatorPrefixes;private $accessorPrefixes;private $arrayMutatorPrefixes;private $enableConstructorExtraction;private $methodReflectionFlags;private $magicMethodsFlags;private $propertyReflectionFlags;private $inflector;private $arrayMutatorPrefixesFirst;private $arrayMutatorPrefixesLast;/*** @param string[]|null $mutatorPrefixes* @param string[]|null $accessorPrefixes* @param string[]|null $arrayMutatorPrefixes*/public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null, bool $enableConstructorExtraction = true, int $accessFlags = self::ALLOW_PUBLIC, InflectorInterface $inflector = null, int $magicMethodsFlags = self::ALLOW_MAGIC_GET | self::ALLOW_MAGIC_SET){$this->mutatorPrefixes = $mutatorPrefixes ?? self::$defaultMutatorPrefixes;$this->accessorPrefixes = $accessorPrefixes ?? self::$defaultAccessorPrefixes;$this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? self::$defaultArrayMutatorPrefixes;$this->enableConstructorExtraction = $enableConstructorExtraction;$this->methodReflectionFlags = $this->getMethodsFlags($accessFlags);$this->propertyReflectionFlags = $this->getPropertyFlags($accessFlags);$this->magicMethodsFlags = $magicMethodsFlags;$this->inflector = $inflector ?? new EnglishInflector();$this->arrayMutatorPrefixesFirst = array_merge($this->arrayMutatorPrefixes, array_diff($this->mutatorPrefixes, $this->arrayMutatorPrefixes));$this->arrayMutatorPrefixesLast = array_reverse($this->arrayMutatorPrefixesFirst);}public function getProperties(string $class, array $context = []): ?array{try {$reflectionClass = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}$reflectionProperties = $reflectionClass->getProperties();$properties = [];foreach ($reflectionProperties as $reflectionProperty) {if ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags) {$properties[$reflectionProperty->name] = $reflectionProperty->name;}}foreach ($reflectionClass->getMethods($this->methodReflectionFlags) as $reflectionMethod) {if ($reflectionMethod->isStatic()) {continue;}$propertyName = $this->getPropertyName($reflectionMethod->name, $reflectionProperties);if (!$propertyName || isset($properties[$propertyName])) {continue;}if ($reflectionClass->hasProperty($lowerCasedPropertyName = lcfirst($propertyName)) || (!$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName))) {$propertyName = $lowerCasedPropertyName;}$properties[$propertyName] = $propertyName;}return $properties ? array_values($properties) : null;}public function getTypes(string $class, string $property, array $context = []): ?array{if ($fromMutator = $this->extractFromMutator($class, $property)) {return $fromMutator;}if ($fromAccessor = $this->extractFromAccessor($class, $property)) {return $fromAccessor;}if (($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction) &&$fromConstructor = $this->extractFromConstructor($class, $property)) {return $fromConstructor;}if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) {return $fromPropertyDeclaration;}return null;}public function getTypesFromConstructor(string $class, string $property): ?array{try {$reflection = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}if (!$reflectionConstructor = $reflection->getConstructor()) {return null;}if (!$reflectionParameter = $this->getReflectionParameterFromConstructor($property, $reflectionConstructor)) {return null;}if (!$reflectionType = $reflectionParameter->getType()) {return null;}if (!$types = $this->extractFromReflectionType($reflectionType, $reflectionConstructor->getDeclaringClass())) {return null;}return $types;}private function getReflectionParameterFromConstructor(string $property, \ReflectionMethod $reflectionConstructor): ?\ReflectionParameter{$reflectionParameter = null;foreach ($reflectionConstructor->getParameters() as $reflectionParameter) {if ($reflectionParameter->getName() === $property) {return $reflectionParameter;}}return null;}public function isReadable(string $class, string $property, array $context = []): ?bool{if ($this->isAllowedProperty($class, $property)) {return true;}return null !== $this->getReadInfo($class, $property, $context);}public function isWritable(string $class, string $property, array $context = []): ?bool{if ($this->isAllowedProperty($class, $property, true)) {return true;}[$reflectionMethod] = $this->getMutatorMethod($class, $property);return null !== $reflectionMethod;}public function isInitializable(string $class, string $property, array $context = []): ?bool{try {$reflectionClass = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}if (!$reflectionClass->isInstantiable()) {return false;}if ($constructor = $reflectionClass->getConstructor()) {foreach ($constructor->getParameters() as $parameter) {if ($property === $parameter->name) {return true;}}} elseif ($parentClass = $reflectionClass->getParentClass()) {return $this->isInitializable($parentClass->getName(), $property);}return false;}public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo{try {$reflClass = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}$allowGetterSetter = $context['enable_getter_setter_extraction'] ?? false;$magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags;$allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL);$allowMagicGet = (bool) ($magicMethods & self::ALLOW_MAGIC_GET);$hasProperty = $reflClass->hasProperty($property);$camelProp = $this->camelize($property);$getsetter = lcfirst($camelProp); // jQuery style, e.g. read: last(), write: last($item)foreach ($this->accessorPrefixes as $prefix) {$methodName = $prefix.$camelProp;if ($reflClass->hasMethod($methodName) && $reflClass->getMethod($methodName)->getModifiers() & $this->methodReflectionFlags && !$reflClass->getMethod($methodName)->getNumberOfRequiredParameters()) {$method = $reflClass->getMethod($methodName);return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $methodName, $this->getReadVisiblityForMethod($method), $method->isStatic(), false);}}if ($allowGetterSetter && $reflClass->hasMethod($getsetter) && ($reflClass->getMethod($getsetter)->getModifiers() & $this->methodReflectionFlags)) {$method = $reflClass->getMethod($getsetter);return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $getsetter, $this->getReadVisiblityForMethod($method), $method->isStatic(), false);}if ($allowMagicGet && $reflClass->hasMethod('__get') && ($reflClass->getMethod('__get')->getModifiers() & $this->methodReflectionFlags)) {return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, false, false);}if ($hasProperty && ($reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags)) {$reflProperty = $reflClass->getProperty($property);return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisiblityForProperty($reflProperty), $reflProperty->isStatic(), true);}if ($allowMagicCall && $reflClass->hasMethod('__call') && ($reflClass->getMethod('__call')->getModifiers() & $this->methodReflectionFlags)) {return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, 'get'.$camelProp, PropertyReadInfo::VISIBILITY_PUBLIC, false, false);}return null;}public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo{try {$reflClass = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}$allowGetterSetter = $context['enable_getter_setter_extraction'] ?? false;$magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags;$allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL);$allowMagicSet = (bool) ($magicMethods & self::ALLOW_MAGIC_SET);$allowConstruct = $context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction;$allowAdderRemover = $context['enable_adder_remover_extraction'] ?? true;$camelized = $this->camelize($property);$constructor = $reflClass->getConstructor();$singulars = $this->inflector->singularize($camelized);$errors = [];if (null !== $constructor && $allowConstruct) {foreach ($constructor->getParameters() as $parameter) {if ($parameter->getName() === $property) {return new PropertyWriteInfo(PropertyWriteInfo::TYPE_CONSTRUCTOR, $property);}}}[$adderAccessName, $removerAccessName, $adderAndRemoverErrors] = $this->findAdderAndRemover($reflClass, $singulars);if ($allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) {$adderMethod = $reflClass->getMethod($adderAccessName);$removerMethod = $reflClass->getMethod($removerAccessName);$mutator = new PropertyWriteInfo(PropertyWriteInfo::TYPE_ADDER_AND_REMOVER);$mutator->setAdderInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $adderAccessName, $this->getWriteVisiblityForMethod($adderMethod), $adderMethod->isStatic()));$mutator->setRemoverInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $removerAccessName, $this->getWriteVisiblityForMethod($removerMethod), $removerMethod->isStatic()));return $mutator;}$errors[] = $adderAndRemoverErrors;foreach ($this->mutatorPrefixes as $mutatorPrefix) {$methodName = $mutatorPrefix.$camelized;[$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $methodName, 1);if (!$accessible) {$errors[] = $methodAccessibleErrors;continue;}$method = $reflClass->getMethod($methodName);if (!\in_array($mutatorPrefix, $this->arrayMutatorPrefixes, true)) {return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $methodName, $this->getWriteVisiblityForMethod($method), $method->isStatic());}}$getsetter = lcfirst($camelized);if ($allowGetterSetter) {[$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $getsetter, 1);if ($accessible) {$method = $reflClass->getMethod($getsetter);return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $getsetter, $this->getWriteVisiblityForMethod($method), $method->isStatic());}$errors[] = $methodAccessibleErrors;}if ($reflClass->hasProperty($property) && ($reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags)) {$reflProperty = $reflClass->getProperty($property);if (\PHP_VERSION_ID < 80100 || !$reflProperty->isReadOnly()) {return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, $this->getWriteVisiblityForProperty($reflProperty), $reflProperty->isStatic());}$errors[] = [sprintf('The property "%s" in class "%s" is a promoted readonly property.', $property, $reflClass->getName())];$allowMagicSet = $allowMagicCall = false;}if ($allowMagicSet) {[$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__set', 2);if ($accessible) {return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, PropertyWriteInfo::VISIBILITY_PUBLIC, false);}$errors[] = $methodAccessibleErrors;}if ($allowMagicCall) {[$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__call', 2);if ($accessible) {return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, 'set'.$camelized, PropertyWriteInfo::VISIBILITY_PUBLIC, false);}$errors[] = $methodAccessibleErrors;}if (!$allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) {$errors[] = [sprintf('The property "%s" in class "%s" can be defined with the methods "%s()" but '.'the new value must be an array or an instance of \Traversable',$property,$reflClass->getName(),implode('()", "', [$adderAccessName, $removerAccessName]))];}$noneProperty = new PropertyWriteInfo();$noneProperty->setErrors(array_merge([], ...$errors));return $noneProperty;}/*** @return Type[]|null*/private function extractFromMutator(string $class, string $property): ?array{[$reflectionMethod, $prefix] = $this->getMutatorMethod($class, $property);if (null === $reflectionMethod) {return null;}$reflectionParameters = $reflectionMethod->getParameters();$reflectionParameter = $reflectionParameters[0];if (!$reflectionType = $reflectionParameter->getType()) {return null;}$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass());if (1 === \count($type) && \in_array($prefix, $this->arrayMutatorPrefixes)) {$type = [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type[0])];}return $type;}/*** Tries to extract type information from accessors.** @return Type[]|null*/private function extractFromAccessor(string $class, string $property): ?array{[$reflectionMethod, $prefix] = $this->getAccessorMethod($class, $property);if (null === $reflectionMethod) {return null;}if ($reflectionType = $reflectionMethod->getReturnType()) {return $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass());}if (\in_array($prefix, ['is', 'can', 'has'])) {return [new Type(Type::BUILTIN_TYPE_BOOL)];}return null;}/*** Tries to extract type information from constructor.** @return Type[]|null*/private function extractFromConstructor(string $class, string $property): ?array{try {$reflectionClass = new \ReflectionClass($class);} catch (\ReflectionException) {return null;}$constructor = $reflectionClass->getConstructor();if (!$constructor) {return null;}foreach ($constructor->getParameters() as $parameter) {if ($property !== $parameter->name) {continue;}$reflectionType = $parameter->getType();return $reflectionType ? $this->extractFromReflectionType($reflectionType, $constructor->getDeclaringClass()) : null;}if ($parentClass = $reflectionClass->getParentClass()) {return $this->extractFromConstructor($parentClass->getName(), $property);}return null;}private function extractFromPropertyDeclaration(string $class, string $property): ?array{try {$reflectionClass = new \ReflectionClass($class);$reflectionProperty = $reflectionClass->getProperty($property);$reflectionPropertyType = $reflectionProperty->getType();if (null !== $reflectionPropertyType && $types = $this->extractFromReflectionType($reflectionPropertyType, $reflectionProperty->getDeclaringClass())) {return $types;}} catch (\ReflectionException) {return null;}$defaultValue = $reflectionClass->getDefaultProperties()[$property] ?? null;if (null === $defaultValue) {return null;}$type = \gettype($defaultValue);$type = static::MAP_TYPES[$type] ?? $type;return [new Type($type, $this->isNullableProperty($class, $property), null, Type::BUILTIN_TYPE_ARRAY === $type)];}private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionClass $declaringClass): array{$types = [];$nullable = $reflectionType->allowsNull();foreach (($reflectionType instanceof \ReflectionUnionType || $reflectionType instanceof \ReflectionIntersectionType) ? $reflectionType->getTypes() : [$reflectionType] as $type) {if (!$type instanceof \ReflectionNamedType) {// Nested composite types are not supported yet.return [];}$phpTypeOrClass = $type->getName();if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass || 'never' === $phpTypeOrClass) {continue;}if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {$types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);} elseif ('void' === $phpTypeOrClass) {$types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);} elseif ($type->isBuiltin()) {$types[] = new Type($phpTypeOrClass, $nullable);} else {$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $declaringClass));}}return $types;}private function resolveTypeName(string $name, \ReflectionClass $declaringClass): string{if ('self' === $lcName = strtolower($name)) {return $declaringClass->name;}if ('parent' === $lcName && $parent = $declaringClass->getParentClass()) {return $parent->name;}return $name;}private function isNullableProperty(string $class, string $property): bool{try {$reflectionProperty = new \ReflectionProperty($class, $property);$reflectionPropertyType = $reflectionProperty->getType();return null !== $reflectionPropertyType && $reflectionPropertyType->allowsNull();} catch (\ReflectionException) {// Return false if the property doesn't exist}return false;}private function isAllowedProperty(string $class, string $property, bool $writeAccessRequired = false): bool{try {$reflectionProperty = new \ReflectionProperty($class, $property);if (\PHP_VERSION_ID >= 80100 && $writeAccessRequired && $reflectionProperty->isReadOnly()) {return false;}return (bool) ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags);} catch (\ReflectionException) {// Return false if the property doesn't exist}return false;}/*** Gets the accessor method.** Returns an array with a the instance of \ReflectionMethod as first key* and the prefix of the method as second or null if not found.*/private function getAccessorMethod(string $class, string $property): ?array{$ucProperty = ucfirst($property);foreach ($this->accessorPrefixes as $prefix) {try {$reflectionMethod = new \ReflectionMethod($class, $prefix.$ucProperty);if ($reflectionMethod->isStatic()) {continue;}if (0 === $reflectionMethod->getNumberOfRequiredParameters()) {return [$reflectionMethod, $prefix];}} catch (\ReflectionException) {// Return null if the property doesn't exist}}return null;}/*** Returns an array with a the instance of \ReflectionMethod as first key* and the prefix of the method as second or null if not found.*/private function getMutatorMethod(string $class, string $property): ?array{$ucProperty = ucfirst($property);$ucSingulars = $this->inflector->singularize($ucProperty);$mutatorPrefixes = \in_array($ucProperty, $ucSingulars, true) ? $this->arrayMutatorPrefixesLast : $this->arrayMutatorPrefixesFirst;foreach ($mutatorPrefixes as $prefix) {$names = [$ucProperty];if (\in_array($prefix, $this->arrayMutatorPrefixes)) {$names = array_merge($names, $ucSingulars);}foreach ($names as $name) {try {$reflectionMethod = new \ReflectionMethod($class, $prefix.$name);if ($reflectionMethod->isStatic()) {continue;}// Parameter can be optional to allow things like: method(array $foo = null)if ($reflectionMethod->getNumberOfParameters() >= 1) {return [$reflectionMethod, $prefix];}} catch (\ReflectionException) {// Try the next prefix if the method doesn't exist}}}return null;}private function getPropertyName(string $methodName, array $reflectionProperties): ?string{$pattern = implode('|', array_merge($this->accessorPrefixes, $this->mutatorPrefixes));if ('' !== $pattern && preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) {if (!\in_array($matches[1], $this->arrayMutatorPrefixes)) {return $matches[2];}foreach ($reflectionProperties as $reflectionProperty) {foreach ($this->inflector->singularize($reflectionProperty->name) as $name) {if (strtolower($name) === strtolower($matches[2])) {return $reflectionProperty->name;}}}return $matches[2];}return null;}/*** Searches for add and remove methods.** @param \ReflectionClass $reflClass The reflection class for the given object* @param array $singulars The singular form of the property name or null** @return array An array containing the adder and remover when found and errors*/private function findAdderAndRemover(\ReflectionClass $reflClass, array $singulars): array{if (!\is_array($this->arrayMutatorPrefixes) && 2 !== \count($this->arrayMutatorPrefixes)) {return [null, null, []];}[$addPrefix, $removePrefix] = $this->arrayMutatorPrefixes;$errors = [];foreach ($singulars as $singular) {$addMethod = $addPrefix.$singular;$removeMethod = $removePrefix.$singular;[$addMethodFound, $addMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $addMethod, 1);[$removeMethodFound, $removeMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $removeMethod, 1);$errors[] = $addMethodAccessibleErrors;$errors[] = $removeMethodAccessibleErrors;if ($addMethodFound && $removeMethodFound) {return [$addMethod, $removeMethod, []];}if ($addMethodFound && !$removeMethodFound) {$errors[] = [sprintf('The add method "%s" in class "%s" was found, but the corresponding remove method "%s" was not found', $addMethod, $reflClass->getName(), $removeMethod)];} elseif (!$addMethodFound && $removeMethodFound) {$errors[] = [sprintf('The remove method "%s" in class "%s" was found, but the corresponding add method "%s" was not found', $removeMethod, $reflClass->getName(), $addMethod)];}}return [null, null, array_merge([], ...$errors)];}/*** Returns whether a method is public and has the number of required parameters and errors.*/private function isMethodAccessible(\ReflectionClass $class, string $methodName, int $parameters): array{$errors = [];if ($class->hasMethod($methodName)) {$method = $class->getMethod($methodName);if (\ReflectionMethod::IS_PUBLIC === $this->methodReflectionFlags && !$method->isPublic()) {$errors[] = sprintf('The method "%s" in class "%s" was found but does not have public access.', $methodName, $class->getName());} elseif ($method->getNumberOfRequiredParameters() > $parameters || $method->getNumberOfParameters() < $parameters) {$errors[] = sprintf('The method "%s" in class "%s" requires %d arguments, but should accept only %d.', $methodName, $class->getName(), $method->getNumberOfRequiredParameters(), $parameters);} else {return [true, $errors];}}return [false, $errors];}/*** Camelizes a given string.*/private function camelize(string $string): string{return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));}/*** Return allowed reflection method flags.*/private function getMethodsFlags(int $accessFlags): int{$methodFlags = 0;if ($accessFlags & self::ALLOW_PUBLIC) {$methodFlags |= \ReflectionMethod::IS_PUBLIC;}if ($accessFlags & self::ALLOW_PRIVATE) {$methodFlags |= \ReflectionMethod::IS_PRIVATE;}if ($accessFlags & self::ALLOW_PROTECTED) {$methodFlags |= \ReflectionMethod::IS_PROTECTED;}return $methodFlags;}/*** Return allowed reflection property flags.*/private function getPropertyFlags(int $accessFlags): int{$propertyFlags = 0;if ($accessFlags & self::ALLOW_PUBLIC) {$propertyFlags |= \ReflectionProperty::IS_PUBLIC;}if ($accessFlags & self::ALLOW_PRIVATE) {$propertyFlags |= \ReflectionProperty::IS_PRIVATE;}if ($accessFlags & self::ALLOW_PROTECTED) {$propertyFlags |= \ReflectionProperty::IS_PROTECTED;}return $propertyFlags;}private function getReadVisiblityForProperty(\ReflectionProperty $reflectionProperty): string{if ($reflectionProperty->isPrivate()) {return PropertyReadInfo::VISIBILITY_PRIVATE;}if ($reflectionProperty->isProtected()) {return PropertyReadInfo::VISIBILITY_PROTECTED;}return PropertyReadInfo::VISIBILITY_PUBLIC;}private function getReadVisiblityForMethod(\ReflectionMethod $reflectionMethod): string{if ($reflectionMethod->isPrivate()) {return PropertyReadInfo::VISIBILITY_PRIVATE;}if ($reflectionMethod->isProtected()) {return PropertyReadInfo::VISIBILITY_PROTECTED;}return PropertyReadInfo::VISIBILITY_PUBLIC;}private function getWriteVisiblityForProperty(\ReflectionProperty $reflectionProperty): string{if ($reflectionProperty->isPrivate()) {return PropertyWriteInfo::VISIBILITY_PRIVATE;}if ($reflectionProperty->isProtected()) {return PropertyWriteInfo::VISIBILITY_PROTECTED;}return PropertyWriteInfo::VISIBILITY_PUBLIC;}private function getWriteVisiblityForMethod(\ReflectionMethod $reflectionMethod): string{if ($reflectionMethod->isPrivate()) {return PropertyWriteInfo::VISIBILITY_PRIVATE;}if ($reflectionMethod->isProtected()) {return PropertyWriteInfo::VISIBILITY_PROTECTED;}return PropertyWriteInfo::VISIBILITY_PUBLIC;}}