Completed
Push — feature/profile-retrieve-impli... ( 3a9ede )
by Michiel
06:40 queued 18s
created

RaListingRepository::getExplicitInstitutionsFor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
/**
4
 * Copyright 2014 SURFnet bv
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace Surfnet\StepupMiddleware\ApiBundle\Identity\Repository;
20
21
use Doctrine\Common\Collections\ArrayCollection;
22
use Doctrine\ORM\EntityManager;
23
use Doctrine\ORM\EntityRepository;
24
use Doctrine\ORM\Mapping;
25
use Surfnet\Stepup\Identity\Collection\InstitutionCollection;
26
use Surfnet\Stepup\Identity\Value\IdentityId;
27
use Surfnet\Stepup\Identity\Value\Institution;
28
use Surfnet\StepupMiddleware\ApiBundle\Authorization\Filter\InstitutionAuthorizationRepositoryFilter;
29
use Surfnet\StepupMiddleware\ApiBundle\Authorization\Value\InstitutionAuthorizationContextInterface;
30
use Surfnet\StepupMiddleware\ApiBundle\Exception\RuntimeException;
31
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaListing;
32
use Surfnet\StepupMiddleware\ApiBundle\Identity\Query\RaListingQuery;
33
use Webmozart\Assert\Assert;
34
35
/**
36
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
37
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
38
 */
