Completed
Push — master ( 3f9c2c...4d9c8a )
by Philip
02:02
created

DoctrineCrudService::createFindAllQueryBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Dontdrinkandroot\Service;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\EntityRepository;
7
use Doctrine\ORM\Mapping\ClassMetadata;
8
use Doctrine\ORM\QueryBuilder;
9
use Doctrine\ORM\Tools\Pagination\Paginator;
10
use Dontdrinkandroot\Repository\TransactionManager;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
15
class DoctrineCrudService extends EntityRepository implements CrudServiceInterface
16
{
17
    /**
18
     * @var  LoggerInterface
19
     */
20
    private $logger;
21
22
    /**
23
     * @var TransactionManager
24
     */
25
    private $transactionManager;
26
27
    /**
28
     * DoctrineCrudService constructor.
29
     *
30
     * @param EntityManager        $em
31
     * @param ClassMetadata|string $class
32
     */
33
    public function __construct(EntityManager $em, $class)
34
    {
35
        $classMetaData = $class;
36
        if (is_string($classMetaData)) {
37
            $classMetaData = $em->getClassMetadata($classMetaData);
38
        }
39
        parent::__construct($em, $classMetaData);
40
        $this->transactionManager = new TransactionManager($em);
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function findAllPaginated(int $page = 1, int $perPage = 50): Paginator
47
    {
48
        $queryBuilder = $this->createFindAllQueryBuilder();
49
        $queryBuilder->setFirstResult(($page - 1) * $perPage);
50
        $queryBuilder->setMaxResults($perPage);
51
52
        return new Paginator($queryBuilder);
53
    }
54
55
    protected function createFindAllQueryBuilder(): QueryBuilder
56
    {
57
        $queryBuilder = $this->createQueryBuilder('entity');
58
59
        return $queryBuilder;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function create($entity)
66
    {
67
        $this->getEntityManager()->persist($entity);
68
        $this->getEntityManager()->flush($entity);
69
70
        return $entity;
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function update($entity)
77
    {
78
        $this->getEntityManager()->flush($entity);
79
80
        return $entity;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function remove($entity)
87
    {
88
        $this->getEntityManager()->remove($entity);
89
        $this->getEntityManager()->flush($entity);
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95
    public function findAssociationPaginated($entity, string $fieldName, int $page = 1, $perPage = 50)
96
    {
97
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
98
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
99
100
        $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
101
102
        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
103
        $queryBuilder->select('association');
104
        $queryBuilder->from($targetClass, 'association');
105
        $queryBuilder->join('association.' . $inverseFieldName, 'entity');
106
        $queryBuilder->where('entity = :entity');
107
        $queryBuilder->setParameter('entity', $entity);
108
109
        $queryBuilder->setFirstResult(($page - 1) * $perPage);
110
        $queryBuilder->setMaxResults($perPage);
111
112
        return new Paginator($queryBuilder);
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function createAssociation($entity, string $fieldName, $child)
119
    {
120
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
121
122
        $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
123
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
124
        $propertyAccessor->setValue($child, $inverseFieldName, $entity);
125
126
        $this->getEntityManager()->persist($child);
127
        $this->getEntityManager()->flush($child);
128
129
        return $child;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function addAssociation($entity, string $fieldName, $id)
136
    {
137
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
138
        $collection = $classMetadata->isCollectionValuedAssociation($fieldName);
139
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
140
141
        if ($collection) {
142
            $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
143
144
            $reference = $this->getEntityManager()->getReference($targetClass, $id);
145
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
146
            $propertyAccessor->setValue($reference, $inverseFieldName, $entity);
147
148
            $this->getEntityManager()->flush($reference);
149
        } else {
150
            $reference = $this->getEntityManager()->getReference($targetClass, $id);
151
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
152
            $propertyAccessor->setValue($entity, $fieldName, $reference);
153
154
            $this->getEntityManager()->flush($entity);
155
        }
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function removeAssociation($entity, string $fieldName, $id)
162
    {
163
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
164
        $collection = $classMetadata->isCollectionValuedAssociation($fieldName);
165
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
166
167
        if ($collection) {
168
            $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
169
170
            $reference = $this->getEntityManager()->getReference($targetClass, $id);
171
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
172
            $propertyAccessor->setValue($reference, $inverseFieldName, null);
173
174
            $this->getEntityManager()->flush($reference);
175
        } else {
176
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
177
            $propertyAccessor->setValue($entity, $fieldName, null);
178
179
            $this->getEntityManager()->flush($entity);
180
        }
181
    }
182
183
    /**
184
     * @param string        $fieldName
185
     * @param ClassMetadata $classMetadata
186
     *
187
     * @return string
188
     */
189
    protected function getInverseFieldName(string $fieldName, ClassMetadata $classMetadata)
190
    {
191
        $association = $classMetadata->getAssociationMapping($fieldName);
192
        if ($classMetadata->isAssociationInverseSide($fieldName)) {
193
            return $association['mappedBy'];
194
        } else {
195
            return $association['inversedBy'];
196
        }
197
    }
198
199
    /**
200
     * @param LoggerInterface $logger
201
     */
202
    public function setLogger(LoggerInterface $logger): void
203
    {
204
        $this->logger = $logger;
205
    }
206
207
    /**
208
     * @return LoggerInterface
209
     */
210
    public function getLogger(): LoggerInterface
211
    {
212
        if (null === $this->logger) {
213
            $this->logger = new NullLogger();
214
        }
215
216
        return $this->logger;
217
    }
218
}
219