Passed
Branch main (b6a268)
by Iain
04:11
created

DoctrineCrudRepository::getList()   C

Complexity

Conditions 12
Paths 146

Size

Total Lines 50
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 30
c 1
b 0
f 0
nc 146
nop 5
dl 0
loc 50
rs 6.5833

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright Humbly Arrogant Ltd 2020-2022.
7
 *
8
 * Use of this software is governed by the Business Source License included in the LICENSE file and at https://getparthenon.com/docs/next/license.
9
 *
10
 * Change Date: TBD ( 3 years after 2.0.0 release )
11
 *
12
 * On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
13
 */
14
15
namespace Parthenon\Athena\Repository;
16
17
use Parthenon\Athena\Entity\DeletableInterface;
18
use Parthenon\Athena\Filters\DoctrineFilterInterface;
19
use Parthenon\Athena\ResultSet;
20
use Parthenon\Common\Exception\GeneralException;
21
use Parthenon\Common\Exception\NoEntityFoundException;
22
use Parthenon\Common\Repository\DoctrineRepository;
23
24
class DoctrineCrudRepository extends DoctrineRepository implements CrudRepositoryInterface
25
{
26
    public function getList(array $filters = [], string $sortKey = 'id', string $sortType = 'ASC', int $limit = self::LIMIT, $lastId = null): ResultSet
27
    {
28
        $sortKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $sortKey))));
29
30
        $parts = explode('\\', $this->entityRepository->getClassName());
31
        $name = end($parts);
32
        $qb = $this->entityRepository->createQueryBuilder($name);
33
34
        $direction = 'DESC' === $sortType ? '<' : '>';
35
        $sortKey = preg_replace('/[^A-Za-z0-9_]+/', '', $sortKey);
36
        $em = $this->entityRepository->getEntityManager();
37
        $columns = $em->getClassMetadata($this->entityRepository->getClassName())->getColumnNames();
38
        $columns = array_map(function ($colName) {
39
            return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $colName))));
40
        }, $columns);
41
42
        if (!in_array($sortKey, $columns)) {
43
            throw new GeneralException("Sort key doesn't exist");
44
        }
45
46
        $qb
47
            ->orderBy($qb->getRootAliases()[0].'.'.$sortKey, $sortType)
48
            ->setMaxResults($limit + 1); // Fetch one more than required for pagination.
49
50
        if ($lastId) {
51
            $qb->where($qb->getRootAliases()[0].'.'.$sortKey.' '.$direction.' :lastId');
52
        }
53
54
        if (is_a($this->entityRepository->getClassName(), DeletableInterface::class, true)) {
55
            $qb->andWhere($qb->getRootAliases()[0].'.isDeleted = false');
56
        }
57
58
        foreach ($filters as $filter) {
59
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
60
                $filter->modifyQueryBuilder($qb);
61
            }
62
        }
63
        $query = $qb->getQuery();
64
65
        foreach ($filters as $filter) {
66
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
67
                $filter->modifyQuery($query);
68
            }
69
        }
70
71
        if ($lastId) {
72
            $query->setParameter(':lastId', $lastId);
73
        }
74
75
        return new ResultSet($query->getResult(), $sortKey, $sortType, $limit);
0 ignored issues
show
Bug introduced by
It seems like $query->getResult() can also be of type integer; however, parameter $results of Parthenon\Athena\ResultSet::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        return new ResultSet(/** @scrutinizer ignore-type */ $query->getResult(), $sortKey, $sortType, $limit);
Loading history...
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function getById($id, $includeDeleted = false)
82
    {
83
        $entity = $this->entityRepository->findOneBy(['id' => $id]);
84
85
        if (!$entity || (false == $includeDeleted && is_a($this->entityRepository->getClassName(), DeletableInterface::class, true) && $entity->isDeleted())) {
86
            throw new NoEntityFoundException();
87
        }
88
89
        return $entity;
90
    }
91
92
    public function delete($entity)
93
    {
94
        if (!$entity instanceof DeletableInterface) {
95
            throw new GeneralException('Excepted deletable entity non given. Must implement '.DeletableInterface::class);
96
        }
97
        $entity->markAsDeleted();
98
        $this->save($entity);
99
    }
100
101
    public function undelete($entity)
102
    {
103
        if (!$entity instanceof DeletableInterface) {
104
            throw new GeneralException('Excepted deletable entity non given. Must implement '.DeletableInterface::class);
105
        }
106
        $entity->unmarkAsDeleted();
107
        $this->save($entity);
108
    }
109
}
110