@see PropertyAccessor::getReadAccessInfo()

@param ReflectionClass $reflClass
@param string          $property

@return array
494978
public static function getReadAccessInfo(ReflectionClass $reflClass, $property)
    {
        $access = array();
        $access['has_property'] = $reflClass->hasProperty($property);

        //method
        $camelProp = str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
        $methods = array('get'.$camelProp, lcfirst($camelProp), 'is'.$camelProp, 'has'.$camelProp);
        foreach ($methods as $method) {
            if ($reflClass->hasMethod($method) && $reflClass->getMethod($method)->isPublic()) {
                $access['type'] = AccessInfo::METHOD;
                $access['name'] = $method;

                return $access;
            }
        }

        //property
        if ($reflClass->hasMethod('__get') && $reflClass->getMethod('__get')->isPublic()) {
            $access['type'] = AccessInfo::PROPERTY;
            $access['name'] = $property;
            $access['ref'] = false;
        } elseif ($access['has_property'] && $reflClass->getProperty($property)->isPublic()) {
            $access['type'] = AccessInfo::PROPERTY;
            $access['name'] = $property;
            $access['ref'] = true;
        } else {
            $access['type'] = 'not_found';
            $access['name'] = sprintf(
                'Neither the property "%s" nor one of the methods "%s()" '.
                'exist and have public access in class "%s".',
                $property,
                implode('()", "', array_merge($methods, ['__get'])),
                $reflClass->name
            );
        }

        return $access;
    }
1091463
public function parse(RefClass $class)
    {
        $result = [];

        $annotations = $this->parseComment($class->docComment);
        foreach ($annotations as $annotation) {
            $annotation->originClass = $class->name;
            $result[]                = $annotation;
        }

        foreach ($class->constants as $constant) {
            foreach ($this->parseComment($constant->docComment) as $annotation) {
                $annotation->originClass    = $class->name;
                $annotation->originConstant = $constant->name;
                $result[]                   = $annotation;
            }
        }

        foreach ($class->properties as $property) {
            foreach ($this->parseComment($property->docComment) as $annotation) {
                $annotation->originClass    = $class->name;
                $annotation->originProperty = $property->name;
                $result[]                   = $annotation;
            }
        }

        foreach ($class->methods as $method) {
            foreach ($this->parseComment($method->docComment) as $annotation) {
                $annotation->originClass  = $class->name;
                $annotation->originMethod = $method->name;
                $result[]                 = $annotation;
            }
        }

        return $result;
    }
924991
protected function extractInterfaceDefinitions(\ReflectionClass $refClass)
    {
        $int = $refClass->getInterfaces();

        //get recursively all parent abstract classes to use as interfaces
        $currentClass = $refClass;
        while ($currentClass->getParentClass()) {
            if ($currentClass->getParentClass()->isAbstract()) {
                $int[] = $currentClass->getParentClass();
            }
            $currentClass = $currentClass->getParentClass();
        }

        //current class can be a object and interface at the same time,
        //When use different object types using discriminator map
        if ($this->reader->getClassAnnotation($refClass, Annotation\InterfaceType::class)) {
            $int[] = $refClass;
        }

        $definitions = [];
        foreach ($int as $intRef) {
            /** @var Annotation\InterfaceType $intAnnot */
            $intAnnot = $this->reader->getClassAnnotation(
                $intRef,
                Annotation\InterfaceType::class
            );

            if ($intAnnot) {
                $intDef = new InterfaceDefinition();
                $intDef->setName($intAnnot->name);
                $intDef->setClass($intRef->getName());

                if (!$intDef->getName() && preg_match('/\w+$/', $intRef->getName(), $matches)) {
                    $intDef->setName(preg_replace('/Interface$/', null, $matches[0]));
                }

                $intDef->setMetas($intAnnot->options);
                $intDef->setDescription($intAnnot->description);
                $intDef->setDiscriminatorMap($intAnnot->discriminatorMap);
                $intDef->setDiscriminatorProperty($intAnnot->discriminatorProperty);
                $intDef->setExclusionPolicy($intAnnot->exclusionPolicy);
                $this->resolveFields($intRef, $intDef);
                if (!$intDef->getName() && preg_match('/\w+$/', $intRef->getName(), $matches)) {
                    $intDef->setName(preg_replace('/Interface$/', null, $matches[0]));
                }

                $definitions[] = $intDef;
            }
        }

        return $definitions;
    }
743622
private static function getPropertyValueByParentClasses($source, string $property): array
    {
        $properties = self::getProperties($source, null, true);

        if (empty($properties)) {
            return [
                null,
                false,
            ];
        }

        foreach ($properties as $reflectionProperty) {
            if ($reflectionProperty->getName() === $property) {
                $byReflectionProperty = self::getPropertyValueByReflectionProperty(
                    $source,
                    $property,
                    $reflectionProperty
                );

                return [
                    $byReflectionProperty[0],
                    true,
                ];
            }
        }

        return [
            null,
            false,
        ];
    }
