Completed
Pull Request — develop (#236)
by
unknown
02:34
created

applyRaLocationRelocatedEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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