Skip to content
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

Introduce convenience methods to narrow types #10701

Merged
merged 1 commit into from
May 15, 2023
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
38 changes: 24 additions & 14 deletions lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\InverseSideMapping;
use Doctrine\ORM\Mapping\ManyToManyAssociationMapping;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Persisters\SqlValueVisitor;
use Doctrine\ORM\Query;
Expand All @@ -33,7 +34,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
{
public function delete(PersistentCollection $collection): void
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping->isOwningSide()) {
return; // ignore inverse side
Expand All @@ -53,7 +54,7 @@ public function delete(PersistentCollection $collection): void

public function update(PersistentCollection $collection): void
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping->isOwningSide()) {
return; // ignore inverse side
Expand Down Expand Up @@ -81,7 +82,7 @@ public function update(PersistentCollection $collection): void

public function get(PersistentCollection $collection, mixed $index): object|null
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping->isIndexed()) {
throw new BadMethodCallException('Selecting a collection by index is only supported on indexed collections.');
Expand Down Expand Up @@ -109,7 +110,7 @@ public function count(PersistentCollection $collection): int
$conditions = [];
$params = [];
$types = [];
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
$id = $this->uow->getEntityIdentifier($collection->getOwner());
$sourceClass = $this->em->getClassMetadata($mapping->sourceEntity);
$association = $this->em->getMetadataFactory()->getOwningSide($mapping);
Expand Down Expand Up @@ -162,15 +163,15 @@ public function count(PersistentCollection $collection): int
*/
public function slice(PersistentCollection $collection, int $offset, int|null $length = null): array
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
$persister = $this->uow->getEntityPersister($mapping['targetEntity']);

return $persister->getManyToManyCollection($mapping, $collection->getOwner(), $offset, $length);
}

