Completed
Push — master ( bfa80e...3adc88 )
by Alexander
02:11
created

GoAspectContainer::getAspect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types = 1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2012, Lisachenko Alexander <[email protected]>
7
 *
8
 * This source file is subject to the license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Go\Core;
13
14
use Doctrine\Common\Annotations\AnnotationReader;
15
use Doctrine\Common\Annotations\FileCacheReader;
16
use Go\Aop\Advisor;
17
use Go\Aop\Aspect;
18
use Go\Aop\Pointcut;
19
use Go\Aop\Pointcut\PointcutGrammar;
20
use Go\Aop\Pointcut\PointcutLexer;
21
use Go\Aop\Pointcut\PointcutParser;
22
use Go\Instrument\ClassLoading\CachePathManager;
23
use ReflectionClass;
24
25
/**
26
 * Aspect container contains list of all pointcuts and advisors
27
 */
28
class GoAspectContainer extends Container
29
{
30
    /**
31
     * List of resources for application
32
     *
33
     * @var array
34
     */
35
    protected $resources = [];
36
37
    /**
38
     * Cached timestamp for resources
39
     *
40
     * @var integer
41
     */
42
    protected $maxTimestamp = 0;
43
44
    /**
45
     * Constructor for container
46
     */
47
    public function __construct()
48
    {
49
        // Register all services in the container
50 9
        $this->share('aspect.loader', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
51 2
            $aspectLoader = new AspectLoader(
52
                $container,
53 2
                $container->get('aspect.annotation.reader')
54
            );
55 2
            $lexer  = $container->get('aspect.pointcut.lexer');
56 2
            $parser = $container->get('aspect.pointcut.parser');
57
58
            // Register general aspect loader extension
59 2
            $aspectLoader->registerLoaderExtension(new GeneralAspectLoaderExtension($lexer, $parser));
60 2
            $aspectLoader->registerLoaderExtension(new IntroductionAspectExtension($lexer, $parser));
61
62 2
            return $aspectLoader;
63 9
        });
64
65 9
        $this->share('aspect.cached.loader', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
66
            $options = $container->get('kernel.options');
67
            if (!empty($options['cacheDir'])) {
68
                $loader = new CachedAspectLoader(
69
                    $container,
70
                    'aspect.loader',
71
                    $container->get('kernel.options')
72
                );
73
            } else {
74
                $loader = $container->get('aspect.loader');
75
            }
76
77
            return $loader;
78 9
        });
79
80 9
        $this->share('aspect.advisor.accessor', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
81
            return new LazyAdvisorAccessor(
82
                $container,
83
                $container->get('aspect.cached.loader')
84
            );
85 9
        });
86
87 9
        $this->share('aspect.advice_matcher', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
88 1
            return new AdviceMatcher(
89 1
                $container->get('aspect.loader'),
90 1
                $container->get('kernel.interceptFunctions')
91
            );
92 9
        });
93
94 9
        $this->share('aspect.annotation.reader', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
95 4
            $options = $container->get('kernel.options');
96 4
            $reader  = new AnnotationReader();
97 4
            if (!empty($options['cacheDir'])) {
98
                $reader = new FileCacheReader(
0 ignored issues
show
Deprecated Code introduced by
The class Doctrine\Common\Annotations\FileCacheReader has been deprecated with message: the FileCacheReader is deprecated and will be removed in version 2.0.0 of doctrine/annotations. Please use the {@see \Doctrine\Common\Annotations\CachedReader} instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
99
                    $reader,
100
                    $options['cacheDir'] . DIRECTORY_SEPARATOR . '_annotations' . DIRECTORY_SEPARATOR,
101
                    $options['debug'],
102
                    0777 & (~$options['cacheFileMode'])
103
                );
104
            }
105
106 4
            return $reader;
107 9
        });
108 9
        $this->share('aspect.cache.path.manager', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
109
            return new CachePathManager($container->get('kernel'));
110 9
        });
111
112
        // Pointcut services
113 9
        $this->share('aspect.pointcut.lexer', function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
114 3
            return new PointcutLexer();
115 9
        });
116 9
        $this->share('aspect.pointcut.parser', function(Container $container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
117 3
            return new PointcutParser(
118 3
                new PointcutGrammar(
119
                    $container,
120 3
                    $container->get('aspect.annotation.reader')
121
                )
122
            );
123 9
        });
124 9
    }
125
126
    /**
127
     * Returns a pointcut by identifier
128
     *
129
     * @param string $id Pointcut identifier
130
     *
131
     * @return Pointcut
132
     */
133 1
    public function getPointcut(string $id) : Pointcut
134
    {
135 1
        return $this->get("pointcut.{$id}");
136
    }
137
138
    /**
139
     * Store the pointcut in the container
140
     *
141
     * @param Pointcut $pointcut Instance
142
     * @param string $id Key for pointcut
143
     */
144 1
    public function registerPointcut(Pointcut $pointcut, string $id)
145
    {
146 1
        $this->set("pointcut.{$id}", $pointcut, ['pointcut']);
147 1
    }
148
149
    /**
150
     * Returns an advisor by identifier
151
     *
152
     * @param string $id Advisor identifier
153
     *
154
     * @return Advisor
155
     */
156
    public function getAdvisor(string $id) : Advisor
157
    {
158
        return $this->get("advisor.{$id}");
159
    }
160
161
    /**
162
     * Store the advisor in the container
163
     *
164
     * @param Advisor $advisor Instance
165
     * @param string $id Key for advisor
166
     */
167 1
    public function registerAdvisor(Advisor $advisor, string $id)
168
    {
169 1
        $this->set("advisor.{$id}", $advisor, ['advisor']);
170 1
    }
171
172
    /**
173
     * Returns an aspect by id or class name
174
     *
175
     * @param string $aspectName Aspect name
176
     *
177
     * @return Aspect
178
     */
179 1
    public function getAspect(string $aspectName) : Aspect
180
    {
181 1
        return $this->get("aspect.{$aspectName}");
182
    }
183
184
    /**
185
     * Register an aspect in the container
186
     *
187
     * @param Aspect $aspect Instance of concrete aspect
188
     */
189 1
    public function registerAspect(Aspect $aspect)
190
    {
191 1
        $refAspect = new ReflectionClass($aspect);
192 1
        $this->set("aspect.{$refAspect->name}", $aspect, ['aspect']);
193 1
        $this->addResource($refAspect->getFileName());
194 1
    }
195
196
    /**
197
     * Add an AOP resource to the container
198
     * Resources is used to check the freshness of AOP cache
199
     *
200
     * @param string $resource Path to the resource
201
     */
202 2
    public function addResource(string $resource)
203
    {
204 2
        $this->resources[]  = $resource;
205 2
        $this->maxTimestamp = 0;
206 2
    }
207
208
    /**
209
     * Returns list of AOP resources
210
     */
211
    public function getResources() : array
212
    {
213
        return $this->resources;
214
    }
215
216
    /**
217
     * Checks the freshness of AOP cache
218
     *
219
     * @param integer $timestamp
220
     *
221
     * @return bool Whether or not concrete file is fresh
222
     */
223 1
    public function isFresh(int $timestamp) : bool
224
    {
225 1
        if (!$this->maxTimestamp && !empty($this->resources)) {
226 1
            $this->maxTimestamp = max(array_map('filemtime', $this->resources));
227
        }
228
229 1
        return $this->maxTimestamp <= $timestamp;
230
    }
231
}
232