Completed
Push — master ( 5467e4...183ea4 )
by Boy
05:06 queued 01:02
created

SensitiveDataMessageStream::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 4
rs 10
c 1
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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\CommandHandlingBundle\SensitiveData\EventSourcing;
20
21
use ArrayIterator;
22
use Broadway\Domain\DomainEventStreamInterface;
23
use Broadway\Domain\DomainMessage;
24
use IteratorAggregate;
25
use Surfnet\StepupMiddleware\CommandHandlingBundle\SensitiveData\Exception\SensitiveDataApplicationException;
26
use Surfnet\StepupMiddleware\CommandHandlingBundle\SensitiveData\Forgettable;
27
28
class SensitiveDataMessageStream implements IteratorAggregate
29
{
30
    /**
31
     * @var array
32
     */
33
    private $messages;
34
35
    /**
36
     * @param SensitiveDataMessage[] $messages
37
     */
38
    public function __construct(array $messages)
39
    {
40
        $this->messages = $messages;
41
    }
42
43
    public function applyToDomainEventStream(DomainEventStreamInterface $domainEventStream)
44
    {
45
        $sensitiveDataMap = $this->createSensitiveDataMap($this->messages);
46
47
        /** @var DomainMessage $domainMessage */
48
        foreach ($domainEventStream as $domainMessage) {
49
            $sensitiveDataMessage = isset($sensitiveDataMap[$domainMessage->getPlayhead()])
50
                ? $sensitiveDataMap[$domainMessage->getPlayhead()]
51
                : null;
52
            unset($sensitiveDataMap[$domainMessage->getPlayhead()]);
53
54
            $this->setSensitiveData($domainMessage, $sensitiveDataMessage);
55
        }
56
57
        if (count($sensitiveDataMap) > 0) {
58
            throw new SensitiveDataApplicationException(sprintf(
59
                '%d sensitive data messages are still to be matched to events',
60
                count($sensitiveDataMap)
61
            ));
62
        }
63
    }
64
65
    public function forget()
66
    {
67
        foreach ($this->messages as $message) {
68
            $message->forget();
69
        }
70
    }
71
72
    public function getIterator()
73
    {
74
        return new ArrayIterator($this->messages);
75
    }
76
77
    /**
78
     * @param DomainMessage $domainMessage
79
     * @param SensitiveDataMessage|null $sensitiveDataMessage
80
     */
81
    private function setSensitiveData(DomainMessage $domainMessage, SensitiveDataMessage $sensitiveDataMessage = null)
82
    {
83
        $event = $domainMessage->getPayload();
84
        $eventIsForgettable = $event instanceof Forgettable;
85
86
        if (!$eventIsForgettable && !$sensitiveDataMessage) {
87
            return;
88
        }
89
90
        if ($eventIsForgettable && !$sensitiveDataMessage) {
91
            throw new SensitiveDataApplicationException(sprintf(
92
                'Sensitive data is missing for event with UUID %s, playhead %d',
93
                $domainMessage->getId(),
94
                $domainMessage->getPlayhead()
95
            ));
96
        }
97
98
        if (!$eventIsForgettable && $sensitiveDataMessage) {
99
            throw new SensitiveDataApplicationException(sprintf(
100
                'Encountered sensitive data for event which does not support sensitive data, UUID %s, playhead %d',
101
                $domainMessage->getId(),
102
                $domainMessage->getPlayhead()
103
            ));
104
        }
105
106
        if ($domainMessage->getId() != $sensitiveDataMessage->getIdentityId()) {
107
            throw new SensitiveDataApplicationException(sprintf(
108
                'Encountered sensitive data from stream %s for event from stream %s',
109
                $sensitiveDataMessage->getIdentityId(),
0 ignored issues
show
Bug introduced by
It seems like $sensitiveDataMessage is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
110
                $domainMessage->getId()
111
            ));
112
        }
113
114
        $event->setSensitiveData($sensitiveDataMessage->getSensitiveData());
115
    }
116
117
    /**
118
     * @param SensitiveDataMessage[] $messages
119
     * @return SensitiveDataMessage[] The same messages, but indexed by their playheads.
120
     */
121
    private function createSensitiveDataMap(array $messages)
122
    {
123
        $map = [];
124
        foreach ($messages as $message) {
125
            $map[$message->getPlayhead()] = $message;
126
        }
127
128
        return $map;
129
    }
130
}
131