Completed
Pull Request — master (#322)
by Luc
04:11
created

Place::createCalendarUpdatedEvent()   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\Place;
4
5
use CultuurNet\Geocoding\Coordinate\Coordinates;
6
use CultuurNet\UDB3\Address\Address;
7
use CultuurNet\UDB3\BookingInfo;
8
use CultuurNet\UDB3\Calendar;
9
use CultuurNet\UDB3\CalendarInterface;
10
use CultuurNet\UDB3\Cdb\ActorItemFactory;
11
use CultuurNet\UDB3\Cdb\UpdateableWithCdbXmlInterface;
12
use CultuurNet\UDB3\ContactPoint;
13
use CultuurNet\UDB3\Event\EventType;
14
use CultuurNet\UDB3\Label;
15
use CultuurNet\UDB3\LabelCollection;
16
use CultuurNet\UDB3\Media\ImageCollection;
17
use CultuurNet\UDB3\Offer\Commands\Image\AbstractUpdateImage;
18
use CultuurNet\UDB3\Language;
19
use CultuurNet\UDB3\Offer\Offer;
20
use CultuurNet\UDB3\Media\Image;
21
use CultuurNet\UDB3\Offer\WorkflowStatus;
22
use CultuurNet\UDB3\Place\Events\AddressTranslated;
23
use CultuurNet\UDB3\Place\Events\AddressUpdated;
24
use CultuurNet\UDB3\Place\Events\BookingInfoUpdated;
25
use CultuurNet\UDB3\Place\Events\CalendarUpdated;
26
use CultuurNet\UDB3\Place\Events\ContactPointUpdated;
27
use CultuurNet\UDB3\Place\Events\DescriptionTranslated;
28
use CultuurNet\UDB3\Place\Events\DescriptionUpdated;
29
use CultuurNet\UDB3\Place\Events\FacilitiesUpdated;
30
use CultuurNet\UDB3\Place\Events\GeoCoordinatesUpdated;
31
use CultuurNet\UDB3\Place\Events\Image\ImagesImportedFromUDB2;
32
use CultuurNet\UDB3\Place\Events\Image\ImagesUpdatedFromUDB2;
33
use CultuurNet\UDB3\Place\Events\ImageAdded;
34
use CultuurNet\UDB3\Place\Events\ImageRemoved;
35
use CultuurNet\UDB3\Place\Events\ImageUpdated;
36
use CultuurNet\UDB3\Place\Events\MainImageSelected;
37
use CultuurNet\UDB3\Place\Events\LabelAdded;
38
use CultuurNet\UDB3\Place\Events\LabelRemoved;
39
use CultuurNet\UDB3\Place\Events\MajorInfoUpdated;
40
use CultuurNet\UDB3\Place\Events\Moderation\Approved;
41
use CultuurNet\UDB3\Place\Events\Moderation\FlaggedAsDuplicate;
42
use CultuurNet\UDB3\Place\Events\Moderation\FlaggedAsInappropriate;
43
use CultuurNet\UDB3\Place\Events\Moderation\Published;
44
use CultuurNet\UDB3\Place\Events\Moderation\Rejected;
45
use CultuurNet\UDB3\Place\Events\OrganizerDeleted;
46
use CultuurNet\UDB3\Place\Events\OrganizerUpdated;
47
use CultuurNet\UDB3\Place\Events\PlaceCreated;
48
use CultuurNet\UDB3\Place\Events\PlaceDeleted;
49
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2;
50
use CultuurNet\UDB3\Place\Events\PlaceUpdatedFromUDB2;
51
use CultuurNet\UDB3\Place\Events\PriceInfoUpdated;
52
use CultuurNet\UDB3\Place\Events\TitleTranslated;
53
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeDeleted;
54
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeUpdated;
55
use CultuurNet\UDB3\PriceInfo\PriceInfo;
56
use CultuurNet\UDB3\Theme;
57
use CultuurNet\UDB3\Title;
58
use DateTimeImmutable;
59
use ValueObjects\StringLiteral\StringLiteral;
60
61
class Place extends Offer implements UpdateableWithCdbXmlInterface
62
{
63
    /**
64
     * @var string
65
     */
66
    private $placeId;
67
68
    public function __construct()
69
    {
70
        parent::__construct();
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function getAggregateRootId()
77
    {
78
        return $this->placeId;
79
    }
80
81
    /**
82
     * Factory method to create a new Place.
83
     *
84
     * @todo Refactor this method so it can be called create. Currently the
85
     * normal behavior for create is taken by the legacy udb2 logic.
86
     * The PlaceImportedFromUDB2 could be a superclass of Place.
87
     *
88
     * @param string $id
89
     * @param Title $title
90
     * @param EventType $eventType
91
     * @param Address $address
92
     * @param CalendarInterface $calendar
93
     * @param Theme|null $theme
94
     * @param DateTimeImmutable|null $publicationDate
95
     *
96
     * @return self
97
     */
98 View Code Duplication
    public static function createPlace(
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...
99
        $id,
100
        Title $title,
101
        EventType $eventType,
102
        Address $address,
103
        CalendarInterface $calendar,
104
        Theme $theme = null,
105
        DateTimeImmutable $publicationDate = null
106
    ) {
107
        $place = new self();
108
        $place->apply(new PlaceCreated(
109
            $id,
110
            $title,
111
            $eventType,
112
            $address,
113
            $calendar,
114
            $theme,
115
            $publicationDate
116
        ));
117
118
        return $place;
119
    }
120
121
    /**
122
     * Apply the place created event.
123
     * @param PlaceCreated $placeCreated
124
     */
125
    protected function applyPlaceCreated(PlaceCreated $placeCreated)
126
    {
127
        $this->placeId = $placeCreated->getPlaceId();
128
        $this->workflowStatus = WorkflowStatus::DRAFT();
129
    }
130
131
    /**
132
     * Update the facilities.
133
     *
134
     * @param array $facilities
135
     */
136
    public function updateFacilities(array $facilities)
137
    {
138
        $this->apply(new FacilitiesUpdated($this->placeId, $facilities));
139
    }
140
141
    /**
142
     * Update the major info.
143
     *
144
     * @param Title $title
145
     * @param EventType $eventType
146
     * @param Address $address
147
     * @param CalendarInterface $calendar
148
     * @param Theme $theme
149
     */
150
    public function updateMajorInfo(
151
        Title $title,
152
        EventType $eventType,
153
        Address $address,
154
        CalendarInterface $calendar,
155
        Theme $theme = null
156
    ) {
157
        $this->apply(
158
            new MajorInfoUpdated(
159
                $this->placeId,
160
                $title,
161
                $eventType,
162
                $address,
163
                $calendar,
164
                $theme
165
            )
166
        );
167
    }
168
169
    /**
170
     * @param Address $address
171
     * @param Language $language
172
     */
173
    public function updateAddress(Address $address, Language $language)
174
    {
175
        if ($language->getCode() === $this->mainLanguage->getCode()) {
176
            $event = new AddressUpdated($this->placeId, $address);
177
        } else {
178
            $event = new AddressTranslated($this->placeId, $address, $language);
179
        }
180
181
        $this->apply($event);
182
    }
183
184
    /**
185
     * @param Coordinates $coordinates
186
     */
187
    public function updateGeoCoordinates(
188
        Coordinates $coordinates
189
    ) {
190
        // Note: DON'T compare to previous coordinates and apply only on
191
        // changes. Various projectors expect GeoCoordinatesUpdated after
192
        // MajorInfoUpdated and PlaceUpdatedFromUDB2, even if the address
193
        // and thus the coordinates haven't actually changed.
194
        $this->apply(new GeoCoordinatesUpdated($this->placeId, $coordinates));
195
    }
196
197
    /**
198
     * Import from UDB2.
199
     *
200
     * @param string $actorId
201
     *   The actor id.
202
     * @param string $cdbXml
203
     *   The cdb xml.
204
     * @param string $cdbXmlNamespaceUri
205
     *   The cdb xml namespace uri.
206
     *
207
     * @return Place
208
     */
209
    public static function importFromUDB2Actor(
210
        $actorId,
211
        $cdbXml,
212
        $cdbXmlNamespaceUri
213
    ) {
214
        $place = new static();
215
        $place->apply(
216
            new PlaceImportedFromUDB2(
217
                $actorId,
218
                $cdbXml,
219
                $cdbXmlNamespaceUri
220
            )
221
        );
222
223
        return $place;
224
    }
225
226
    /**
227
     * @param PlaceImportedFromUDB2 $placeImported
228
     */
229 View Code Duplication
    public function applyPlaceImportedFromUDB2(
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...
230
        PlaceImportedFromUDB2 $placeImported
231
    ) {
232
        $this->placeId = $placeImported->getActorId();
233
234
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
235
            $placeImported->getCdbXmlNamespaceUri(),
236
            $placeImported->getCdbXml()
237
        );
238
239
        $this->importWorkflowStatus($udb2Actor);
240
        $this->labels = LabelCollection::fromKeywords($udb2Actor->getKeywords(true));
241
    }
242
243
    /**
244
     * @param PlaceUpdatedFromUDB2 $placeUpdatedFromUDB2
245
     */
246 View Code Duplication
    public function applyPlaceUpdatedFromUDB2(
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...
247
        PlaceUpdatedFromUDB2 $placeUpdatedFromUDB2
248
    ) {
249
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
250
            $placeUpdatedFromUDB2->getCdbXmlNamespaceUri(),
251
            $placeUpdatedFromUDB2->getCdbXml()
252
        );
253
254
        $this->importWorkflowStatus($udb2Actor);
255
        $this->labels = LabelCollection::fromKeywords($udb2Actor->getKeywords(true));
256
    }
257
258
    /**
259
     * @inheritdoc
260
     */
261
    public function updateWithCdbXml($cdbXml, $cdbXmlNamespaceUri)
262
    {
263
        ActorItemFactory::createActorFromCdbXml($cdbXmlNamespaceUri, $cdbXml);
264
265
        $this->apply(
266
            new PlaceUpdatedFromUDB2(
267
                $this->placeId,
268
                $cdbXml,
269
                $cdbXmlNamespaceUri
270
            )
271
        );
272
    }
273
274
    /**
275
     * @param Label $label
276
     * @return LabelAdded
277
     */
278
    protected function createLabelAddedEvent(Label $label)
279
    {
280
        return new LabelAdded($this->placeId, $label);
281
    }
282
283
    /**
284
     * @param Label $label
285
     * @return LabelRemoved
286
     */
287
    protected function createLabelRemovedEvent(Label $label)
288
    {
289
        return new LabelRemoved($this->placeId, $label);
290
    }
291
292
    protected function createImageAddedEvent(Image $image)
293
    {
294
        return new ImageAdded($this->placeId, $image);
295
    }
296
297
    protected function createImageRemovedEvent(Image $image)
298
    {
299
        return new ImageRemoved($this->placeId, $image);
300
    }
301
302
    protected function createImageUpdatedEvent(
303
        AbstractUpdateImage $updateImageCommand
304
    ) {
305
        return new ImageUpdated(
306
            $this->placeId,
307
            $updateImageCommand->getMediaObjectId(),
308
            $updateImageCommand->getDescription(),
309
            $updateImageCommand->getCopyrightHolder()
310
        );
311
    }
312
313
    protected function createMainImageSelectedEvent(Image $image)
314
    {
315
        return new MainImageSelected($this->placeId, $image);
316
    }
317
318
    /**
319
     * @param Language $language
320
     * @param StringLiteral $title
321
     * @return TitleTranslated
322
     */
323
    protected function createTitleTranslatedEvent(Language $language, StringLiteral $title)
324
    {
325
        return new TitleTranslated($this->placeId, $language, $title);
326
    }
327
328
    /**
329
     * @param Language $language
330
     * @param StringLiteral $description
331
     * @return DescriptionTranslated
332
     */
333
    protected function createDescriptionTranslatedEvent(Language $language, StringLiteral $description)
334
    {
335
        return new DescriptionTranslated($this->placeId, $language, $description);
336
    }
337
338
    /**
339
     * @param string $description
340
     * @return DescriptionUpdated
341
     */
342
    protected function createDescriptionUpdatedEvent($description)
343
    {
344
        return new DescriptionUpdated($this->placeId, $description);
345
    }
346
347
    /**
348
     * @inheritdoc
349
     */
350
    protected function createCalendarUpdatedEvent(Calendar $calendar)
351
    {
352
        return new CalendarUpdated($this->placeId, $calendar);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \CultuurNet\U...s->placeId, $calendar); (CultuurNet\UDB3\Place\Events\CalendarUpdated) is incompatible with the return type declared by the abstract method CultuurNet\UDB3\Offer\Of...ateCalendarUpdatedEvent of type CultuurNet\UDB3\Offer\AbstractCalendarUpdated.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
353
    }
