%PDF- %PDF-
Direktori : /home/graphicd/www/vebto/vendor/roave/better-reflection/src/Reflection/ |
Current File : /home/graphicd/www/vebto/vendor/roave/better-reflection/src/Reflection/ReflectionProperty.php |
<?php declare(strict_types=1); namespace Roave\BetterReflection\Reflection; use Closure; use InvalidArgumentException; use phpDocumentor\Reflection\Type; use PhpParser\Node; use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Property as PropertyNode; use ReflectionException; use ReflectionProperty as CoreReflectionProperty; use Roave\BetterReflection\NodeCompiler\CompileNodeToValue; use Roave\BetterReflection\NodeCompiler\CompilerContext; use Roave\BetterReflection\Reflection\Exception\ClassDoesNotExist; use Roave\BetterReflection\Reflection\Exception\NoObjectProvided; use Roave\BetterReflection\Reflection\Exception\NotAnObject; use Roave\BetterReflection\Reflection\Exception\ObjectNotInstanceOfClass; use Roave\BetterReflection\Reflection\Exception\Uncloneable; use Roave\BetterReflection\Reflection\StringCast\ReflectionPropertyStringCast; use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\TypesFinder\FindPropertyType; use Roave\BetterReflection\Util\CalculateReflectionColum; use Roave\BetterReflection\Util\GetFirstDocComment; use function class_exists; use function func_num_args; use function get_class; use function is_object; class ReflectionProperty { /** @var ReflectionClass */ private $declaringClass; /** @var ReflectionClass */ private $implementingClass; /** @var PropertyNode */ private $node; /** @var int */ private $positionInNode; /** @var Namespace_|null */ private $declaringNamespace; /** @var bool */ private $declaredAtCompileTime = true; /** @var Reflector */ private $reflector; private function __construct() { } /** * Create a reflection of a class's property by its name */ public static function createFromName(string $className, string $propertyName) : self { return ReflectionClass::createFromName($className)->getProperty($propertyName); } /** * Create a reflection of an instance's property by its name * * @param object $instance * * @throws InvalidArgumentException * @throws ReflectionException * @throws IdentifierNotFound */ public static function createFromInstance($instance, string $propertyName) : self { return ReflectionClass::createFromInstance($instance)->getProperty($propertyName); } public function __toString() : string { return ReflectionPropertyStringCast::toString($this); } /** * @internal * * @param PropertyNode $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver */ public static function createFromNode( Reflector $reflector, PropertyNode $node, int $positionInNode, ?Namespace_ $declaringNamespace, ReflectionClass $declaringClass, ReflectionClass $implementingClass, bool $declaredAtCompileTime = true ) : self { $prop = new self(); $prop->reflector = $reflector; $prop->node = $node; $prop->positionInNode = $positionInNode; $prop->declaringNamespace = $declaringNamespace; $prop->declaringClass = $declaringClass; $prop->implementingClass = $implementingClass; $prop->declaredAtCompileTime = $declaredAtCompileTime; return $prop; } /** * Set the default visibility of this property. Use the core \ReflectionProperty::IS_* values as parameters, e.g.: * * @throws InvalidArgumentException */ public function setVisibility(int $newVisibility) : void { $this->node->flags &= ~Class_::MODIFIER_PRIVATE & ~Class_::MODIFIER_PROTECTED & ~Class_::MODIFIER_PUBLIC; switch ($newVisibility) { case CoreReflectionProperty::IS_PRIVATE: $this->node->flags |= Class_::MODIFIER_PRIVATE; break; case CoreReflectionProperty::IS_PROTECTED: $this->node->flags |= Class_::MODIFIER_PROTECTED; break; case CoreReflectionProperty::IS_PUBLIC: $this->node->flags |= Class_::MODIFIER_PUBLIC; break; default: throw new InvalidArgumentException('Visibility should be \ReflectionProperty::IS_PRIVATE, ::IS_PROTECTED or ::IS_PUBLIC constants'); } } /** * Has the property been declared at compile-time? * * Note that unless the property is static, this is hard coded to return * true, because we are unable to reflect instances of classes, therefore * we can be sure that all properties are always declared at compile-time. */ public function isDefault() : bool { return $this->declaredAtCompileTime; } /** * Get the core-reflection-compatible modifier values. */ public function getModifiers() : int { $val = 0; $val += $this->isStatic() ? CoreReflectionProperty::IS_STATIC : 0; $val += $this->isPublic() ? CoreReflectionProperty::IS_PUBLIC : 0; $val += $this->isProtected() ? CoreReflectionProperty::IS_PROTECTED : 0; $val += $this->isPrivate() ? CoreReflectionProperty::IS_PRIVATE : 0; return $val; } /** * Get the name of the property. */ public function getName() : string { return $this->node->props[$this->positionInNode]->name->name; } /** * Is the property private? */ public function isPrivate() : bool { return $this->node->isPrivate(); } /** * Is the property protected? */ public function isProtected() : bool { return $this->node->isProtected(); } /** * Is the property public? */ public function isPublic() : bool { return $this->node->isPublic(); } /** * Is the property static? */ public function isStatic() : bool { return $this->node->isStatic(); } /** * Get the DocBlock type hints as an array of strings. * * @return string[] */ public function getDocBlockTypeStrings() : array { $stringTypes = []; foreach ($this->getDocBlockTypes() as $type) { $stringTypes[] = (string) $type; } return $stringTypes; } /** * Get the types defined in the DocBlocks. This returns an array because * the parameter may have multiple (compound) types specified (for example * when you type hint pipe-separated "string|null", in which case this * would return an array of Type objects, one for string, one for null. * * @return Type[] */ public function getDocBlockTypes() : array { return (new FindPropertyType())->__invoke($this, $this->declaringNamespace); } public function getDeclaringClass() : ReflectionClass { return $this->declaringClass; } public function getImplementingClass() : ReflectionClass { return $this->implementingClass; } public function getDocComment() : string { return GetFirstDocComment::forNode($this->node); } /** * Get the default value of the property (as defined before constructor is * called, when the property is defined) * * @return scalar|array<scalar>|null */ public function getDefaultValue() { $defaultValueNode = $this->node->props[$this->positionInNode]->default; if ($defaultValueNode === null) { return null; } return (new CompileNodeToValue())->__invoke( $defaultValueNode, new CompilerContext($this->reflector, $this->getDeclaringClass()) ); } /** * Get the line number that this property starts on. */ public function getStartLine() : int { return $this->node->getStartLine(); } /** * Get the line number that this property ends on. */ public function getEndLine() : int { return $this->node->getEndLine(); } public function getStartColumn() : int { return CalculateReflectionColum::getStartColumn($this->declaringClass->getLocatedSource()->getSource(), $this->node); } public function getEndColumn() : int { return CalculateReflectionColum::getEndColumn($this->declaringClass->getLocatedSource()->getSource(), $this->node); } public function getAst() : PropertyNode { return $this->node; } public function getPositionInAst() : int { return $this->positionInNode; } /** * {@inheritdoc} * * @throws Uncloneable */ public function __clone() { throw Uncloneable::fromClass(self::class); } /** * @param object|null $object * * @return mixed * * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass */ public function getValue($object = null) { $declaringClassName = $this->getDeclaringClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($declaringClassName); return Closure::bind(function (string $declaringClassName, string $propertyName) { return $declaringClassName::${$propertyName}; }, null, $declaringClassName)->__invoke($declaringClassName, $this->getName()); } $instance = $this->assertObject($object); return Closure::bind(function (object $instance, string $propertyName) { return $instance->{$propertyName}; }, $instance, $declaringClassName)->__invoke($instance, $this->getName()); } /** * @param object $object * @param mixed|null $value * * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass */ public function setValue($object, $value = null) : void { $declaringClassName = $this->getDeclaringClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($declaringClassName); Closure::bind(function (string $declaringClassName, string $propertyName, $value) : void { $declaringClassName::${$propertyName} = $value; }, null, $declaringClassName)->__invoke($declaringClassName, $this->getName(), func_num_args() === 2 ? $value : $object); return; } $instance = $this->assertObject($object); Closure::bind(function ($instance, string $propertyName, $value) : void { $instance->{$propertyName} = $value; }, $instance, $declaringClassName)->__invoke($instance, $this->getName(), $value); } /** * Does this property allow null? */ public function allowsNull() : bool { if (! $this->hasType()) { return true; } return $this->node->type instanceof NullableType; } /** * Get the ReflectionType instance representing the type declaration for * this property * * (note: this has nothing to do with DocBlocks). */ public function getType() : ?ReflectionType { $type = $this->node->type; if ($type === null) { return null; } if ($type instanceof NullableType) { $type = $type->type; } return ReflectionType::createFromTypeAndReflector((string) $type, $this->allowsNull(), $this->reflector); } /** * Does this property have a type declaration? * * (note: this has nothing to do with DocBlocks). */ public function hasType() : bool { return $this->node->type !== null; } /** * Set the property type declaration. */ public function setType(string $newPropertyType) : void { $this->node->type = new Node\Name($newPropertyType); } /** * Remove the property type declaration completely. */ public function removeType() : void { $this->node->type = null; } /** * @throws ClassDoesNotExist * * @psalm-assert class-string $className */ private function assertClassExist(string $className) : void { if (! class_exists($className, false)) { throw new ClassDoesNotExist('Property cannot be retrieved as the class is not loaded'); } } /** * @param mixed $object * * @return object * * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass * * @psalm-assert object $object */ private function assertObject($object) { if ($object === null) { throw NoObjectProvided::create(); } if (! is_object($object)) { throw NotAnObject::fromNonObject($object); } $declaringClassName = $this->getDeclaringClass()->getName(); if (get_class($object) !== $declaringClassName) { throw ObjectNotInstanceOfClass::fromClassName($declaringClassName); } return $object; } }