Completed
Pull Request — master (#440)
by
unknown
25:11
created

BaseAdvice   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 65
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 4
lcom 1
cbo 1
dl 0
loc 65
rs 10
c 0
b 0
f 0

3 Methods

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