Completed
Push — 1.x ( c183a4...05b51a )
by Alexander
8s
created

DynamicClosureMethodInvocation::proceed()   D

Complexity

Conditions 10
Paths 29

Size

Total Lines 41
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 41
ccs 25
cts 25
cp 1
rs 4.8196
cc 10
eloc 26
nc 29
nop 0
crap 10

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\Aop\Framework;
12
13
class DynamicClosureMethodInvocation extends AbstractMethodInvocation
14
{
15
    /**
16
     * Closure to use
17
     *
18
     * @var \Closure
19
     */
20
    protected $closureToCall = null;
21
22
    /**
23
     * Previous instance/scope of invocation
24
     *
25
     * @var null|object|string
26
     */
27
    protected $previousInstance = null;
28
29
    /**
30
     * Invokes original method and return result from it
31
     *
32
     * @return mixed
33
     */
34 6
    public function proceed()
35
    {
36 6
        if (isset($this->advices[$this->current])) {
37
            /** @var $currentInterceptor \Go\Aop\Intercept\Interceptor */
38 1
            $currentInterceptor = $this->advices[$this->current++];
39
40 1
            return $currentInterceptor->invoke($this);
41
        }
42
43
        // Fill the closure only once if it's empty
44 6
        if (!$this->closureToCall) {
45 6
            $this->closureToCall = $this->reflectionMethod->getClosure($this->instance);
46
        }
47
48
        // Rebind the closure if instance was changed since last time
49 6
        if ($this->previousInstance !== $this->instance) {
50 6
            $this->closureToCall    = $this->closureToCall->bindTo($this->instance, $this->reflectionMethod->class);
51 6
            $this->previousInstance = $this->instance;
52
        }
53
54 6
        $closureToCall = $this->closureToCall;
55 6
        $args          = $this->arguments;
56
57 6
        switch (count($args)) {
58 6
            case 0:
59 3
                return $closureToCall();
60 3
            case 1:
61 2
                return $closureToCall($args[0]);
62 2
            case 2:
63 2
                return $closureToCall($args[0], $args[1]);
64 1
            case 3:
65 1
                return $closureToCall($args[0], $args[1], $args[2]);
66 1
            case 4:
67 1
                return $closureToCall($args[0], $args[1], $args[2], $args[3]);
68 1
            case 5:
69 1
                return $closureToCall($args[0], $args[1], $args[2], $args[3], $args[4]);
70
            default:
71 1
                return forward_static_call_array($closureToCall, $args);
72
        }
73
74
    }
75
76
    /**
77
     * Invokes current method invocation with all interceptors
78
     *
79
     * @param null|object|string $instance Invocation instance (class name for static methods)
80
     * @param array $arguments List of arguments for method invocation
81
     *
82
     * @return mixed Result of invocation
83
     */
84 24
    final public function __invoke($instance = null, array $arguments = [])
85
    {
86 24
        if ($this->level) {
87 3
            $this->stackFrames[] = [$this->arguments, $this->instance, $this->current];
88
        }
89
90
        try {
91 24
            ++$this->level;
92
93 24
            $this->current   = 0;
94 24
            $this->instance  = $instance;
95 24
            $this->arguments = $arguments;
96
97 24
            $result = $this->proceed();
98 24
        } finally {
99 24
            --$this->level;
100
        }
101
102 24
        if ($this->level) {
103 3
            list($this->arguments, $this->instance, $this->current) = array_pop($this->stackFrames);
104
        }
105
106 24
        return $result;
107
    }
108
}
109