Passed
Pull Request — master (#739)
by Michael
02:38
created

Finder   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 92
ccs 38
cts 38
cp 1
rs 10
c 0
b 0
f 0
wmc 15

5 Methods

Rating   Name   Duplication   Size   Complexity  
A loadMigrationClasses() 0 18 5
A requireOnce() 0 3 1
A isReflectionClassInNamespace() 0 7 2
A loadMigrations() 0 27 4
A getRealPath() 0 9 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Finder;
6
7
use Doctrine\Migrations\Finder\Exception\InvalidDirectory;
8
use Doctrine\Migrations\Finder\Exception\NameIsReserved;
9
use ReflectionClass;
10
use const SORT_STRING;
11
use function assert;
12
use function get_declared_classes;
13
use function in_array;
14
use function is_dir;
15
use function ksort;
16
use function realpath;
17
use function strlen;
18
use function strncmp;
19
use function substr;
20
21
/**
22
 * The Finder class is responsible for for finding migrations on disk at a given path.
23
 */
24
abstract class Finder implements MigrationFinder
25
{
26 41
    protected static function requireOnce(string $path) : void
27
    {
28 41
        require_once $path;
29 41
    }
30
31
    /**
32
     * @throws InvalidDirectory
33
     */
34 110
    protected function getRealPath(string $directory) : string
35
    {
36 110
        $dir = realpath($directory);
37
38 110
        if ($dir === false || ! is_dir($dir)) {
39 4
            throw InvalidDirectory::new($directory);
40
        }
41
42 106
        return $dir;
43
    }
44
45
    /**
46
     * @param string[] $files
47
     *
48
     * @return string[]
49
     *
50
     * @throws NameIsReserved
51
     */
52 106
    protected function loadMigrations(array $files, ?string $namespace) : array
53
    {
54 106
        $includedFiles = [];
55 106
        foreach ($files as $file) {
56 41
            static::requireOnce($file);
57
58 41
            $realFile = realpath($file);
59 41
            assert($realFile !== false);
60
61 41
            $includedFiles[] = $realFile;
62
        }
63
64 106
        $classes  = $this->loadMigrationClasses($includedFiles, $namespace);
65 106
        $versions = [];
66 106
        foreach ($classes as $class) {
67 41
            $version = substr($class->getShortName(), 7);
68
69 41
            if ($version === '0') {
70 1
                throw NameIsReserved::new($version);
71
            }
72
73 40
            $versions[$version] = $class->getName();
74
        }
75
76 105
        ksort($versions, SORT_STRING);
77
78 105
        return $versions;
79
    }
80
81
    /**
82
     * Look up all declared classes and find those classes contained
83
     * in the given `$files` array.
84
     *
85
     * @param string[]    $files     The set of files that were `required`
86
     * @param string|null $namespace If not null only classes in this namespace will be returned
87
     * @return ReflectionClass[] the classes in `$files`
88
     */
89 106
    protected function loadMigrationClasses(array $files, ?string $namespace) : array
90
    {
91 106
        $classes = [];
92 106
        foreach (get_declared_classes() as $class) {
93 106
            $reflectionClass = new ReflectionClass($class);
94
95 106
            if (! in_array($reflectionClass->getFileName(), $files, true)) {
96 106
                continue;
97
            }
98
99 41
            if ($namespace !== null && ! $this->isReflectionClassInNamespace($reflectionClass, $namespace)) {
100 3
                continue;
101
            }
102
103 41
            $classes[] = $reflectionClass;
104
        }
105
106 106
        return $classes;
107
    }
108
109 33
    private function isReflectionClassInNamespace(ReflectionClass $reflectionClass, string $namespace) : bool
110
    {
111 33
        if (strncmp($reflectionClass->getName(), $namespace . '\\', strlen($namespace) + 1) === 0) {
112 33
            return true;
113
        }
114
115 3
        return false;
116
    }
117
}
118