Skip to content

Commit

Permalink
Merge pull request #1751 from doctrine/2.11.x-merge-up-into-2.12.x_bk…
Browse files Browse the repository at this point in the history
…pDMTMR
  • Loading branch information
ostrolucky committed Feb 6, 2024
2 parents 4089f14 + fb22c93 commit 99fcc69
Show file tree
Hide file tree
Showing 32 changed files with 150 additions and 196 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/static-analysis.yml
Expand Up @@ -14,11 +14,6 @@ jobs:
name: "Static Analysis with Psalm"
runs-on: "ubuntu-22.04"

strategy:
matrix:
php-version:
- "7.4"

steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
Expand All @@ -27,7 +22,7 @@ jobs:
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
php-version: "8.2"

- name: "Enforce using stable dependencies"
run: "composer config minimum-stability stable"
Expand Down
2 changes: 2 additions & 0 deletions ConnectionFactory.php
Expand Up @@ -78,6 +78,7 @@ public function createConnection(array $params, ?Configuration $config = null, ?
}

$overriddenOptions = [];
/** @psalm-suppress InvalidArrayOffset We should adjust when https://github.com/vimeo/psalm/issues/8984 is fixed */
if (isset($params['connection_override_options'])) {
trigger_deprecation('doctrine/doctrine-bundle', '2.4', 'The "connection_override_options" connection parameter is deprecated');
$overriddenOptions = $params['connection_override_options'];
Expand All @@ -97,6 +98,7 @@ public function createConnection(array $params, ?Configuration $config = null, ?
}
}

/** @psalm-suppress InvalidArrayOffset We should adjust when https://github.com/vimeo/psalm/issues/8984 is fixed */
if (! isset($params['pdo']) && (! isset($params['charset']) || $overriddenOptions || isset($params['dbname_suffix']))) {
$wrapperClass = null;

Expand Down
14 changes: 5 additions & 9 deletions DataCollector/DoctrineDataCollector.php
Expand Up @@ -41,7 +41,7 @@
* regions: array<"puts"|"hits"|"misses", array<string, int>>,
* },
* connections: list<string>,
* entities: array<string, array<class-string, class-string>>,
* entities: array<string, array<class-string, array{class: class-string, file: false|string, line: false|int}>>,
* errors: array<string, array<class-string, list<string>>>,
* managers: list<string>,
* queries: array<string, list<QueryType>>,
Expand All @@ -55,7 +55,7 @@ class DoctrineDataCollector extends BaseCollector

/**
* @var mixed[][]|null
* @psalm-var ?array<string, list<QueryType&array{count: int, index: int, executionPercent: float}>>
* @psalm-var ?array<string, list<QueryType&array{count: int, index: int, executionPercent?: float}>>
*/
private ?array $groupedQueries = null;

Expand All @@ -66,11 +66,7 @@ public function __construct(ManagerRegistry $registry, bool $shouldValidateSchem
$this->registry = $registry;
$this->shouldValidateSchema = $shouldValidateSchema;

if ($debugDataHolder === null) {
parent::__construct($registry);
} else {
parent::__construct($registry, $debugDataHolder);
}
parent::__construct($registry, $debugDataHolder);
}

public function collect(Request $request, Response $response, ?Throwable $exception = null): void
Expand Down Expand Up @@ -184,7 +180,7 @@ public function collect(Request $request, Response $response, ?Throwable $except
$this->groupedQueries = null;
}

