Completed
Push — master ( 91676c...354384 )
by Alexander
02:23
created

GoAspectContainer::getPointcut()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
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\CachedReader;
16
use Doctrine\Common\Cache as DoctrineCache;
17
use Go\Aop\Advisor;
18
use Go\Aop\Aspect;
19
use Go\Aop\Pointcut;
20
use Go\Aop\Pointcut\PointcutGrammar;
21
use Go\Aop\Pointcut\PointcutLexer;
22
use Go\Aop\Pointcut\PointcutParser;
23
use Go\Instrument\ClassLoading\CachePathManager;
24
use ReflectionClass;
25
26
/**
27
 * Aspect container contains list of all pointcuts and advisors
28
 */
29
class GoAspectContainer extends Container
30
{
31
    /**
32
     * List of resources for application
33
     *
34
     * @var string[]
35
     */
36
    protected $resources = [];
37
38
    /**
39
     * Cached timestamp for resources
40
     *
41
     * @var integer
42
     */
43
    protected $maxTimestamp = 0;
44
45
    /**
46
     * Constructor for container
47
     */
48 11
    public function __construct()
49
    {
50
        // Register all services in the container
51
        $this->share('aspect.loader', function (Container $container) {
52 2
            $aspectLoader = new AspectLoader(
53 2
                $container,
54 2
                $container->get('aspect.annotation.reader')
55
            );
56 2
            $lexer  = $container->get('aspect.pointcut.lexer');
57 2
            $parser = $container->get('aspect.pointcut.parser');
58
59
            // Register general aspect loader extension
60 2
            $aspectLoader->registerLoaderExtension(new GeneralAspectLoaderExtension($lexer, $parser));
61 2
            $aspectLoader->registerLoaderExtension(new IntroductionAspectExtension($lexer, $parser));
62
63 2
            return $aspectLoader;
64 11
        });
65
66
        $this->share('aspect.cached.loader', function (Container $container) {
67 1
            $options = $container->get('kernel.options');
68 1
            if (!empty($options['cacheDir'])) {
69 1
                $loader = new CachedAspectLoader(
70 1
                    $container,
71 1
                    'aspect.loader',
72 1
                    $container->get('kernel.options')
73
                );
74
            } else {
75
                $loader = $container->get('aspect.loader');
76
            }
77
78 1
            return $loader;
79 11
        });
80
81
        $this->share('aspect.advisor.accessor', function (Container $container) {
82 1
            return new LazyAdvisorAccessor(
83 1
                $container,
84 1
                $container->get('aspect.cached.loader')
85
            );
86 11
        });
87
88
        $this->share('aspect.advice_matcher', function (Container $container) {
89 2
            return new AdviceMatcher(
90 2
                $container->get('kernel.interceptFunctions')
91
            );
92 11
        });
93
94
        $this->share('aspect.annotation.cache', function (Container $container) {
95 5
            $options = $container->get('kernel.options');
96
97 5
            if (!empty($options['annotationCache'])) {
98
                return $options['annotationCache'];
99
            }
100
101 5
            if (!empty($options['cacheDir'])) {
102 1
                return new DoctrineCache\FilesystemCache(
103 1
                    $options['cacheDir'] . DIRECTORY_SEPARATOR . '_annotations' . DIRECTORY_SEPARATOR,
104 1
                    '.annotations.cache',
105 1
                    0777 & (~$options['cacheFileMode'])
106
                );
107
            }
108
109 4
            return new DoctrineCache\ArrayCache();
110 11
        });
111
112
        $this->share('aspect.annotation.reader', function (Container $container) {
113 4
            $options = $container->get('kernel.options');
114
115 4
            return new CachedReader(
116 4
                new AnnotationReader(),
117 4
                $container->get('aspect.annotation.cache'),
118 4
                $options['debug'] ?? false
119
            );
120 11
        });
121
122
        $this->share('aspect.cache.path.manager', function (Container $container) {
123 1
            return new CachePathManager($container->get('kernel'));
124 11
        });
125
126
        // Pointcut services
127
        $this->share('aspect.pointcut.lexer', function () {
128 3
            return new PointcutLexer();
129 11
        });
130
        $this->share('aspect.pointcut.parser', function (Container $container) {
131 3
            return new PointcutParser(
132 3
                new PointcutGrammar(
133 3
                    $container,
134 3
                    $container->get('aspect.annotation.reader')
135
                )
136
            );
137 11
        });
138 11
    }
139
140
    /**
141
     * Returns a pointcut by identifier
142
     */
143 1
    public function getPointcut(string $id): Pointcut
144
    {
145 1
        return $this->get("pointcut.{$id}");
146
    }
147
148
    /**
149
     * Store the pointcut in the container
150
     */
151 1
    public function registerPointcut(Pointcut $pointcut, string $id): void
152
    {
153 1
        $this->set("pointcut.{$id}", $pointcut, ['pointcut']);
154 1
    }
155
156
    /**
157
     * Returns an advisor by identifier
158
     */
159
    public function getAdvisor(string $id): Advisor
160
    {
161
        return $this->get("advisor.{$id}");
162
    }
163
164
    /**
165
     * Store the advisor in the container
166
     */
167 2
    public function registerAdvisor(Advisor $advisor, string $id): void
168
    {
169 2
        $this->set("advisor.{$id}", $advisor, ['advisor']);
170 2
    }
171
172
    /**
173
     * Returns an aspect by id or class name
174
     */
175 1
    public function getAspect(string $aspectName): Aspect
176
    {
177 1
        return $this->get("aspect.{$aspectName}");
178
    }
179
180
    /**
181
     * Register an aspect in the container
182
     */
183 2
    public function registerAspect(Aspect $aspect): void
184
    {
185 2
        $refAspect = new ReflectionClass($aspect);
186 2
        $this->set("aspect.{$refAspect->name}", $aspect, ['aspect']);
187 2
        $this->addResource($refAspect->getFileName());
188 2
    }
189
190
    /**
191
     * Add an AOP resource to the container
192
     * Resources is used to check the freshness of AOP cache
193
     *
194
     * @param string $resource Path to the resource
195
     */
196 3
    public function addResource(string $resource)
197
    {
198 3
        $this->resources[]  = $resource;
199 3
        $this->maxTimestamp = 0;
200 3
    }
201
202
    /**
203
     * Returns list of AOP resources
204
     */
205
    public function getResources(): array
206
    {
207
        return $this->resources;
208
    }
209
210
    /**
211
     * Checks the freshness of AOP cache
212
     *
213
     * @return bool Whether or not concrete file is fresh
214
     */
215 1
    public function isFresh(int $timestamp): bool
216
    {
217 1
        if (!$this->maxTimestamp && !empty($this->resources)) {
218 1
            $this->maxTimestamp = max(array_map('filemtime', $this->resources));
219
        }
220
221 1
        return $this->maxTimestamp <= $timestamp;
222
    }
223
}
224