Completed
Push — master ( f31334...7e3a8f )
by Joachim
14:16
created

AbstractRepository::persist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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;
0 ignored issues
show
Bug introduced by
The type Loevgaard\DandomainFound...AbstractRepositoryTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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
30
     * @throws \Doctrine\ORM\ORMException
31
     */
32
    public function persist($object) : void
33
    {
34
        $this->getEntityManager()->persist($object);
35
    }
36
37
    /**
38
     * @param null|object|array $entity
39
     * @throws \Doctrine\ORM\ORMException
40
     * @throws \Doctrine\ORM\OptimisticLockException
41
     */
42
    public function flush($entity = null) : void
43
    {
44
        $this->getEntityManager()->flush($entity);
45
    }
46
47
    /**
48
     * @param object $entity
49
     * @throws \Doctrine\ORM\ORMException
50
     * @throws \Doctrine\ORM\OptimisticLockException
51
     */
52
    public function save($entity)
53
    {
54
        $this->getEntityManager()->persist($entity);
55
        $this->getEntityManager()->flush();
56
    }
57
58
    /**
59
     * @param array $options
60
     * @return \Generator
61
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
62
     * @throws \Doctrine\ORM\ORMException
63
     * @throws \Doctrine\ORM\OptimisticLockException
64
     */
65
    public function iterate(array $options = []): \Generator
66
    {
67
        $options['iterate'] = true;
68
        $this->setOptions($options);
69
70
        return $this->result($this->createQueryBuilder('c'));
71
    }
72
73
    /**
74
     * Will remove entities based on the ids you input.
75
     *
76
     * @param int[] $in
77
     * @param int[] $notIn
78
     */
79
    public function removeByIds(array $in = [], array $notIn = [])
80
    {
81
        if (!count($in) && !count($notIn)) {
82
            return;
83
        }
84
85
        $qb = $this->createQueryBuilder('e');
86
87
        if ($this->getClassMetadata()->hasField('deletedAt')) {
88
            $qb->update()
89
                ->set('e.deletedAt', ':date')
90
                ->setParameter('date', new DateTimeImmutable())
91
            ;
92
        } else {
93
            $qb->delete();
94
        }
95
96
        if (count($in)) {
97
            $qb->andWhere($qb->expr()->in('e.id', ':inIds'));
98
            $qb->setParameter('inIds', $in);
99
        }
100
101
        if (count($notIn)) {
102
            $qb->andWhere($qb->expr()->notIn('e.id', ':notInIds'));
103
            $qb->setParameter('notInIds', $notIn);
104
        }
105
106
        $qb->getQuery()->execute();
107
    }
108
109
    /**
110
     * @param QueryBuilder $qb
111
     * @return \Generator|mixed
112
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
113
     * @throws \Doctrine\ORM\ORMException
114
     * @throws \Doctrine\ORM\OptimisticLockException
115
     */
116
    protected function result(QueryBuilder $qb)
117
    {
118
        $resolver = new OptionsResolver();
119
        $this->configureOptions($resolver);
120
        $options = $resolver->resolve($this->options);
121
122
        // reset options
123
        $this->options = [];
124
125
        if($options['iterate']) {
126
            return $this->generator($qb, $options);
127
        } else {
128
            return $qb->getQuery()->getResult();
129
        }
130
    }
131
132
    /**
133
     * @param QueryBuilder $qb
134
     * @param array $options
135
     * @return \Generator
136
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
137
     * @throws \Doctrine\ORM\ORMException
138
     * @throws \Doctrine\ORM\OptimisticLockException
139
     */
140
    protected function generator(QueryBuilder $qb, array $options) : \Generator
141
    {
142
        $em = $this->getEntityManager();
143
144
        $result = $qb->getQuery()->iterate();
145
        $i = 1;
146
        foreach ($result as $item) {
147
            $obj = $item[0];
148
            yield $obj;
149
150
            if ($options['update']) {
151
                if (0 == $i % $options['bulkSize']) {
152
                    $em->flush();
153
                    $em->clear();
154
                }
155
            } else {
156
                $em->detach($obj);
157
            }
158
159
            ++$i;
160
        }
161
162
        if ($options['update']) {
163
            $em->flush();
164
            $em->clear();
165
        }
166
    }
167
168
    /**
169
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
170
     */
171
    public function clearAll()
172
    {
173
        $this->getEntityManager()->clear();
174
    }
175
176
    /**
177
     * @param $id
178
     *
179
     * @return bool|\Doctrine\Common\Proxy\Proxy|null|object
180
     *
181
     * @throws \Doctrine\ORM\ORMException
182
     */
183
    public function getReference($id)
184
    {
185
        return $this->getEntityManager()->getReference($this->getClassName(), $id);
186
    }
187
188
    /**
189
     * @param array $options
190
     * @return AbstractRepository
191
     */
192
    public function setOptions(array $options)
193
    {
194
        $this->options = $options;
195
        return $this;
196
    }
197
198
    /**
199
     * On 90% of the entities there is an external id so we put this helper method here
200
     * so that all these repository doesn't have to implement the same method, instead they
201
     * can call this method and just create the type hint and validation of input.
202
     *
203
     * @param $externalId
204
     *
205
     * @return null|object
206
     */
207
    protected function _findOneByExternalId($externalId)
208
    {
209
        $obj = $this->findOneBy([
210
            'externalId' => $externalId,
211
        ]);
212
213
        return $obj;
214
    }
215
216
    protected function configureOptions(OptionsResolver $resolver)
217
    {
218
        $resolver->setDefaults([
219
            'iterate' => false,
220
            'update' => false,
221
            'bulkSize' => 50,
222
        ]);
223
    }
224
}
225