Completed
Pull Request — 1.x (#286)
by Alexander
02:43
created

CachedAspectLoader   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 11
c 2
b 1
f 0
lcom 1
cbo 1
dl 0
loc 113
ccs 0
cts 47
cp 0
rs 10

6 Methods

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