Completed
Push — feature/update-projections ( 828044 )
by Michiel
03:55
created

applyUseRaaOptionChangedEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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
 * InstitutionConfiguration aggregate root
58
 *
59
 * Some things to know about this aggregate:
60
 *
61
 * 1. The aggregate is instantiated by InstitutionConfigurationCommandHandler by calling the
62
 *    handleReconfigureInstitutionConfigurationOptionsCommand method. It does so, not by using the projections to build
63
 *    the aggregate but by playing the events onto the aggregate.
64
 * 2. If one of the configuration options should be nullable, take a look at the applyUseRaOptionChangedEvent doc block
65
 *
66
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Events and value objects
67
 * @SuppressWarnings(PHPMD.TooManyMethods) AggregateRoot
68
 * @SuppressWarnings(PHPMD.TooManyPublicMethods) AggregateRoot
69
 */
70
class InstitutionConfiguration extends EventSourcedAggregateRoot implements InstitutionConfigurationInterface
71
{
72
    /**
73
     * @var InstitutionConfigurationId
74
     */
75
    private $institutionConfigurationId;
76
77
    /**
78
     * @var Institution
79
     */
80
    private $institution;
81
82
    /**
83
     * @var RaLocationList
84
     */
85
    private $raLocations;
86
87
    /**
88
     * @var UseRaLocationsOption
89
     */
90
    private $useRaLocationsOption;
91
92
    /**
93
     * @var ShowRaaContactInformationOption
94
     */
95
    private $showRaaContactInformationOption;
96
97
    /**
98
     * @var VerifyEmailOption
99
     */
100
    private $verifyEmailOption;
101
102
    /**
103
     * @var NumberOfTokensPerIdentityOption
104
     */
105
    private $numberOfTokensPerIdentityOption;
106
107
    /**
108
     * @var UseRaOption
109
     */
110
    private $useRaOption;
111
112
    /**
113
     * @var UseRaaOption
114
     */
115
116
    private $useRaaOption;
117
118
    /**
119
     * @var SelectRaaOption
120
     */
121
    private $selectRaaOption;
122
123
    /**
124
     * @var AllowedSecondFactorList
125
     */
126
    private $allowedSecondFactorList;
127
128
    /**
129
     * @var boolean
130
     */
131
    private $isMarkedAsDestroyed;
132
133
    /**
134
     * @param InstitutionConfigurationId $institutionConfigurationId
135
     * @param Institution $institution
136
     * @return InstitutionConfiguration
137
     */
138
    public static function create(InstitutionConfigurationId $institutionConfigurationId, Institution $institution)
139
    {
140
        $institutionConfiguration = new self;
141
        $institutionConfiguration->apply(
142
            new NewInstitutionConfigurationCreatedEvent(
143
                $institutionConfigurationId,
144
                $institution,
145
                UseRaLocationsOption::getDefault(),
146
                ShowRaaContactInformationOption::getDefault(),
147
                VerifyEmailOption::getDefault(),
148
                NumberOfTokensPerIdentityOption::getDefault(),
149
                UseRaOption::getDefault(),
150
                UseRaaOption::getDefault(),
151
                SelectRaaOption::getDefault()
152
            )
153
        );
154
        $institutionConfiguration->apply(new AllowedSecondFactorListUpdatedEvent(
155
            $institutionConfigurationId,
156
            $institution,
157
            AllowedSecondFactorList::blank()
158
        ));
159
160
        return $institutionConfiguration;
161
    }
162
163
    /**
164
     * @return InstitutionConfiguration
165
     */
166
    public function rebuild()
167
    {
168
        // We can only rebuild a destroyed InstitutionConfiguration, all other cases are not valid
169
        if ($this->isMarkedAsDestroyed !== true) {
170
            throw new DomainException('Cannot rebuild InstitutionConfiguration as it has not been destroyed');
171
        }
172
173
        $this->apply(
174
            new NewInstitutionConfigurationCreatedEvent(
175
                $this->institutionConfigurationId,
176
                $this->institution,
177
                UseRaLocationsOption::getDefault(),
178
                ShowRaaContactInformationOption::getDefault(),
179
                VerifyEmailOption::getDefault(),
180
                NumberOfTokensPerIdentityOption::getDefault(),
181
                UseRaOption::getDefault(),
182
                UseRaaOption::getDefault(),
183
                SelectRaaOption::getDefault()
184
            )
185
        );
186
        $this->apply(new AllowedSecondFactorListUpdatedEvent(
187
            $this->institutionConfigurationId,
188
            $this->institution,
189
            AllowedSecondFactorList::blank()
190
        ));
191
192
        return $this;
193
    }
194
195
    final public function __construct()
196
    {
197
    }
198
199
    public function configureUseRaLocationsOption(UseRaLocationsOption $useRaLocationsOption)
200
    {
201
        if ($this->useRaLocationsOption->equals($useRaLocationsOption)) {
202
            return;
203
        }
204
205
        $this->apply(
206
            new UseRaLocationsOptionChangedEvent(
207
                $this->institutionConfigurationId,
208
                $this->institution,
209
                $useRaLocationsOption
210
            )
211
        );
212
    }
213
214
    public function configureShowRaaContactInformationOption(ShowRaaContactInformationOption $showRaaContactInformationOption)
215
    {
216
        if ($this->showRaaContactInformationOption->equals($showRaaContactInformationOption)) {
217
            return;
218
        }
219
220
        $this->apply(
221
            new ShowRaaContactInformationOptionChangedEvent(
222
                $this->institutionConfigurationId,
223
                $this->institution,
224
                $showRaaContactInformationOption
225
            )
226
        );
227
    }
228
229
    public function configureVerifyEmailOption(VerifyEmailOption $verifyEmailOption)
230
    {
231
        if ($this->verifyEmailOption->equals($verifyEmailOption)) {
232
            return;
233
        }
234
235
        $this->apply(
236
            new VerifyEmailOptionChangedEvent(
237
                $this->institutionConfigurationId,
238
                $this->institution,
239
                $verifyEmailOption
240
            )
241
        );
242
    }
243
244
    public function configureNumberOfTokensPerIdentityOption(
245
        NumberOfTokensPerIdentityOption $numberOfTokensPerIdentityOption
246
    ) {
247
248
        $this->apply(
249
            new NumberOfTokensPerIdentityOptionChangedEvent(
250
                $this->institutionConfigurationId,
251
                $this->institution,
252
                $numberOfTokensPerIdentityOption
253
            )
254
        );
255
    }
256
257
    public function configureUseRaOption(UseRaOption $useRaOption)
258
    {
259
        if ($this->useRaOption->equals($useRaOption)) {
260
            return;
261
        }
262
263
        $this->apply(
264
            new UseRaOptionChangedEvent(
265
                $this->institutionConfigurationId,
266
                $this->institution,
267
                $useRaOption
268
            )
269
        );
270
    }
271
272
    public function configureUseRaaOption(UseRaaOption $useRaaOption)
273
    {
274
        if ($this->useRaaOption->equals($useRaaOption)) {
275
            return;
276
        }
277
278
        $this->apply(
279
            new UseRaaOptionChangedEvent(
280
                $this->institutionConfigurationId,
281
                $this->institution,
282
                $useRaaOption
283
            )
284
        );
285
    }
286
287
    public function configureSelectRaaOption(SelectRaaOption $selectRaaOption)
288
    {
289
        if ($this->selectRaaOption->equals($selectRaaOption)) {
290
            return;
291
        }
292
293
        $this->apply(
294
            new SelectRaaOptionChangedEvent(
295
                $this->institutionConfigurationId,
296
                $this->institution,
297
                $selectRaaOption
298
            )
299
        );
300
    }
301
302
    public function updateAllowedSecondFactorList(AllowedSecondFactorList $allowedSecondFactorList)
303
    {
304
        // AllowedSecondFactorList can be null for InstitutionConfigurations for which this functionality did not exist
305
        if ($this->allowedSecondFactorList !== null
306
            && $this->allowedSecondFactorList->equals($allowedSecondFactorList)
307
        ) {
308
            return;
309
        }
310
311
        $this->apply(
312
            new AllowedSecondFactorListUpdatedEvent(
313
                $this->institutionConfigurationId,
314
                $this->institution,
315
                $allowedSecondFactorList
316
            )
317
        );
318
    }
319
320
    /**
321
     * @param RaLocationId $raLocationId
322
     * @param RaLocationName $raLocationName
323
     * @param Location $location
324
     * @param ContactInformation $contactInformation
325
     */
326
    public function addRaLocation(
327
        RaLocationId $raLocationId,
328
        RaLocationName $raLocationName,
329
        Location $location,
330
        ContactInformation $contactInformation
331
    ) {
332 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...
333
            throw new DomainException(sprintf(
334
                'Cannot add RaLocation with RaLocationId "%s" to RaLocations of InstitutionConfiguration "%s":'
335
                . ' it is already present',
336
                $raLocationId,
337
                $this->getAggregateRootId()
338
            ));
339
        }
340
341
        $this->apply(new RaLocationAddedEvent(
342
            $this->institutionConfigurationId,
343
            $this->institution,
344
            $raLocationId,
345
            $raLocationName,
346
            $location,
347
            $contactInformation
348
        ));
349
    }
