Completed
Push — master ( 26e92d...7c0346 )
by Philip
25:00
created

DoctrineCrudService::createAssociation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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