GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#197)
by joseph
19:59
created

AbstractEntityRepository::getEntityFqn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 10
ccs 0
cts 10
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories;
4
5
use Doctrine\Common\Collections\Criteria;
6
use Doctrine\DBAL\Types\ConversionException;
7
use Doctrine\ORM\EntityManagerInterface;
8
use Doctrine\ORM\EntityRepository;
9
use Doctrine\ORM\LazyCriteriaCollection;
10
use Doctrine\ORM\Mapping\ClassMetadata;
11
use Doctrine\ORM\NativeQuery;
12
use Doctrine\ORM\Query;
13
use Doctrine\ORM\QueryBuilder;
14
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
15
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factory\EntityFactoryInterface;
16
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
17
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
18
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
19
use Ramsey\Uuid\UuidInterface;
20
21
/**
22
 * Class AbstractEntityRepository
23
 *
24
 * This provides a base class that handles instantiating the correctly configured EntityRepository and provides an
25
 * extensible baseline for further customisation
26
 *
27
 * We have extracted an interface from the standard Doctrine EntityRepository and implemented that
28
 * However, so we can add type safety, we can't "actually" implement it
29
 *
30
 * We have also deliberately left out the magic calls. Please make real methods in your concrete repository class
31
 *
32
 * Note, there are quite a few PHPMD warnings, however it needs to respect the legacy interface so they are being
33
 * suppressed
34
 *
35
 * @package EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories
36
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
37
 * @SuppressWarnings(PHPMD.ExcessivePublicCount)
38
 * @SuppressWarnings(PHPMD.NumberOfChildren)
39
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
40
 */
