Completed
Pull Request — master (#344)
by Luc
05:16
created

Place::createPlace()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 20

Duplication

Lines 24
Ratio 100 %

Importance

Changes 0
Metric Value
dl 24
loc 24
rs 8.9713
c 0
b 0
f 0
cc 1
eloc 20
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\ThemeUpdated;
53
use CultuurNet\UDB3\Place\Events\TitleTranslated;
54
use CultuurNet\UDB3\Place\Events\TitleUpdated;
55
use CultuurNet\UDB3\Place\Events\TypeUpdated;
56
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeDeleted;
57
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeUpdated;
58
use CultuurNet\UDB3\PriceInfo\PriceInfo;
59
use CultuurNet\UDB3\Theme;
60
use CultuurNet\UDB3\Title;
61
use DateTimeImmutable;
62
use ValueObjects\StringLiteral\StringLiteral;
63
64
class Place extends Offer implements UpdateableWithCdbXmlInterface
65
{
66
    /**
67
     * @var string
68
     */
69
    private $placeId;
70
71
    public function __construct()
72
    {
73
        parent::__construct();
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function getAggregateRootId()
80
    {
81
        return $this->placeId;
82
    }
83
84
    /**
85
     * Factory method to create a new Place.
86
     *
87
     * @todo Refactor this method so it can be called create. Currently the
88
     * normal behavior for create is taken by the legacy udb2 logic.
89
     * The PlaceImportedFromUDB2 could be a superclass of Place.
90
     *
91
     * @param string $id
92
     * @param Language $mainLanguage
93
     * @param Title $title
94
     * @param EventType $eventType
95
     * @param Address $address
96
     * @param CalendarInterface $calendar
97
     * @param Theme|null $theme
98
     * @param DateTimeImmutable|null $publicationDate
99
     *
100
     * @return self
101
     */
102 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...
103
        $id,
104
        Language $mainLanguage,
105
        Title $title,
106
        EventType $eventType,
107
        Address $address,
108
        CalendarInterface $calendar,
109
        Theme $theme = null,
110
        DateTimeImmutable $publicationDate = null
111
    ) {
112
        $place = new self();
113
        $place->apply(new PlaceCreated(
114
            $id,
115
            $mainLanguage,
116
            $title,
117
            $eventType,
118
            $address,
119
            $calendar,
120
            $theme,
121
            $publicationDate
122
        ));
123
124
        return $place;
125
    }
126
127
    /**
128
     * Apply the place created event.
129
     * @param PlaceCreated $placeCreated
130
     */
131
    protected function applyPlaceCreated(PlaceCreated $placeCreated)
132
    {
133
        $this->mainLanguage = $placeCreated->getMainLanguage();
134
        $this->placeId = $placeCreated->getPlaceId();
135
        $this->workflowStatus = WorkflowStatus::DRAFT();
136
    }
137
138
    /**
139
     * Update the major info.
140
     *
141
     * @param Title $title
142
     * @param EventType $eventType
143
     * @param Address $address
144
     * @param CalendarInterface $calendar
145
     * @param Theme $theme
146
     */
147
    public function updateMajorInfo(
148
        Title $title,
149
        EventType $eventType,
150
        Address $address,
151
        CalendarInterface $calendar,
152
        Theme $theme = null
153
    ) {
154
        $this->apply(
155
            new MajorInfoUpdated(
156
                $this->placeId,
157
                $title,
158
                $eventType,
159
                $address,
160
                $calendar,
161
                $theme
162
            )
163
        );
164
    }
165
166
    /**
167
     * @param Address $address
168
     * @param Language $language
169
     */
170
    public function updateAddress(Address $address, Language $language)
171
    {
172
        if ($language->getCode() === $this->mainLanguage->getCode()) {
173
            $event = new AddressUpdated($this->placeId, $address);
174
        } else {
175
            $event = new AddressTranslated($this->placeId, $address, $language);
176
        }
177
178
        $this->apply($event);
179
    }
180
181
    /**
182
     * Import from UDB2.
183
     *
184
     * @param string $actorId
185
     *   The actor id.
186
     * @param string $cdbXml
187
     *   The cdb xml.
188
     * @param string $cdbXmlNamespaceUri
189
     *   The cdb xml namespace uri.
190
     *
191
     * @return Place
192
     */
193
    public static function importFromUDB2Actor(
194
        $actorId,
195
        $cdbXml,
196
        $cdbXmlNamespaceUri
197
    ) {
198
        $place = new static();
199
        $place->apply(
200
            new PlaceImportedFromUDB2(
201
                $actorId,
202
                $cdbXml,
203
                $cdbXmlNamespaceUri
204
            )
205
        );
206
207
        return $place;
208
    }
209
210
    /**
211
     * @param PlaceImportedFromUDB2 $placeImported
212
     */
213 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...
214
        PlaceImportedFromUDB2 $placeImported
215
    ) {
216
        $this->placeId = $placeImported->getActorId();
217
218
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
219
            $placeImported->getCdbXmlNamespaceUri(),
220
            $placeImported->getCdbXml()
221
        );
222
223
        $this->importWorkflowStatus($udb2Actor);
224
        $this->labels = LabelCollection::fromKeywords($udb2Actor->getKeywords(true));
225
    }