350
351
    /**
352
     * @param RaLocationId $raLocationId
353
     * @param RaLocationName $raLocationName
354
     * @param Location $location
355
     * @param ContactInformation $contactInformation
356
     */
357
    public function changeRaLocation(
358
        RaLocationId $raLocationId,
359
        RaLocationName $raLocationName,
360
        Location $location,
361
        ContactInformation $contactInformation
362
    ) {
363 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...
364
            throw new DomainException(sprintf(
365
                'Cannot change RaLocation with RaLocationId "%s" in RaLocations of InstitutionConfiguration "%s":'
366
                . ' it is not present',
367
                $raLocationId,
368
                $this->getAggregateRootId()
369
            ));
370
        }
371
372
        $raLocation = $this->raLocations->getById($raLocationId);
373
374
        if (!$raLocation->getName()->equals($raLocationName)) {
375
            $this->apply(
376
                new RaLocationRenamedEvent($this->institutionConfigurationId, $raLocationId, $raLocationName)
377
            );
378
        }
379
        if (!$raLocation->getLocation()->equals($location)) {
380
            $this->apply(
381
                new RaLocationRelocatedEvent($this->institutionConfigurationId, $raLocationId, $location)
382
            );
383
        }
384
        if (!$raLocation->getContactInformation()->equals($contactInformation)) {
385
            $this->apply(
386
                new RaLocationContactInformationChangedEvent(
387
                    $this->institutionConfigurationId,
388
                    $raLocationId,
389
                    $contactInformation
390
                )
391
            );
392
        }
