ToManyAssociationLoadingStrategy::load()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 23
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 40
rs 9.552
1
<?php
2
3
namespace Malef\Associate\DoctrineOrm\Loader\LoadingStrategy;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\ORM\PersistentCollection;
7
use Malef\Associate\DoctrineOrm\Loader\ChunkingStrategy\ChunkingStrategy;
8
use Malef\Associate\DoctrineOrm\Metadata\AssociationMetadataAdapter;
9
use Symfony\Component\PropertyAccess\PropertyAccess;
10
11
class ToManyAssociationLoadingStrategy implements AssociationLoadingStrategyInterface
12
{
13
    /**
14
     * @var \Malef\Associate\DoctrineOrm\Loader\ChunkingStrategy\ChunkingStrategy
15
     */
16
    protected $chunkingStrategy;
17
18
    public function __construct(ChunkingStrategy $chunkingStrategy)
19
    {
20
        $this->chunkingStrategy = $chunkingStrategy;
21
    }
22
23
    public function supports(AssociationMetadataAdapter $associationMetadataAdapter): bool
24
    {
25
        return $associationMetadataAdapter->isToMany();
26
    }
27
28
    public function load(ArrayCollection $sourceEntities, AssociationMetadataAdapter $associationMetadataAdapter): void
29
    {
30
        if ($sourceEntities->isEmpty()) {
31
            return;
32
        }
33
34
        $sourceClassMetadataAdapter = $associationMetadataAdapter->getSourceClassMetadataAdapter();
35
36
        // TODO Clean this up. What other situations need to be handled? What about uninitialized proxies here?
37
38
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
39
        $filteredSourceIdentities = $sourceEntities->filter(
40
            function ($sourceEntity) use ($propertyAccessor, $associationMetadataAdapter) {
41
                $propertyValue = $propertyAccessor->getValue($sourceEntity, $associationMetadataAdapter->getName());
42
43
                return $propertyValue instanceof PersistentCollection && !$propertyValue->isInitialized();
44
            }
45
        );
46
47
        // TODO For initialized collections we should probably check if all items are initialized.
48
49
        foreach ($this->chunkingStrategy->chunk($filteredSourceIdentities) as $entityChunk) {
50
            $queryBuilder = $sourceClassMetadataAdapter->createQueryBuilder('s');
51
            $queryBuilder
52
                ->select(
53
                    sprintf('PARTIAL s.{%s}', $sourceClassMetadataAdapter->getIdentifierFieldName()),
54
                    't'
55
                )
56
                ->leftJoin(
57
                    sprintf('s.%s', $associationMetadataAdapter->getName()),
58
                    't'
59
                )
60
                ->andWhere(
61
                    $queryBuilder->expr()->in(
62
                        's',
63
                        $sourceClassMetadataAdapter->getIdentifierValueForMany($entityChunk)->getValues()
64
                    )
65
                )
66
                ->getQuery()
67
                ->execute();
68
        }
69
    }
70
}
71