Completed
Pull Request — master (#47)
by Mateusz
06:44
created

CacheManagerImpl::refreshCacheFile()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5.0073

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 25
ccs 14
cts 15
cp 0.9333
rs 8.439
cc 5
eloc 14
nc 4
nop 0
crap 5.0073
1
<?php
2
3
/*
4
 * This file is part of the puli/manager Module.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Manager\Cache;
13
14
use Puli\Manager\Api\Cache\CacheFile;
15
use Puli\Manager\Api\Cache\CacheManager;
16
use Puli\Manager\Api\Config\Config;
17
use Puli\Manager\Api\Context\ProjectContext;
18
use Puli\Manager\Api\Module\Module;
19
use Puli\Manager\Api\Module\ModuleFile;
20
use Puli\Manager\Api\Module\ModuleList;
21
use Puli\Manager\Api\Module\ModuleManager;
22
use Puli\Manager\Api\Module\RootModule;
23
use Puli\Manager\Api\Module\RootModuleFile;
24
use Puli\Manager\Assert\Assert;
25
use Puli\Manager\Json\JsonStorage;
26
use Webmozart\Expression\Expr;
27
use Webmozart\Expression\Expression;
28
use Webmozart\PathUtil\Path;
29
30
/**
31
 * Manages cached Modules information.
32
 *
33
 * @since  1.0
34
 *
35
 * @author Mateusz Sojda <[email protected]>
36
 */
37
class CacheManagerImpl implements CacheManager
38
{
39
    /**
40
     * @var ModuleManager
41
     */
42
    private $moduleManager;
43
44
    /**
45
     * @var JsonStorage
46
     */
47
    private $storage;
48
49
    /**
50
     * @var ProjectContext
51
     */
52
    private $context;
53
54
    /**
55
     * @var string
56
     */
57
    private $rootDir;
58
59
    /**
60
     * @var RootModuleFile
61
     */
62
    private $rootModuleFile;
63
64
    /**
65
     * @var ModuleList
66
     */
67
    private $modules;
68
69
    /**
70
     * Creates new cache manager.
71
     *
72
     * @param ModuleManager  $moduleManager The Module manager.
73
     * @param JsonStorage    $storage       The file storage.
74
     * @param ProjectContext $context       Project context.
75
     */
76 29
    public function __construct(ModuleManager $moduleManager, JsonStorage $storage, ProjectContext $context)
77
    {
78 29
        $this->moduleManager = $moduleManager;
79 29
        $this->storage = $storage;
80 29
        $this->context = $context;
81 29
        $this->rootDir = $context->getRootDirectory();
82 29
        $this->rootModuleFile = $context->getRootModuleFile();
83 29
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 27
    public function getContext()
89
    {
90 27
        return $this->context;
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96 23
    public function getCacheFile()
97
    {
98 23
        $path = $this->getContext()->getConfig()->get(Config::CACHE_FILE);
99 23
        $path = Path::makeAbsolute($path, $this->rootDir);
100
101 23
        if (!$this->storage->fileExists($path)) {
102 22
            $this->refreshCacheFile();
103
        }
104
105 23
        $cacheFile = $this->storage->loadCacheFile($path);
106
107 23
        return $cacheFile;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 26
    public function refreshCacheFile()
114
    {
115 26
        $path = $this->getContext()->getConfig()->get(Config::CACHE_FILE);
116 26
        $path = Path::makeAbsolute($path, $this->rootDir);
117
118 26
        if ($this->storage->fileExists($path) && false === $this->isRootModuleFileModified()) {
119 1
            return;
120
        }
121
122 25
        $cacheFile = new CacheFile(Path::makeAbsolute($path, $this->rootDir));
123
124 25
        foreach ($this->getInstalledModules() as $module) {
125 25
            $moduleFile = $module->getModuleFile();
126 25
            if (false === $moduleFile instanceof ModuleFile) {
127
                continue;
128
            }
129
130 25
            $cacheFile->addModuleFile($moduleFile);
131
132 25
            $installInfo = $module->getInstallInfo();
133 25
            $cacheFile->addInstallInfo($installInfo);
134
        }
135
136 25
        $this->storage->saveCacheFile($cacheFile);
137 25
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 2
    public function getModule($name)
143
    {
144 2
        Assert::string($name, 'The Module name must be a string. Got: %s');
145
146 1
        $this->assertModulesLoaded();
147
148 1
        return $this->modules->get($name);
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 1
    public function getRootModule()
155
    {
156 1
        $this->assertModulesLoaded();
157
158 1
        return $this->modules->getRootModule();
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164 16
    public function getModules()
165
    {
166 16
        $this->assertModulesLoaded();
167
168 16
        return clone $this->modules;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174 4 View Code Duplication
    public function findModules(Expression $expr)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
175
    {
176 4
        $this->assertModulesLoaded();
177
178 4
        $modules = new ModuleList();
179
180 4
        foreach ($this->modules as $module) {
181 4
            if ($expr->evaluate($module)) {
182 4
                $modules->add($module);
183
            }
184
        }
185
186 4
        return $modules;
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 2
    public function hasModule($name)
193
    {
194 2
        Assert::string($name, 'The Module name must be a string. Got: %s');
195
196 1
        $this->assertModulesLoaded();
197
198 1
        return $this->modules->contains($name);
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204 1 View Code Duplication
    public function hasModules(Expression $expr = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
205
    {
206 1
        $this->assertModulesLoaded();
207
208 1
        if (!$expr) {
209 1
            return !$this->modules->isEmpty();
210
        }
211
212 1
        foreach ($this->modules as $module) {
213 1
            if ($expr->evaluate($module)) {
214 1
                return true;
215
            }
216
        }
217
218 1
        return false;
219
    }
220
221 21
    private function assertModulesLoaded()
222
    {
223 21
        if (!$this->modules) {
224 21
            $this->loadModules();
225
        }
226 21
    }
227
228 21
    private function loadModules()
229
    {
230 21
        $cacheFile = $this->getCacheFile();
231
232 21
        $this->modules = new ModuleList();
233 21
        $this->modules->add(new RootModule($this->rootModuleFile, $this->rootDir));
234
235 21
        foreach ($cacheFile->getModuleFiles() as $moduleFile) {
236 21
            $this->modules->add($this->buildModule($moduleFile, $cacheFile));
237
        }
238 21
    }
239
240 25
    private function getInstalledModules()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
241
    {
242 25
        $modules = $this->moduleManager->findModules(Expr::true());
243
244 25
        return $modules->getInstalledModules();
245
    }
246
247 21
    private function buildModule(ModuleFile $moduleFile, CacheFile $cacheFile)
248
    {
249 21
        $installInfo = $cacheFile->getInstallInfo($moduleFile->getModuleName());
250 21
        $installPath = Path::makeAbsolute($installInfo->getInstallPath(), $this->rootDir);
251
252 21
        return new Module($moduleFile, $installPath, $installInfo);
253
    }
254
255 3
    private function isRootModuleFileModified()
256
    {
257 3
        $cacheFilePath = $this->getContext()->getConfig()->get(Config::CACHE_FILE);
258 3
        $cacheFilePath = Path::makeAbsolute($cacheFilePath, $this->rootDir);
259
260 3
        clearstatcache(true, $cacheFilePath);
261 3
        $cacheFileMtime = filemtime($cacheFilePath);
262
263 3
        $rootModuleFilePath = $this->rootModuleFile->getPath();
264
265 3
        if (false === $this->storage->fileExists($rootModuleFilePath)) {
266 1
            return true;
267
        }
268
269 2
        clearstatcache(true, $rootModuleFilePath);
270 2
        $rootModuleFileMtime = filemtime($rootModuleFilePath);
271
272 2
        if ($rootModuleFileMtime > $cacheFileMtime) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $rootModuleFileMtime > $cacheFileMtime;.
Loading history...
273 1
            return true;
274
        }
275
276 1
        return false;
277
    }
278
}
279