Completed
Pull Request — master (#306)
by Luc
06:57 queued 01:33
created

Organizer::applyWebsiteUpdated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace CultuurNet\UDB3\Organizer;
4
5
use Broadway\EventSourcing\EventSourcedAggregateRoot;
6
use CultuurNet\UDB3\Address\Address;
7
use CultuurNet\UDB3\Cdb\ActorItemFactory;
8
use CultuurNet\UDB3\Cdb\UpdateableWithCdbXmlInterface;
9
use CultuurNet\UDB3\ContactPoint;
10
use CultuurNet\UDB3\Label;
11
use CultuurNet\UDB3\LabelAwareAggregateRoot;
12
use CultuurNet\UDB3\LabelCollection;
13
use CultuurNet\UDB3\Language;
14
use CultuurNet\UDB3\Organizer\Events\AddressUpdated;
15
use CultuurNet\UDB3\Organizer\Events\ContactPointUpdated;
16
use CultuurNet\UDB3\Organizer\Events\LabelAdded;
17
use CultuurNet\UDB3\Organizer\Events\LabelRemoved;
18
use CultuurNet\UDB3\Organizer\Events\OrganizerCreated;
19
use CultuurNet\UDB3\Organizer\Events\OrganizerCreatedWithUniqueWebsite;
20
use CultuurNet\UDB3\Organizer\Events\OrganizerDeleted;
21
use CultuurNet\UDB3\Organizer\Events\OrganizerImportedFromUDB2;
22
use CultuurNet\UDB3\Organizer\Events\OrganizerUpdatedFromUDB2;
23
use CultuurNet\UDB3\Organizer\Events\TitleTranslated;
24
use CultuurNet\UDB3\Organizer\Events\TitleUpdated;
25
use CultuurNet\UDB3\Organizer\Events\WebsiteUpdated;
26
use CultuurNet\UDB3\Title;
27
use ValueObjects\Web\Url;
28
29
class Organizer extends EventSourcedAggregateRoot implements UpdateableWithCdbXmlInterface, LabelAwareAggregateRoot
30
{
31
    /**
32
     * The actor id.
33
     *
34
     * @var string
35
     */
36
    protected $actorId;
37
38
    /**
39
     * @var Language
40
     */
41
    private $mainLanguage;
42
43
    /**
44
     * @var Url
45
     */
46
    private $website;
47
48
    /**
49
     * @var Title[]
50
     */
51
    private $titles;
52
53
    /**
54
     * @var Address|null
55
     */
56
    private $address;
57
58
    /**
59
     * @var ContactPoint
60
     */
61
    private $contactPoint;
62
63
    /**
64
     * @var LabelCollection
65
     */
66
    private $labels;
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getAggregateRootId()
72
    {
73
        return $this->actorId;
74
    }
75
76
    public function __construct()
77
    {
78
        // For now the main language is hard coded on nl.
79
        // In the future it should be set on create.
80
        $this->mainLanguage = new Language('nl');
81
82
        // Contact points can be empty, but we only want to start recording
83
        // ContactPointUpdated events as soon as the organizer is updated
84
        // with a non-empty contact point. To enforce this we initialize the
85
        // aggregate state with an empty contact point.
86
        $this->contactPoint = new ContactPoint();
87
        $this->labels = new LabelCollection();
88
    }
89
90
    /**
91
     * Import from UDB2.
92
     *
93
     * @param string $actorId
94
     *   The actor id.
95
     * @param string $cdbXml
96
     *   The cdb xml.
97
     * @param string $cdbXmlNamespaceUri
98
     *   The cdb xml namespace uri.
99
     *
100
     * @return Organizer
101
     *   The actor.
102
     */
103
    public static function importFromUDB2(
104
        $actorId,
105
        $cdbXml,
106
        $cdbXmlNamespaceUri
107
    ) {
108
        $organizer = new static();
109
        $organizer->apply(
110
            new OrganizerImportedFromUDB2(
111
                $actorId,
112
                $cdbXml,
113
                $cdbXmlNamespaceUri
114
            )
115
        );
116
117
        return $organizer;
118
    }
119
120
    /**
121
     * Factory method to create a new Organizer.
122
     *
123
     * @param string $id
124
     * @param Url $website
125
     * @param Title $title
126
     * @return Organizer
127
     */
128
    public static function create(
129
        $id,
130
        Url $website,
131
        Title $title
132
    ) {
133
        $organizer = new self();
134
135
        $organizer->apply(
136
            new OrganizerCreatedWithUniqueWebsite($id, $website, $title)
137
        );
138
139
        return $organizer;
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145
    public function updateWithCdbXml($cdbXml, $cdbXmlNamespaceUri)
146
    {
147
        $this->apply(
148
            new OrganizerUpdatedFromUDB2(
149
                $this->actorId,
150
                $cdbXml,
151
                $cdbXmlNamespaceUri
152
            )
153
        );
154
    }
155
156
    /**
157
     * @param Url $website
158
     */
159
    public function updateWebsite(Url $website)
160
    {
161
        if (is_null($this->website) || !$this->website->sameValueAs($website)) {
162
            $this->apply(
163
                new WebsiteUpdated(
164
                    $this->actorId,
165
                    $website
166
                )
167
            );
168
        }
169
    }
170
171
    /**
172
     * @param Title $title
173
     * @param Language $language
174
     */
175
    public function updateTitle(
176
        Title $title,
177
        Language $language
178
    ) {
179
        if ($this->isTitleChanged($title, $language)) {
180
            if ($language->getCode() !== $this->mainLanguage->getCode()) {
181
                $event = new TitleTranslated(
182
                    $this->actorId,
183
                    $title,
184
                    $language
185
                );
186
            } else {
187
                $event = new TitleUpdated(
188
                    $this->actorId,
189
                    $title
190
                );
191
            }
192
193
            $this->apply($event);
194
        }
195
    }
196
197
    /**
198
     * @param Address $address
199
     */
200
    public function updateAddress(Address $address)
201
    {
202
        if (is_null($this->address) || !$this->address->sameAs($address)) {
203
            $this->apply(
204
                new AddressUpdated($this->actorId, $address)
205
            );
206
        }
207
    }
208
209
    /**
210
     * @param ContactPoint $contactPoint
211
     */
212
    public function updateContactPoint(ContactPoint $contactPoint)
213
    {
214
        if (!$this->contactPoint->sameAs($contactPoint)) {
215
            $this->apply(
216
                new ContactPointUpdated($this->actorId, $contactPoint)
217
            );
218
        }
219
    }
220
221
    /**
222
     * @inheritdoc
223
     */
224
    public function addLabel(Label $label)
225
    {
226
        if (!$this->labels->contains($label)) {
227
            $this->apply(new LabelAdded($this->actorId, $label));
228
        }
229
    }
230
231
    /**
232
     * @inheritdoc
233
     */
234
    public function removeLabel(Label $label)
235
    {
236
        if ($this->labels->contains($label)) {
237
            $this->apply(new LabelRemoved($this->actorId, $label));
238
        }
239
    }
240
241
    public function delete()
242
    {
243
        $this->apply(
244
            new OrganizerDeleted($this->getAggregateRootId())
245
        );
246
    }
247
248
    /**
249
     * Apply the organizer created event.
250
     * @param OrganizerCreated $organizerCreated
251
     */
252
    protected function applyOrganizerCreated(OrganizerCreated $organizerCreated)
253
    {
254
        $this->actorId = $organizerCreated->getOrganizerId();
255
256
        $this->setTitle($organizerCreated->getTitle(), $this->mainLanguage);
257
    }
258
259
    /**
260
     * Apply the organizer created event.
261
     * @param OrganizerCreatedWithUniqueWebsite $organizerCreated
262
     */
263
    protected function applyOrganizerCreatedWithUniqueWebsite(OrganizerCreatedWithUniqueWebsite $organizerCreated)
264
    {
265
        $this->actorId = $organizerCreated->getOrganizerId();
266
267
        $this->website = $organizerCreated->getWebsite();
268
269
        $this->setTitle($organizerCreated->getTitle(), $this->mainLanguage);
270
    }
271
272
    /**
273
     * @param OrganizerImportedFromUDB2 $organizerImported
274
     */
275 View Code Duplication
    protected function applyOrganizerImportedFromUDB2(
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...
276
        OrganizerImportedFromUDB2 $organizerImported
277
    ) {
278
        $this->actorId = (string) $organizerImported->getActorId();
279
280
        $actor = ActorItemFactory::createActorFromCdbXml(
281
            $organizerImported->getCdbXmlNamespaceUri(),
282
            $organizerImported->getCdbXml()
283
        );
284
285
        $this->setTitle($this->getTitle($actor), $this->mainLanguage);
0 ignored issues
show
Bug introduced by
It seems like $this->getTitle($actor) can be null; however, setTitle() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
286
287
        $this->labels = LabelCollection::fromKeywords($actor->getKeywords(true));
288
    }
289
290
    /**
291
     * @param OrganizerUpdatedFromUDB2 $organizerUpdatedFromUDB2
292
     */
293 View Code Duplication
    protected function applyOrganizerUpdatedFromUDB2(
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...
294
        OrganizerUpdatedFromUDB2 $organizerUpdatedFromUDB2
295
    ) {
296
        $actor = ActorItemFactory::createActorFromCdbXml(
297
            $organizerUpdatedFromUDB2->getCdbXmlNamespaceUri(),
298
            $organizerUpdatedFromUDB2->getCdbXml()
299
        );
300
301
        $this->setTitle($this->getTitle($actor), $this->mainLanguage);
0 ignored issues
show
Bug introduced by
It seems like $this->getTitle($actor) can be null; however, setTitle() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
302
303
        $this->labels = LabelCollection::fromKeywords($actor->getKeywords(true));
304
    }
305
306
    /**
307
     * @param WebsiteUpdated $websiteUpdated
308
     */
309
    protected function applyWebsiteUpdated(WebsiteUpdated $websiteUpdated)
310
    {
311
        $this->website = $websiteUpdated->getWebsite();
312
    }
313
314
    /**
315
     * @param TitleUpdated $titleUpdated
316
     */
317
    protected function applyTitleUpdated(TitleUpdated $titleUpdated)
318
    {
319
        $this->setTitle($titleUpdated->getTitle(), $this->mainLanguage);
320
    }
321
322
    /**
323
     * @param TitleTranslated $titleTranslated
324
     */
325
    protected function applyTitleTranslated(TitleTranslated $titleTranslated)
326
    {
327
        $this->setTitle($titleTranslated->getTitle(), $titleTranslated->getLanguage());
328
    }
329
330
    /**
331
     * @param AddressUpdated $addressUpdated
332
     */
333
    protected function applyAddressUpdated(AddressUpdated $addressUpdated)
334
    {
335
        $this->address = $addressUpdated->getAddress();
336
    }
337
338
    /**
339
     * @param ContactPointUpdated $contactPointUpdated
340
     */
341
    protected function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated)
342
    {
343
        $this->contactPoint = $contactPointUpdated->getContactPoint();
344
    }
345
346
    /**
347
     * @param LabelAdded $labelAdded
348
     */
349
    protected function applyLabelAdded(LabelAdded $labelAdded)
350
    {
351
        $this->labels = $this->labels->with($labelAdded->getLabel());
352
    }
353
354
    /**
355
     * @param LabelRemoved $labelRemoved
356
     */
357
    protected function applyLabelRemoved(LabelRemoved $labelRemoved)
358
    {
359
        $this->labels = $this->labels->without($labelRemoved->getLabel());
360
    }
361
362
    /**
363
     * @param \CultureFeed_Cdb_Item_Actor $actor
364
     * @return null|Title
365
     */
366
    private function getTitle(\CultureFeed_Cdb_Item_Actor $actor)
367
    {
368
        $details = $actor->getDetails();
369
        $details->rewind();
370
371
        // The first language detail found will be used to retrieve
372
        // properties from which in UDB3 are not any longer considered
373
        // to be language specific.
374
        if ($details->valid()) {
375
            return new Title($details->current()->getTitle());
376
        } else {
377
            return null;
378
        }
379
    }
380
381
    /**
382
     * @param Title $title
383
     * @param Language $language
384
     */
385
    private function setTitle(Title $title, Language $language)
386
    {
387
        $this->titles[$language->getCode()] = $title;
388
    }
389
390
    /**
391
     * @param Title $title
392
     * @param Language $language
393
     * @return bool
394
     */
395
    private function isTitleChanged(Title $title, Language $language)
396
    {
397
        return !isset($this->titles[$language->getCode()]) ||
398
            !$title->sameValueAs($this->titles[$language->getCode()]);
399
    }
400
}
401