226
227
    /**
228
     * @param PlaceUpdatedFromUDB2 $placeUpdatedFromUDB2
229
     */
230 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...
231
        PlaceUpdatedFromUDB2 $placeUpdatedFromUDB2
232
    ) {
233
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
234
            $placeUpdatedFromUDB2->getCdbXmlNamespaceUri(),
235
            $placeUpdatedFromUDB2->getCdbXml()
236
        );
237
238
        $this->importWorkflowStatus($udb2Actor);
239
        $this->labels = LabelCollection::fromKeywords($udb2Actor->getKeywords(true));
240
    }
241
242
    /**
243
     * @inheritdoc
244
     */
245
    public function updateWithCdbXml($cdbXml, $cdbXmlNamespaceUri)
246
    {
247
        ActorItemFactory::createActorFromCdbXml($cdbXmlNamespaceUri, $cdbXml);
248
249
        $this->apply(
250
            new PlaceUpdatedFromUDB2(
251
                $this->placeId,
252
                $cdbXml,
253
                $cdbXmlNamespaceUri
254
            )
255
        );
256
    }
257
258
    /**
259
     * @param Label $label
260
     * @return LabelAdded
261
     */
262
    protected function createLabelAddedEvent(Label $label)
263
    {
264
        return new LabelAdded($this->placeId, $label);
265
    }
266
267
    /**
268
     * @param Label $label
269
     * @return LabelRemoved
270
     */
271
    protected function createLabelRemovedEvent(Label $label)
272
    {
273
        return new LabelRemoved($this->placeId, $label);
274
    }
275
276
    protected function createImageAddedEvent(Image $image)
277
    {
278
        return new ImageAdded($this->placeId, $image);
279
    }
280
281
    protected function createImageRemovedEvent(Image $image)
282
    {
283
        return new ImageRemoved($this->placeId, $image);
284
    }
285
286
    protected function createImageUpdatedEvent(
287
        AbstractUpdateImage $updateImageCommand
288
    ) {
289
        return new ImageUpdated(
290
            $this->placeId,
291
            $updateImageCommand->getMediaObjectId(),
292
            $updateImageCommand->getDescription(),
293
            $updateImageCommand->getCopyrightHolder()
294
        );
295
    }
296
297
    protected function createMainImageSelectedEvent(Image $image)
298
    {
299
        return new MainImageSelected($this->placeId, $image);
300
    }
301
302
    /**
303
     * @param Language $language
304
     * @param StringLiteral $title
305
     * @return TitleTranslated
306
     */
307
    protected function createTitleTranslatedEvent(Language $language, StringLiteral $title)
308
    {
309
        return new TitleTranslated($this->placeId, $language, $title);
310
    }
311
312
    /**
313
     * @param Title $title
314
     * @return TitleUpdated
315
     */
316
    protected function createTitleUpdatedEvent(Title $title)
317
    {
318
        return new TitleUpdated($this->placeId, $title);
319
    }
320
321
    /**
322
     * @param Language $language
323
     * @param StringLiteral $description
324
     * @return DescriptionTranslated
325
     */
326
    protected function createDescriptionTranslatedEvent(Language $language, StringLiteral $description)
327
    {
328
        return new DescriptionTranslated($this->placeId, $language, $description);
329
    }
330
331
    /**
332
     * @param string $description
333
     * @return DescriptionUpdated
334
     */
335
    protected function createDescriptionUpdatedEvent($description)
336
    {
337
        return new DescriptionUpdated($this->placeId, $description);
338
    }
339
340
    /**
341
     * @inheritdoc
342
     */
343
    protected function createCalendarUpdatedEvent(Calendar $calendar)
344
    {
345
        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...
346
    }
347
    
348
    /**
349
     * @param string $typicalAgeRange
350
     * @return TypicalAgeRangeUpdated
351
     */