/** @return array<string, array<string, string>> */
/** @return array<string, array<class-string, array{class: class-string, file: false|string, line: false|int}>> */
public function getEntities()
{
return $this->data['entities'];
Expand Down Expand Up @@ -243,7 +239,7 @@ public function getInvalidEntityCount()

/**
* @return string[][]
* @psalm-return array<string, list<QueryType&array{count: int, index: int, executionPercent: float}>>
* @psalm-return array<string, list<QueryType&array{count: int, index: int, executionPercent?: float}>>
*/
public function getGroupedQueries()
{
Expand Down
6 changes: 2 additions & 4 deletions DependencyInjection/Compiler/DoctrineOrmMappingsPass.php
Expand Up @@ -17,8 +17,6 @@
* Class for Symfony bundles to configure mappings for model classes not in the
* auto-mapped folder.
*
* NOTE: alias is only supported by Symfony 2.6+ and will be ignored with older versions.
*
* @final since 2.9
*/
class DoctrineOrmMappingsPass extends RegisterMappingsPass
Expand Down Expand Up @@ -141,8 +139,8 @@ public static function createAnnotationMappingDriver(array $namespaces, array $d
}

/**
* @param string[] $namespaces List of namespaces that are handled with annotation mapping
* @param string[] $directories List of directories to look for annotated classes
* @param string[] $namespaces List of namespaces that are handled with attribute mapping
* @param string[] $directories List of directories to look for classes with attributes
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
Expand Down
2 changes: 1 addition & 1 deletion DependencyInjection/Compiler/EntityListenerPass.php
Expand Up @@ -94,7 +94,7 @@ public function process(ContainerBuilder $container)
}
}

/** @param array{entity: class-string, event?: ?string} $attributes */
/** @param array{entity: class-string, event?: ?string, method?: string} $attributes */
private function attachToListener(ContainerBuilder $container, string $name, string $class, array $attributes): void
{
$listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $name);
Expand Down
4 changes: 3 additions & 1 deletion DependencyInjection/Configuration.php
Expand Up @@ -505,7 +505,9 @@ private function addOrmSection(ArrayNodeDefinition $node): void
})
->end()
->end()
->booleanNode('enable_lazy_ghost_objects')->defaultValue(! method_exists(ProxyFactory::class, 'resetUninitializedProxy'))
->booleanNode('enable_lazy_ghost_objects')
->defaultValue(! method_exists(ProxyFactory::class, 'resetUninitializedProxy'))
->info('Enables the new implementation of proxies based on lazy ghosts instead of using the legacy implementation')
->end()
->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end()
->scalarNode('proxy_namespace')->defaultValue('Proxies')->end()
Expand Down
15 changes: 11 additions & 4 deletions DependencyInjection/DoctrineExtension.php
Expand Up @@ -82,6 +82,12 @@
* DoctrineExtension is an extension for the Doctrine DBAL and ORM library.
*
* @final since 2.9
* @psalm-type DBALConfig = array{
* connections: array<string, array{logging: bool, profiling: bool, profiling_collect_backtrace: bool}>,
* driver_schemes: array<string, string>,
* default_connection: string,
* types: array<string, string>,
* }
*/
class DoctrineExtension extends AbstractDoctrineExtension
{
Expand Down Expand Up @@ -155,8 +161,8 @@ private function processConfigurationPrependingDefaults(ConfigurationInterface $
*
* <doctrine:dbal id="myconn" dbname="sfweb" user="root" />
*
* @param array<string, mixed> $config An array of configuration settings
* @param ContainerBuilder $container A ContainerBuilder instance
* @param DBALConfig $config An array of configuration settings
* @param ContainerBuilder $container A ContainerBuilder instance
*/
protected function dbalLoad(array $config, ContainerBuilder $container)
{
Expand Down Expand Up @@ -533,6 +539,7 @@ protected function ormLoad(array $config, ContainerBuilder $container)

$entityManagers = [];
foreach (array_keys($config['entity_managers']) as $name) {
/** @psalm-suppress InvalidArrayOffset */
$entityManagers[$name] = sprintf('doctrine.orm.%s_entity_manager', $name);
}

Expand All @@ -547,7 +554,6 @@ protected function ormLoad(array $config, ContainerBuilder $container)

if ($config['enable_lazy_ghost_objects'] ?? false) {
// available in Symfony 6.2 and higher
/** @psalm-suppress UndefinedClass */
if (! trait_exists(LazyGhostTrait::class)) {
throw new LogicException(
'Lazy ghost objects cannot be enabled because the "symfony/var-exporter" library'
Expand All @@ -566,7 +572,7 @@ protected function ormLoad(array $config, ContainerBuilder $container)
'Lazy ghost objects cannot be disabled for ORM 3.',
);
} elseif (PHP_VERSION_ID >= 80100) {
trigger_deprecation('doctrine/doctrine-bundle', '2.11', 'Not setting "enable_lazy_ghost_objects" to true is deprecated.');
trigger_deprecation('doctrine/doctrine-bundle', '2.11', 'Not setting "doctrine.orm.enable_lazy_ghost_objects" to true is deprecated.');
}

$options = ['auto_generate_proxy_classes', 'enable_lazy_ghost_objects', 'proxy_dir', 'proxy_namespace'];
Expand Down Expand Up @@ -838,6 +844,7 @@ protected function loadOrmEntityManagerMappingInformation(array $entityManager,
$this->registerMappingDrivers($entityManager, $container);

$container->getDefinition($this->getObjectManagerElementName($entityManager['name'] . '_metadata_driver'));
/** @psalm-suppress NoValue $this->drivers is set by $this->loadMappingInformation() call */
foreach (array_keys($this->drivers) as $driverType) {
$mappingService = $this->getObjectManagerElementName($entityManager['name'] . '_' . $driverType . '_metadata_driver');
$mappingDriverDef = $container->getDefinition($mappingService);
Expand Down
5 changes: 3 additions & 2 deletions DoctrineBundle.php
Expand Up @@ -13,9 +13,9 @@
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\RemoveProfilerControllerPass;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\WellKnownSchemaFilterPass;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Proxy\Autoloader;
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\DoctrineValidationPass;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterUidTypePass;
Expand Down Expand Up @@ -97,10 +97,11 @@ public function boot()

if ($this->container->getParameter('doctrine.orm.auto_generate_proxy_classes')) {
// See https://github.com/symfony/symfony/pull/3419 for usage of references
/** @psalm-suppress UnsupportedPropertyReferenceUsage */
$container = &$this->container;

$proxyGenerator = static function ($proxyDir, $proxyNamespace, $class) use (&$container): void {
$originalClassName = ClassUtils::getRealClass($class);
$originalClassName = (new DefaultProxyClassNameResolver())->resolveClassName($class);
$registry = $container->get('doctrine');
assert($registry instanceof Registry);

Expand Down
21 changes: 19 additions & 2 deletions Repository/ServiceEntityRepositoryProxy.php
Expand Up @@ -41,25 +41,35 @@ public function __construct(
$this->repository = $this->resolveRepository();
}

/** @psalm-suppress MethodSignatureMismatch This proxy is used only in combination with newer parent class */
public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder
{
return ($this->repository ??= $this->resolveRepository())
->createQueryBuilder($alias, $indexBy);
}

/** @psalm-suppress MethodSignatureMismatch This proxy is used only in combination with newer parent class */
public function createResultSetMappingBuilder(string $alias): ResultSetMappingBuilder
{
return ($this->repository ??= $this->resolveRepository())
->createResultSetMappingBuilder($alias);
}

/** @psalm-suppress MethodSignatureMismatch This proxy is used only in combination with newer parent class */
public function find(mixed $id, LockMode|int|null $lockMode = null, int|null $lockVersion = null): object|null
{
/** @psalm-suppress InvalidReturnStatement This proxy is used only in combination with newer parent class */
return ($this->repository ??= $this->resolveRepository())
->find($id, $lockMode, $lockVersion);
}

/** {@inheritDoc} */
/**
* {@inheritDoc}
*
* @psalm-suppress InvalidReturnStatement This proxy is used only in combination with newer parent class
* @psalm-suppress MethodSignatureMismatch This proxy is used only in combination with newer parent class
* @psalm-suppress InvalidReturnType This proxy is used only in combination with newer parent class
*/
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
return ($this->repository ??= $this->resolveRepository())
Expand All @@ -69,6 +79,7 @@ public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = nu
/** {@inheritDoc} */
public function findOneBy(array $criteria, ?array $orderBy = null): object|null
{
/** @psalm-suppress InvalidReturnStatement This proxy is used only in combination with newer parent class */
return ($this->repository ??= $this->resolveRepository())
->findOneBy($criteria, $orderBy);
}
Expand All @@ -79,7 +90,11 @@ public function count(array $criteria = []): int
return ($this->repository ??= $this->resolveRepository())->count($criteria);
}

/** {@inheritDoc} */
/**
* {@inheritDoc}
*
* @psalm-suppress MethodSignatureMismatch This proxy is used only in combination with newer parent class
*/
public function __call(string $method, array $arguments): mixed
{
return ($this->repository ??= $this->resolveRepository())->$method(...$arguments);
Expand All @@ -95,8 +110,10 @@ protected function getEntityManager(): EntityManagerInterface
return ($this->repository ??= $this->resolveRepository())->getEntityManager();
}

/** @psalm-suppress InvalidReturnType This proxy is used only in combination with newer parent class */
protected function getClassMetadata(): ClassMetadata
{
/** @psalm-suppress InvalidReturnStatement This proxy is used only in combination with newer parent class */
return ($this->repository ??= $this->resolveRepository())->getClassMetadata();
}

Expand Down
2 changes: 2 additions & 0 deletions Resources/doc/configuration.rst
Expand Up @@ -219,6 +219,8 @@ Configuration Reference
auto_generate_proxy_classes: false
proxy_dir: "%kernel.cache_dir%/doctrine/orm/Proxies"
proxy_namespace: Proxies
# Enables the new implementation of proxies based on lazy ghosts instead of using the legacy implementation
enable_lazy_ghost_objects: false
entity_managers:
Expand Down
17 changes: 11 additions & 6 deletions Resources/views/Collector/db.html.twig
Expand Up @@ -447,9 +447,16 @@
var targetElement = document.getElementById(targetId);
if (targetElement.style.display != 'block') {
Sfjs.load(targetId, link.href, null, function(xhr, el) {
el.innerHTML = 'An error occurred while loading the query explanation.';
});
if (targetElement.getAttribute('data-sfurl') !== link.href) {
fetch(link.href, {
headers: {'X-Requested-With': 'XMLHttpRequest'}
}).then(async function (response) {
targetElement.innerHTML = await response.text()
targetElement.setAttribute('data-sfurl', link.href)
}, function () {
targetElement.innerHTML = 'An error occurred while loading the query explanation.';
})
}
targetElement.style.display = 'block';
link.innerHTML = 'Hide query explanation';
Expand Down Expand Up @@ -490,15 +497,13 @@
});
for (i = 0; i < items.length; ++i) {
Sfjs.removeClass(items[i], i % 2 ? 'even' : 'odd');
Sfjs.addClass(items[i], i % 2 ? 'odd' : 'even');
target.appendChild(items[i]);
}
}
if (navigator.clipboard) {
document.querySelectorAll('[data-clipboard-text]').forEach(function(button) {
Sfjs.removeClass(button, 'hidden');
button.classList.remove('hidden');
button.addEventListener('click', function() {
navigator.clipboard.writeText(button.getAttribute('data-clipboard-text'));
})
Expand Down
4 changes: 2 additions & 2 deletions Tests/CacheSchemaSubscriberTest.php
Expand Up @@ -95,13 +95,13 @@ public function getSchemaSubscribers(): Generator
{
/**
* available in Symfony 6.3
*
* @psalm-suppress UndefinedClass
*/
yield ['cache.adapter.doctrine_dbal', 'doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_listener', DoctrineDbalCacheAdapterSchemaListener::class];

/**
* available in Symfony 5.1 and up to Symfony 5.4 (deprecated)
*
* @psalm-suppress UndefinedClass
*/
yield ['cache.adapter.pdo', 'doctrine.orm.listeners.pdo_cache_adapter_doctrine_schema_subscriber', PdoCacheAdapterDoctrineSchemaSubscriber::class];
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/Command/CreateDatabaseDoctrineTest.php
Expand Up @@ -86,7 +86,7 @@ private function getMockContainer(string $connectionName, ?array $params = null)
->willReturn($mockConnection);

$mockContainer = $this->getMockBuilder(Container::class)
->setMethods(['get'])
->onlyMethods(['get'])
->getMock();

$mockContainer->expects($this->any())
Expand Down
2 changes: 1 addition & 1 deletion Tests/Command/DropDatabaseDoctrineTest.php
Expand Up @@ -168,7 +168,7 @@ private function getMockContainer(string $connectionName, array $params): MockOb
->willReturn($mockConnection);

$mockContainer = $this->getMockBuilder(Container::class)
->setMethods(['get'])
->onlyMethods(['get'])
->getMock();

$mockContainer->expects($this->any())
Expand Down
3 changes: 3 additions & 0 deletions Tests/ConnectionFactoryTest.php
Expand Up @@ -96,6 +96,7 @@ public function testConnectionOverrideOptions(): void
'password' => 'wordpass',
];

/** @psalm-suppress InvalidArgument We should adjust when https://github.com/vimeo/psalm/issues/8984 is fixed */
$connection = (new ConnectionFactory([]))->createConnection(
[
'url' => 'mysql://root:password@database:3306/main?serverVersion=mariadb-10.5.8',
Expand All @@ -119,6 +120,7 @@ public function testConnectionCharsetFromUrl()

public function testDbnameSuffix(): void
{
/** @psalm-suppress InvalidArgument We should adjust when https://github.com/vimeo/psalm/issues/8984 is fixed */
$connection = (new ConnectionFactory([]))->createConnection(
[
'url' => 'mysql://root:password@database:3306/main?serverVersion=mariadb-10.5.8',
Expand All @@ -132,6 +134,7 @@ public function testDbnameSuffix(): void

public function testDbnameSuffixForReplicas(): void
{
/** @psalm-suppress InvalidArgument We should adjust when https://github.com/vimeo/psalm/issues/8984 is fixed */
$connection = (new ConnectionFactory([]))->createConnection(
[
'driver' => 'pdo_mysql',
Expand Down

0 comments on commit 99fcc69

Please sign in to comment.