Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3 || ^2",
"doctrine/lexer": "^3",
"doctrine/persistence": "^3.3.1 || ^4",
"psr/cache": "^1 || ^2 || ^3",
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/var-exporter": "^6.3.9 || ^7.0"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/rela589n/doctrine-persistence.git"
}
],
"require-dev": {
"doctrine/coding-standard": "^13.0",
"doctrine/persistence": "^3.3.1 || ^4.0@dev",
"phpbench/phpbench": "^1.0",
"phpdocumentor/guides-cli": "^1.4",
"phpstan/extension-installer": "^1.4",
Expand Down
4 changes: 2 additions & 2 deletions docs/en/reference/advanced-configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ steps of configuration.

$config = new Configuration;
$config->setMetadataCache($metadataCache);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCache($queryCache);

Expand Down Expand Up @@ -154,7 +154,7 @@ The attribute driver can be injected in the ``Doctrine\ORM\Configuration``:
<?php
use Doctrine\ORM\Mapping\Driver\AttributeDriver;

$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$config->setMetadataDriverImpl($driverImpl);

The path information to the entities is required for the attribute
Expand Down
7 changes: 7 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,13 @@ parameters:
count: 1
path: src/Mapping/DefaultQuoteStrategy.php

-
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\Driver\\AttributeDriver\:\:\$filePaths\.$#'
identifier: property.notFound # property is available starting from doctrine/persistence 4.1
count: 1
path: src/Mapping/Driver/AttributeDriver.php
reportUnmatched: false

-
message: '#^Method Doctrine\\ORM\\Mapping\\Driver\\AttributeDriver\:\:isRepeatedPropertyDeclaration\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
Expand Down
24 changes: 20 additions & 4 deletions src/Mapping/Driver/AttributeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
use Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver;
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
use InvalidArgumentException;
use LogicException;
use ReflectionClass;
use ReflectionMethod;
use Traversable;

use function assert;
use function class_exists;
use function constant;
use function defined;
use function is_file;
use function property_exists;
use function reset;
use function sprintf;

class AttributeDriver implements MappingDriver
Expand All @@ -35,10 +40,10 @@ class AttributeDriver implements MappingDriver
private readonly AttributeReader $reader;

/**
* @param array<string> $paths
* @param true $reportFieldsWhereDeclared no-op, to be removed in 4.0
* @param iterable<string> $paths iterable of source file paths, or an array of directories.
* @param true $reportFieldsWhereDeclared no-op, to be removed in 4.0
*/
public function __construct(array $paths, bool $reportFieldsWhereDeclared = true)
public function __construct(iterable $paths, bool $reportFieldsWhereDeclared = true)
{
if (! $reportFieldsWhereDeclared) {
throw new InvalidArgumentException(sprintf(
Expand All @@ -47,8 +52,19 @@ public function __construct(array $paths, bool $reportFieldsWhereDeclared = true
));
}

$pathsAreFilePaths = $paths instanceof Traversable || ($paths !== [] && is_file(reset($paths)));

if ($pathsAreFilePaths) {
if (! property_exists(self::class, 'filePaths')) {
throw new LogicException('Source file paths support for AttributeDriver is available since doctrine/persistence 4.1.');
}

$this->filePaths = $paths;
} else {
$this->addPaths($paths);
}

$this->reader = new AttributeReader();
$this->addPaths($paths);
}

public function isTransient(string $className): bool
Expand Down
12 changes: 6 additions & 6 deletions src/ORMSetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ final class ORMSetup
/**
* Creates a configuration with an attribute metadata driver.
*
* @param string[] $paths
* @param iterable<string> $paths
*/
public static function createAttributeMetadataConfiguration(
array $paths,
iterable $paths,
bool $isDevMode = false,
string|null $proxyDir = null,
CacheItemPoolInterface|null $cache = null,
Expand All @@ -47,24 +47,24 @@ public static function createAttributeMetadataConfiguration(
}

$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
$config->setMetadataDriverImpl(new AttributeDriver($paths));
$config->setMetadataDriverImpl(new AttributeDriver($paths, true));

return $config;
}

/**
* Creates a configuration with an attribute metadata driver.
*
* @param string[] $paths
* @param iterable<string> $paths
*/
public static function createAttributeMetadataConfig(
array $paths,
iterable $paths,
bool $isDevMode = false,
string|null $cacheNamespaceSeed = null,
CacheItemPoolInterface|null $cache = null,
): Configuration {
$config = self::createConfig($isDevMode, $cacheNamespaceSeed, $cache);
$config->setMetadataDriverImpl(new AttributeDriver($paths));
$config->setMetadataDriverImpl(new AttributeDriver($paths, true));

return $config;
}
Expand Down
14 changes: 3 additions & 11 deletions tests/Performance/EntityManagerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Tests\Mocks\ArrayResultFactory;
use Doctrine\Tests\Mocks\AttributeDriverFactory;
use Doctrine\Tests\TestUtil;

use function array_map;
use function realpath;

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

TestUtil::configureProxies($config);
$config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL);
$config->setMetadataDriverImpl(new AttributeDriver([
realpath(__DIR__ . '/Models/Cache'),
realpath(__DIR__ . '/Models/GeoNames'),
]));
$config->setMetadataDriverImpl(AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../Tests/Models/Cache', __DIR__ . '/../Tests/Models/GeoNames']));

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

TestUtil::configureProxies($config);
$config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL);
$config->setMetadataDriverImpl(new AttributeDriver([
realpath(__DIR__ . '/Models/Cache'),
realpath(__DIR__ . '/Models/Generic'),
realpath(__DIR__ . '/Models/GeoNames'),
]));
$config->setMetadataDriverImpl(AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../Tests/Models/Cache', __DIR__ . '/../Tests/Models/Generic', __DIR__ . '/../Tests/Models/GeoNames']));

// A connection that doesn't really do anything
$connection = new class ([], new Driver(), null, new EventManager()) extends Connection
Expand Down
37 changes: 37 additions & 0 deletions tests/Tests/Mocks/AttributeDriverFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Mocks;

use Composer\InstalledVersions;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\Persistence\Mapping\Driver\DirectoryFilesIterator;
use Doctrine\Persistence\Mapping\Driver\FilePathNameIterator;

use function version_compare;

final class AttributeDriverFactory
{
/** @param list<string> $paths */
public static function createAttributeDriver(array $paths = []): AttributeDriver
{
if (! self::isFilePathsSupported()) {
return new AttributeDriver($paths, true);
}

$filePaths = new FilePathNameIterator(new DirectoryFilesIterator($paths));

return new AttributeDriver($filePaths, true);
}

public static function isFilePathsSupported(): bool
{
return version_compare(InstalledVersions::getVersion('doctrine/persistence'), '4.1', '>=');
}

public static function pathFiles(string $path): FilePathNameIterator
{
return new FilePathNameIterator(new DirectoryFilesIterator([$path]));
}
}
4 changes: 2 additions & 2 deletions tests/Tests/Mocks/EntityManagerMock.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\TestUtil;
Expand All @@ -26,7 +25,8 @@ public function __construct(Connection $conn, Configuration|null $config = null,
if ($config === null) {
$config = new Configuration();
TestUtil::configureProxies($config);
$config->setMetadataDriverImpl(new AttributeDriver([]));
$attributeDriver = AttributeDriverFactory::createAttributeDriver();
$config->setMetadataDriverImpl($attributeDriver);
}

parent::__construct($conn, $config, $eventManager);
Expand Down
7 changes: 4 additions & 3 deletions tests/Tests/ORM/Functional/EnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use Doctrine\DBAL\Types\EnumType;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Mapping\MappingException;
use Doctrine\ORM\Query\Expr\Func;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Tests\Mocks\AttributeDriverFactory;
use Doctrine\Tests\Models\DataTransferObjects\DtoWithArrayOfEnums;
use Doctrine\Tests\Models\DataTransferObjects\DtoWithEnum;
use Doctrine\Tests\Models\Enums\Card;
Expand All @@ -28,7 +28,6 @@
use PHPUnit\Framework\Attributes\DataProvider;

use function class_exists;
use function dirname;
use function sprintf;
use function uniqid;

Expand All @@ -38,7 +37,9 @@ public function setUp(): void
{
parent::setUp();

$this->_em = $this->getEntityManager(null, new AttributeDriver([dirname(__DIR__, 2) . '/Models/Enums'], true));
$mappingDriver = AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../../Models/Enums']);

$this->_em = $this->getEntityManager(null, $mappingDriver);
$this->_schemaTool = new SchemaTool($this->_em);

if ($this->isSecondLevelCacheEnabled) {
Expand Down
5 changes: 3 additions & 2 deletions tests/Tests/ORM/Functional/Locking/LockAgentWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Tests\Mocks\AttributeDriverFactory;
use Doctrine\Tests\ORM\Functional\Locking\Doctrine\ORM\Query;
use Doctrine\Tests\TestUtil;
use GearmanWorker;
Expand Down Expand Up @@ -116,8 +117,8 @@ protected function createEntityManager(Connection $conn): EntityManagerInterface
TestUtil::configureProxies($config);
$config->setAutoGenerateProxyClasses(true);

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

$config->setQueryCache(new ArrayAdapter());
Expand Down
10 changes: 3 additions & 7 deletions tests/Tests/ORM/Functional/ReadonlyPropertiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Tests\Mocks\AttributeDriverFactory;
use Doctrine\Tests\Models\ReadonlyProperties\Author;
use Doctrine\Tests\Models\ReadonlyProperties\Book;
use Doctrine\Tests\Models\ReadonlyProperties\SimpleBook;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\Tests\TestUtil;

use function dirname;

class ReadonlyPropertiesTest extends OrmFunctionalTestCase
{
protected function setUp(): void
Expand All @@ -22,10 +20,8 @@ protected function setUp(): void
static::$sharedConn = TestUtil::getConnection();
}

$this->_em = $this->getEntityManager(null, new AttributeDriver(
[dirname(__DIR__, 2) . '/Models/ReadonlyProperties'],
true,
));
$attributeDriver = AttributeDriverFactory::createAttributeDriver([__DIR__ . '/../../Models/ReadonlyProperties']);
$this->_em = $this->getEntityManager(null, $attributeDriver);
$this->_schemaTool = new SchemaTool($this->_em);

parent::setUp();
Expand Down
29 changes: 27 additions & 2 deletions tests/Tests/ORM/Mapping/AttributeDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,42 @@
use Doctrine\ORM\Mapping\JoinColumnMapping;
use Doctrine\ORM\Mapping\MappingAttribute;
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Tests\Mocks\AttributeDriverFactory;
use Doctrine\Tests\Models\Cache\City;
use Doctrine\Tests\ORM\Mapping\Fixtures\AttributeEntityWithNestedJoinColumns;
use InvalidArgumentException;
use LogicException;
use stdClass;

class AttributeDriverTest extends MappingDriverTestCase
{
protected function loadDriver(): MappingDriver
{
$paths = [];
return AttributeDriverFactory::createAttributeDriver();
}

public function testDriverCanAcceptListOfFilePaths(): void
{
if (! AttributeDriverFactory::isFilePathsSupported()) {
self::markTestSkipped('This test is only relevant for versions of doctrine/persistence >= 4.1');
}

$driver = new AttributeDriver(['1' => __DIR__ . '/../../Models/Cache/City.php']);

self::assertSame([], $driver->getPaths(), 'Directory paths must be empty, since file paths are used');
self::assertSame([0 => City::class], $driver->getAllClassNames());
}

public function testFilePathsCanBeUsedOnlyStartingFromPersistence41(): void
{
if (AttributeDriverFactory::isFilePathsSupported()) {
self::markTestSkipped('This test is only relevant for versions of doctrine/persistence < 4.1');
}

$this->expectException(LogicException::class);
$this->expectExceptionMessage('available since doctrine/persistence 4.1');

return new AttributeDriver($paths, true);
new AttributeDriver([__DIR__ . '/../../Models/Cache/City.php']);
}

public function testOriginallyNestedAttributesDeclaredWithoutOriginalParent(): void
Expand Down
Loading