393
    }
394
395
    /**
396
     * @param RaLocationId $raLocationId
397
     */
398
    public function removeRaLocation(RaLocationId $raLocationId)
399
    {
400 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...
401
            throw new DomainException(sprintf(
402
                'Cannot remove RaLocation with RaLocationId "%s" in RaLocations of InstitutionConfiguration "%s":'
403
                . ' it is not present',
404
                $raLocationId,
405
                $this->getAggregateRootId()
406
            ));
407
        }
408
409
        $this->apply(new RaLocationRemovedEvent($this->institutionConfigurationId, $raLocationId));
410
    }
411
412
    /**
413
     * @return void
414
     */
415
    public function destroy()
416
    {
417
        $this->apply(new InstitutionConfigurationRemovedEvent($this->institutionConfigurationId, $this->institution));
418
    }
419
420
    public function getAggregateRootId()
421
    {
422
        return $this->institutionConfigurationId;
423
    }
424
425
    protected function applyNewInstitutionConfigurationCreatedEvent(NewInstitutionConfigurationCreatedEvent $event)
426
    {
427
        $this->institutionConfigurationId      = $event->institutionConfigurationId;
428
        $this->institution                     = $event->institution;
429
        $this->useRaLocationsOption            = $event->useRaLocationsOption;
430
        $this->showRaaContactInformationOption = $event->showRaaContactInformationOption;
431
        $this->verifyEmailOption               = $event->verifyEmailOption;
432
        $this->numberOfTokensPerIdentityOption = $event->numberOfTokensPerIdentityOption;
433
434
        // Apply the FGA options
435
        $this->useRaOption = $event->useRaOption;
436
        $this->useRaaOption = $event->useRaaOption;
437
        $this->selectRaaOption = $event->selectRaaOption;
438
439
        $this->raLocations                     = new RaLocationList([]);
440
        $this->isMarkedAsDestroyed             = false;
441
    }
442
443
    /**
444
     * Apply the UseRaOptionChangedEvent
445
     *
446
     * To ensure the aggregate is correctly populated with the FGA options we ensure the UseRaOptionChangedEvent
447
     * can be applied on the aggregate. Refraining from doing this would result in the $this->useRaOption field only
448
     * being applied when applyNewInstitutionConfigurationCreatedEvent is called. And this might not be the case if
449
     * the fields where null'ed (removed from configuration).
450
     *
451
     * This also applies for applyUseRaaOptionChangedEvent & applySelectRaaOptionChangedEvent
452
     *
453
     * @param UseRaOptionChangedEvent $event
454
     */
