108 lines
2.8 KiB
PHP
108 lines
2.8 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Doctrine\Migrations\Finder;
|
||
|
|
||
|
use Doctrine\Migrations\Finder\Exception\InvalidDirectory;
|
||
|
use Doctrine\Migrations\Finder\Exception\NameIsReserved;
|
||
|
use ReflectionClass;
|
||
|
|
||
|
use function assert;
|
||
|
use function get_declared_classes;
|
||
|
use function in_array;
|
||
|
use function is_dir;
|
||
|
use function realpath;
|
||
|
use function strlen;
|
||
|
use function strncmp;
|
||
|
|
||
|
/**
|
||
|
* The Finder class is responsible for for finding migrations on disk at a given path.
|
||
|
*/
|
||
|
abstract class Finder implements MigrationFinder
|
||
|
{
|
||
|
protected static function requireOnce(string $path): void
|
||
|
{
|
||
|
require_once $path;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @throws InvalidDirectory
|
||
|
*/
|
||
|
protected function getRealPath(string $directory): string
|
||
|
{
|
||
|
$dir = realpath($directory);
|
||
|
|
||
|
if ($dir === false || ! is_dir($dir)) {
|
||
|
throw InvalidDirectory::new($directory);
|
||
|
}
|
||
|
|
||
|
return $dir;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string[] $files
|
||
|
*
|
||
|
* @return string[]
|
||
|
*
|
||
|
* @throws NameIsReserved
|
||
|
*/
|
||
|
protected function loadMigrations(array $files, ?string $namespace): array
|
||
|
{
|
||
|
$includedFiles = [];
|
||
|
foreach ($files as $file) {
|
||
|
static::requireOnce($file);
|
||
|
|
||
|
$realFile = realpath($file);
|
||
|
assert($realFile !== false);
|
||
|
|
||
|
$includedFiles[] = $realFile;
|
||
|
}
|
||
|
|
||
|
$classes = $this->loadMigrationClasses($includedFiles, $namespace);
|
||
|
$versions = [];
|
||
|
foreach ($classes as $class) {
|
||
|
$versions[] = $class->getName();
|
||
|
}
|
||
|
|
||
|
return $versions;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Look up all declared classes and find those classes contained
|
||
|
* in the given `$files` array.
|
||
|
*
|
||
|
* @param string[] $files The set of files that were `required`
|
||
|
* @param string|null $namespace If not null only classes in this namespace will be returned
|
||
|
*
|
||
|
* @return ReflectionClass<object>[] the classes in `$files`
|
||
|
*/
|
||
|
protected function loadMigrationClasses(array $files, ?string $namespace = null): array
|
||
|
{
|
||
|
$classes = [];
|
||
|
foreach (get_declared_classes() as $class) {
|
||
|
$reflectionClass = new ReflectionClass($class);
|
||
|
|
||
|
if (! in_array($reflectionClass->getFileName(), $files, true)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($namespace !== null && ! $this->isReflectionClassInNamespace($reflectionClass, $namespace)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$classes[] = $reflectionClass;
|
||
|
}
|
||
|
|
||
|
return $classes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param ReflectionClass<object> $reflectionClass
|
||
|
*/
|
||
|
private function isReflectionClassInNamespace(ReflectionClass $reflectionClass, string $namespace): bool
|
||
|
{
|
||
|
return strncmp($reflectionClass->getName(), $namespace . '\\', strlen($namespace) + 1) === 0;
|
||
|
}
|
||
|
}
|