Completed
Push — master ( efe256...811ea7 )
by Alexander
11s
created

CachedAspectLoader::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
declare(strict_types = 1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2014, 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 Go\Aop\Advisor;
15
use Go\Aop\Aspect;
16
use Go\Aop\Pointcut;
17
use ReflectionClass;
18
19
/**
20
 * Cached loader is responsible for faster initialization of pointcuts/advisors for concrete aspect
21
 *
22
 * @property AspectLoader loader
23
 */
24
class CachedAspectLoader extends AspectLoader
25
{
26
27
    /**
28
     * Path to the cache directory
29
     *
30
     * @var null|string
31
     */
32
    protected $cacheDir;
33
34
    /**
35
     * File mode for the cache files
36
     *
37
     * @var integer
38
     */
39
    protected $cacheFileMode;
40
41
    /**
42
     * Identifier of original loader
43
     */
44
    protected $loaderId;
45
46
    /**
47
     * Cached loader constructor
48
     *
49
     * @param array $options List of kernel options
50
     */
51 1
    public function __construct(AspectContainer $container, string $loaderId, array $options = [])
52
    {
53 1
        $this->cacheDir      = $options['cacheDir'] ?? null;
54 1
        $this->cacheFileMode = $options['cacheFileMode'];
55 1
        $this->loaderId      = $loaderId;
56 1
        $this->container     = $container;
57 1
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 1
    public function load(Aspect $aspect): array
63
    {
64 1
        $refAspect = new ReflectionClass($aspect);
65 1
        $fileName  = $this->cacheDir . '/_aspect/' . sha1($refAspect->getName());
66
67
        // If cache is present and actual, then use it
68 1
        if (file_exists($fileName) && filemtime($fileName) >= filemtime($refAspect->getFileName())) {
69
            $loadedItems = $this->loadFromCache($fileName);
70
        } else {
71 1
            $loadedItems = $this->loader->load($aspect);
72 1
            $this->saveToCache($loadedItems, $fileName);
73
        }
74
75 1
        return $loadedItems;
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function registerLoaderExtension(AspectLoaderExtension $loader): void
82
    {
83
        $this->loader->registerLoaderExtension($loader);
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 1
    public function __get($name)
90
    {
91 1
        if ($name === 'loader') {
92 1
            $this->loader = $this->container->get($this->loaderId);
93
94 1
            return $this->loader;
95
        }
96
        throw new \RuntimeException('Not implemented');
97
    }
98
99
100
    /**
101
     * Loads pointcuts and advisors from the file
102
     *
103
     * @return Pointcut[]|Advisor[]
104
     */
105
    protected function loadFromCache(string $fileName): array
106
    {
107
        $content     = file_get_contents($fileName);
108
        $loadedItems = unserialize($content);
109
110
        return $loadedItems;
111
    }
112
113
    /**
114
     * Save pointcuts and advisors to the file
115
     *
116
     * @param Pointcut[]|Advisor[] $items List of items to store
117
     */
118 1
    protected function saveToCache(array $items, string $fileName): void
119
    {
120 1
        $content       = serialize($items);
121 1
        $directoryName = dirname($fileName);
122 1
        if (!is_dir($directoryName)) {
123 1
            mkdir($directoryName, $this->cacheFileMode, true);
124
        }
125 1
        file_put_contents($fileName, $content, LOCK_EX);
126
        // For cache files we don't want executable bits by default
127 1
        chmod($fileName, $this->cacheFileMode & (~0111));
128 1
    }
129
}
130