welcome back to dyb-tech
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder\Exception;
|
||||
|
||||
interface FinderException
|
||||
{
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder\Exception;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class InvalidDirectory extends InvalidArgumentException implements FinderException
|
||||
{
|
||||
public static function new(string $directory): self
|
||||
{
|
||||
return new self(sprintf('Cannot load migrations from "%s" because it is not a valid directory', $directory));
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder\Exception;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
use const PHP_EOL;
|
||||
|
||||
final class NameIsReserved extends InvalidArgumentException implements FinderException
|
||||
{
|
||||
public static function new(string $version): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Cannot load a migrations with the name "%s" because it is reserved by Doctrine Migrations.'
|
||||
. PHP_EOL
|
||||
. 'It is used to revert all migrations including the first one.',
|
||||
$version,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?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|null $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|null $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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder;
|
||||
|
||||
use function glob;
|
||||
use function rtrim;
|
||||
|
||||
/**
|
||||
* The GlobFinder class finds migrations in a directory using the PHP glob() function.
|
||||
*/
|
||||
final class GlobFinder extends Finder
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function findMigrations(string $directory, string|null $namespace = null): array
|
||||
{
|
||||
$dir = $this->getRealPath($directory);
|
||||
|
||||
$files = glob(rtrim($dir, '/') . '/Version*.php');
|
||||
if ($files === false) {
|
||||
$files = [];
|
||||
}
|
||||
|
||||
return $this->loadMigrations($files, $namespace);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder;
|
||||
|
||||
/**
|
||||
* The MigrationFinder interface defines the interface used for finding migrations in a given directory and namespace.
|
||||
*/
|
||||
interface MigrationFinder
|
||||
{
|
||||
/**
|
||||
* @param string $directory The directory which the finder should search
|
||||
* @param string|null $namespace If not null only classes in this namespace will be returned
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function findMigrations(string $directory, string|null $namespace = null): array;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Migrations\Finder;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use RegexIterator;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* The RecursiveRegexFinder class recursively searches the given directory for migrations.
|
||||
*/
|
||||
final class RecursiveRegexFinder extends Finder
|
||||
{
|
||||
private string $pattern;
|
||||
|
||||
public function __construct(string|null $pattern = null)
|
||||
{
|
||||
$this->pattern = $pattern ?? sprintf(
|
||||
'#^.+\\%s[^\\%s]+\\.php$#i',
|
||||
DIRECTORY_SEPARATOR,
|
||||
DIRECTORY_SEPARATOR,
|
||||
);
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function findMigrations(string $directory, string|null $namespace = null): array
|
||||
{
|
||||
$dir = $this->getRealPath($directory);
|
||||
|
||||
return $this->loadMigrations(
|
||||
$this->getMatches($this->createIterator($dir)),
|
||||
$namespace,
|
||||
);
|
||||
}
|
||||
|
||||
private function createIterator(string $dir): RegexIterator
|
||||
{
|
||||
return new RegexIterator(
|
||||
new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
),
|
||||
$this->getPattern(),
|
||||
RegexIterator::GET_MATCH,
|
||||
);
|
||||
}
|
||||
|
||||
private function getPattern(): string
|
||||
{
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function getMatches(RegexIterator $iteratorFilesMatch): array
|
||||
{
|
||||
$files = [];
|
||||
foreach ($iteratorFilesMatch as $file) {
|
||||
$files[] = $file[0];
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user