FileUpdate::getFiles()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 19
c 5
b 0
f 0
dl 0
loc 33
rs 9.3222
cc 5
nc 4
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Package\Injector;
6
7
use BEAR\AppMeta\AbstractAppMeta;
8
use FilesystemIterator;
9
use RecursiveDirectoryIterator;
10
use RecursiveIteratorIterator;
11
use SplFileInfo;
12
13
use function array_map;
14
use function assert;
15
use function file_exists;
16
use function filemtime;
17
use function glob;
18
use function is_string;
19
use function max;
20
use function preg_match;
21
use function preg_quote;
22
use function rtrim;
23
use function sprintf;
24
use function str_replace;
25
26
use const DIRECTORY_SEPARATOR;
27
28
final class FileUpdate
29
{
30
    private int $updateTime;
31
    private string $srcRegex;
32
    private string $varRegex;
33
34
    public function __construct(AbstractAppMeta $meta)
35
    {
36
        $normalizedAppDir = str_replace('\\', '/', rtrim($meta->appDir, '\\/')) . '/';
37
        $this->srcRegex = sprintf('#^(?!.*(%ssrc/Resource)).*?$#m', $normalizedAppDir);
38
        $this->varRegex = sprintf(
39
            '#^(?!%s(?:var%stmp|var%slog|var%stemplates|var%sphinx)).*$#',
40
            preg_quote($normalizedAppDir, '#'),
41
            preg_quote(DIRECTORY_SEPARATOR, '#'),
42
            preg_quote(DIRECTORY_SEPARATOR, '#'),
43
            preg_quote(DIRECTORY_SEPARATOR, '#'),
44
            preg_quote(DIRECTORY_SEPARATOR, '#'),
45
        );
46
        $this->updateTime = $this->getLatestUpdateTime($meta);
47
    }
48
49
    public function isNotUpdated(AbstractAppMeta $meta): bool
50
    {
51
        return $this->getLatestUpdateTime($meta) === $this->updateTime;
52
    }
53
54
    public function getLatestUpdateTime(AbstractAppMeta $meta): int
55
    {
56
        $srcFiles = $this->getFiles($meta->appDir . DIRECTORY_SEPARATOR . 'src', $this->srcRegex);
57
        $varFiles = $this->getFiles($meta->appDir . DIRECTORY_SEPARATOR . 'var', $this->varRegex);
58
        $envFiles = (array) glob($meta->appDir . DIRECTORY_SEPARATOR . '.env*');
59
        $scanFiles = [...$srcFiles, ...$varFiles, ...$envFiles];
60
        $composerLock = $meta->appDir . DIRECTORY_SEPARATOR . 'composer.lock';
61
        if (file_exists($composerLock)) {
62
            $scanFiles[] = $composerLock;
63
        }
64
65
        /** @psalm-suppress all -- ignore filemtime could return false */
66
        return (int) max(array_map([$this, 'filemtime'], $scanFiles));
67
    }
68
69
    /** @SuppressWarnings(PHPMD.UnusedPrivateMethod) */
70
    private function filemtime(string $filename): string
71
    {
72
        return (string) filemtime($filename);
73
    }
74
75
    /**
76
     * @return list<string>
0 ignored issues
show
Bug introduced by
The type BEAR\Package\Injector\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
77
     *
78
     * @psalm-assert non-empty-string $regex
79
     */
80
    private function getFiles(string $path, string $regex): array
81
    {
82
        $iteratorPath = str_replace('/', DIRECTORY_SEPARATOR, $path);
83
        $rdi = new RecursiveDirectoryIterator(
84
            $iteratorPath,
85
            FilesystemIterator::CURRENT_AS_FILEINFO
86
            | FilesystemIterator::KEY_AS_PATHNAME
87
            | FilesystemIterator::SKIP_DOTS,
88
        );
89
        $rdiIterator = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::LEAVES_ONLY);
90
91
        /** @var list<string> $files */
92
        $files = [];
93
        foreach ($rdiIterator as $key => $fileInfo) {
94
            assert(is_string($key) && $key !== '');
95
            assert($fileInfo instanceof SplFileInfo);
96
            /** @var non-empty-string $normalizedFileName */
97
            $normalizedFileName = str_replace('\\', '/', $key);
98
            assert($regex !== '');
99
            if (! preg_match($regex, $normalizedFileName)) {
100
                continue;
101
            }
102
103
            if (! $fileInfo->isFile()) {
104
                // @codeCoverageIgnoreStart
105
                continue;
106
                // @codeCoverageIgnoreEnd
107
            }
108
109
            $files[] = $normalizedFileName;
110
        }
111
112
        return $files;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $files returns the type BEAR\Package\Injector\list which is incompatible with the type-hinted return array.
Loading history...
113
    }
114
}
115