Completed
Pull Request — master (#248)
by Alexander
02:46
created

BaseAdvice::createScopeCallback()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 34
ccs 0
cts 9
cp 0
rs 8.439
cc 6
eloc 22
nc 4
nop 3
crap 42
1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2011, 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
use Closure;
14
use Go\Aop\Features;
15
use ReflectionFunction;
16
use ReflectionMethod;
17
use Go\Core\AspectKernel;
18
19
/**
20
 * Base class for all framework advices implementations
21
 *
22
 *  This class describe an action taken by the AOP framework at a particular
23
 * joinpoint. Different types of advice include "around", "before" and "after"
24
 * advices.
25
 *
26
 *  Around advice is an advice that surrounds a joinpoint such as a method
27
 * invocation. This is the most powerful kind of advice. Around advices will
28
 * perform custom behavior before and after the method invocation. They are
29
 * responsible for choosing whether to proceed to the joinpoint or to shortcut
30
 * executing by returning their own return value or throwing an exception.
31
 *  After and before advices are simple closures that will be invoked after and
32
 * before main invocation.
33
 *  Framework model an advice as an PHP-closure interceptor, maintaining a
34
 * chain of interceptors "around" the joinpoint:
35
 *   function (Joinpoint $joinPoint) {
36
 *      echo 'Before action';
37
 *      // call chain here with Joinpoint->proceed() method
38
 *      $result = $joinPoint->proceed();
39
 *      echo 'After action';
40
 *      return $result;
41
 *   }
42
 */
43
abstract class BaseAdvice implements OrderedAdvice
44
{
45
    /**
46
     * Advice order
47
     *
48
     * @var int
49
     */
50
    protected $order = 0;
51
52
    /**
53
     * Local cache of advices for faster unserialization on big projects
54
     *
55
     * @var array|Closure[]
56
     */
57
    protected static $localAdvicesCache = [];
58
59
    /**
60
     * Returns the advice order
61
     *
62
     * @return int
63
     */
64
    public function getAdviceOrder()
65
    {
66
        return $this->order;
67
    }
68
69
    /**
70
     * Serialize advice method into array
71
     *
72
     * @param Closure $adviceMethod An advice for aspect
73
     *
74
     * @return array
75
     */
76
    public static function serializeAdvice(Closure $adviceMethod)
77
    {
78
        $refAdvice = new ReflectionFunction($adviceMethod);
79
80
        return [
81
            'method' => $refAdvice->name,
82
            'aspect' => get_class($refAdvice->getClosureThis())
83
        ];
84
    }
85
86
    /**
87
     * Unserialize an advice
88
     *
89
     * @param array $adviceData Information about advice
90
     *
91
     * @return Closure
92
     */
93
    public static function unserializeAdvice(array $adviceData)
94
    {
95
        $aspectName = $adviceData['aspect'];
96
        $methodName = $adviceData['method'];
97
98
        if (!isset(static::$localAdvicesCache["$aspectName->$methodName"])) {
99
            $refMethod = new ReflectionMethod($aspectName, $methodName);
100
            $aspect    = AspectKernel::getInstance()->getContainer()->getAspect($aspectName);
101
            $advice    = $refMethod->getClosure($aspect);
102
            static::$localAdvicesCache["$aspectName->$methodName"] = $advice;
103
        }
104
105
        return static::$localAdvicesCache["$aspectName->$methodName"];
106
    }
107
}
108