Skip to content

Commit 582a0b8

Browse files
committed
Feature: add support for $sourceFilePathNames
In the scope of doctrine/persistence#429 (available from `doctrine/persistence` >= 4.1) there was added `ColocatedMappingDriver::$sourceFilePathNames`, which allows passing the iterable of file paths for the mapping driver to use. This commit integrates those changes into `AttributeDriver`. Since `doctrine/orm` maintains the support for `doctrine/persistence` of older versions, `AttributeDriver` ensures that `$sourceFilePathNames` is actually defined. Tests use `InstalledVersions` to opt into new behaviour if `doctrine/persistence` is at least version 4.1. `AttributeDriver` now accepts a new boolean to opt into the new behaviour. This flag is used to distinguish between an array of directory paths (the existing way) and iterable of file paths (the new way). The old behaviour can be adapted into new by using `glob()` search on directory paths.
1 parent 7606162 commit 582a0b8

File tree

15 files changed

+124
-55
lines changed

15 files changed

+124
-55
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"symfony/var-exporter": "^6.3.9 || ^7.0"
3838
},
3939
"require-dev": {
40+
"doctrine/persistence": "^3.3.1 || ^4.0 || 4.1.x-dev",
4041
"doctrine/coding-standard": "^13.0",
4142
"phpbench/phpbench": "^1.0",
4243
"phpdocumentor/guides-cli": "^1.4",

docs/en/reference/advanced-configuration.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ steps of configuration.
2929
3030
$config = new Configuration;
3131
$config->setMetadataCache($metadataCache);
32-
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
32+
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
3333
$config->setMetadataDriverImpl($driverImpl);
3434
$config->setQueryCache($queryCache);
3535
@@ -154,7 +154,7 @@ The attribute driver can be injected in the ``Doctrine\ORM\Configuration``:
154154
<?php
155155
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
156156
157-
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
157+
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
158158
$config->setMetadataDriverImpl($driverImpl);
159159
160160
The path information to the entities is required for the attribute

src/Mapping/Driver/AttributeDriver.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
use Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver;
1414
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
1515
use InvalidArgumentException;
16+
use LogicException;
1617
use ReflectionClass;
1718
use ReflectionMethod;
1819

1920
use function assert;
2021
use function class_exists;
2122
use function constant;
2223
use function defined;
24+
use function is_array;
25+
use function property_exists;
2326
use function sprintf;
2427

2528
class AttributeDriver implements MappingDriver
@@ -35,10 +38,11 @@ class AttributeDriver implements MappingDriver
3538
private readonly AttributeReader $reader;
3639

3740
/**
38-
* @param array<string> $paths
39-
* @param true $reportFieldsWhereDeclared no-op, to be removed in 4.0
41+
* @param iterable<string> $paths iterable of source file path names (if {@see $pathsAsFilePaths}), or an array of directories.
42+
* @param true $reportFieldsWhereDeclared no-op, to be removed in 4.0
43+
* @param bool $pathsAsFilePaths whether {@see $paths} are paths to files or directories
4044
*/
41-
public function __construct(array $paths, bool $reportFieldsWhereDeclared = true)
45+
public function __construct(iterable $paths, bool $reportFieldsWhereDeclared = true, bool $pathsAsFilePaths = false)
4246
{
4347
if (! $reportFieldsWhereDeclared) {
4448
throw new InvalidArgumentException(sprintf(
@@ -47,8 +51,19 @@ public function __construct(array $paths, bool $reportFieldsWhereDeclared = true
4751
));
4852
}
4953

54+
if ($pathsAsFilePaths) {
55+
if (! property_exists(self::class, 'sourceFilePathNames')) {
56+
throw new LogicException('Source file path names support for AttributeDriver is available since doctrine/persistence 4.1.');
57+
}
58+
59+
$this->sourceFilePathNames = $paths;
60+
} elseif (is_array($paths)) {
61+
$this->addPaths($paths);
62+
} else {
63+
throw new LogicException('The $paths argument must be an array of directories.');
64+
}
65+
5066
$this->reader = new AttributeReader();
51-
$this->addPaths($paths);
5267
}
5368

5469
public function isTransient(string $className): bool

src/ORMSetup.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public static function createAttributeMetadataConfiguration(
3535
bool $isDevMode = false,
3636
string|null $proxyDir = null,
3737
CacheItemPoolInterface|null $cache = null,
38+
bool $pathsAsFilePaths = false,
3839
): Configuration {
3940
if (PHP_VERSION_ID >= 80400) {
4041
Deprecation::trigger(
@@ -47,7 +48,7 @@ public static function createAttributeMetadataConfiguration(
4748
}
4849

4950
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
50-
$config->setMetadataDriverImpl(new AttributeDriver($paths));
51+
$config->setMetadataDriverImpl(new AttributeDriver($paths, true, $pathsAsFilePaths));
5152

5253
return $config;
5354
}
@@ -62,9 +63,10 @@ public static function createAttributeMetadataConfig(
6263
bool $isDevMode = false,
6364
string|null $cacheNamespaceSeed = null,
6465
CacheItemPoolInterface|null $cache = null,
66+
bool $pathsAsFilePaths = false,
6567
): Configuration {
6668
$config = self::createConfig($isDevMode, $cacheNamespaceSeed, $cache);
67-
$config->setMetadataDriverImpl(new AttributeDriver($paths));
69+
$config->setMetadataDriverImpl(new AttributeDriver($paths, true, $pathsAsFilePaths));
6870

6971
return $config;
7072
}

tests/Performance/EntityManagerFactory.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@
1313
use Doctrine\ORM\Configuration;
1414
use Doctrine\ORM\EntityManager;
1515
use Doctrine\ORM\EntityManagerInterface;
16-
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
1716
use Doctrine\ORM\Proxy\ProxyFactory;
1817
use Doctrine\ORM\Tools\SchemaTool;
1918
use Doctrine\Tests\Mocks\ArrayResultFactory;
19+
use Doctrine\Tests\Mocks\AttributeDriverFactory;
2020
use Doctrine\Tests\TestUtil;
2121

2222
use function array_map;
23-
use function realpath;
2423

2524
final class EntityManagerFactory
2625
{
@@ -30,10 +29,7 @@ public static function getEntityManager(array $schemaClassNames): EntityManagerI
3029

3130
TestUtil::configureProxies($config);
3231
$config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL);
33-
$config->setMetadataDriverImpl(new AttributeDriver([
34-
realpath(__DIR__ . '/Models/Cache'),
35-
realpath(__DIR__ . '/Models/GeoNames'),
36-
]));
32+
$config->setMetadataDriverImpl(AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../Tests/Models/Cache', __DIR__ . '/../Tests/Models/GeoNames']));
3733

3834
$entityManager = new EntityManager(
3935
DriverManager::getConnection([
@@ -55,11 +51,7 @@ public static function makeEntityManagerWithNoResultsConnection(): EntityManager
5551

5652
TestUtil::configureProxies($config);
5753
$config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL);
58-
$config->setMetadataDriverImpl(new AttributeDriver([
59-
realpath(__DIR__ . '/Models/Cache'),
60-
realpath(__DIR__ . '/Models/Generic'),
61-
realpath(__DIR__ . '/Models/GeoNames'),
62-
]));
54+
$config->setMetadataDriverImpl(AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../Tests/Models/Cache', __DIR__ . '/../Tests/Models/Generic', __DIR__ . '/../Tests/Models/GeoNames']));
6355

6456
// A connection that doesn't really do anything
6557
$connection = new class ([], new Driver(), null, new EventManager()) extends Connection
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Mocks;
6+
7+
use Composer\InstalledVersions;
8+
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
9+
use LogicException;
10+
11+
use function array_map;
12+
use function array_merge;
13+
use function assert;
14+
use function glob;
15+
use function realpath;
16+
use function version_compare;
17+
18+
use const GLOB_BRACE;
19+
20+
final class AttributeDriverFactory
21+
{
22+
/** @param list<string> $paths */
23+
public static function createAttributeDriver(array $paths = []): AttributeDriver
24+
{
25+
if (! self::isPathsFilePathsSupported()) {
26+
return new AttributeDriver($paths, true, false);
27+
}
28+
29+
$filePaths = array_merge(...array_map(self::pathFiles(...), $paths));
30+
31+
return new AttributeDriver($filePaths, true, true);
32+
}
33+
34+
public static function isPathsFilePathsSupported(): bool
35+
{
36+
return version_compare(InstalledVersions::getVersion('doctrine/persistence'), '4.1', '>=');
37+
}
38+
39+
/** @return list<string> */
40+
public static function pathFiles(string $path): array
41+
{
42+
$realpath = realpath($path);
43+
44+
assert($realpath !== false);
45+
46+
return glob($realpath . '/{,*/}*.php', GLOB_BRACE)
47+
?: throw new LogicException('Could not load driver files');
48+
}
49+
}

tests/Tests/Mocks/EntityManagerMock.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Doctrine\DBAL\Connection;
99
use Doctrine\ORM\Configuration;
1010
use Doctrine\ORM\EntityManager;
11-
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
1211
use Doctrine\ORM\Proxy\ProxyFactory;
1312
use Doctrine\ORM\UnitOfWork;
1413
use Doctrine\Tests\TestUtil;
@@ -26,7 +25,8 @@ public function __construct(Connection $conn, Configuration|null $config = null,
2625
if ($config === null) {
2726
$config = new Configuration();
2827
TestUtil::configureProxies($config);
29-
$config->setMetadataDriverImpl(new AttributeDriver([]));
28+
$attributeDriver = AttributeDriverFactory::createAttributeDriver();
29+
$config->setMetadataDriverImpl($attributeDriver);
3030
}
3131

3232
parent::__construct($conn, $config, $eventManager);

tests/Tests/ORM/Functional/EnumTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
use Doctrine\DBAL\Types\EnumType;
88
use Doctrine\ORM\AbstractQuery;
99
use Doctrine\ORM\Mapping\Column;
10-
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
1110
use Doctrine\ORM\Mapping\MappingException;
1211
use Doctrine\ORM\Query\Expr\Func;
1312
use Doctrine\ORM\Tools\SchemaTool;
13+
use Doctrine\Tests\Mocks\AttributeDriverFactory;
1414
use Doctrine\Tests\Models\DataTransferObjects\DtoWithArrayOfEnums;
1515
use Doctrine\Tests\Models\DataTransferObjects\DtoWithEnum;
1616
use Doctrine\Tests\Models\Enums\Card;
@@ -28,7 +28,6 @@
2828
use PHPUnit\Framework\Attributes\DataProvider;
2929

3030
use function class_exists;
31-
use function dirname;
3231
use function sprintf;
3332
use function uniqid;
3433

@@ -38,7 +37,9 @@ public function setUp(): void
3837
{
3938
parent::setUp();
4039

41-
$this->_em = $this->getEntityManager(null, new AttributeDriver([dirname(__DIR__, 2) . '/Models/Enums'], true));
40+
$mappingDriver = AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../../Models/Enums']);
41+
42+
$this->_em = $this->getEntityManager(null, $mappingDriver);
4243
$this->_schemaTool = new SchemaTool($this->_em);
4344

4445
if ($this->isSecondLevelCacheEnabled) {

tests/Tests/ORM/Functional/Locking/LockAgentWorker.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Doctrine\ORM\Configuration;
1010
use Doctrine\ORM\EntityManager;
1111
use Doctrine\ORM\EntityManagerInterface;
12+
use Doctrine\Tests\Mocks\AttributeDriverFactory;
1213
use Doctrine\Tests\ORM\Functional\Locking\Doctrine\ORM\Query;
1314
use Doctrine\Tests\TestUtil;
1415
use GearmanWorker;
@@ -116,8 +117,8 @@ protected function createEntityManager(Connection $conn): EntityManagerInterface
116117
TestUtil::configureProxies($config);
117118
$config->setAutoGenerateProxyClasses(true);
118119

119-
$annotDriver = new AttributeDriver([__DIR__ . '/../../../Models/']);
120-
$config->setMetadataDriverImpl($annotDriver);
120+
$attributeDriver = AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../../../Models']);
121+
$config->setMetadataDriverImpl($attributeDriver);
121122
$config->setMetadataCache(new ArrayAdapter());
122123

123124
$config->setQueryCache(new ArrayAdapter());

tests/Tests/ORM/Functional/ReadonlyPropertiesTest.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44

55
namespace Doctrine\Tests\ORM\Functional;
66

7-
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
87
use Doctrine\ORM\Tools\SchemaTool;
8+
use Doctrine\Tests\Mocks\AttributeDriverFactory;
99
use Doctrine\Tests\Models\ReadonlyProperties\Author;
1010
use Doctrine\Tests\Models\ReadonlyProperties\Book;
1111
use Doctrine\Tests\Models\ReadonlyProperties\SimpleBook;
1212
use Doctrine\Tests\OrmFunctionalTestCase;
1313
use Doctrine\Tests\TestUtil;
1414

15-
use function dirname;
16-
1715
class ReadonlyPropertiesTest extends OrmFunctionalTestCase
1816
{
1917
protected function setUp(): void
@@ -22,10 +20,8 @@ protected function setUp(): void
2220
static::$sharedConn = TestUtil::getConnection();
2321
}
2422

25-
$this->_em = $this->getEntityManager(null, new AttributeDriver(
26-
[dirname(__DIR__, 2) . '/Models/ReadonlyProperties'],
27-
true,
28-
));
23+
$attributeDriver = AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../../Models/ReadonlyProperties']);
24+
$this->_em = $this->getEntityManager(null, $attributeDriver);
2925
$this->_schemaTool = new SchemaTool($this->_em);
3026

3127
parent::setUp();

0 commit comments

Comments
 (0)