Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of phpunit/php-code-coverage.
4
 *
5
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
11
 
12
use function file_get_contents;
13
use function file_put_contents;
14
use function implode;
15
use function is_file;
16
use function md5;
17
use function serialize;
18
use function unserialize;
19
use SebastianBergmann\CodeCoverage\Util\Filesystem;
20
use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
21
 
22
/**
23
 * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
24
 */
25
final class CachingFileAnalyser implements FileAnalyser
26
{
27
    /**
28
     * @var ?string
29
     */
30
    private static $cacheVersion;
31
 
32
    /**
33
     * @var FileAnalyser
34
     */
35
    private $analyser;
36
 
37
    /**
38
     * @var array
39
     */
40
    private $cache = [];
41
 
42
    /**
43
     * @var string
44
     */
45
    private $directory;
46
 
47
    public function __construct(string $directory, FileAnalyser $analyser)
48
    {
49
        Filesystem::createDirectory($directory);
50
 
51
        $this->analyser  = $analyser;
52
        $this->directory = $directory;
53
    }
54
 
55
    public function classesIn(string $filename): array
56
    {
57
        if (!isset($this->cache[$filename])) {
58
            $this->process($filename);
59
        }
60
 
61
        return $this->cache[$filename]['classesIn'];
62
    }
63
 
64
    public function traitsIn(string $filename): array
65
    {
66
        if (!isset($this->cache[$filename])) {
67
            $this->process($filename);
68
        }
69
 
70
        return $this->cache[$filename]['traitsIn'];
71
    }
72
 
73
    public function functionsIn(string $filename): array
74
    {
75
        if (!isset($this->cache[$filename])) {
76
            $this->process($filename);
77
        }
78
 
79
        return $this->cache[$filename]['functionsIn'];
80
    }
81
 
82
    /**
83
     * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int}
84
     */
85
    public function linesOfCodeFor(string $filename): array
86
    {
87
        if (!isset($this->cache[$filename])) {
88
            $this->process($filename);
89
        }
90
 
91
        return $this->cache[$filename]['linesOfCodeFor'];
92
    }
93
 
94
    public function executableLinesIn(string $filename): array
95
    {
96
        if (!isset($this->cache[$filename])) {
97
            $this->process($filename);
98
        }
99
 
100
        return $this->cache[$filename]['executableLinesIn'];
101
    }
102
 
103
    public function ignoredLinesFor(string $filename): array
104
    {
105
        if (!isset($this->cache[$filename])) {
106
            $this->process($filename);
107
        }
108
 
109
        return $this->cache[$filename]['ignoredLinesFor'];
110
    }
111
 
112
    public function process(string $filename): void
113
    {
114
        $cache = $this->read($filename);
115
 
116
        if ($cache !== false) {
117
            $this->cache[$filename] = $cache;
118
 
119
            return;
120
        }
121
 
122
        $this->cache[$filename] = [
123
            'classesIn'         => $this->analyser->classesIn($filename),
124
            'traitsIn'          => $this->analyser->traitsIn($filename),
125
            'functionsIn'       => $this->analyser->functionsIn($filename),
126
            'linesOfCodeFor'    => $this->analyser->linesOfCodeFor($filename),
127
            'ignoredLinesFor'   => $this->analyser->ignoredLinesFor($filename),
128
            'executableLinesIn' => $this->analyser->executableLinesIn($filename),
129
        ];
130
 
131
        $this->write($filename, $this->cache[$filename]);
132
    }
133
 
134
    /**
135
     * @return mixed
136
     */
137
    private function read(string $filename)
138
    {
139
        $cacheFile = $this->cacheFile($filename);
140
 
141
        if (!is_file($cacheFile)) {
142
            return false;
143
        }
144
 
145
        return unserialize(
146
            file_get_contents($cacheFile),
147
            ['allowed_classes' => false]
148
        );
149
    }
150
 
151
    /**
152
     * @param mixed $data
153
     */
154
    private function write(string $filename, $data): void
155
    {
156
        file_put_contents(
157
            $this->cacheFile($filename),
158
            serialize($data)
159
        );
160
    }
161
 
162
    private function cacheFile(string $filename): string
163
    {
164
        return $this->directory . DIRECTORY_SEPARATOR . md5($filename . "\0" . file_get_contents($filename) . "\0" . self::cacheVersion());
165
    }
166
 
167
    private static function cacheVersion(): string
168
    {
169
        if (self::$cacheVersion !== null) {
170
            return self::$cacheVersion;
171
        }
172
 
173
        $buffer = [];
174
 
175
        foreach ((new FileIteratorFacade)->getFilesAsArray(__DIR__, '.php') as $file) {
176
            $buffer[] = $file;
177
            $buffer[] = file_get_contents($file);
178
        }
179
 
180
        self::$cacheVersion = md5(implode("\0", $buffer));
181
 
182
        return self::$cacheVersion;
183
    }
184
}