1 | <?php |
||
25 | abstract class AbstractMethodInvocation extends AbstractInvocation implements MethodInvocation |
||
26 | { |
||
27 | /** |
||
28 | * Instance of object for invoking |
||
29 | */ |
||
30 | protected ?object $instance; |
||
|
|||
31 | |||
32 | /** |
||
33 | * Instance of reflection method for invocation |
||
34 | */ |
||
35 | protected AnnotatedReflectionMethod $reflectionMethod; |
||
36 | |||
37 | /** |
||
38 | * Class name scope for static invocation |
||
39 | */ |
||
40 | protected string $scope = ''; |
||
41 | |||
42 | /** |
||
43 | * This static string variable holds the name of field to use to avoid extra "if" section in the __invoke method |
||
44 | * |
||
45 | * Overridden in children classes and initialized via LSB |
||
46 | */ |
||
47 | protected static string $propertyName; |
||
48 | |||
49 | /** |
||
50 | * Constructor for method invocation |
||
51 | 24 | * |
|
52 | * @param array $advices List of advices for this invocation |
||
53 | 24 | */ |
|
54 | 24 | public function __construct(array $advices, string $className, string $methodName) |
|
55 | 24 | { |
|
56 | parent::__construct($advices); |
||
57 | $this->reflectionMethod = $method = new AnnotatedReflectionMethod($className, $methodName); |
||
58 | 24 | ||
59 | 4 | // Give an access to call protected method |
|
60 | if ($method->isProtected()) { |
||
61 | 24 | $method->setAccessible(true); |
|
62 | } |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Invokes current method invocation with all interceptors |
||
67 | * |
||
68 | * @param null|object|string $instance Invocation instance (class name for static methods) |
||
69 | * @param array $arguments List of arguments for method invocation |
||
70 | * @param array $variadicArguments Additional list of variadic arguments |
||
71 | * |
||
72 | 20 | * @return mixed Result of invocation |
|
73 | */ |
||
74 | 20 | final public function __invoke($instance = null, array $arguments = [], array $variadicArguments = []) |
|
75 | 2 | { |
|
76 | if ($this->level > 0) { |
||
77 | $this->stackFrames[] = [$this->arguments, $this->scope, $this->instance, $this->current]; |
||
78 | 20 | } |
|
79 | |||
80 | if (count($variadicArguments) > 0) { |
||
81 | $arguments = array_merge($arguments, $variadicArguments); |
||
82 | } |
||
83 | 20 | ||
84 | try { |
||
85 | 20 | ++$this->level; |
|
86 | 20 | ||
87 | 20 | $this->current = 0; |
|
88 | $this->arguments = $arguments; |
||
89 | 20 | ||
90 | $this->{static::$propertyName} = $instance; |
||
91 | 20 | ||
92 | return $this->proceed(); |
||
93 | 20 | } finally { |
|
94 | 20 | --$this->level; |
|
95 | |||
96 | if ($this->level > 0) { |
||
97 | [$this->arguments, $this->scope, $this->instance, $this->current] = array_pop($this->stackFrames); |
||
98 | } else { |
||
99 | $this->instance = null; |
||
100 | $this->arguments = []; |
||
101 | } |
||
102 | } |
||
103 | } |
||
104 | 3 | ||
105 | /** |
||
106 | 3 | * Gets the method being called. |
|
107 | * |
||
108 | * @return AnnotatedReflectionMethod Covariant, the method being called. |
||
109 | */ |
||
110 | public function getMethod(): AnnotatedReflectionMethod |
||
111 | { |
||
112 | return $this->reflectionMethod; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Returns friendly description of this joinpoint |
||
117 | */ |
||
118 | final public function __toString(): string |
||
119 | { |
||
120 | return sprintf( |
||
121 | 'execution(%s%s%s())', |
||
122 | $this->getScope(), |
||
123 | $this->reflectionMethod->isStatic() ? '::' : '->', |
||
124 | $this->reflectionMethod->name |
||
125 | 1 | ); |
|
126 | } |
||
127 | } |
||
128 |