352
    protected function createTypicalAgeRangeUpdatedEvent($typicalAgeRange)
353
    {
354
        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...
355
    }
356
357
    /**
358
     * @return TypicalAgeRangeDeleted
359
     */
360
    protected function createTypicalAgeRangeDeletedEvent()
361
    {
362
        return new TypicalAgeRangeDeleted($this->placeId);
363
    }
364
365
    /**
366
     * @param string $organizerId
367
     * @return OrganizerUpdated
368
     */
369
    protected function createOrganizerUpdatedEvent($organizerId)
370
    {
371
        return new OrganizerUpdated($this->placeId, $organizerId);
372
    }
373
374
    /**
375
     * @param string $organizerId
376
     * @return OrganizerDeleted
377
     */
378
    protected function createOrganizerDeletedEvent($organizerId)
379
    {
380
        return new OrganizerDeleted($this->placeId, $organizerId);
381
    }
382
383
    /**
384
     * @param ContactPoint $contactPoint
385
     * @return ContactPointUpdated
386
     */
387
    protected function createContactPointUpdatedEvent(ContactPoint $contactPoint)
388
    {
389
        return new ContactPointUpdated($this->placeId, $contactPoint);
390
    }
391
392
    /**
393
     * @inheritdoc
394
     */
395
    protected function createGeoCoordinatesUpdatedEvent(Coordinates $coordinates)
396
    {
397
        return new GeoCoordinatesUpdated($this->placeId, $coordinates);
398
    }
399
400
    /**
401
     * @param BookingInfo $bookingInfo
402
     * @return BookingInfoUpdated
403
     */
404
    protected function createBookingInfoUpdatedEvent(BookingInfo $bookingInfo)
405
    {
406
        return new BookingInfoUpdated($this->placeId, $bookingInfo);
407
    }
408
409
    /**
410
     * @param PriceInfo $priceInfo
411
     * @return PriceInfoUpdated
412
     */
413
    protected function createPriceInfoUpdatedEvent(PriceInfo $priceInfo)
414
    {
415
        return new PriceInfoUpdated($this->placeId, $priceInfo);
416
    }
417
418
    /**
419
     * @return PlaceDeleted
420
     */
421
    protected function createOfferDeletedEvent()
422
    {
423
        return new PlaceDeleted($this->placeId);
424
    }
425
426
    /**
427
     * @inheritDoc
428
     */
429
    protected function createPublishedEvent(\DateTimeInterface $publicationDate)
430
    {
431
        return new Published($this->placeId, $publicationDate);
432
    }
433
434
    /**
435
     * @inheritDoc
436
     */
437
    protected function createApprovedEvent()
438
    {
439
        return new Approved($this->placeId);
440
    }
441
442
    /**
443
     * @inheritDoc
444
     */
445
    protected function createRejectedEvent(StringLiteral $reason)
446
    {
447
        return new Rejected($this->placeId, $reason);
448
    }
449
450
    /**
451
     * @inheritDoc
452
     */
453
    protected function createFlaggedAsDuplicate()
454
    {
455
        return new FlaggedAsDuplicate($this->placeId);
456
    }
457
458
    /**
459
     * @inheritDoc
460
     */
461
    protected function createFlaggedAsInappropriate()
462
    {
463
        return new FlaggedAsInappropriate($this->placeId);
464
    }
465
466
    /**
467
     * @inheritDoc
468
     * @return ImagesImportedFromUDB2
469
     */
470
    protected function createImagesImportedFromUDB2(ImageCollection $images)
471
    {
472
        return new ImagesImportedFromUDB2($this->placeId, $images);
473
    }
474
475
    /**
476
     * @inheritDoc
477
     * @return ImagesUpdatedFromUDB2
478
     */
479
    protected function createImagesUpdatedFromUDB2(ImageCollection $images)
480
    {
481
        return new ImagesUpdatedFromUDB2($this->placeId, $images);
482
    }
483
484
    protected function createTypeUpdatedEvent(EventType $type)
485
    {
486
        return new TypeUpdated($this->placeId, $type);
487
    }
488
489
    protected function createThemeUpdatedEvent(Theme $theme)
490
    {
491
        return new ThemeUpdated($this->placeId, $theme);
492
    }
493
494
    /**
495
     * @inheritdoc
496
     */
497
    protected function createFacilitiesUpdatedEvent(array $facilities)
498
    {
499
        return new FacilitiesUpdated($this->placeId, $facilities);
500
    }
501
}
502