Completed
Push — master ( 6fc36f...2a3f70 )
by Joachim
52:46 queued 37:35
created

AbstractRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
ccs 0
cts 2
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Loevgaard\DandomainFoundation\Repository;
4
5
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
6
use Doctrine\Common\Persistence\ManagerRegistry;
7
use Doctrine\ORM\QueryBuilder;
8
use Loevgaard\DandomainDateTime\DateTimeImmutable;
9
use Loevgaard\DandomainFoundation\Repository\Generated\AbstractRepositoryTrait;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
12
abstract class AbstractRepository extends ServiceEntityRepository implements RepositoryInterface
13
{
14
    use AbstractRepositoryTrait;
15
16
    /**
17
     * @var array
18
     */
19
    protected $options;
20
21
    public function __construct(ManagerRegistry $registry, string $entityClass)
22
    {
23
        $this->options = [];
24
25
        parent::__construct($registry, $entityClass);
26
    }
27
28
    /**
29
     * @param object $entity
30
     * @throws \Doctrine\ORM\ORMException
31
     * @throws \Doctrine\ORM\OptimisticLockException
32
     */
33
    public function save($entity)
34
    {
35
        $this->getEntityManager()->persist($entity);
36
        $this->getEntityManager()->flush();
37
    }
38
39
    /**
40
     * @param array $options
41
     * @return \Generator
42
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
43
     * @throws \Doctrine\ORM\ORMException
44
     * @throws \Doctrine\ORM\OptimisticLockException
45
     */
46
    public function iterate(array $options = []): \Generator
47
    {
48
        $options['iterate'] = true;
49
        $this->setOptions($options);
50
51
        return $this->result($this->createQueryBuilder('c'));
52
    }
53
54
    /**
55
     * Will remove entities based on the ids you input.
56
     *
57
     * @param int[] $in
58
     * @param int[] $notIn
59
     */
60
    public function removeByIds(array $in = [], array $notIn = [])
61
    {
62
        if (!count($in) && !count($notIn)) {
63
            return;
64
        }
65
66
        $qb = $this->createQueryBuilder('e');
67
68
        if ($this->getClassMetadata()->hasField('deletedAt')) {
69
            $qb->update()
70
                ->set('e.deletedAt', ':date')
71
                ->setParameter('date', new DateTimeImmutable())
72
            ;
73
        } else {
74
            $qb->delete();
75
        }
76
77
        if (count($in)) {
78
            $qb->andWhere($qb->expr()->in('e.id', ':inIds'));
79
            $qb->setParameter('inIds', $in);
80
        }
81
82
        if (count($notIn)) {
83
            $qb->andWhere($qb->expr()->notIn('e.id', ':notInIds'));
84
            $qb->setParameter('notInIds', $notIn);
85
        }
86
87
        $qb->getQuery()->execute();
88
    }
89
90
    /**
91
     * @param QueryBuilder $qb
92
     * @return \Generator|mixed
93
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
94
     * @throws \Doctrine\ORM\ORMException
95
     * @throws \Doctrine\ORM\OptimisticLockException
96
     */
97
    protected function result(QueryBuilder $qb)
98
    {
99
        $resolver = new OptionsResolver();
100
        $this->configureOptions($resolver);
101
        $options = $resolver->resolve($this->options);
102
103
        // reset options
104
        $this->options = [];
105
106
        if($options['iterate']) {
107
            $em = $this->getEntityManager();
108
109
            $result = $qb->getQuery()->iterate();
110
            $i = 1;
111
            foreach ($result as $item) {
112
                $obj = $item[0];
113
                yield $obj;
114
115
                if ($options['update']) {
116
                    if (0 == $i % $options['bulkSize']) {
117
                        $em->flush();
118
                        $em->clear();
119
                    }
120
                } else {
121
                    $em->detach($obj);
122
                }
123
124
                ++$i;
125
            }
126
127
            if ($options['update']) {
128
                $em->flush();
129
                $em->clear();
130
            }
131
        } else {
132
            return $qb->getQuery()->getResult();
133
        }
134
    }
135
136
    /**
137
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
138
     */
139
    public function clearAll()
140
    {
141
        $this->getEntityManager()->clear();
142
    }
143
144
    /**
145
     * @param $id
146
     *
147
     * @return bool|\Doctrine\Common\Proxy\Proxy|null|object
148
     *
149
     * @throws \Doctrine\ORM\ORMException
150
     */
151
    public function getReference($id)
152
    {
153
        return $this->getEntityManager()->getReference($this->getClassName(), $id);
154
    }
155
156
    /**
157
     * @param array $options
158
     * @return AbstractRepository
159
     */
160
    public function setOptions(array $options)
161
    {
162
        $this->options = $options;
163
        return $this;
164
    }
165
166
    /**
167
     * On 90% of the entities there is an external id so we put this helper method here
168
     * so that all these repository doesn't have to implement the same method, instead they
169
     * can call this method and just create the type hint and validation of input.
170
     *
171
     * @param $externalId
172
     *
173
     * @return null|object
174
     */
175
    protected function _findOneByExternalId($externalId)
176
    {
177
        $obj = $this->findOneBy([
178
            'externalId' => $externalId,
179
        ]);
180
181
        return $obj;
182
    }
183
184
    protected function configureOptions(OptionsResolver $resolver)
185
    {
186
        $resolver->setDefaults([
187
            'iterate' => false,
188
            'update' => false,
189
            'bulkSize' => 50,
190
        ]);
191
    }
192
}
193