242504
public function loadMetadataForClass(\ReflectionClass $reflectionClass)
    {
        $className = $reflectionClass->getName();
        $classMetadata = new ClassMetadata($className);
        $classMetadata->fileResources[] = $reflectionClass->getFileName();

        $encryptionAnnotation = $this->reader->getClassAnnotation(
            $reflectionClass,
            'Jagilpe\\EncryptionBundle\\Annotation\\EncryptedEntity'
        );
        /** @var EncryptedEntity $encryptionAnnotation */
        if ($encryptionAnnotation) {
            $classMetadata->encryptionEnabled = $encryptionAnnotation->enabled;
            $classMetadata->encryptionMode = $encryptionAnnotation->mode;

            $encryptedFileAnnotation = $this->reader->getClassAnnotation(
                $reflectionClass,
                'Jagilpe\\EncryptionBundle\\Annotation\\EncryptedFile'
            );

            /** @var EncryptedFile $encryptedFileAnnotation */
            if ($encryptedFileAnnotation) {
                $classMetadata->encryptedFile = $encryptedFileAnnotation->enabled;
                $classMetadata->encryptedFileMode = $encryptedFileAnnotation->mode;
            }

            foreach ($reflectionClass->getProperties() as $reflectionProperty) {
                $propertyAnnotation = $this->reader->getPropertyAnnotation(
                    $reflectionProperty,
                    'Jagilpe\\EncryptionBundle\\Annotation\\EncryptedField'
                );

                /** @var EncryptedField $propertyAnnotation */
                if ($propertyAnnotation) {
                    $propertyMetadata = new PropertyMetadata($reflectionClass->getName(), $reflectionProperty->getName());
                    $propertyMetadata->encrypted = $propertyAnnotation->enabled;

                    $classMetadata->addPropertyMetadata($propertyMetadata);
                }
            }
        }
        else {
            $classMetadata->encryptionEnabled = false;
        }

        return $classMetadata;
    }
729917
protected function retrieveDeclarationPlace(\ReflectionProperty $refProperty)
    {
        static $declarationCache = array();

        // Early return from the cache.
        $declaringClass = $refProperty->getDeclaringClass();
        $key = $refProperty->name . '::' . $declaringClass->name;
        if (isset($declarationCache[$key])) {
            return $declarationCache[$key];
        }

        // A class can not redeclare a property from a trait that it is using.
        // Hence, if one of the traits has the same property that we are
        // analysing, it is probably declared there.
        // Traits on the other hand can redeclare their properties.
        // I'm not sure how to get the actual declaration place, when dealing
        // with several layers of traits. We will not parse the source code
        // for an answer.
        $type = '<br />in class: ';
        if (method_exists($declaringClass, 'getTraits')) {
            foreach ($refProperty->getDeclaringClass()->getTraits() as $trait) {
                if ($trait->hasProperty($refProperty->name)) {
                    if (count($trait->getTraitNames()) > 0) {
                        // Multiple layers of traits!
                        return $declarationCache[$key] = '';
                    }
                    // From a trait.
                    $declaringClass = $trait;
                    $type = '<br />in trait: ';
                    break;
                }
            }
        }

        $filename = $declaringClass->getFileName();

        if (empty($filename) === true) {
            return $declarationCache[$key] = static::UNKNOWN_DECLARATION;
        }

        return $declarationCache[$key] = $this->pool->fileService
                ->filterFilePath($declaringClass->getFileName()) . $type . $declaringClass->name;
    }
911500
protected function readClassMetadata($className)
	{
		/** @var DT\Metadata[] $result */
		$result = [];
		$reflection = new \ReflectionClass($className);
		$reader = new AnnotationReader();
		//Read property annotations
		$propertyFilter = \ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE;
		foreach ($reflection->getProperties($propertyFilter) as $property)
		{
			foreach (self::readPropertyAnnotations($property, $reader) as $subset => list($data, $strategy, $validators))
			{
				//Get or create metadata for subset
				$metadata = null;
				if (isset($result[$subset]))
				{
					$metadata = $result[$subset];
				}
				else
				{
					$metadata = new DT\Metadata();
					$metadata->className = $className;
					$metadata->subset = $subset;
					$result[$subset] = $metadata;
				}
				//Process field name
				$field = (empty($data->field)? $property->getName() : $data->field);
				if (in_array($field, $metadata->fields))
				{
					throw new \LogicException(
						sprintf('Invalid metadata for %s: duplicate field %s in subset "%s".', $className, $field, $data->subset)
					);
				}
				$metadata->fields[] = $field;
				//Process direct access property
				if ($property->isPublic())
				{
					$metadata->properties[$field] = $property->getName();
				}
				else
				{
					$methodNameBase = str_replace('_', '', ucwords($property->getName(), '_'));
					if ($data->getter === null)
					{
						$data->getter = 'get'. $methodNameBase;
					}
					if ($data->setter === null)
					{
						$data->setter = 'set'. $methodNameBase;
					}
				}
				//Process property getter
				if ((!empty($data->getter)) && self::isValidGetter($reflection, $data->getter))
				{
					$metadata->getters[$field] = $data->getter;
				}
				//Process property setter
				if ((!empty($data->setter)) && self::isValidSetter($reflection, $data->setter))
				{
					$metadata->setters[$field] = $data->setter;
				}
				//Copy strategy
				$metadata->strategies[$field] = $strategy;
				//Process nullable flag
				$metadata->nullables[$field] = $data->nullable;
				//Copy validators
				$metadata->validators[$field] = $validators;
			}
		}
		//Read class annotations
		foreach ($reader->getClassAnnotations($reflection) as $annotation)
		{
			if (($annotation instanceof DT\Annotation\Validator) && isset($result[$annotation->subset]))
			{
				$result[$annotation->subset]->validators[DT\Validator::GLOBAL_VALIDATOR_KEY][] = $annotation;
			}
		}
		return $result;
	}
