Skip to content
Merged
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
2 changes: 1 addition & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2301,7 +2301,7 @@ from 2.0 have to configure the annotation driver if they don't use `Configuratio

## Scalar mappings can now be omitted from DQL result

You are now allowed to mark scalar SELECT expressions as HIDDEN an they are not hydrated anymore.
You are now allowed to mark scalar SELECT expressions as HIDDEN and they are not hydrated anymore.
Example:

SELECT u, SUM(a.id) AS HIDDEN numArticles FROM User u LEFT JOIN u.Articles a ORDER BY numArticles DESC HAVING numArticles > 10
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/second-level-cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Caching mode
* Read Write cache employs locks before update/delete.
* Use if data needs to be updated.
* Slowest strategy.
* To use it a the cache region implementation must support locking.
* To use it the cache region implementation must support locking.


Built-in cached persisters
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ have to register them yourself.
All the commands of the Doctrine Console require access to the
``EntityManager``. You have to inject it into the console application.

Here is an example of a the project-specific ``bin/doctrine`` binary.
Here is an example of a project-specific ``bin/doctrine`` binary.

.. code-block:: php

Expand Down
2 changes: 1 addition & 1 deletion src/AbstractQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ public function setResultCacheId(string|null $id): static
}

/**
* Executes the query and returns a the resulting Statement object.
* Executes the query and returns the resulting Statement object.
*
* @return Result|int The executed database statement that holds
* the results, or an integer indicating how
Expand Down
2 changes: 1 addition & 1 deletion src/Mapping/MappingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public static function oneToManyRequiresMappedBy(string $entityName, string $fie

public static function joinTableRequired(string $fieldName): self
{
return new self(sprintf("The mapping of field '%s' requires an the 'joinTable' attribute.", $fieldName));
return new self(sprintf("The mapping of field '%s' requires the 'joinTable' attribute.", $fieldName));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/DDC2359Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function testIssue(): void
$entityManager->expects(self::any())->method('getConnection')->willReturn($connection);
$entityManager
->method('getEventManager')
->willReturn($this->createMock(EventManager::class));
->willReturn(new EventManager());

$metadataFactory->method('newClassMetadataInstance')->willReturn($mockMetadata);
$metadataFactory->expects(self::once())->method('wakeupReflection');
Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/GH10387Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static function classHierachies(): Generator
{
yield 'hierarchy with Entity classes only' => [[GH10387EntitiesOnlyRoot::class, GH10387EntitiesOnlyMiddle::class, GH10387EntitiesOnlyLeaf::class]];
yield 'MappedSuperclass in the middle of the hierarchy' => [[GH10387MappedSuperclassRoot::class, GH10387MappedSuperclassMiddle::class, GH10387MappedSuperclassLeaf::class]];
yield 'abstract entity the the root and in the middle of the hierarchy' => [[GH10387AbstractEntitiesRoot::class, GH10387AbstractEntitiesMiddle::class, GH10387AbstractEntitiesLeaf::class]];
yield 'abstract entity at the root and in the middle of the hierarchy' => [[GH10387AbstractEntitiesRoot::class, GH10387AbstractEntitiesMiddle::class, GH10387AbstractEntitiesLeaf::class]];
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/GH6394Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected function setUp(): void
}

/**
* Test the the version of an entity can be fetched, when the id field and
* Test the version of an entity can be fetched, when the id field and
* the id column are different.
*/
#[Group('6393')]
Expand Down
84 changes: 17 additions & 67 deletions tests/Tests/ORM/Hydration/AbstractHydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#[CoversClass(AbstractHydrator::class)]
class AbstractHydratorTest extends OrmFunctionalTestCase
{
private EventManager&MockObject $mockEventManager;
private EventManager $eventManager;
private Result&MockObject $mockResult;
private ResultSetMapping&MockObject $mockResultMapping;
private DummyHydrator $hydrator;
Expand All @@ -38,7 +38,7 @@ protected function setUp(): void

$mockConnection = $this->createMock(Connection::class);
$mockEntityManagerInterface = $this->createMock(EntityManagerInterface::class);
$this->mockEventManager = $this->createMock(EventManager::class);
$this->eventManager = new EventManager();
$this->mockResult = $this->createMock(Result::class);
$this->mockResultMapping = $this->createMock(ResultSetMapping::class);

Expand All @@ -47,7 +47,7 @@ protected function setUp(): void
->willReturn($this->createMock(AbstractPlatform::class));
$mockEntityManagerInterface
->method('getEventManager')
->willReturn($this->mockEventManager);
->willReturn($this->eventManager);
$mockEntityManagerInterface
->method('getConnection')
->willReturn($mockConnection);
Expand All @@ -66,85 +66,29 @@ protected function setUp(): void
#[Group('#1515')]
public function testOnClearEventListenerIsDetachedOnCleanup(): void
{
$eventListenerHasBeenRegistered = false;

$this
->mockEventManager
->expects(self::once())
->method('addEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertFalse($eventListenerHasBeenRegistered);
$eventListenerHasBeenRegistered = true;
});

$this
->mockEventManager
->expects(self::once())
->method('removeEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertTrue($eventListenerHasBeenRegistered);
});

