Completed
Push — master ( e9ba41...791922 )
by Alex
14s queued 12s
created

CascadeDeleteService::deleteAssociation()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 22
rs 9.8666
cc 4
nc 3
nop 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 CascadeDeleteService extends AbstractCascadeService
17
{
18
    /**
19
     * @param EntityManagerInterface $entityManager
20
     * @param string                 $entityName
21
     * @param EntityInterface        $entity
22
     * @param array                  $deleteOptions
23
     * @param array                  $deleteCollectionOptions
24
     *
25
     * @throws EntityRepositoryException
26
     * @throws PersistenceException
27
     */
28
    public function deleteAssociations(
29
        EntityManagerInterface $entityManager,
30
        string $entityName,
31
        EntityInterface $entity,
32
        array $deleteOptions = [],
33
        array $deleteCollectionOptions = []
34
    ): void {
35
        $deleteOptions = array_replace_recursive($this->options, $deleteOptions);
36
        $deleteCollectionOptions = array_replace_recursive($this->collectionOptions, $deleteCollectionOptions);
37
38
        $classMetadata = $this->getClassMetadata($entityManager, $entityName);
39
        $mappings = $classMetadata->getAssociationMappings();
40
41
        $this->logger->info(
42
            sprintf('Processing cascade delete 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['isCascadeRemove']
52
                )
53
                || true !== $mapping['isCascadeRemove']
54
            ) {
55
                // We only want to save associations that are configured to cascade delete/remove
56
                continue;
57
            }
58
59
            $this->logger->info(
60
                sprintf(
61
                    'The entity field \'%s::%s\' is configured for cascade delete operations for target entity \'%s\'',
62
                    $entityName,
63
                    $mappings['fieldName'],
64
                    $mappings['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
                $errorMessage = sprintf(
77
                    'The entity field \'%s::%s\' value could not be resolved',
78
                    $entityName,
79
                    $mappings['fieldName']
80
                );
81
82
                $this->logger->error($errorMessage);
83
84
                throw new PersistenceException($errorMessage);
85
            }
86
87
            $this->logger->info(
88
                sprintf(
89
                    'Performing cascading delete operations for field \'%s::%s\'',
90
                    $entityName,
91
                    $mappings['fieldName']
92
                )
93
            );
94
95
            $this->deleteAssociation(
96
                $entityManager,
97
                $mapping['targetEntity'],
98
                $targetEntityOrCollection,
99
                (is_iterable($targetEntityOrCollection) ? $deleteCollectionOptions : $deleteOptions)
100
            );
101
        }
102
    }
103
104
    /**
105
     * @param EntityManagerInterface $entityManager
106
     * @param string                 $targetEntityName
107
     * @param                        $entityOrCollection
108
     * @param array                  $options
109
     *
110
     * @throws PersistenceException
111
     * @throws EntityRepositoryException
112
     */
113
    public function deleteAssociation(
114
        EntityManagerInterface $entityManager,
115
        string $targetEntityName,
116
        $entityOrCollection,
117
        array $options = []
118
    ): void {
119
        $targetRepository = $this->getTargetRepository($entityManager, $targetEntityName);
120
121
        if (is_iterable($entityOrCollection)) {
122
            $targetRepository->deleteCollection($entityOrCollection, $options);
123
        } elseif ($entityOrCollection instanceof EntityInterface) {
124
            $targetRepository->delete($entityOrCollection, $options);
125
        } else {
126
            $errorMessage = sprintf(
127
                'Unable to cascade save target entity \'%s\': The entity or collection is of an invalid type \'%s\'',
128
                $targetEntityName,
129
                (is_object($entityOrCollection) ? get_class($entityOrCollection) : gettype($entityOrCollection))
130
            );
131
132
            $this->logger->error($errorMessage);
133
134
            throw new PersistenceException($errorMessage);
135
        }
136
    }
137
}
138