354
    
355
    /**
356
     * @param string $typicalAgeRange
357
     * @return TypicalAgeRangeUpdated
358
     */
359
    protected function createTypicalAgeRangeUpdatedEvent($typicalAgeRange)
360
    {
361
        return new TypicalAgeRangeUpdated($this->placeId, $typicalAgeRange);
0 ignored issues
show
Documentation introduced by
$typicalAgeRange is of type string, but the function expects a object<CultuurNet\UDB3\Offer\AgeRange>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
362
    }
363
364
    /**
365
     * @return TypicalAgeRangeDeleted
366
     */
367
    protected function createTypicalAgeRangeDeletedEvent()
368
    {
369
        return new TypicalAgeRangeDeleted($this->placeId);
370
    }
371
372
    /**
373
     * @param string $organizerId
374
     * @return OrganizerUpdated
375
     */
376
    protected function createOrganizerUpdatedEvent($organizerId)
377
    {
378
        return new OrganizerUpdated($this->placeId, $organizerId);
379
    }
380
381
    /**
382
     * @param string $organizerId
383
     * @return OrganizerDeleted
384
     */
385
    protected function createOrganizerDeletedEvent($organizerId)
386
    {
387
        return new OrganizerDeleted($this->placeId, $organizerId);
388
    }
389
390
    /**
391
     * @param ContactPoint $contactPoint
392
     * @return ContactPointUpdated
393
     */
