DoctrineCrudRepository::getList()   F
last analyzed

Complexity

Conditions 19
Paths 13836

Size

Total Lines 67
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 19
eloc 38
c 1
b 0
f 0
nc 13836
nop 6
dl 0
loc 67
rs 0.3499

How to fix   Long Method    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 (C) 2020-2025 Iain Cambridge
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
10
 * the Free Software Foundation, either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\Athena\Repository;
23
24
use Parthenon\Athena\Entity\DeletableInterface;
25
use Parthenon\Athena\Filters\DoctrineFilterInterface;
26
use Parthenon\Athena\ResultSet;
27
use Parthenon\Common\Exception\GeneralException;
28
use Parthenon\Common\Exception\NoEntityFoundException;
29
use Parthenon\Common\Repository\DoctrineRepository;
30
31
class DoctrineCrudRepository extends DoctrineRepository implements CrudRepositoryInterface
32
{
33
    public function getList(array $filters = [], string $sortKey = 'id', string $sortType = 'ASC', int $limit = self::LIMIT, $lastId = null, $firstId = null): ResultSet
34
    {
35
        $sortKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $sortKey))));
36
37
        $qb = $this->createQueryBuilder();
38
39
        $direction = 'DESC' === $sortType ? '<' : '>';
40
        $firstDirection = 'DESC' === $sortType ? '>' : '<';
41
        if ($firstId) {
42
            $sortType = ('DESC' === $sortType) ? 'ASC' : 'DESC';
43
        }
44
45
        $sortKey = preg_replace('/[^A-Za-z0-9_]+/', '', $sortKey);
46
        $em = $this->entityRepository->getEntityManager();
47
        $columns = $em->getClassMetadata($this->entityRepository->getClassName())->getColumnNames();
48
        $columns = array_map(function ($colName) {
49
            return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $colName))));
50
        }, $columns);
51
52
        if (!in_array($sortKey, $columns)) {
53
            throw new GeneralException("Sort key doesn't exist");
54
        }
55
56
        $qb->orderBy($qb->getRootAliases()[0].'.'.$sortKey, $sortType);
57
58
        if ($limit > 0) {
59
            $qb->setMaxResults($limit + 1); // Fetch one more than required for pagination.
60
        }
61
62
        if ($lastId) {
63
            $qb->where($qb->getRootAliases()[0].'.'.$sortKey.' '.$direction.' :lastId');
64
        }
65
        if ($firstId) {
66
            $qb->where($qb->getRootAliases()[0].'.'.$sortKey.' '.$firstDirection.' :firstId');
67
        }
68
69
        if (is_a($this->entityRepository->getClassName(), DeletableInterface::class, true)) {
70
            $qb->andWhere($qb->getRootAliases()[0].'.isDeleted = false');
71
        }
72
73
        foreach ($filters as $filter) {
74
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
75
                $filter->modifyQueryBuilder($qb);
76
            }
77
        }
78
        $query = $qb->getQuery();
79
80
        foreach ($filters as $filter) {
81
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
82
                $filter->modifyQuery($query);
83
            }
84
        }
85
86
        if ($lastId) {
87
            $query->setParameter(':lastId', $lastId);
88
        }
89
        if ($firstId) {
90
            $query->setParameter(':firstId', $firstId);
91
        }
92
93
        $results = $query->getResult();
94
95
        if ($firstId) {
96
            $results = array_reverse($results);
0 ignored issues
show
Bug introduced by
It seems like $results can also be of type integer; however, parameter $array of array_reverse() 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

96
            $results = array_reverse(/** @scrutinizer ignore-type */ $results);
Loading history...
97
        }
98
99
        return new ResultSet($results, $sortKey, $sortType, $limit);
100
    }
101
102
    public function getById($id, $includeDeleted = false)
103
    {
104
        $entity = $this->entityRepository->findOneBy(['id' => $id]);
105
106
        if (!$entity || (false == $includeDeleted && is_a($this->entityRepository->getClassName(), DeletableInterface::class, true) && $entity->isDeleted())) {
107
            throw new NoEntityFoundException();
108
        }
109
110
        return $entity;
111
    }
112
113
    public function delete($entity)
114
    {
115
        if (!$entity instanceof DeletableInterface) {
116
            throw new GeneralException('Excepted deletable entity non given. Must implement '.DeletableInterface::class);
117
        }
118
        $entity->markAsDeleted();
119
        $this->save($entity);
120
    }
121
122
    public function undelete($entity)
123
    {
124
        if (!$entity instanceof DeletableInterface) {
125
            throw new GeneralException('Excepted deletable entity non given. Must implement '.DeletableInterface::class);
126
        }
127
        $entity->unmarkAsDeleted();
128
        $this->save($entity);
129
    }
130
131
    public function getByIds(array $ids): ResultSet
132
    {
133
        $qb = $this->createQueryBuilder();
134
135
        $qb->where($qb->getRootAliases()[0].'.id in (:ids)')
136
            ->setParameter('ids', $ids);
137
138
        $query = $qb->getQuery();
139
140
        return new ResultSet($query->getResult(), 'id', 'asc', count($ids));
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

140
        return new ResultSet(/** @scrutinizer ignore-type */ $query->getResult(), 'id', 'asc', count($ids));
Loading history...
141
    }
142
}
143