Completed
Pull Request — master (#47)
by Mateusz
06:38
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 15
    public function __construct(ModuleManager $moduleManager, JsonStorage $storage, ProjectContext $context)
77
    {
78 15
        $this->moduleManager = $moduleManager;
79 15
        $this->storage = $storage;
80 15
        $this->context = $context;
81 15
        $this->rootDir = $context->getRootDirectory();
82 15
        $this->rootModuleFile = $context->getRootModuleFile();
83 15
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 13
    public function getContext()
89
    {
90 13
        return $this->context;
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96 8
    public function getCacheFile()
97
    {
98 8
        $path = $this->getContext()->getConfig()->get(Config::CACHE_FILE);
99 8
        $path = Path::makeAbsolute($path, $this->rootDir);
100
101 8
        if (!$this->storage->fileExists($path)) {
102 7
            $this->refreshCacheFile();
103
        }
104
105 8
        $cacheFile = $this->storage->loadCacheFile($path);
106
107 8
        return $cacheFile;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 11
    public function refreshCacheFile()
114
    {
115 11
        $path = $this->getContext()->getConfig()->get(Config::CACHE_FILE);
116 11
        $path = Path::makeAbsolute($path, $this->rootDir);
117
118 11
        if ($this->storage->fileExists($path) && false === $this->isRootModuleFileModified()) {
119 1
            return;
120
        }
121
122 10
        $cacheFile = new CacheFile(Path::makeAbsolute($path, $this->rootDir));
123
124 10
        foreach ($this->getInstalledModules() as $module) {
125 10
            $moduleFile = $module->getModuleFile();
126 10
            if (false === $moduleFile instanceof ModuleFile) {
127
                continue;
128
            }
129
130 10
            $cacheFile->addModuleFile($moduleFile);
131
132 10
            $installInfo = $module->getInstallInfo();
133 10
            $cacheFile->addInstallInfo($installInfo);
134
        }
135
136 10
        $this->storage->saveCacheFile($cacheFile);
137 10
    }
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 1
    public function getModules()
165
    {
166 1
        $this->assertModulesLoaded();
167
168 1
        return clone $this->modules;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174 1 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 1
        $this->assertModulesLoaded();
177
178 1
        $modules = new ModuleList();
179
180 1
        foreach ($this->modules as $module) {
181 1
            if ($expr->evaluate($module)) {
182 1
                $modules->add($module);
183
            }
184
        }
185
186 1
        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 6
    private function assertModulesLoaded()
222
    {
223 6
        if (!$this->modules) {
224 6
            $this->loadModules();
225
        }
226 6
    }
227
228 6
    private function loadModules()
229
    {
230 6
        $cacheFile = $this->getCacheFile();
231
232 6
        $this->modules = new ModuleList();
233 6
        $this->modules->add(new RootModule($this->rootModuleFile, $this->rootDir));
234
235 6
        foreach ($cacheFile->getModuleFiles() as $moduleFile) {
236 6
            $this->modules->add($this->buildModule($moduleFile, $cacheFile));
237
        }
238 6
    }
239
240 10
    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 10
        $modules = $this->moduleManager->findModules(Expr::true());
243
244 10
        return $modules->getInstalledModules();
245
    }
246
247 6
    private function buildModule(ModuleFile $moduleFile, CacheFile $cacheFile)
248
    {
249 6
        $installInfo = $cacheFile->getInstallInfo($moduleFile->getModuleName());
250 6
        $installPath = Path::makeAbsolute($installInfo->getInstallPath(), $this->rootDir);
251
252 6
        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