949630
private function getProperty(State $state, $class, $property)
    {
        $refClass = $this->getClass($state, $class);

        if (!isset($refClass->properties[$property])) {
            throw new MarkupException(sprintf('property %s::$%s does not exist', $class, $property));
        }

        return $refClass->properties[$property];
    }
151953
public static function fetchStaticProperty($class, $property)
    {
        $refl = new \ReflectionClass($class);
        $prop = $refl->getProperty($property);
        $prop->setAccessible(true);

        return $prop->getValue();
    }
925817
public function getPropertyMapper($property)
    {
        if( !$this->propertyMapper ) {
            throw new NoPropertyMapperSet();
        }
        $refl = new ReflectionClass($this->propertyMapper);
        return $refl->newInstance($property);
    }
377286
private function dumpProperty($object, \ReflectionProperty $property, int $level): string
    {
        if ($property->isStatic()) {
            return '';
        }

        if (
            !($object instanceof \stdClass)
            && strpos($property->getDocComment(), '@invisible') !== false
        ) {
            //Memory loop while reading doc comment for stdClass variables?
            //Report a PHP bug about treating comment INSIDE property declaration as doc comment.
            return '';
        }

        //Property access level
        $access = $this->getAccess($property);

        //To read private and protected properties
        $property->setAccessible(true);

        if ($object instanceof \stdClass) {
            $name = $this->style->apply($property->getName(), 'dynamic');
        } else {
            //Property name includes access level
            $name = $property->getName() . $this->style->apply(':' . $access, 'access', $access);
        }

        return $this->dumpValue($property->getValue($object), $name, $level + 1);
    }
300998
private function getReflectionProperty($className, $property)
    {
        if (!isset(self::$properties[$className])) {
            self::$properties[$className] = array();
        }

        if (!isset(self::$properties[$className][$property])) {
            try {
                $rflProperty = new ReflectionProperty($className, $property);
                $rflProperty->setAccessible(true);
            } catch (ReflectionException $e) {
                if (($parentClass = get_parent_class($className)) !== false) {
                    $rflProperty = $this->getReflectionProperty($parentClass, $property);
                } else {
                    throw $e;
                }
            }

            self::$properties[$className][$property] = $rflProperty;
        }

        return self::$properties[$className][$property];
    }
1186695
public function getPropertyClass(\ReflectionProperty $property) : ?string
    {
        $types = $this->getPropertyTypes($property);

        if (count($types) === 1) {
            $type = $types[0];

            if ($type[0] === '\\') {
                return substr($type, 1);
            }
        }

        return null;
    }
152709
public function getData($property = AnDomain::ACCESS_PUBLIC, $default = null)
    {
        $description = $this->getEntityDescription();

        if (gettype($property) === 'integer') {
            $properties = $this->getEntityDescription()->getProperty();
            $access = (int) $property;
            $data = array();

            foreach ($properties as $name => $property) {
                if ($property->getReadAccess() >= $access) {
                    $data[$name] = $this->getData($name);
                }
            }

            return $data;
        }

        if (!$prop = $description->getProperty($property)) {
            return $this->get($property, $default);
        }

        $method = 'get'.ucfirst($property);

        if ($this->methodExists($method)) {
            $value = $this->$method();
        } else {
            $value = $this->get($property);
        }

        if (is_null($value)) {
            $value = $default;
        }

        return $value;
    }
481403
private function getPropertyValue(ReflectionClass $reflection, $property, $object)
    {
        $propertyReflection = $this->accessProperty($reflection, $property);
        $value = $propertyReflection->getValue($object);
        $propertyReflection->setAccessible(false);

        return $value;
    }
563142
protected function getDependencies(ReflectionClass $refl) {
        if (!$refl->isInstantiable()) {
            return [];
        }

        $constr = $refl->getConstructor();

        if (!$constr) {
            return [];
        }

        return $constr->getParameters();
    }
572487
private function readMethodCallees($class, ReflectionMethod $method)
    {
        $callees = array();

        // read parent annotations
        try {
            $prototype = $method->getPrototype();
            // error occurs on every second PHP stable release - getPrototype() returns itself
            if ($prototype->getDeclaringClass()->getName() !== $method->getDeclaringClass()->getName()) {
                $callees = array_merge($callees, $this->readMethodCallees($class, $prototype));
            }
        } catch (ReflectionException $e) {
        }

        if ($docBlock = $method->getDocComment()) {
            $callees = array_merge($callees, $this->readDocBlockCallees($class, $method, $docBlock));
        }

        return $callees;
    }