Completed
Pull Request — master (#463)
by Alexander
30:17 queued 05:15
created

StaticClosureMethodInvocation   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 1
dl 0
loc 86
ccs 13
cts 13
cp 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
/*
5
 * Go! AOP framework
6
 *
7
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
8
 *
9
 * This source file is subject to the license that is bundled
10
 * with this source code in the file LICENSE.
11
 */
12
13
namespace Go\Aop\Framework;
14
15
use Closure;
16
17
/**
18
 * Static closure method invocation is responsible to call static methods via closure
19
 */
20
final class StaticClosureMethodInvocation extends AbstractMethodInvocation
21
{
22
    /**
23
     * Closure to use
24
     */
25
    protected ?Closure $closureToCall = null;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '?', expecting T_FUNCTION or T_CONST
Loading history...
26
27
    /**
28
     * Previous scope of invocation
29
     */
30
    protected ?string $previousScope = null;
31
32
    /**
33
     * For static calls we store given argument as 'scope' property
34
     */
35
    protected static string $propertyName = 'scope';
36
37
    /**
38 13
     * Proceeds all registered advices for the static method and returns an invocation result
39
     */
40 13
    public function proceed()
41 1
    {
42
        if (isset($this->advices[$this->current])) {
43 1
            $currentInterceptor = $this->advices[$this->current++];
44
45
            return $currentInterceptor->invoke($this);
46
        }
47 13
48 13
        // Rebind the closure if scope (class name) was changed since last time
49 13
        if ($this->previousScope !== $this->scope) {
50
            if ($this->closureToCall === null) {
51 13
                $this->closureToCall = self::getStaticInvoker(
52 13
                    $this->reflectionMethod->class,
53
                    $this->reflectionMethod->name
54
                );
55 13
            }
56
            $this->closureToCall = $this->closureToCall->bindTo(null, $this->scope);
57
            $this->previousScope = $this->scope;
58
        }
59
60
        return ($this->closureToCall)($this->arguments);
61
    }
62 13
63
    /**
64
     * Returns static method invoker for the concrete method in the class
65 13
     */
66 13
    protected static function getStaticInvoker(string $className, string $methodName): Closure
67
    {
68
        return fn(array $args) => forward_static_call_array([$className, $methodName], $args);
69
    }
70
71
    /**
72
     * Checks if the current joinpoint is dynamic or static
73
     *
74
     * Dynamic joinpoint contains a reference to an object that can be received via getThis() method call
75
     *
76
     * @see ClassJoinpoint::getThis()
77
     */
78
    final public function isDynamic(): bool
79
    {
80
        return false;
81
    }
82
83
    /**
84
     * Returns the object for which current joinpoint is invoked
85
     *
86
     * @return object Instance of object or null for static call/unavailable context
87
     */
88
    final public function getThis(): ?object
89
    {
90
        return null;
91
    }
92
93
    /**
94
     * Returns the static scope name (class name) of this joinpoint.
95
     */
96
    final public function getScope(): string
97
    {
98
        // $this->scope contains the current class scope that was received via static::class
99
        return $this->scope;
100
    }
101
}
102