394
    protected function createContactPointUpdatedEvent(ContactPoint $contactPoint)
395
    {
396
        return new ContactPointUpdated($this->placeId, $contactPoint);
397
    }
398
399
    /**
400
     * @param BookingInfo $bookingInfo
401
     * @return BookingInfoUpdated
402
     */
403
    protected function createBookingInfoUpdatedEvent(BookingInfo $bookingInfo)
404
    {
405
        return new BookingInfoUpdated($this->placeId, $bookingInfo);
406
    }
407
408
    /**
409
     * @param PriceInfo $priceInfo
410
     * @return PriceInfoUpdated
411
     */
412
    protected function createPriceInfoUpdatedEvent(PriceInfo $priceInfo)
413
    {
414
        return new PriceInfoUpdated($this->placeId, $priceInfo);
415
    }
416
417
    /**
418
     * @return PlaceDeleted
419
     */
420
    protected function createOfferDeletedEvent()
421
    {
422
        return new PlaceDeleted($this->placeId);
423
    }
424
425
    /**
426
     * @inheritDoc
427
     */
428
    protected function createPublishedEvent(\DateTimeInterface $publicationDate)
429
    {
430
        return new Published($this->placeId, $publicationDate);
431
    }
432
433
    /**
434
     * @inheritDoc
435
     */
