Passed
Push — main ( 5e0116...8ff6e1 )
by Iain
17:24
created

DoctrineCrudRepository::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright Iain Cambridge 2020-2023.
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.2.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, $firstId = null): ResultSet
27
    {
28
        $sortKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $sortKey))));
29
30
        $qb = $this->createQueryBuilder();
31
32
        $direction = 'DESC' === $sortType ? '<' : '>';
33
        $firstDirection = 'DESC' === $sortType ? '>' : '<';
34
        if ($firstId) {
35
            $sortType = ('DESC' === $sortType) ? 'ASC' : 'DESC';
36
        }
37
38
        $sortKey = preg_replace('/[^A-Za-z0-9_]+/', '', $sortKey);
39
        $em = $this->entityRepository->getEntityManager();
40
        $columns = $em->getClassMetadata($this->entityRepository->getClassName())->getColumnNames();
41
        $columns = array_map(function ($colName) {
42
            return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $colName))));
43
        }, $columns);
44
45
        if (!in_array($sortKey, $columns)) {
46
            throw new GeneralException("Sort key doesn't exist");
47
        }
48
49
        $qb->orderBy($qb->getRootAliases()[0].'.'.$sortKey, $sortType);
50
51
        if ($limit > 0) {
52
            $qb->setMaxResults($limit + 1); // Fetch one more than required for pagination.
53
        }
54
55
        if ($lastId) {
56
            $qb->where($qb->getRootAliases()[0].'.'.$sortKey.' '.$direction.' :lastId');
57
        }
58
        if ($firstId) {
59
            $qb->where($qb->getRootAliases()[0].'.'.$sortKey.' '.$firstDirection.' :firstId');
60
        }
61
62
        if (is_a($this->entityRepository->getClassName(), DeletableInterface::class, true)) {
63
            $qb->andWhere($qb->getRootAliases()[0].'.isDeleted = false');
64
        }
65
66
        foreach ($filters as $filter) {
67
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
68
                $filter->modifyQueryBuilder($qb);
69
            }
70
        }
71
        $query = $qb->getQuery();
72
73
        foreach ($filters as $filter) {
74
            if ($filter instanceof DoctrineFilterInterface && $filter->hasData()) {
75
                $filter->modifyQuery($query);
76
            }
77
        }
78
79
        if ($lastId) {
80
            $query->setParameter(':lastId', $lastId);
81
        }
82
        if ($firstId) {
83
            $query->setParameter(':firstId', $firstId);
84
        }
85
86
        $results = $query->getResult();
87
88
        if ($firstId) {
89
            $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

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

136
        return new ResultSet(/** @scrutinizer ignore-type */ $query->getResult(), 'id', 'asc', count($ids));
Loading history...
137
    }
138
}
139