%PDF- %PDF-
| Direktori : /home/graphicd/public_html/vebto/vendor/roave/better-reflection/src/Reflection/ |
| Current File : /home/graphicd/public_html/vebto/vendor/roave/better-reflection/src/Reflection/ReflectionMethod.php |
<?php
declare(strict_types=1);
namespace Roave\BetterReflection\Reflection;
use Closure;
use InvalidArgumentException;
use OutOfBoundsException;
use PhpParser\Node\Stmt\ClassMethod as MethodNode;
use PhpParser\Node\Stmt\Namespace_;
use ReflectionException;
use ReflectionMethod as CoreReflectionMethod;
use Roave\BetterReflection\Reflection\Exception\ClassDoesNotExist;
use Roave\BetterReflection\Reflection\Exception\InvalidAbstractFunctionNodeType;
use Roave\BetterReflection\Reflection\Exception\NoObjectProvided;
use Roave\BetterReflection\Reflection\Exception\NotAnObject;
use Roave\BetterReflection\Reflection\Exception\ObjectNotInstanceOfClass;
use Roave\BetterReflection\Reflection\StringCast\ReflectionMethodStringCast;
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
use Roave\BetterReflection\Reflector\Reflector;
use function class_exists;
use function get_class;
use function is_object;
use function sprintf;
use function strtolower;
class ReflectionMethod extends ReflectionFunctionAbstract
{
/** @var ReflectionClass */
private $declaringClass;
/** @var ReflectionClass */
private $implementingClass;
/** @var MethodNode */
private $methodNode;
/** @var string|null */
private $aliasName;
/**
* @internal
*
* @param MethodNode $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver
*
* @throws InvalidAbstractFunctionNodeType
*/
public static function createFromNode(
Reflector $reflector,
MethodNode $node,
?Namespace_ $namespace,
ReflectionClass $declaringClass,
ReflectionClass $implementingClass,
?string $aliasName = null
) : self {
$method = new self();
$method->declaringClass = $declaringClass;
$method->implementingClass = $implementingClass;
$method->methodNode = $node;
$method->aliasName = $aliasName;
$method->populateFunctionAbstract($reflector, $node, $declaringClass->getLocatedSource(), $namespace);
return $method;
}
/**
* Create a reflection of a method by it's name using a named class
*
* @throws IdentifierNotFound
* @throws OutOfBoundsException
*/
public static function createFromName(string $className, string $methodName) : self
{
return ReflectionClass::createFromName($className)->getMethod($methodName);
}
/**
* Create a reflection of a method by it's name using an instance
*
* @param object $instance
*
* @throws InvalidArgumentException
* @throws ReflectionException
* @throws IdentifierNotFound
* @throws OutOfBoundsException
*/
public static function createFromInstance($instance, string $methodName) : self
{
return ReflectionClass::createFromInstance($instance)->getMethod($methodName);
}
public function getShortName() : string
{
if ($this->aliasName !== null) {
return $this->aliasName;
}
return parent::getShortName();
}
public function getAliasName() : ?string
{
return $this->aliasName;
}
/**
* Find the prototype for this method, if it exists. If it does not exist
* it will throw a MethodPrototypeNotFound exception.
*
* @throws Exception\MethodPrototypeNotFound
*/
public function getPrototype() : self
{
$currentClass = $this->getDeclaringClass();
while ($currentClass) {
foreach ($currentClass->getImmediateInterfaces() as $interface) {
if ($interface->hasMethod($this->getName())) {
return $interface->getMethod($this->getName());
}
}
$currentClass = $currentClass->getParentClass();
if ($currentClass === null || ! $currentClass->hasMethod($this->getName())) {
break;
}
$prototype = $currentClass->getMethod($this->getName())->findPrototype();
if ($prototype !== null) {
return $prototype;
}
}
throw new Exception\MethodPrototypeNotFound(sprintf(
'Method %s::%s does not have a prototype',
$this->getDeclaringClass()->getName(),
$this->getName()
));
}
private function findPrototype() : ?self
{
if ($this->isAbstract()) {
return $this;
}
if ($this->isPrivate()) {
return null;
}
try {
return $this->getPrototype();
} catch (Exception\MethodPrototypeNotFound $e) {
return $this;
}
}
/**
* Get the core-reflection-compatible modifier values.
*/
public function getModifiers() : int
{
$val = 0;
$val += $this->isStatic() ? CoreReflectionMethod::IS_STATIC : 0;
$val += $this->isPublic() ? CoreReflectionMethod::IS_PUBLIC : 0;
$val += $this->isProtected() ? CoreReflectionMethod::IS_PROTECTED : 0;
$val += $this->isPrivate() ? CoreReflectionMethod::IS_PRIVATE : 0;
$val += $this->isAbstract() ? CoreReflectionMethod::IS_ABSTRACT : 0;
$val += $this->isFinal() ? CoreReflectionMethod::IS_FINAL : 0;
return $val;
}
public function __toString() : string
{
return ReflectionMethodStringCast::toString($this);
}
public function inNamespace() : bool
{
return false;
}
/**
* Is the method abstract.
*/
public function isAbstract() : bool
{
return $this->methodNode->isAbstract() || $this->declaringClass->isInterface();
}
/**
* Is the method final.
*/
public function isFinal() : bool
{
return $this->methodNode->isFinal();
}
/**
* Is the method private visibility.
*/
public function isPrivate() : bool
{
return $this->methodNode->isPrivate();
}
/**
* Is the method protected visibility.
*/
public function isProtected() : bool
{
return $this->methodNode->isProtected();
}
/**
* Is the method public visibility.
*/
public function isPublic() : bool
{
return $this->methodNode->isPublic();
}
/**
* Is the method static.
*/
public function isStatic() : bool
{
return $this->methodNode->isStatic();
}
/**
* Is the method a constructor.
*/
public function isConstructor() : bool
{
if (strtolower($this->getName()) === '__construct') {
return true;
}
$declaringClass = $this->getDeclaringClass();
if ($declaringClass->inNamespace()) {
return false;
}
return strtolower($this->getName()) === strtolower($declaringClass->getShortName());
}
/**
* Is the method a destructor.
*/
public function isDestructor() : bool
{
return strtolower($this->getName()) === '__destruct';
}
/**
* Get the class that declares this method.
*/
public function getDeclaringClass() : ReflectionClass
{
return $this->declaringClass;
}
public function getImplementingClass() : ReflectionClass
{
return $this->implementingClass;
}
public function isInternal() : bool
{
return $this->declaringClass->getLocatedSource()->isInternal();
}
/**
* @param object|null $object
*
* @throws ClassDoesNotExist
* @throws NoObjectProvided
* @throws NotAnObject
* @throws ObjectNotInstanceOfClass
*/
public function getClosure($object = null) : Closure
{
$declaringClassName = $this->getDeclaringClass()->getName();
if ($this->isStatic()) {
$this->assertClassExist($declaringClassName);
return function (...$args) {
return $this->callStaticMethod($args);
};
}
$instance = $this->assertObject($object);
return function (...$args) use ($instance) {
return $this->callObjectMethod($instance, $args);
};
}
/**
* @param object|null $object
* @param mixed ...$args
*
* @return mixed
*
* @throws ClassDoesNotExist
* @throws NoObjectProvided
* @throws NotAnObject
* @throws ObjectNotInstanceOfClass
*/
public function invoke($object = null, ...$args)
{
return $this->invokeArgs($object, $args);
}
/**
* @param object|null $object
* @param mixed[] $args
*
* @return mixed
*
* @throws ClassDoesNotExist
* @throws NoObjectProvided
* @throws NotAnObject
* @throws ObjectNotInstanceOfClass
*/
public function invokeArgs($object = null, array $args = [])
{
$declaringClassName = $this->getDeclaringClass()->getName();
if ($this->isStatic()) {
$this->assertClassExist($declaringClassName);
return $this->callStaticMethod($args);
}
return $this->callObjectMethod($this->assertObject($object), $args);
}
/**
* @param mixed[] $args
*
* @return mixed
*/
private function callStaticMethod(array $args)
{
$declaringClassName = $this->getDeclaringClass()->getName();
return Closure::bind(function (string $declaringClassName, string $methodName, array $methodArgs) {
return $declaringClassName::{$methodName}(...$methodArgs);
}, null, $declaringClassName)->__invoke($declaringClassName, $this->getName(), $args);
}
/**
* @param object $object
* @param mixed[] $args
*
* @return mixed
*/
private function callObjectMethod($object, array $args)
{
return Closure::bind(function ($object, string $methodName, array $methodArgs) {
return $object->{$methodName}(...$methodArgs);
}, $object, $this->getDeclaringClass()->getName())->__invoke($object, $this->getName(), $args);
}
/**
* @throws ClassDoesNotExist
*/
private function assertClassExist(string $className) : void
{
if (! class_exists($className, false)) {
throw new ClassDoesNotExist(sprintf('Method of class %s cannot be used as the class is not loaded', $className));
}
}
/**
* @param mixed $object
*
* @return object
*
* @throws NoObjectProvided
* @throws NotAnObject
* @throws ObjectNotInstanceOfClass
*/
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;
}
}