41
abstract class AbstractEntityRepository implements EntityRepositoryInterface
42
{
43
    /**
44
     * @var EntityManagerInterface
45
     */
46
    protected $entityManager;
47
    /**
48
     * @var EntityRepository
49
     */
50
    protected $entityRepository;
51
    /**
52
     * @var string
53
     */
54
    protected $repositoryFactoryFqn;
55
    /**
56
     * @var ClassMetadata|null
57
     */
58
    protected $metaData;
59
    /**
60
     * @var NamespaceHelper
61
     */
62
    protected $namespaceHelper;
63
    /**
64
     * @var EntityFactoryInterface
65
     */
66
    private $entityFactory;
67
68
    /**
69
     * AbstractEntityRepositoryFactory constructor.
70
     *
71
     * @param EntityManagerInterface $entityManager
72
     * @param EntityFactoryInterface $entityFactory
73
     * @param NamespaceHelper|null   $namespaceHelper
74
     */
75
    public function __construct(
76
        EntityManagerInterface $entityManager,
77
        EntityFactoryInterface $entityFactory,
78
        NamespaceHelper $namespaceHelper
79
    ) {
80
        $this->entityManager   = $entityManager;
81
        $this->namespaceHelper = $namespaceHelper;
82
        $this->entityFactory   = $entityFactory;
83
        $this->initRepository();
84
    }
85
86
    protected function initRepository(): void
87
    {
88
        if (null === $this->metaData) {
89
            $entityFqn      = $this->getEntityFqn();
90
            $this->metaData = $this->entityManager->getClassMetadata($entityFqn);
91
        }
92
93
        $this->entityRepository = new EntityRepository($this->entityManager, $this->metaData);
94
    }
95
96
    protected function getEntityFqn(): string
97
    {
98
        return '\\' . \str_replace(
99
            [
100
                    'Entity\\Repositories',
101
                ],
102
            [
103
                    'Entities',
104
                ],
105
            $this->namespaceHelper->cropSuffix(static::class, 'Repository')
106
        );
107
    }
108
109
    public function getRandomResultFromQueryBuilder(QueryBuilder $queryBuilder, string $entityAlias): ?EntityInterface
110
    {
111
        $count = $this->getCountForQueryBuilder($queryBuilder, $entityAlias);
112
        if (0 === $count) {
113
            return null;
114
        }
115
116
        $queryBuilder->setMaxResults(1);
117
        $limitIndex = random_int(0, $count - 1);
118
        $results    = $queryBuilder->getQuery()
119
                                   ->setFirstResult($limitIndex)
120
                                   ->execute();
121
        $entity     = current($results);
122
        if (null === $entity) {
123
            return null;
124
        }
125
        $this->initialiseEntity($entity);
126
127
        return $entity;
128
    }
129
130
    public function getCountForQueryBuilder(QueryBuilder $queryBuilder, string $aliasToCount): int
131
    {
132
        $clone = clone $queryBuilder;
133
        $clone->select($queryBuilder->expr()->count($aliasToCount));
134
135
        return (int)$clone->getQuery()->getSingleScalarResult();
136
    }
137
138
    public function initialiseEntity(EntityInterface $entity)
139
    {
140
        $this->entityFactory->initialiseEntity($entity);
141
142
        return $entity;
143
    }
144
145
    /**
146
     * @return array|EntityInterface[]
147
     */
148
    public function findAll(): array
149
    {
150
        return $this->initialiseEntities($this->entityRepository->findAll());
151
    }
152
153
    public function initialiseEntities($entities)
154
    {
155
        foreach ($entities as $entity) {
156
            $this->initialiseEntity($entity);
157
        }
158
159
        return $entities;
160
    }
161
162
    /**
163
     * @param mixed    $id
164
     * @param int|null $lockMode
165
     * @param int|null $lockVersion
166
     *
167
     * @return EntityInterface
168
     * @throws DoctrineStaticMetaException
169
     */
170
    public function get($id, ?int $lockMode = null, ?int $lockVersion = null)
171
    {
172
        try {
173
            $entity = $this->find($id, $lockMode, $lockVersion);
174
        } catch (ConversionException $e) {
175
            $error = 'Failed getting by id ' . $id
176
                     . ', unless configured as an int ID entity, this should be a valid UUID';
177
            throw new DoctrineStaticMetaException($error, $e->getCode(), $e);
178
        }
179
        if ($entity === null) {
180
            throw new DoctrineStaticMetaException('Could not find the entity with id ' . $id);
181
        }
182
183
        return $this->initialiseEntity($entity);
184
    }
185
186
    /**
187
     * @param mixed    $id
188
     * @param int|null $lockMode
189
     * @param int|null $lockVersion
190
     *
191
     * @return EntityInterface|null
192
     */
193
    public function find($id, ?int $lockMode = null, ?int $lockVersion = null)
194
    {
195
        $entity = $this->entityRepository->find($id, $lockMode, $lockVersion);
196
        if (null === $entity) {
197
            return null;
198
        }
199
        if ($entity instanceof EntityInterface) {
200
            $this->initialiseEntity($entity);
201
202
            return $entity;
203
        }
204
    }
205
206
    /**
207
     * @param array      $criteria
208
     * @param array|null $orderBy
209
     *
210
     * @return EntityInterface
211
     */
212
    public function getOneBy(array $criteria, ?array $orderBy = null)
213
    {
214
        $result = $this->findOneBy($criteria, $orderBy);
215
        if ($result === null) {
216
            throw new \RuntimeException('Could not find the entity');
217
        }
218
219
        return $this->initialiseEntity($result);
220
    }
221
222
    public function mapCriteriaSetUuidsToStrings(array $criteria): array
223
    {
224
        foreach ($criteria as $property => $value) {
225
            if ($value instanceof EntityInterface) {
226
                $criteria[$property] = $value->getId();
227
            }
228
            if ($value instanceof UuidInterface) {
229
                $criteria[$property] = $value->toString();
230
            }
231
        }
232
233
        return $criteria;
234
    }
235
236
    /**
237
     * @param array      $criteria
238
     * @param array|null $orderBy
239
     *
240
     * @return EntityInterface|null
241
     */
242
    public function findOneBy(array $criteria, ?array $orderBy = null)
243
    {
244
        $criteria = $this->mapCriteriaSetUuidsToStrings($criteria);
245
        $entity   = $this->entityRepository->findOneBy($criteria, $orderBy);
246
        if (null === $entity) {
247
            return null;
248
        }
249
        if ($entity instanceof EntityInterface) {
250
            $this->initialiseEntity($entity);
251
252
            return $entity;
253
        }
254
    }
255
256
    /**
257
     * @param array $criteria
258
     *
259
     * @return EntityInterface|null
260
     */
261
    public function getRandomOneBy(array $criteria)
262
    {
263
        $found = $this->getRandomBy($criteria, 1);
264
        if ([] === $found) {
265
            throw new \RuntimeException('Failed finding any Entities with this criteria');
266
        }
267
        $entity = current($found);
268
        if ($entity instanceof EntityInterface) {
269
            return $entity;
270
        }
271
        throw new \RuntimeException('Unexpected Entity Type ' . get_class($entity));
272
    }
273
274
    /**
275
     * @param array $criteria
276
     *
277
     * @param int   $numToGet
278
     *
279
     * @return EntityInterface[]|array
280
     */
281
    public function getRandomBy(array $criteria, int $numToGet = 1): array
282
    {
283
        $count = $this->count($criteria);
284
        if (0 === $count) {
285
            return [];
286
        }
287
        $randOffset = rand(0, $count - $numToGet);
288
289
        return $this->findBy($criteria, null, $numToGet, $randOffset);
290
    }
291
292
    public function count(array $criteria = []): int
293
    {
294
        $criteria = $this->mapCriteriaSetUuidsToStrings($criteria);
295
296
        return $this->entityRepository->count($criteria);
297
    }
298
299
    /**
300
     * @return array|EntityInterface[]
301
     */
302
    public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
303
    {
304
        $criteria = $this->mapCriteriaSetUuidsToStrings($criteria);
305
306
        return $this->initialiseEntities($this->entityRepository->findBy($criteria, $orderBy, $limit, $offset));
307
    }
308
309
    public function matching(Criteria $criteria): LazyCriteriaCollection
310
    {
311
        $collection = $this->entityRepository->matching($criteria);
312
        if ($collection instanceof LazyCriteriaCollection) {
0 ignored issues
show
introduced by
$collection is always a sub-type of Doctrine\ORM\LazyCriteriaCollection.
Loading history...
313
            return $this->initialiseEntities($collection);
314
        }
0 ignored issues
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 312 is false. This is incompatible with the type-hinted return Doctrine\ORM\LazyCriteriaCollection. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
315
    }
316
317
    public function createQueryBuilder(string $alias, string $indexBy = null): QueryBuilder
318
    {
319
        #return $this->entityRepository->createQueryBuilder($alias, $indexBy);
320
        return (new UuidQueryBuilder($this->entityManager))
321
            ->select($alias)
322
            ->from($this->getClassName(), $alias, $indexBy);
323
    }
324
325
    public function getClassName(): string
326
    {
327
        return $this->entityRepository->getClassName();
328
    }
329
330
    public function createResultSetMappingBuilder(string $alias): Query\ResultSetMappingBuilder
331
    {
332
        return $this->entityRepository->createResultSetMappingBuilder($alias);
333
    }
334
335
    public function createNamedQuery(string $queryName): Query
336
    {
337
        return $this->entityRepository->createNamedQuery($queryName);
338
    }
339
340
    public function createNativeNamedQuery(string $queryName): NativeQuery
341
    {
342
        return $this->entityRepository->createNativeNamedQuery($queryName);
343
    }
344
345
    public function clear(): void
346
    {
347
        $this->entityRepository->clear();
348
    }
349
}
350