public function containsKey(PersistentCollection $collection, mixed $key): bool
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping->isIndexed()) {
throw new BadMethodCallException('Selecting a collection by index is only supported on indexed collections.');
Expand Down Expand Up @@ -209,7 +210,7 @@ public function contains(PersistentCollection $collection, object $element): boo
*/
public function loadCriteria(PersistentCollection $collection, Criteria $criteria): array
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
$owner = $collection->getOwner();
$ownerMetadata = $this->em->getClassMetadata($owner::class);
$id = $this->uow->getEntityIdentifier($owner);
Expand Down Expand Up @@ -364,7 +365,7 @@ protected function getOnConditionSQL(AssociationMapping $mapping): array
protected function getDeleteSQL(PersistentCollection $collection): string
{
$columns = [];
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
assert($mapping->isManyToManyOwningSide());
$class = $this->em->getClassMetadata($collection->getOwner()::class);
$joinTable = $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform);
Expand All @@ -384,7 +385,7 @@ protected function getDeleteSQL(PersistentCollection $collection): string
*/
protected function getDeleteSQLParameters(PersistentCollection $collection): array
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
assert($mapping->isManyToManyOwningSide());
$identifier = $this->uow->getEntityIdentifier($collection->getOwner());

Expand Down Expand Up @@ -415,7 +416,7 @@ protected function getDeleteSQLParameters(PersistentCollection $collection): arr
*/
protected function getDeleteRowSQL(PersistentCollection $collection): array
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
assert($mapping->isManyToManyOwningSide());
$class = $this->em->getClassMetadata($mapping->sourceEntity);
$targetClass = $this->em->getClassMetadata($mapping->targetEntity);
Expand Down Expand Up @@ -464,7 +465,7 @@ protected function getInsertRowSQL(PersistentCollection $collection): array
{
$columns = [];
$types = [];
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
assert($mapping->isManyToManyOwningSide());
$class = $this->em->getClassMetadata($mapping->sourceEntity);
$targetClass = $this->em->getClassMetadata($mapping->targetEntity);
Expand Down Expand Up @@ -514,7 +515,7 @@ private function collectJoinTableColumnParameters(
object $element,
): array {
$params = [];
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
assert($mapping->isManyToManyOwningSide());
$isComposite = count($mapping->joinTableColumns) > 2;

Expand Down Expand Up @@ -563,7 +564,7 @@ private function getJoinTableRestrictionsWithKey(
string $key,
bool $addFilters,
): array {
$filterMapping = $collection->getMapping();
$filterMapping = $this->getMapping($collection);
$mapping = $filterMapping;
$indexBy = $mapping->indexBy();
$id = $this->uow->getEntityIdentifier($collection->getOwner());
Expand Down Expand Up @@ -653,7 +654,7 @@ private function getJoinTableRestrictions(
object $element,
bool $addFilters,
): array {
$filterMapping = $collection->getMapping();
$filterMapping = $this->getMapping($collection);
$mapping = $filterMapping;

if (! $mapping->isOwningSide()) {
Expand Down Expand Up @@ -757,4 +758,13 @@ private function getLimitSql(Criteria $criteria): string

return $this->platform->modifyLimitQuery('', $limit, $offset ?? 0);
}

private function getMapping(PersistentCollection $collection): AssociationMapping&ManyToManyAssociationMapping
{
$mapping = $collection->getMapping();

assert($mapping instanceof ManyToManyAssociationMapping);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this assert even needed here when the type hint only allows AssociationMapping instances that implement ManyToManyAssociationMapping?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, otherwise SA will complain that nothing proves we return that type although we claim we do.


return $mapping;
}
}
19 changes: 14 additions & 5 deletions lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Doctrine\Common\Collections\Criteria;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Utility\PersisterHelper;

Expand All @@ -27,7 +28,7 @@ public function delete(PersistentCollection $collection): void
// The only valid case here is when you have weak entities. In this
// scenario, you have @OneToMany with orphanRemoval=true, and replacing
// the entire collection with a new would trigger this operation.
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping['orphanRemoval']) {
// Handling non-orphan removal should never happen, as @OneToMany
Expand All @@ -53,8 +54,7 @@ public function update(PersistentCollection $collection): void

public function get(PersistentCollection $collection, mixed $index): object|null
{
$mapping = $collection->getMapping();
assert($mapping->isOneToMany());
$mapping = $this->getMapping($collection);

if (! $mapping->isIndexed()) {
throw new BadMethodCallException('Selecting a collection by index is only supported on indexed collections.');
Expand Down Expand Up @@ -101,7 +101,7 @@ public function slice(PersistentCollection $collection, int $offset, int|null $l

public function containsKey(PersistentCollection $collection, mixed $key): bool
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);

if (! $mapping->isIndexed()) {
throw new BadMethodCallException('Selecting a collection by index is only supported on indexed collections.');
Expand Down Expand Up @@ -148,7 +148,7 @@ public function loadCriteria(PersistentCollection $collection, Criteria $criteri
/** @throws DBALException */
private function deleteEntityCollection(PersistentCollection $collection): int
{
$mapping = $collection->getMapping();
$mapping = $this->getMapping($collection);
$identifier = $this->uow->getEntityIdentifier($collection->getOwner());
$sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
Expand Down Expand Up @@ -230,4 +230,13 @@ private function deleteJoinedEntityCollection(PersistentCollection $collection):

return $numDeleted;
}

private function getMapping(PersistentCollection $collection): OneToManyAssociationMapping
{
$mapping = $collection->getMapping();

assert($mapping->isOneToMany());

return $mapping;
}
}
5 changes: 4 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ parameters:
-
message: "#^Access to an undefined property .*Mapping\\:\\:\\$(inversedBy|mappedBy|joinColumns|joinTableColumns|(relation|source|target)To(Target|Source)KeyColumns|joinTable|indexBy)\\.$#"
paths:
- lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php
- lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php
- lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
- lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
Expand All @@ -51,3 +50,7 @@ parameters:
paths:
- lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
- lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php

-
message: '#^.*OneToManyPersister::getMapping\(\) should return.*#'
path: lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php
4 changes: 1 addition & 3 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -725,9 +725,7 @@
<code><![CDATA[$collection->getOwner()]]></code>
<code><![CDATA[$collection->getOwner()]]></code>
</PossiblyNullArgument>
<UndefinedPropertyFetch>
<code><![CDATA[$mapping->mappedBy]]></code>
</UndefinedPropertyFetch>
<UndefinedPropertyFetch/>
</file>
<file src="lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php">
<DocblockTypeContradiction>
Expand Down