-
-
Notifications
You must be signed in to change notification settings - Fork 74
Support ClassLocator in StaticPHPDriver #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 4.2.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,115 +5,32 @@ | |
| namespace Doctrine\Persistence\Mapping\Driver; | ||
|
|
||
| use Doctrine\Persistence\Mapping\ClassMetadata; | ||
| use Doctrine\Persistence\Mapping\MappingException; | ||
| use RecursiveDirectoryIterator; | ||
| use RecursiveIteratorIterator; | ||
| use ReflectionClass; | ||
|
|
||
| use function array_unique; | ||
| use function get_declared_classes; | ||
| use function in_array; | ||
| use function is_dir; | ||
| use function method_exists; | ||
| use function realpath; | ||
|
|
||
| /** | ||
| * The StaticPHPDriver calls a static loadMetadata() method on your entity | ||
| * classes where you can manually populate the ClassMetadata instance. | ||
| */ | ||
| class StaticPHPDriver implements MappingDriver | ||
| { | ||
| /** | ||
| * Paths of entity directories. | ||
| * | ||
| * @var array<int, string> | ||
| */ | ||
| private array $paths = []; | ||
| use ColocatedMappingDriver; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This introduces more public methods to the class. Maybe it needs to be documented in UPGRADE.md |
||
|
|
||
| /** | ||
| * Map of all class names. | ||
| * | ||
| * @var array<int, string> | ||
| * @phpstan-var list<class-string> | ||
| */ | ||
| private array|null $classNames = null; | ||
|
|
||
| /** @param array<int, string>|string $paths */ | ||
| public function __construct(array|string $paths) | ||
| { | ||
| $this->addPaths((array) $paths); | ||
| } | ||
|
|
||
| /** @param array<int, string> $paths */ | ||
| public function addPaths(array $paths): void | ||
| /** @param array<int, string>|string|ClassLocator $paths */ | ||
| public function __construct(array|string|ClassLocator $paths) | ||
| { | ||
| $this->paths = array_unique([...$this->paths, ...$paths]); | ||
| if ($paths instanceof ClassLocator) { | ||
| $this->classLocator = $paths; | ||
| } else { | ||
| $this->addPaths((array) $paths); | ||
| } | ||
| } | ||
|
|
||
| public function loadMetadataForClass(string $className, ClassMetadata $metadata): void | ||
| { | ||
| $className::loadMetadata($metadata); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| * | ||
| * @todo Same code exists in ColocatedMappingDriver, should we re-use it | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This deleted code is duplicate of |
||
| * somehow or not worry about it? | ||
| */ | ||
| public function getAllClassNames(): array | ||
| { | ||
| if ($this->classNames !== null) { | ||
| return $this->classNames; | ||
| } | ||
|
|
||
| if ($this->paths === []) { | ||
| throw MappingException::pathRequiredForDriver(static::class); | ||
| } | ||
|
|
||
| $classes = []; | ||
| $includedFiles = []; | ||
|
|
||
| foreach ($this->paths as $path) { | ||
| if (! is_dir($path)) { | ||
| throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); | ||
| } | ||
|
|
||
| $iterator = new RecursiveIteratorIterator( | ||
| new RecursiveDirectoryIterator($path), | ||
| RecursiveIteratorIterator::LEAVES_ONLY, | ||
| ); | ||
|
|
||
| foreach ($iterator as $file) { | ||
| if ($file->getBasename('.php') === $file->getBasename()) { | ||
| continue; | ||
| } | ||
|
|
||
| $sourceFile = realpath($file->getPathName()); | ||
| require_once $sourceFile; | ||
| $includedFiles[] = $sourceFile; | ||
| } | ||
| } | ||
|
|
||
| $declared = get_declared_classes(); | ||
|
|
||
| foreach ($declared as $className) { | ||
| $rc = new ReflectionClass($className); | ||
|
|
||
| $sourceFile = $rc->getFileName(); | ||
|
|
||
| if (! in_array($sourceFile, $includedFiles, true) || $this->isTransient($className)) { | ||
| continue; | ||
| } | ||
|
|
||
| $classes[] = $className; | ||
| } | ||
|
|
||
| $this->classNames = $classes; | ||
|
|
||
| return $classes; | ||
| } | ||
|
|
||
| public function isTransient(string $className): bool | ||
| { | ||
| return ! method_exists($className, 'loadMetadata'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,9 @@ | |
| namespace Doctrine\Tests\Persistence\Mapping; | ||
|
|
||
| use Doctrine\Persistence\Mapping\ClassMetadata; | ||
| use Doctrine\Persistence\Mapping\Driver\ClassNames; | ||
| use Doctrine\Persistence\Mapping\Driver\StaticPHPDriver; | ||
| use Doctrine\Tests\Persistence\Mapping\_files\colocated\Entity; | ||
| use PHPUnit\Framework\TestCase; | ||
|
|
||
| class StaticPHPDriverTest extends TestCase | ||
|
|
@@ -15,24 +17,23 @@ public function testLoadMetadata(): void | |
| $metadata = $this->createMock(ClassMetadata::class); | ||
| $metadata->expects(self::once())->method('getFieldNames'); | ||
|
|
||
| $driver = new StaticPHPDriver([__DIR__]); | ||
| $driver->loadMetadataForClass(TestEntity::class, $metadata); | ||
| $driver = new StaticPHPDriver([]); | ||
| $driver->loadMetadataForClass(Entity::class, $metadata); | ||
| } | ||
|
|
||
| public function testGetAllClassNames(): void | ||
| { | ||
| $driver = new StaticPHPDriver([__DIR__]); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This directory contains |
||
| $driver = new StaticPHPDriver([__DIR__ . '/_files/colocated/']); | ||
| $classNames = $driver->getAllClassNames(); | ||
|
|
||
| self::assertContains(TestEntity::class, $classNames); | ||
| self::assertContains(Entity::class, $classNames); | ||
| } | ||
| } | ||
|
|
||
| class TestEntity | ||
| { | ||
| /** @phpstan-param ClassMetadata<object> $metadata */ | ||
| public static function loadMetadata(ClassMetadata $metadata): void | ||
| public function testGetAllClassesNamesWithClassLocator(): void | ||
| { | ||
| $metadata->getFieldNames(); | ||
| $driver = new StaticPHPDriver(new ClassNames([Entity::class])); | ||
| $classNames = $driver->getAllClassNames(); | ||
|
|
||
| self::assertSame([Entity::class], $classNames); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use the key of the array when iterating. Relaxing this type si that
array<int, string>is accepted, which is the result ofarray_unique.