Passed
Pull Request — master (#5)
by Alex
03:18
created

CascadeSaveService   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 57
dl 0
loc 118
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
B saveAssociations() 0 71 6
A saveAssociation() 0 22 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\DoctrineEntityRepository\Persistence;
6
7
use Arp\DoctrineEntityRepository\Exception\EntityRepositoryException;
8
use Arp\DoctrineEntityRepository\Persistence\Exception\PersistenceException;
9
use Arp\Entity\EntityInterface;
10
use Doctrine\ORM\EntityManagerInterface;
11
12
/**
13
 * @author  Alex Patterson <[email protected]>
14
 * @package Arp\DoctrineEntityRepository\Persistence
15
 */
16
class CascadeSaveService extends AbstractCascadeService
17
{
18
    /**
19
     * @param EntityManagerInterface $entityManager
20
     * @param string                 $entityName
21
     * @param EntityInterface        $entity
22
     * @param array                  $saveOptions
23
     * @param array                  $saveCollectionOptions
24
     *
25
     * @throws PersistenceException
26
     * @throws EntityRepositoryException
27
     */
28
    public function saveAssociations(
29
        EntityManagerInterface $entityManager,
30
        string $entityName,
31
        EntityInterface $entity,
32
        array $saveOptions = [],
33
        array $saveCollectionOptions = []
34
    ): void {
35
        $saveOptions = array_replace_recursive($this->options, $saveOptions);
36
        $saveCollectionOptions = array_replace_recursive($this->collectionOptions, $saveCollectionOptions);
37
38
        $classMetadata = $this->getClassMetadata($entityManager, $entityName);
39
        $mappings = $classMetadata->getAssociationMappings();
40
41
        $this->logger->info(
42
            sprintf('Processing cascade save operations for for entity class \'%s\'', $entityName)
43
        );
44
45
        foreach ($mappings as $mapping) {
46
            if (
47
                !isset(
48
                    $mapping['targetEntity'],
49
                    $mapping['fieldName'],
50
                    $mapping['type'],
51
                    $mapping['isCascadePersist']
52
                )
53
                || true !== $mapping['isCascadePersist']
54
            ) {
55
                // We only want to save associations that are configured to cascade persist
56
                continue;
57
            }
58
59
            $this->logger->info(
60
                sprintf(
61
                    'The entity field \'%s::%s\' is configured for cascade operations for target entity \'%s\'',
62
                    $entityName,
63
                    $mapping['fieldName'],
64
                    $mapping['targetEntity']
65
                )
66
            );
67
68
            $targetEntityOrCollection = $this->resolveTargetEntityOrCollection(
69
                $entity,
70
                $mapping['fieldName'],
71
                $classMetadata,
72
                $this->getClassMetadata($entityManager, $mapping['targetEntity'])
73
            );
74
75
            if (!$this->isValidAssociation($targetEntityOrCollection, $mapping)) {
76
                $this->logger->info(
77
                    sprintf(
78
                        'The entity field \'%s::%s\' value could not be resolved',
79
                        $entityName,
80
                        $mapping['fieldName']
81
                    )
82
                );
83
                continue;
84
            }
85
86
            $this->logger->info(
87
                sprintf(
88
                    'Performing cascading save operations for field \'%s::%s\'',
89
                    $entityName,
90
                    $mapping['fieldName']
91
                )
92
            );
93
94
            $this->saveAssociation(
95
                $entityManager,
96
                $mapping['targetEntity'],
97
                $targetEntityOrCollection,
98
                (is_iterable($targetEntityOrCollection) ? $saveCollectionOptions : $saveOptions)
99
            );
100
        }
101
    }
102
103
    /**
104
     * @param EntityManagerInterface                     $entityManager
105
     * @param string                                     $targetEntityName
106
     * @param EntityInterface|EntityInterface[]|iterable $entityOrCollection
107
     * @param array                                      $options
108
     *
109
     * @throws PersistenceException
110
     * @throws EntityRepositoryException
111
     */
112
    public function saveAssociation(
113
        EntityManagerInterface $entityManager,
114
        string $targetEntityName,
115
        $entityOrCollection,
116
        array $options = []
117
    ): void {
118
        if (is_iterable($entityOrCollection)) {
119
            $targetRepository = $this->getTargetRepository($entityManager, $targetEntityName);
120
            $targetRepository->saveCollection($entityOrCollection, $options);
0 ignored issues
show
Bug introduced by
It seems like $entityOrCollection can also be of type Arp\Entity\EntityInterface; however, parameter $collection of Arp\DoctrineEntityReposi...rface::saveCollection() does only seem to accept iterable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

120
            $targetRepository->saveCollection(/** @scrutinizer ignore-type */ $entityOrCollection, $options);
Loading history...
121
        } elseif ($entityOrCollection instanceof EntityInterface) {
122
            $targetRepository = $this->getTargetRepository($entityManager, $targetEntityName);
123
            $targetRepository->save($entityOrCollection, $options);
124
        } else {
125
            $errorMessage = sprintf(
126
                'Unable to cascade save target entity \'%s\': The entity or collection is of an invalid type \'%s\'',
127
                $targetEntityName,
128
                (is_object($entityOrCollection) ? get_class($entityOrCollection) : gettype($entityOrCollection))
129
            );
130
131
            $this->logger->error($errorMessage);
132
133
            throw new PersistenceException($errorMessage);
134
        }
135
    }
136
}
137