455
    protected function applyUseRaOptionChangedEvent(UseRaOptionChangedEvent $event)
456
    {
457
        $this->useRaOption = $event->useRaOption;
458
    }
459
460
    protected function applyUseRaaOptionChangedEvent(UseRaaOptionChangedEvent $event)
461
    {
462
        $this->useRaaOption = $event->useRaaOption;
463
    }
464
465
    protected function applySelectRaaOptionChangedEvent(SelectRaaOptionChangedEvent $event)
466
    {
467
        $this->selectRaaOption = $event->selectRaaOption;
468
    }
469
470
    protected function applyUseRaLocationsOptionChangedEvent(UseRaLocationsOptionChangedEvent $event)
471
    {
472
        $this->useRaLocationsOption = $event->useRaLocationsOption;
473
    }
474
475
    protected function applyShowRaaContactInformationOptionChangedEvent(
476
        ShowRaaContactInformationOptionChangedEvent $event
477
    ) {
478
        $this->showRaaContactInformationOption = $event->showRaaContactInformationOption;
479
    }
480
481
    protected function applyVerifyEmailOptionChangedEvent(
482
        VerifyEmailOptionChangedEvent $event
483
    ) {
484
        $this->verifyEmailOption = $event->verifyEmailOption;
485
    }
486
487
    protected function applyNumberOfTokensPerIdentityOptionChangedEvent(
488
        NumberOfTokensPerIdentityOptionChangedEvent $event
489
    ) {
490
        $this->numberOfTokensPerIdentityOption = $event->numberOfTokensPerIdentityOption;
491
    }
492
493
    protected function applyAllowedSecondFactorListUpdatedEvent(AllowedSecondFactorListUpdatedEvent $event)
494
    {
495
        $this->allowedSecondFactorList = $event->allowedSecondFactorList;
496
    }
497
498
    protected function applyRaLocationAddedEvent(RaLocationAddedEvent $event)
499
    {
500
        $this->raLocations->add(
501
            RaLocation::create(
502
                $event->raLocationId,
503
                $event->raLocationName,
504
                $event->location,
505
                $event->contactInformation
506
            )
507
        );
508
    }
509
510
    protected function applyRaLocationRenamedEvent(RaLocationRenamedEvent $event)
511
    {
512
        $raLocation = $this->raLocations->getById($event->raLocationId);
513
        $raLocation->rename($event->raLocationName);
514
    }
515
516
    protected function applyRaLocationRelocatedEvent(RaLocationRelocatedEvent $event)
517
    {
518
        $raLocation = $this->raLocations->getById($event->raLocationId);
519
        $raLocation->relocate($event->location);
520
    }
521
522
    protected function applyRaLocationContactInformationChangedEvent(RaLocationContactInformationChangedEvent $event)
523
    {
524
        $raLocation = $this->raLocations->getById($event->raLocationId);
525
        $raLocation->changeContactInformation($event->contactInformation);
526
    }
527
528
    protected function applyRaLocationRemovedEvent(RaLocationRemovedEvent $event)
529
    {
530
        $this->raLocations->removeWithId($event->raLocationId);
531
    }
532
533
    /**
534
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
535
     * @param InstitutionConfigurationRemovedEvent $event
536
     */
537
    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...
538
    {
539
        // reset all configuration to defaults. This way, should it be rebuild, it seems like it is new again
540
        $this->raLocations                     = new RaLocationList([]);
541
        $this->useRaLocationsOption            = UseRaLocationsOption::getDefault();
542
        $this->showRaaContactInformationOption = ShowRaaContactInformationOption::getDefault();
543
        $this->verifyEmailOption               = VerifyEmailOption::getDefault();
544
        $this->numberOfTokensPerIdentityOption = NumberOfTokensPerIdentityOption::getDefault();
545
        $this->allowedSecondFactorList         = AllowedSecondFactorList::blank();
546
        $this->useRaOption = UseRaOption::getDefault();
547
        $this->useRaaOption = UseRaaOption::getDefault();
548
        $this->selectRaaOption = SelectRaaOption::getDefault();
549
550
        $this->isMarkedAsDestroyed             = true;
551
    }
552
}
553