Completed
Pull Request — develop (#232)
by Michiel
05:06 queued 02:35
created

InstitutionConfiguration   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 450
Duplicated Lines 5.33 %

Coupling/Cohesion

Components 1
Dependencies 30

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 30
dl 24
loc 450
rs 8.8798
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 24 1
A rebuild() 0 28 2
A __construct() 0 3 1
A configureUseRaLocationsOption() 0 14 2
A configureShowRaaContactInformationOption() 0 14 2
A configureVerifyEmailOption() 0 14 2
A configureNumberOfTokensPerIdentityOption() 0 15 2
A configureUseRaOption() 0 14 2
A configureUseRaaOption() 0 14 2
A configureSelectRaaOption() 0 14 2
A updateAllowedSecondFactorList() 0 17 3
A addRaLocation() 8 24 2
A changeRaLocation() 8 37 5
A removeRaLocation() 8 13 2
A destroy() 0 4 1
A getAggregateRootId() 0 4 1
A applyNewInstitutionConfigurationCreatedEvent() 0 11 1
A applyUseRaLocationsOptionChangedEvent() 0 4 1
A applyShowRaaContactInformationOptionChangedEvent() 0 5 1
A applyVerifyEmailOptionChangedEvent() 0 5 1
A applyNumberOfTokensPerIdentityOptionChangedEvent() 0 5 1
A applyAllowedSecondFactorListUpdatedEvent() 0 4 1
A applyRaLocationAddedEvent() 0 11 1
A applyRaLocationRenamedEvent() 0 5 1
A applyRaLocationRelocatedEvent() 0 5 1
A applyRaLocationContactInformationChangedEvent() 0 5 1
A applyRaLocationRemovedEvent() 0 4 1
A applyInstitutionConfigurationRemovedEvent() 0 12 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like InstitutionConfiguration often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use InstitutionConfiguration, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Copyright 2016 SURFnet B.V.
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\Stepup\Configuration;
20
21
use Broadway\EventSourcing\EventSourcedAggregateRoot;
22
use Surfnet\Stepup\Configuration\Api\InstitutionConfiguration as InstitutionConfigurationInterface;
23
use Surfnet\Stepup\Configuration\Entity\RaLocation;
24
use Surfnet\Stepup\Configuration\Event\AllowedSecondFactorListUpdatedEvent;
25
use Surfnet\Stepup\Configuration\Event\InstitutionConfigurationRemovedEvent;
26
use Surfnet\Stepup\Configuration\Event\NewInstitutionConfigurationCreatedEvent;
27
use Surfnet\Stepup\Configuration\Event\NumberOfTokensPerIdentityOptionChangedEvent;
28
use Surfnet\Stepup\Configuration\Event\RaLocationAddedEvent;
29
use Surfnet\Stepup\Configuration\Event\RaLocationContactInformationChangedEvent;
30
use Surfnet\Stepup\Configuration\Event\RaLocationRelocatedEvent;
31
use Surfnet\Stepup\Configuration\Event\RaLocationRemovedEvent;
32
use Surfnet\Stepup\Configuration\Event\RaLocationRenamedEvent;
33
use Surfnet\Stepup\Configuration\Event\SelectRaaOptionChangedEvent;
34
use Surfnet\Stepup\Configuration\Event\ShowRaaContactInformationOptionChangedEvent;
35
use Surfnet\Stepup\Configuration\Event\UseRaaOptionChangedEvent;
36
use Surfnet\Stepup\Configuration\Event\UseRaLocationsOptionChangedEvent;
37
use Surfnet\Stepup\Configuration\Event\UseRaOptionChangedEvent;
38
use Surfnet\Stepup\Configuration\Event\VerifyEmailOptionChangedEvent;
39
use Surfnet\Stepup\Configuration\Value\AllowedSecondFactorList;
40
use Surfnet\Stepup\Configuration\Value\ContactInformation;
41
use Surfnet\Stepup\Configuration\Value\Institution;
42
use Surfnet\Stepup\Configuration\Value\InstitutionConfigurationId;
43
use Surfnet\Stepup\Configuration\Value\Location;
44
use Surfnet\Stepup\Configuration\Value\NumberOfTokensPerIdentityOption;
45
use Surfnet\Stepup\Configuration\Value\RaLocationId;
46
use Surfnet\Stepup\Configuration\Value\RaLocationList;
47
use Surfnet\Stepup\Configuration\Value\RaLocationName;
48
use Surfnet\Stepup\Configuration\Value\SelectRaaOption;
49
use Surfnet\Stepup\Configuration\Value\ShowRaaContactInformationOption;
50
use Surfnet\Stepup\Configuration\Value\UseRaaOption;
51
use Surfnet\Stepup\Configuration\Value\UseRaLocationsOption;
52
use Surfnet\Stepup\Configuration\Value\UseRaOption;
53
use Surfnet\Stepup\Configuration\Value\VerifyEmailOption;
54
use Surfnet\Stepup\Exception\DomainException;
55
56
/**
57
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Events and value objects
58
 * @SuppressWarnings(PHPMD.TooManyMethods) AggregateRoot
59
 * @SuppressWarnings(PHPMD.TooManyPublicMethods) AggregateRoot
60
 */
61
class InstitutionConfiguration extends EventSourcedAggregateRoot implements InstitutionConfigurationInterface
62
{
63
    /**
64
     * @var InstitutionConfigurationId
65
     */
66
    private $institutionConfigurationId;
67
68
    /**
69
     * @var Institution
70
     */
71
    private $institution;
72
73
    /**
74
     * @var RaLocationList
75
     */
76
    private $raLocations;
77
78
    /**
79
     * @var UseRaLocationsOption
80
     */
81
    private $useRaLocationsOption;
82
83
    /**
84
     * @var ShowRaaContactInformationOption
85
     */
86
    private $showRaaContactInformationOption;
87
88
    /**
89
     * @var VerifyEmailOption
90
     */
91
    private $verifyEmailOption;
92
93
    /**
94
     * @var NumberOfTokensPerIdentityOption
95
     */
96
    private $numberOfTokensPerIdentityOption;
97
98
    /**
99
     * @var UseRaOption
100
     */
101
    private $useRaOption;
102
103
    /**
104
     * @var UseRaaOption
105
     */
106
107
    private $useRaaOption;
108
109
    /**
110
     * @var SelectRaaOption
111
     */
112
    private $selectRaaOption;
113
114
    /**
115
     * @var AllowedSecondFactorList
116
     */
117
    private $allowedSecondFactorList;
118
119
    /**
120
     * @var boolean
121
     */
122
    private $isMarkedAsDestroyed;
123
124
    /**
125
     * @param InstitutionConfigurationId $institutionConfigurationId
126
     * @param Institution $institution
127
     * @return InstitutionConfiguration
128
     */
129
    public static function create(InstitutionConfigurationId $institutionConfigurationId, Institution $institution)
130
    {
131
        $institutionConfiguration = new self;
132
        $institutionConfiguration->apply(
133
            new NewInstitutionConfigurationCreatedEvent(
134
                $institutionConfigurationId,
135
                $institution,
136
                UseRaLocationsOption::getDefault(),
137
                ShowRaaContactInformationOption::getDefault(),
138
                VerifyEmailOption::getDefault(),
139
                NumberOfTokensPerIdentityOption::getDefault(),
140
                UseRaOption::getDefault(),
141
                UseRaaOption::getDefault(),
142
                SelectRaaOption::getDefault()
143
            )
144
        );
145
        $institutionConfiguration->apply(new AllowedSecondFactorListUpdatedEvent(
146
            $institutionConfigurationId,
147
            $institution,
148
            AllowedSecondFactorList::blank()
149
        ));
150
151
        return $institutionConfiguration;
152
    }
153
154
    /**
155
     * @return InstitutionConfiguration
156
     */
157
    public function rebuild()
158
    {
159
        // We can only rebuild a destroyed InstitutionConfiguration, all other cases are not valid
160
        if ($this->isMarkedAsDestroyed !== true) {
161
            throw new DomainException('Cannot rebuild InstitutionConfiguration as it has not been destroyed');
162
        }
163
164
        $this->apply(
165
            new NewInstitutionConfigurationCreatedEvent(
166
                $this->institutionConfigurationId,
167
                $this->institution,
168
                UseRaLocationsOption::getDefault(),
169
                ShowRaaContactInformationOption::getDefault(),
170
                VerifyEmailOption::getDefault(),
171
                NumberOfTokensPerIdentityOption::getDefault(),
172
                UseRaOption::getDefault(),
173
                UseRaaOption::getDefault(),
174
                SelectRaaOption::getDefault()
175
            )
176
        );
177
        $this->apply(new AllowedSecondFactorListUpdatedEvent(
178
            $this->institutionConfigurationId,
179
            $this->institution,
180
            AllowedSecondFactorList::blank()
181
        ));
182
183
        return $this;
184
    }
185
186
    final public function __construct()
187
    {
188
    }
189
190
    public function configureUseRaLocationsOption(UseRaLocationsOption $useRaLocationsOption)
191
    {
192
        if ($this->useRaLocationsOption->equals($useRaLocationsOption)) {
193
            return;
194
        }
195
196
        $this->apply(
197
            new UseRaLocationsOptionChangedEvent(
198
                $this->institutionConfigurationId,
199
                $this->institution,
200
                $useRaLocationsOption
201
            )
202
        );
203
    }
204
205
    public function configureShowRaaContactInformationOption(ShowRaaContactInformationOption $showRaaContactInformationOption)
206
    {
207
        if ($this->showRaaContactInformationOption->equals($showRaaContactInformationOption)) {
208
            return;
209
        }
210
211
        $this->apply(
212
            new ShowRaaContactInformationOptionChangedEvent(
213
                $this->institutionConfigurationId,
214
                $this->institution,
215
                $showRaaContactInformationOption
216
            )
217
        );
218
    }
219
220
    public function configureVerifyEmailOption(VerifyEmailOption $verifyEmailOption)
221
    {
222
        if ($this->verifyEmailOption->equals($verifyEmailOption)) {
223
            return;
224
        }
225
226
        $this->apply(
227
            new VerifyEmailOptionChangedEvent(
228
                $this->institutionConfigurationId,
229
                $this->institution,
230
                $verifyEmailOption
231
            )
232
        );
233
    }
234
235
    public function configureNumberOfTokensPerIdentityOption(
236
        NumberOfTokensPerIdentityOption $numberOfTokensPerIdentityOption
237
    ) {
238
        if ($this->numberOfTokensPerIdentityOption->equals($numberOfTokensPerIdentityOption)) {
239
            return;
240
        }
241
242
        $this->apply(
243
            new NumberOfTokensPerIdentityOptionChangedEvent(
244
                $this->institutionConfigurationId,
245
                $this->institution,
246
                $numberOfTokensPerIdentityOption
247
            )
248
        );
249
    }
250
251
    public function configureUseRaOption(UseRaOption $useRaOption)
252
    {
253
        if ($this->useRaOption->equals($useRaOption)) {
254
            return;
255
        }
256
257
        $this->apply(
258
            new UseRaOptionChangedEvent(
259
                $this->institutionConfigurationId,
260
                $this->institution,
261
                $useRaOption
262
            )
263
        );
264
    }
265
266
    public function configureUseRaaOption(UseRaaOption $useRaaOption)
267
    {
268
        if ($this->useRaaOption->equals($useRaaOption)) {
269
            return;
270
        }
271
272
        $this->apply(
273
            new UseRaaOptionChangedEvent(
274
                $this->institutionConfigurationId,
275
                $this->institution,
276
                $useRaaOption
277
            )
278
        );
279
    }
280
281
    public function configureSelectRaaOption(SelectRaaOption $selectRaaOption)
282
    {
283
        if ($this->selectRaaOption->equals($selectRaaOption)) {
284
            return;
285
        }
286
287
        $this->apply(
288
            new SelectRaaOptionChangedEvent(
289
                $this->institutionConfigurationId,
290
                $this->institution,
291
                $selectRaaOption
292
            )
293
        );
294
    }
295
296
    public function updateAllowedSecondFactorList(AllowedSecondFactorList $allowedSecondFactorList)
297
    {
298
        // AllowedSecondFactorList can be null for InstitutionConfigurations for which this functionality did not exist
299
        if ($this->allowedSecondFactorList !== null
300
            && $this->allowedSecondFactorList->equals($allowedSecondFactorList)
301
        ) {
302
            return;
303
        }
304
305
        $this->apply(
306
            new AllowedSecondFactorListUpdatedEvent(
307
                $this->institutionConfigurationId,
308
                $this->institution,
309
                $allowedSecondFactorList
310
            )
311
        );
312
    }
313
314
    /**
315
     * @param RaLocationId $raLocationId
316
     * @param RaLocationName $raLocationName
317
     * @param Location $location
318
     * @param ContactInformation $contactInformation
319
     */
320
    public function addRaLocation(
321
        RaLocationId $raLocationId,
322
        RaLocationName $raLocationName,
323
        Location $location,
324
        ContactInformation $contactInformation
325
    ) {
326 View Code Duplication
        if ($this->raLocations->containsWithId($raLocationId)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
327
            throw new DomainException(sprintf(
328
                'Cannot add RaLocation with RaLocationId "%s" to RaLocations of InstitutionConfiguration "%s":'
329
                . ' it is already present',
330
                $raLocationId,
331
                $this->getAggregateRootId()
332
            ));
333
        }
334
335
        $this->apply(new RaLocationAddedEvent(
336
            $this->institutionConfigurationId,
337
            $this->institution,
338
            $raLocationId,
339
            $raLocationName,
340
            $location,
341
            $contactInformation
342
        ));
343
    }
344
345
    /**
346
     * @param RaLocationId $raLocationId
347
     * @param RaLocationName $raLocationName
348
     * @param Location $location
349
     * @param ContactInformation $contactInformation
350
     */
351
    public function changeRaLocation(
352
        RaLocationId $raLocationId,
353
        RaLocationName $raLocationName,
354
        Location $location,
355
        ContactInformation $contactInformation
356
    ) {
357 View Code Duplication
        if (!$this->raLocations->containsWithId($raLocationId)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
358
            throw new DomainException(sprintf(
359
                'Cannot change RaLocation with RaLocationId "%s" in RaLocations of InstitutionConfiguration "%s":'
360
                . ' it is not present',
361
                $raLocationId,
362
                $this->getAggregateRootId()
363
            ));
364
        }
365
366
        $raLocation = $this->raLocations->getById($raLocationId);
367
368
        if (!$raLocation->getName()->equals($raLocationName)) {
369
            $this->apply(
370
                new RaLocationRenamedEvent($this->institutionConfigurationId, $raLocationId, $raLocationName)
371
            );
372
        }
373
        if (!$raLocation->getLocation()->equals($location)) {
374
            $this->apply(
375
                new RaLocationRelocatedEvent($this->institutionConfigurationId, $raLocationId, $location)
376
            );
377
        }
378
        if (!$raLocation->getContactInformation()->equals($contactInformation)) {
379
            $this->apply(
380
                new RaLocationContactInformationChangedEvent(
381
                    $this->institutionConfigurationId,
382
                    $raLocationId,
383
                    $contactInformation
384
                )
385
            );
386
        }
387
    }
388
389
    /**
390
     * @param RaLocationId $raLocationId
391
     */
392
    public function removeRaLocation(RaLocationId $raLocationId)
393
    {
394 View Code Duplication
        if (!$this->raLocations->containsWithId($raLocationId)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
395
            throw new DomainException(sprintf(
396
                'Cannot remove RaLocation with RaLocationId "%s" in RaLocations of InstitutionConfiguration "%s":'
397
                . ' it is not present',
398
                $raLocationId,
399
                $this->getAggregateRootId()
400
            ));
401
        }
402
403
        $this->apply(new RaLocationRemovedEvent($this->institutionConfigurationId, $raLocationId));
404
    }
405
406
    /**
407
     * @return void
408
     */
409
    public function destroy()
410
    {
411
        $this->apply(new InstitutionConfigurationRemovedEvent($this->institutionConfigurationId, $this->institution));
412
    }
413
414
    public function getAggregateRootId()
415
    {
416
        return $this->institutionConfigurationId;
417
    }
418
419
    protected function applyNewInstitutionConfigurationCreatedEvent(NewInstitutionConfigurationCreatedEvent $event)
420
    {
421
        $this->institutionConfigurationId      = $event->institutionConfigurationId;
422
        $this->institution                     = $event->institution;
423
        $this->useRaLocationsOption            = $event->useRaLocationsOption;
424
        $this->showRaaContactInformationOption = $event->showRaaContactInformationOption;
425
        $this->verifyEmailOption               = $event->verifyEmailOption;
426
        $this->numberOfTokensPerIdentityOption = $event->numberOfTokensPerIdentityOption;
427
        $this->raLocations                     = new RaLocationList([]);
428
        $this->isMarkedAsDestroyed             = false;
429
    }
430
431
    protected function applyUseRaLocationsOptionChangedEvent(UseRaLocationsOptionChangedEvent $event)
432
    {
433
        $this->useRaLocationsOption = $event->useRaLocationsOption;
434
    }
435
436
    protected function applyShowRaaContactInformationOptionChangedEvent(
437
        ShowRaaContactInformationOptionChangedEvent $event
438
    ) {
439
        $this->showRaaContactInformationOption = $event->showRaaContactInformationOption;
440
    }
441
442
    protected function applyVerifyEmailOptionChangedEvent(
443
        VerifyEmailOptionChangedEvent $event
444
    ) {
445
        $this->verifyEmailOption = $event->verifyEmailOption;
446
    }
447
448
    protected function applyNumberOfTokensPerIdentityOptionChangedEvent(
449
        NumberOfTokensPerIdentityOptionChangedEvent $event
450
    ) {
451
        $this->numberOfTokensPerIdentityOption = $event->numberOfTokensPerIdentityOption;
452
    }
453
454
    protected function applyAllowedSecondFactorListUpdatedEvent(AllowedSecondFactorListUpdatedEvent $event)
455
    {
456
        $this->allowedSecondFactorList = $event->allowedSecondFactorList;
457
    }
458
459
    protected function applyRaLocationAddedEvent(RaLocationAddedEvent $event)
460
    {
461
        $this->raLocations->add(
462
            RaLocation::create(
463
                $event->raLocationId,
464
                $event->raLocationName,
465
                $event->location,
466
                $event->contactInformation
467
            )
468
        );
469
    }
470
471
    protected function applyRaLocationRenamedEvent(RaLocationRenamedEvent $event)
472
    {
473
        $raLocation = $this->raLocations->getById($event->raLocationId);
474
        $raLocation->rename($event->raLocationName);
475
    }
476
477
    protected function applyRaLocationRelocatedEvent(RaLocationRelocatedEvent $event)
478
    {
479
        $raLocation = $this->raLocations->getById($event->raLocationId);
480
        $raLocation->relocate($event->location);
481
    }
482
483
    protected function applyRaLocationContactInformationChangedEvent(RaLocationContactInformationChangedEvent $event)
484
    {
485
        $raLocation = $this->raLocations->getById($event->raLocationId);
486
        $raLocation->changeContactInformation($event->contactInformation);
487
    }
488
489
    protected function applyRaLocationRemovedEvent(RaLocationRemovedEvent $event)
490
    {
491
        $this->raLocations->removeWithId($event->raLocationId);
492
    }
493
494
    /**
495
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
496
     * @param InstitutionConfigurationRemovedEvent $event
497
     */
498
    protected function applyInstitutionConfigurationRemovedEvent(InstitutionConfigurationRemovedEvent $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
499
    {
500
        // reset all configuration to defaults. This way, should it be rebuild, it seems like it is new again
501
        $this->raLocations                     = new RaLocationList([]);
502
        $this->useRaLocationsOption            = UseRaLocationsOption::getDefault();
503
        $this->showRaaContactInformationOption = ShowRaaContactInformationOption::getDefault();
504
        $this->verifyEmailOption               = VerifyEmailOption::getDefault();
505
        $this->numberOfTokensPerIdentityOption = NumberOfTokensPerIdentityOption::getDefault();
506
        $this->allowedSecondFactorList         = AllowedSecondFactorList::blank();
507
508
        $this->isMarkedAsDestroyed             = true;
509
    }
510
}
511