iterator_to_array($this->hydrator->toIterable($this->mockResult, $this->mockResultMapping));
$iterator = $this->hydrator->toIterable($this->mockResult, $this->mockResultMapping);
iterator_to_array($iterator);
self::assertTrue($this->hydrator->hasListener);
self::assertFalse($this->eventManager->hasListeners(Events::onClear));
}

#[Group('#6623')]
public function testHydrateAllRegistersAndClearsAllAttachedListeners(): void
{
$eventListenerHasBeenRegistered = false;

$this
->mockEventManager
->expects(self::once())
->method('addEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertFalse($eventListenerHasBeenRegistered);
$eventListenerHasBeenRegistered = true;
});

$this
->mockEventManager
->expects(self::once())
->method('removeEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertTrue($eventListenerHasBeenRegistered);
});

$this->hydrator->hydrateAll($this->mockResult, $this->mockResultMapping);
self::assertTrue($this->hydrator->hasListener);
self::assertFalse($this->eventManager->hasListeners(Events::onClear));
}

#[Group('#8482')]
public function testHydrateAllClearsAllAttachedListenersEvenOnError(): void
{
$eventListenerHasBeenRegistered = false;

$this
->mockEventManager
->expects(self::once())
->method('addEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertFalse($eventListenerHasBeenRegistered);
$eventListenerHasBeenRegistered = true;
});

$this
->mockEventManager
->expects(self::once())
->method('removeEventListener')
->with([Events::onClear], $this->hydrator)
->willReturnCallback(function () use (&$eventListenerHasBeenRegistered): void {
$this->assertTrue($eventListenerHasBeenRegistered);
});

$this->hydrator->throwException = true;

$this->expectException(LogicException::class);
$this->hydrator->hydrateAll($this->mockResult, $this->mockResultMapping);
self::assertTrue($this->hydrator->hasListener);
self::assertFalse($this->eventManager->hasListeners(Events::onClear));
}

public function testEnumCastsIntegerBackedEnumValues(): void
Expand Down Expand Up @@ -198,6 +142,7 @@ public function testToIterableIfYieldAndBreakBeforeFinishAlwaysCleansUp(): void
class DummyHydrator extends AbstractHydrator
{
public bool $throwException = false;
public bool $hasListener = false;

public function buildEnumForTesting(mixed $value, string $enumType): BackedEnum|array
{
Expand All @@ -213,4 +158,9 @@ protected function hydrateAllData(): array

return [];
}

public function prepare(): void
{
$this->hasListener = $this->em->getEventManager()->hasListeners(Events::onClear);
}
}