Completed
Push — standalone ( 57bbfc...ea253f )
by Philip
03:00
created

DoctrineEntityRepositoryCrudService   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 83.87%

Importance

Changes 0
Metric Value
wmc 13
c 0
b 0
f 0
lcom 2
cbo 7
dl 0
loc 145
ccs 52
cts 62
cp 0.8387
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A findById() 0 8 2
A listPaginated() 0 8 1
A isUuid() 0 4 1
A create() 0 7 1
A update() 0 6 1
A remove() 0 5 1
A listAssociationPaginated() 0 21 1
A addToCollection() 0 13 1
A removeFromCollection() 0 13 1
A getInverseFieldName() 0 9 2
1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Service;
4
5
use Doctrine\ORM\EntityRepository;
6
use Doctrine\ORM\Mapping\ClassMetadata;
7
use Doctrine\ORM\Tools\Pagination\Paginator;
8
use Symfony\Component\PropertyAccess\PropertyAccess;
9
10
class DoctrineEntityRepositoryCrudService extends EntityRepository implements CrudServiceInterface
11
{
12 28
    public function __construct($entityManager, $entityClass)
13
    {
14 28
        parent::__construct($entityManager, $entityManager->getClassMetadata($entityClass));
15 28
    }
16
17
    /**
18
     * {@inheritdoc}
19
     */
20 22
    public function findById($id)
21
    {
22 22
        if ($this->isUuid($id)) {
23
            return $this->findOneBy(['uuid' => $id]);
24
        }
25
26 22
        return $this->find($id);
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32 6
    public function listPaginated(int $page, int $perPage = 50): Paginator
33
    {
34 6
        $queryBuilder = $this->createQueryBuilder('entity');
35 6
        $queryBuilder->setFirstResult(($page - 1) * $perPage);
36 6
        $queryBuilder->setMaxResults($perPage);
37
38 6
        return new Paginator($queryBuilder);
39
    }
40
41 22
    protected function isUuid($id)
42
    {
43 22
        return 1 === preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $id);
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    public function create($entity)
50
    {
51
        $this->getEntityManager()->persist($entity);
52
        $this->getEntityManager()->flush($entity);
53
54
        return $entity;
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 2
    public function update($entity)
61
    {
62 2
        $this->getEntityManager()->flush($entity);
63
64 2
        return $entity;
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function remove($entity)
71
    {
72
        $this->getEntityManager()->remove($entity);
73
        $this->getEntityManager()->flush($entity);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 6
    public function listAssociationPaginated($entity, string $fieldName, int $page = 1, $perPage = 50)
80
    {
81 6
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
82 6
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
83
84 6
        $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
85
86 6
        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
87 6
        $queryBuilder->select('association');
88 6
        $queryBuilder->from($targetClass, 'association');
89 6
        $queryBuilder->join('association.' . $inverseFieldName, 'entity');
90 6
        $queryBuilder->where('entity = :entity');
91 6
        $queryBuilder->setParameter('entity', $entity);
92
93 6
        $queryBuilder->setFirstResult(($page - 1) * $perPage);
94 6
        $queryBuilder->setMaxResults($perPage);
95
96 6
        $queryBuilder->getQuery();
97
98 6
        return new Paginator($queryBuilder);
99
    }
100
101
    /**
102
     * @param object     $entity
103
     * @param string     $fieldName
104
     * @param string|int $id
105
     */
106 2
    public function addToCollection($entity, string $fieldName, $id)
107
    {
108 2
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
109 2
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
110
111 2
        $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
112
113 2
        $reference = $this->getEntityManager()->getReference($targetClass, $id);
114 2
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
115 2
        $propertyAccessor->setValue($reference, $inverseFieldName, $entity);
0 ignored issues
show
Bug introduced by
It seems like $reference defined by $this->getEntityManager(...ence($targetClass, $id) on line 113 can also be of type null; however, Symfony\Component\Proper...rtyAccessor::setValue() does only seem to accept object|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
116
117 2
        $this->getEntityManager()->flush($reference);
118 2
    }
119
120
    /**
121
     * @param object     $entity
122
     * @param string     $fieldName
123
     * @param string|int $id
124
     */
125 2
    public function removeFromCollection($entity, string $fieldName, $id)
126
    {
127 2
        $classMetadata = $this->getEntityManager()->getClassMetadata(get_class($entity));
128 2
        $targetClass = $classMetadata->getAssociationTargetClass($fieldName);
129
130 2
        $inverseFieldName = $this->getInverseFieldName($fieldName, $classMetadata);
131
132 2
        $reference = $this->getEntityManager()->getReference($targetClass, $id);
133 2
        $propertyAccessor = PropertyAccess::createPropertyAccessor();
134 2
        $propertyAccessor->setValue($reference, $inverseFieldName, null);
0 ignored issues
show
Bug introduced by
It seems like $reference defined by $this->getEntityManager(...ence($targetClass, $id) on line 132 can also be of type null; however, Symfony\Component\Proper...rtyAccessor::setValue() does only seem to accept object|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
135
136 2
        $this->getEntityManager()->flush($reference);
137 2
    }
138
139
    /**
140
     * @param string        $fieldName
141
     * @param ClassMetadata $classMetadata
142
     *
143
     * @return string
144
     */
145 6
    public function getInverseFieldName(string $fieldName, ClassMetadata $classMetadata)
146
    {
147 6
        $association = $classMetadata->getAssociationMapping($fieldName);
148 6
        if ($classMetadata->isAssociationInverseSide($fieldName)) {
149 6
            return $association['mappedBy'];
150
        } else {
151
            return $association['inversedBy'];
152
        }
153
    }
154
}
155