Completed
Push — develop ( 141adb...8f70d4 )
by Jaap
05:39
created

ProjectDescriptorMapper::save()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4.074

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 1
dl 0
loc 29
ccs 15
cts 18
cp 0.8333
crap 4.074
rs 9.456
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @author    Mike van Riel <[email protected]>
11
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
12
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
13
 * @link      http://phpdoc.org
14
 */
15
16
namespace phpDocumentor\Descriptor\Cache;
17
18
use phpDocumentor\Descriptor\FileDescriptor;
19
use phpDocumentor\Descriptor\ProjectDescriptor;
20
use phpDocumentor\Reflection\File;
21
use Psr\Cache\CacheItemPoolInterface;
22
use Stash\Item;
23
24
/**
25
 * Maps a projectDescriptor to and from a cache instance.
26
 */
27
final class ProjectDescriptorMapper
28
{
29
    const FILE_PREFIX = 'phpDocumentor/projectDescriptor/files/';
30
31
    const FILE_LIST = 'phpDocumentor/projectDescriptor/filelist';
32
33
    const KEY_SETTINGS = 'phpDocumentor/projectDescriptor/settings';
34
35
    /** @var CacheItemPoolInterface */
36
    private $cache;
37
38
    /**
39
     * Initializes this mapper with the given cache instance.
40
     */
41 1
    public function __construct(CacheItemPoolInterface $cache)
42
    {
43 1
        $this->cache = $cache;
44 1
    }
45
46
    /**
47
     * Returns the Project Descriptor from the cache.
48
     */
49 1
    public function populate(ProjectDescriptor $projectDescriptor): void
50
    {
51 1
        $this->loadCacheItemAsSettings($projectDescriptor);
52
53 1
        $fileList = $this->cache->getItem(self::FILE_LIST)->get();
54 1
        if ($fileList !== null) {
55
            /** @var Item $item */
56 1
            foreach ($this->cache->getItems($fileList) as $item) {
57 1
                $file = $item->get();
58
59 1
                if ($file instanceof FileDescriptor) {
60 1
                    $projectDescriptor->getFiles()->set($file->getPath(), $file);
61
                }
62
            }
63
        }
64 1
    }
65
66
    /**
67
     * Stores a Project Descriptor in the Cache.
68
     */
69 1
    public function save(ProjectDescriptor $projectDescriptor): void
70
    {
71 1
        $fileListItem = $this->cache->getItem(self::FILE_LIST);
72 1
        $currentFileList = $fileListItem->get();
73
74
        // store the settings for this Project Descriptor
75 1
        $item = $this->cache->getItem(self::KEY_SETTINGS);
76 1
        $this->cache->saveDeferred($item->set($projectDescriptor->getSettings()));
77
78
        // store cache items
79 1
        $fileKeys = [];
80 1
        foreach ($projectDescriptor->getFiles() as $file) {
81 1
            $key = self::FILE_PREFIX . md5($file->getPath());
82 1
            $fileKeys[] = $key;
83 1
            $item = $this->cache->getItem($key);
84 1
            $this->cache->saveDeferred($item->set($file));
85
        }
86
87 1
        $this->cache->saveDeferred($fileListItem->set($fileKeys));
88 1
        $this->cache->commit();
89
90 1
        if ($currentFileList !== null) {
91
            // remove any keys that are no longer used.
92
            $invalidatedKeys = array_diff($currentFileList, $fileKeys);
93
            if ($invalidatedKeys) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $invalidatedKeys of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
94
                $this->cache->deleteItems($invalidatedKeys);
95
            }
96
        }
97 1
    }
98
99
    /**
100
     * Removes all files in cache that do not occur in the given FileSet Collection.
101
     *
102
     * @param File[] $files
103
     */
104
    public function garbageCollect(array $files) : void
105
    {
106
        $fileListItem = $this->cache->getItem(self::FILE_LIST);
107
        $cachedFileList = $fileListItem->get();
108
109
        if ($cachedFileList !== null) {
110
            $realFileKeys = array_map(
111
                static function (File $file) {
112
                    return self::FILE_PREFIX . md5($file->path());
113
                },
114
                $files
115
            );
116
117
            $this->cache->deleteItems(array_diff($cachedFileList, $realFileKeys));
118
        }
119
    }
120
121
    private function loadCacheItemAsSettings(ProjectDescriptor $projectDescriptor): void
122
    {
123
        $item = $this->cache->getItem(self::KEY_SETTINGS);
124
        if ($item->isHit()) {
125
            $settings = $item->get();
126
            $projectDescriptor->setSettings($settings);
127
        }
128
    }
129
}
130