Completed
Push — develop ( 8eb671...133594 )
by Mike
19:30 queued 09:24
created

Descriptor/Cache/ProjectDescriptorMapper.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 InvalidArgumentException;
19
use phpDocumentor\Descriptor\FileDescriptor;
20
use phpDocumentor\Descriptor\ProjectDescriptor;
21
use phpDocumentor\Descriptor\ProjectDescriptor\Settings;
22
use Zend\Cache\Storage\IterableInterface;
23
use Zend\Cache\Storage\OptimizableInterface;
24
use Zend\Cache\Storage\StorageInterface;
25
26
/**
27
 * Maps a projectDescriptor to and from a cache instance.
28
 */
29
final class ProjectDescriptorMapper
30
{
31
    const FILE_PREFIX = 'file_';
32
33
    const KEY_SETTINGS = 'settings';
34
35
    /** @var StorageInterface|IterableInterface */
36
    private $cache;
37
38
    /**
39
     * Initializes this mapper with the given cache instance.
40
     */
41 3
    public function __construct(StorageInterface $cache)
42
    {
43 3
        if (!$cache instanceof IterableInterface) {
44 1
            throw new InvalidArgumentException(
45
                'ProjectDescriptorMapper should also be an iterable Storage type'
46
            );
47 3
        }
48 3
49
        $this->cache = $cache;
50
    }
51
52
    /**
53 1
     * Returns the Cache instance for this Mapper.
54
     */
55 1
    public function getCache(): StorageInterface
56
    {
57
        return $this->cache;
58
    }
59
60
    /**
61 1
     * Returns the Project Descriptor from the cache.
62
     */
63 1
    public function populate(ProjectDescriptor $projectDescriptor): void
64
    {
65 1
        $this->loadCacheItemAsSettings($projectDescriptor, self::KEY_SETTINGS);
66 1
67
        foreach ($this->getCache() as $key) {
68 1
            $this->loadCacheItemAsFile($projectDescriptor, $key);
69
        }
70
    }
71
72
    /**
73 1
     * Stores a Project Descriptor in the Cache.
74
     */
75 1
    public function save(ProjectDescriptor $projectDescriptor): void
76 1
    {
77
        $keys = [];
78 1
        $cache = $this->getCache();
79
80
        foreach ($cache as $key) {
81
            $keys[] = $key;
82
        }
83 1
84
        // store the settings for this Project Descriptor
85
        $cache->setItem(self::KEY_SETTINGS, $projectDescriptor->getSettings());
86 1
87 1
        // store cache items
88
        $usedKeys = [self::KEY_SETTINGS];
89
        foreach ($projectDescriptor->getFiles() as $file) {
90
            $key = self::FILE_PREFIX . md5($file->getPath());
91
            $usedKeys[] = $key;
92
            $cache->setItem($key, $file);
93
        }
94 1
95 1
        // remove any keys that are no longer used.
96
        $invalidatedKeys = array_diff($keys, $usedKeys);
97
        if ($invalidatedKeys) {
0 ignored issues
show
Bug Best Practice introduced by Mike van Riel
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...
98
            $cache->removeItems($invalidatedKeys);
99 1
        }
100
101
        if ($cache instanceof OptimizableInterface) {
102 1
            $cache->optimize();
103
        }
104
    }
105
106
    /**
107
     * Removes all files in cache that do not occur in the given FileSet Collection.
108
     *
109
     * @todo restore this?
110
     */
111
    public function garbageCollect($collection)
112
    {
113
//        $projectRoot = $collection->getProjectRoot();
114
//        $filenames = $collection->getFilenames();
115
//
116
//        foreach ($filenames as &$name) {
117
//            // the cache key contains a path relative to the project root; here we expect absolute paths.
118
//            $name = self::FILE_PREFIX . md5(substr($name, strlen($projectRoot)));
119
//        }
120
//
121
//        foreach ($this->getCache() as $item) {
122
//            if (substr($item, 0, strlen(self::FILE_PREFIX)) === self::FILE_PREFIX &&
123
//                  !in_array($item, $filenames, true)
124
//            ) {
125
//                $this->getCache()->removeItem($item);
126
//            }
127
//        }
128
    }
129
130
    private function loadCacheItemAsFile(ProjectDescriptor $projectDescriptor, string $key): void
131
    {
132
        $item = $this->getCache()->getItem($key);
133
134
        if ($item instanceof FileDescriptor) {
135
            $projectDescriptor->getFiles()->set($item->getPath(), $item);
136
        }
137
    }
138
139
    private function loadCacheItemAsSettings(ProjectDescriptor $projectDescriptor, string $key): void
140
    {
141
        $item = $this->getCache()->getItem($key);
142
143
        if ($item instanceof Settings) {
144
            $projectDescriptor->setSettings($item);
145
        }
146
    }
147
}
148