436
    protected function createApprovedEvent()
437
    {
438
        return new Approved($this->placeId);
439
    }
440
441
    /**
442
     * @inheritDoc
443
     */
444
    protected function createRejectedEvent(StringLiteral $reason)
445
    {
446
        return new Rejected($this->placeId, $reason);
447
    }
448
449
    /**
450
     * @inheritDoc
451
     */
452
    protected function createFlaggedAsDuplicate()
453
    {
454
        return new FlaggedAsDuplicate($this->placeId);
455
    }
456
457
    /**
458
     * @inheritDoc
459
     */
460
    protected function createFlaggedAsInappropriate()
461
    {
462
        return new FlaggedAsInappropriate($this->placeId);
463
    }
464
465
    /**
466
     * @inheritDoc
467
     * @return ImagesImportedFromUDB2
468
     */
469
    protected function createImagesImportedFromUDB2(ImageCollection $images)
470
    {
471
        return new ImagesImportedFromUDB2($this->placeId, $images);
472
    }
473
474
    /**
475
     * @inheritDoc
476
     * @return ImagesUpdatedFromUDB2
477
     */
478
    protected function createImagesUpdatedFromUDB2(ImageCollection $images)
479
    {
480
        return new ImagesUpdatedFromUDB2($this->placeId, $images);
481
    }
482
}
483