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

GeneralAspectLoaderExtension::load()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 25
ccs 0
cts 14
cp 0
rs 8.8571
cc 3
eloc 16
nc 3
nop 3
crap 12
1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2012, 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\Core;
12
13
use Go\Aop\Advisor;
14
use Go\Aop\Aspect;
15
use Go\Aop\Framework;
16
use Go\Aop\Pointcut;
17
use Go\Aop\PointFilter;
18
use Go\Aop\Support;
19
use Go\Aop\Support\DefaultPointcutAdvisor;
20
use Go\Lang\Annotation;
21
22
/**
23
 * General aspect loader add common support for general advices, declared as annotations
24
 */
25
class GeneralAspectLoaderExtension extends AbstractAspectLoaderExtension
26
{
27
28
    /**
29
     * General aspect loader works with annotations from aspect
30
     *
31
     * For extension that works with annotations additional metaInformation will be passed
32
     *
33
     * @return string
34
     */
35
    public function getKind()
36
    {
37
        return self::KIND_ANNOTATION;
38
    }
39
40
    /**
41
     * General aspect loader works only with methods of aspect
42
     *
43
     * @return string|array
44
     */
45 2
    public function getTarget()
46
    {
47 2
        return self::TARGET_METHOD;
48
    }
49
50
    /**
51
     * Checks if loader is able to handle specific point of aspect
52
     *
53
     * @param Aspect $aspect Instance of aspect
54
     * @param mixed|\ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflection Reflection of point
55
     * @param mixed|null $metaInformation Additional meta-information, e.g. annotation for method
56
     *
57
     * @return boolean true if extension is able to create an advisor from reflection and metaInformation
58
     */
59
    public function supports(Aspect $aspect, $reflection, $metaInformation = null)
60
    {
61
        return $metaInformation instanceof Annotation\Interceptor
62
                || $metaInformation instanceof Annotation\Pointcut;
63
    }
64
65
    /**
66
     * Loads definition from specific point of aspect into the container
67
     *
68
     * @param Aspect $aspect Instance of aspect
69
     * @param mixed|\ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflection Reflection of point
70
     * @param mixed|null $metaInformation Additional meta-information, e.g. annotation for method
71
     *
72
     * @return array|Pointcut[]|Advisor[]
73
     *
74
     * @throws \UnexpectedValueException
75
     */
76
    public function load(Aspect $aspect, $reflection, $metaInformation = null)
77
    {
78
        $loadedItems    = [];
79
        $pointcut       = $this->parsePointcut($aspect, $reflection, $metaInformation);
80
        $methodId       = get_class($aspect) . '->' . $reflection->name;
81
        $adviceCallback = $reflection->getClosure($aspect);
82
83
        switch (true) {
84
            // Register a pointcut by its name
85
            case ($metaInformation instanceof Annotation\Pointcut):
86
                $loadedItems[$methodId] = $pointcut;
87
                break;
88
89
            case ($pointcut instanceof PointFilter):
90
                $advice = $this->getInterceptor($metaInformation, $adviceCallback);
91
92
                $loadedItems[$methodId] = new DefaultPointcutAdvisor($pointcut, $advice);
93
                break;
94
95
            default:
96
                throw new \UnexpectedValueException("Unsupported pointcut class: " . get_class($pointcut));
97
        }
98
99
        return $loadedItems;
100
    }
101
102
    /**
103
     * @param $metaInformation
104
     * @param $adviceCallback
105
     * @return \Go\Aop\Intercept\Interceptor
106
     * @throws \UnexpectedValueException
107
     */
108
    protected function getInterceptor($metaInformation, $adviceCallback)
109
    {
110
        $adviceOrder        = $metaInformation->order;
111
        $pointcutExpression = $metaInformation->value;
112
        switch (true) {
113
            case ($metaInformation instanceof Annotation\Before):
114
                return new Framework\BeforeInterceptor($adviceCallback, $adviceOrder, $pointcutExpression);
115
116
            case ($metaInformation instanceof Annotation\After):
117
                return new Framework\AfterInterceptor($adviceCallback, $adviceOrder, $pointcutExpression);
118
119
            case ($metaInformation instanceof Annotation\Around):
120
                return new Framework\AroundInterceptor($adviceCallback, $adviceOrder, $pointcutExpression);
121
122
            case ($metaInformation instanceof Annotation\AfterThrowing):
123
                return new Framework\AfterThrowingInterceptor($adviceCallback, $adviceOrder, $pointcutExpression);
124
125
            default:
126
                throw new \UnexpectedValueException("Unsupported method meta class: " . get_class($metaInformation));
127
        }
128
    }
129
}
130