39
class RaListingRepository extends EntityRepository
40
{
41
    /**
42
     * @var InstitutionAuthorizationRepositoryFilter
43
     */
44
    private $authorizationRepositoryFilter;
45
46
    public function __construct(
47
        EntityManager $em,
48
        Mapping\ClassMetadata $class,
49
        InstitutionAuthorizationRepositoryFilter $authorizationRepositoryFilter
50
    ) {
51
        parent::__construct($em, $class);
52
        $this->authorizationRepositoryFilter = $authorizationRepositoryFilter;
53
    }
54
55
    /**
56
     * @param IdentityId $identityId The RA's identity id.
57
     * @return null|RaListing[]
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
58
     */
59
    public function findByIdentityId(IdentityId $identityId)
60
    {
61
        return parent::findBy(['identityId' => (string) $identityId]);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (findBy() instead of findByIdentityId()). Are you sure this is correct? If so, you might want to change this to $this->findBy().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
62
    }
63
64
    /**
65
     * @param IdentityId $identityId The RA's identity id.
66
     * @param Institution $raInstitution
67
     * @return null|RaListing
0 ignored issues
show
Documentation introduced by
Should the return type not be object|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
68
     */
69
    public function findByIdentityIdAndRaInstitution(IdentityId $identityId, Institution $raInstitution)
70
    {
71
        return parent::findOneBy([
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (findOneBy() instead of findByIdentityIdAndRaInstitution()). Are you sure this is correct? If so, you might want to change this to $this->findOneBy().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
72
            'identityId' => (string) $identityId,
73
            'raInstitution' => (string) $raInstitution,
74
        ]);
75
    }
76
77
78
    /**
79
     * @param IdentityId $identityId The RA's identity id.
80
     * @param Institution $raInstitution
81
     * @param InstitutionAuthorizationContextInterface $authorizationContext
82
     * @return null|RaListing
83
     */
84
    public function findByIdentityIdAndRaInstitutionWithContext(
85
        IdentityId $identityId,
86
        Institution $raInstitution,
87
        InstitutionAuthorizationContextInterface $authorizationContext
88
    ) {
89
        $queryBuilder = $this->createQueryBuilder('r')
90
            ->where('r.identityId = :identityId')
91
            ->andWhere('r.raInstitution = :raInstitution')
92
            ->setParameter('identityId', $identityId)
93
            ->setParameter('raInstitution', (string)$raInstitution)
94
            ->orderBy('r.raInstitution');
95
96
        // Modify query to filter on authorization
97
        $this->authorizationRepositoryFilter->filter(
98
            $queryBuilder,
99
            $authorizationContext,
100
            'r.raInstitution',
101
            'iac'
102
        );
103
104
        return $queryBuilder->getQuery()->getOneOrNullResult();
105
    }
106
107
    /**
108
     * @param IdentityId $identityId The RA's identity id.
109
     * @param Institution $institution
110
     * @return RaListing[]
111
     */
112
    public function findByIdentityIdAndInstitution(IdentityId $identityId, Institution $institution)
113
    {
114
        return parent::findBy([
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (findBy() instead of findByIdentityIdAndInstitution()). Are you sure this is correct? If so, you might want to change this to $this->findBy().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
115
            'identityId' => (string) $identityId,
116
            'institution' => (string) $institution,
117
        ]);
118
    }
119
120
    public function save(RaListing $raListingEntry)
121
    {
122
        $this->getEntityManager()->persist($raListingEntry);
123
        $this->getEntityManager()->flush();
124
    }
125
126
    /**
127
     * @SuppressWarnings(PHPMD.CyclomaticComplexity) The amount of if statements do not necessarily make the method
128
     * @SuppressWarnings(PHPMD.NPathComplexity)      below complex or hard to maintain.
129
     *
130
     * @param RaListingQuery $query
131
     * @return \Doctrine\ORM\Query
132
     */
133
    public function createSearchQuery(RaListingQuery $query)
134
    {
135
        $queryBuilder = $this->createQueryBuilder('r');
136
137
        // Modify query to filter on authorization
138
        $this->authorizationRepositoryFilter->filter(
139
            $queryBuilder,
140
            $query->authorizationContext,
141
            'r.raInstitution',
142
            'iac'
143
        );
144
145
        if ($query->institution) {
146
            $queryBuilder
147
                ->andWhere('r.institution = :institution')
148
                ->setParameter('institution', $query->institution);
149
        }
150
151
        if ($query->identityId) {
152
            $queryBuilder
153
                ->andWhere('r.identityId = :identityId')
154
                ->setParameter('identityId', (string) $query->identityId);
155
        }
156
157
        if ($query->name) {
158
            $queryBuilder
159
                ->andWhere('r.commonName LIKE :name')
160
                ->setParameter('name', sprintf('%%%s%%', $query->name));
161
        }
162
163
        if ($query->email) {
164
            $queryBuilder
165
                ->andWhere('r.email LIKE :email')
166
                ->setParameter('email', sprintf('%%%s%%', $query->email));
167
        }
168
169
        if ($query->role) {
170
            $queryBuilder
171
                ->andWhere('r.role = :role')
172
                ->setParameter('role', (string) $query->role);
173
        }
174
175
        if ($query->raInstitution) {
176
            $queryBuilder
177
                ->andWhere('r.raInstitution = :raInstitution')
178
                ->setParameter('raInstitution', (string) $query->raInstitution);
179
        }
180
181
        if (!$query->orderBy) {
182
            return $queryBuilder->getQuery();
183
        }
184
185
        $orderDirection = $query->orderDirection === 'asc' ? 'ASC' : 'DESC';
186
187
        switch ($query->orderBy) {
188
            case 'commonName':
189
                $queryBuilder->orderBy('r.commonName', $orderDirection);
190
                break;
191
            default:
192
                throw new RuntimeException(sprintf('Unknown order by column "%s"', $query->orderBy));
193
        }
194
195
        return $queryBuilder->getQuery();
196
    }
197
198
    /**
199
     * @param Institution $raInstitution
200
     * @return ArrayCollection
201
     */
202
    public function listRasFor(Institution $raInstitution)
203
    {
204
        $listings = $this->createQueryBuilder('rl')
205
            ->where('rl.raInstitution = :institution')
206
            ->setParameter('institution', $raInstitution)
207
            ->getQuery()
208
            ->getResult();
209
210
        return new ArrayCollection($listings);
211
    }
212
213
    /**
214
     * @param IdentityId $identityId
215
     * @return void
216
     */
217 View Code Duplication
    public function removeByIdentityId(IdentityId $identityId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
    {
219
        $this->getEntityManager()->createQueryBuilder()
220
            ->delete($this->_entityName, 'ral')
221
            ->where('ral.identityId = :identityId')
222
            ->andWhere('ral.raInstitution = :institution')
223
            ->setParameter('identityId', $identityId->getIdentityId())
224
            ->getQuery()
225
            ->execute();
226
    }
227
228
    /**
229
     * @param IdentityId $identityId
230
     * @param Institution $raInstitution
231
     * @return void
232
     */
233 View Code Duplication
    public function removeByIdentityIdAndRaInstitution(IdentityId $identityId, Institution $raInstitution)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
    {
235
        $this->getEntityManager()->createQueryBuilder()
236
            ->delete($this->_entityName, 'ral')
237
            ->where('ral.identityId = :identityId')
238
            ->andWhere('ral.raInstitution = :institution')
239
            ->setParameter('identityId', $identityId->getIdentityId())
240
            ->setParameter('institution', $raInstitution)
241
            ->getQuery()
242
            ->execute();
243
    }
244
245
    /**
246
     * @param IdentityId $identityId
247
     * @param Institution $institution
248
     * @return void
249
     */
250 View Code Duplication
    public function removeByIdentityIdAndInstitution(IdentityId $identityId, Institution $institution)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252
        $this->getEntityManager()->createQueryBuilder()
253
            ->delete($this->_entityName, 'ral')
254
            ->where('ral.identityId = :identityId')
255
            ->andWhere('ral.institution = :institution')
256
            ->setParameter('identityId', $identityId->getIdentityId())
257
            ->setParameter('institution', $institution)
258
            ->getQuery()
259
            ->execute();
260
    }
261
262
    /**
263
     * Select the explicitly appointed institutions by identity id and role
264
     *
265
     * These are the institutions where the given identity fulfils the specified role as
266
     * he/she is listed as a ra(a) there.
267
     *
268
     * @param IdentityId $actorId
269
     * @param string $role
270
     * @return InstitutionCollection
271
     */
272
    public function getExplicitInstitutionsFor(IdentityId $actorId, $role)
273
    {
274
        Assert::stringNotEmpty($role, 'Role must have a string value');
275
        Assert::oneOf($role, ['ra', 'raa'], 'Role must either be ra or raa');
276
277
        $qb = $this->createQueryBuilder('r')
278
            ->select("r.institution")
279
            ->where("r.identityId = :identityId")
280
            ->andWhere("r.role = :role")
281
            ->groupBy("r.institution");
282
283
        $qb->setParameter('identityId', (string)$actorId);
284
        $qb->setParameter('role', $role);
285
286
        $institutions = $qb->getQuery()->getArrayResult();
287
288
        $result = new InstitutionCollection();
289
        foreach ($institutions as $institution) {
290
            $result->add(new Institution((string)$institution['institution']));
291
        }
292
293
        return $result;
294
    }
295
}
296