Completed
Pull Request — master (#239)
by Luc
04:44
created

OfferCommandHandler   D

Complexity

Total Complexity 31

Size/Duplication

Total Lines 476
Duplicated Lines 3.99 %

Coupling/Cohesion

Components 1
Dependencies 28

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 28
dl 19
loc 476
rs 4.9
c 0
b 0
f 0

49 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A handle() 0 12 2
A getCommandHandlers() 19 19 4
getAddLabelClassName() 0 1 ?
getDeleteLabelClassName() 0 1 ?
getTranslateTitleClassName() 0 1 ?
getTranslateDescriptionClassName() 0 1 ?
getAddImageClassName() 0 1 ?
getUpdateImageClassName() 0 1 ?
getRemoveImageClassName() 0 1 ?
getSelectMainImageClassName() 0 1 ?
getUpdateDescriptionClassName() 0 1 ?
getUpdateTypicalAgeRangeClassName() 0 1 ?
getDeleteTypicalAgeRangeClassName() 0 1 ?
getUpdateOrganizerClassName() 0 1 ?
getDeleteOrganizerClassName() 0 1 ?
getUpdateContactPointClassName() 0 1 ?
getUpdateBookingInfoClassName() 0 1 ?
getUpdatePriceInfoClassName() 0 1 ?
getDeleteOfferClassName() 0 1 ?
getPublishClassName() 0 1 ?
getApproveClassName() 0 1 ?
getRejectClassName() 0 1 ?
getFlagAsDuplicateClassName() 0 1 ?
getFlagAsInappropriateClassName() 0 1 ?
A handleAddLabel() 0 14 1
A handleDeleteLabel() 0 6 1
A handleTranslateTitle() 0 6 1
A handleTranslateDescription() 0 6 1
A handleAddImage() 0 6 1
A handleRemoveImage() 0 6 1
A handleUpdateImage() 0 6 1
A handleSelectMainImage() 0 6 1
A handleUpdateDescription() 0 11 1
A handleUpdateTypicalAgeRange() 0 11 1
A handleDeleteTypicalAgeRange() 0 9 1
A handleUpdateOrganizer() 0 11 1
A handleDeleteOrganizer() 0 10 1
A handleUpdateContactPoint() 0 11 1
A handleUpdateBookingInfo() 0 10 1
A handleUpdatePriceInfo() 0 10 1
A handleDeleteOffer() 0 6 1
A handlePublish() 0 6 1
A handleApprove() 0 6 1
A handleReject() 0 6 1
A handleFlagAsDuplicate() 0 6 1
A handleFlagAsInappropriate() 0 6 1
A load() 0 4 1
A loadOrganizer() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace CultuurNet\UDB3\Offer;
4
5
use Broadway\Repository\RepositoryInterface;
6
use CultuurNet\UDB3\CommandHandling\Udb3CommandHandler;
7
use CultuurNet\UDB3\Label;
8
use CultuurNet\UDB3\Label\ReadModels\JSON\Repository\ReadRepositoryInterface;
9
use CultuurNet\UDB3\Label\ValueObjects\Visibility;
10
use CultuurNet\UDB3\Offer\Commands\AbstractAddLabel;
11
use CultuurNet\UDB3\Offer\Commands\AbstractDeleteLabel;
12
use CultuurNet\UDB3\Offer\Commands\AbstractDeleteOffer;
13
use CultuurNet\UDB3\Offer\Commands\AbstractDeleteOrganizer;
14
use CultuurNet\UDB3\Offer\Commands\AbstractDeleteTypicalAgeRange;
15
use CultuurNet\UDB3\Offer\Commands\AbstractUpdateBookingInfo;
16
use CultuurNet\UDB3\Offer\Commands\AbstractUpdateContactPoint;
17
use CultuurNet\UDB3\Offer\Commands\AbstractUpdateDescription;
18
use CultuurNet\UDB3\Offer\Commands\AbstractUpdateOrganizer;
19
use CultuurNet\UDB3\Offer\Commands\AbstractUpdatePriceInfo;
20
use CultuurNet\UDB3\Offer\Commands\AbstractUpdateTypicalAgeRange;
21
use CultuurNet\UDB3\Offer\Commands\Image\AbstractAddImage;
22
use CultuurNet\UDB3\Offer\Commands\Image\AbstractRemoveImage;
23
use CultuurNet\UDB3\Offer\Commands\Image\AbstractSelectMainImage;
24
use CultuurNet\UDB3\Offer\Commands\Image\AbstractUpdateImage;
25
use CultuurNet\UDB3\Offer\Commands\AbstractTranslateDescription;
26
use CultuurNet\UDB3\Offer\Commands\AbstractTranslateTitle;
27
use CultuurNet\UDB3\Offer\Commands\Moderation\AbstractApprove;
28
use CultuurNet\UDB3\Offer\Commands\Moderation\AbstractFlagAsDuplicate;
29
use CultuurNet\UDB3\Offer\Commands\Moderation\AbstractFlagAsInappropriate;
30
use CultuurNet\UDB3\Offer\Commands\Moderation\AbstractPublish;
31
use CultuurNet\UDB3\Offer\Commands\Moderation\AbstractReject;
32
use CultuurNet\UDB3\Organizer\Organizer;
33
use ValueObjects\String\String as StringLiteral;
34
35
abstract class OfferCommandHandler extends Udb3CommandHandler
36
{
37
    /**
38
     * @var RepositoryInterface
39
     */
40
    protected $offerRepository;
41
42
    /**
43
     * @var RepositoryInterface
44
     */
45
    protected $organizerRepository;
46
47
    /**
48
     * @var RepositoryInterface
49
     */
50
    protected $labelRepository;
51
52
    /**
53
     * @param RepositoryInterface $offerRepository
54
     * @param RepositoryInterface $organizerRepository
55
     * @param ReadRepositoryInterface $labelRepository
56
     */
57
    public function __construct(
58
        RepositoryInterface $offerRepository,
59
        RepositoryInterface $organizerRepository,
60
        ReadRepositoryInterface $labelRepository
61
    ) {
62
        $this->offerRepository = $offerRepository;
63
        $this->organizerRepository = $organizerRepository;
64
        $this->labelRepository = $labelRepository;
0 ignored issues
show
Documentation Bug introduced by
It seems like $labelRepository of type object<CultuurNet\UDB3\L...eadRepositoryInterface> is incompatible with the declared type object<Broadway\Repository\RepositoryInterface> of property $labelRepository.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function handle($command)
71
    {
72
        $commandName = get_class($command);
73
        $commandHandlers = $this->getCommandHandlers();
74
75
        if (isset($commandHandlers[$commandName])) {
76
            $handler = $commandHandlers[$commandName];
77
            call_user_func(array($this, $handler), $command);
78
        } else {
79
            parent::handle($command);
80
        }
81
    }
82
83
    /**
84
     * @return string[]
85
     *   An associative array of commands and their handler methods.
86
     */
87 View Code Duplication
    private function getCommandHandlers()
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...
88
    {
89
        $commands = [];
90
91
        foreach (get_class_methods($this) as $method) {
92
            $matches = [];
93
            if (preg_match('/^handle(.+)$/', $method, $matches)) {
94
                $command = $matches[1];
95
                $classNameMethod = 'get' . $command . 'ClassName';
96
97
                if (method_exists($this, $classNameMethod)) {
98
                    $commandFullClassName = call_user_func(array($this, $classNameMethod));
99
                    $commands[$commandFullClassName] = $method;
100
                }
101
            }
102
        }
103
104
        return $commands;
105
    }
106
107
    /**
108
     * @return string
109
     */
110
    abstract protected function getAddLabelClassName();
111
112
    /**
113
     * @return string
114
     */
115
    abstract protected function getDeleteLabelClassName();
116
117
    /**
118
     * @return string
119
     */
120
    abstract protected function getTranslateTitleClassName();
121
122
    /**
123
     * @return string
124
     */
125
    abstract protected function getTranslateDescriptionClassName();
126
127
    /**
128
     * @return string
129
     */
130
    abstract protected function getAddImageClassName();
131
132
    /**
133
     * @return string
134
     */
135
    abstract protected function getUpdateImageClassName();
136
137
    /**
138
     * @return string
139
     */
140
    abstract protected function getRemoveImageClassName();
141
142
    /**
143
     * @return string
144
     */
145
    abstract protected function getSelectMainImageClassName();
146
147
    /**
148
     * @return string
149
     */
150
    abstract protected function getUpdateDescriptionClassName();
151
152
    /**
153
     * @return string
154
     */
155
    abstract protected function getUpdateTypicalAgeRangeClassName();
156
157
    /**
158
     * @return string
159
     */
160
    abstract protected function getDeleteTypicalAgeRangeClassName();
161
162
    /**
163
     * @return string
164
     */
165
    abstract protected function getUpdateOrganizerClassName();
166
167
    /**
168
     * @return string
169
     */
170
    abstract protected function getDeleteOrganizerClassName();
171
172
    /**
173
     * @return string
174
     */
175
    abstract protected function getUpdateContactPointClassName();
176
177
    /**
178
     * @return string
179
     */
180
    abstract protected function getUpdateBookingInfoClassName();
181
182
    /**
183
     * @return string
184
     */
185
    abstract protected function getUpdatePriceInfoClassName();
186
187
    /**
188
     * @return string
189
     */
190
    abstract protected function getDeleteOfferClassName();
191
192
    /**
193
     * @return string
194
     */
195
    abstract protected function getPublishClassName();
196
197
    /**
198
     * @return string
199
     */
200
    abstract protected function getApproveClassName();
201
202
    /**
203
     * @return string
204
     */
205
    abstract protected function getRejectClassName();
206
207
    /**
208
     * @return string
209
     */
210
    abstract protected function getFlagAsDuplicateClassName();
211
212
    /**
213
     * @return string
214
     */
215
    abstract protected function getFlagAsInappropriateClassName();
216
217
    /**
218
     * @param AbstractAddLabel $addLabel
219
     */
220
    private function handleAddLabel(AbstractAddLabel $addLabel)
221
    {
222
        $offer = $this->load($addLabel->getItemId());
223
224
        $labelName = new StringLiteral((string)$addLabel->getLabel());
225
        $label = $this->labelRepository->getByName($labelName);
0 ignored issues
show
Bug introduced by
The method getByName() does not seem to exist on object<Broadway\Repository\RepositoryInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
226
227
        $offer->addLabel(new Label(
228
            $label->getName()->toNative(),
229
            $label->getVisibility() === Visibility::VISIBLE()
230
        ));
231
232
        $this->offerRepository->save($offer);
233
    }
234
235
    /**
236
     * @param AbstractDeleteLabel $deleteLabel
237
     */
238
    private function handleDeleteLabel(AbstractDeleteLabel $deleteLabel)
239
    {
240
        $offer = $this->load($deleteLabel->getItemId());
241
        $offer->deleteLabel($deleteLabel->getLabel());
242
        $this->offerRepository->save($offer);
243
    }
244
245
    /**
246
     * @param AbstractTranslateTitle $translateTitle
247
     */
248
    private function handleTranslateTitle(AbstractTranslateTitle $translateTitle)
249
    {
250
        $offer = $this->load($translateTitle->getItemId());
251
        $offer->translateTitle($translateTitle->getLanguage(), $translateTitle->getTitle());
0 ignored issues
show
Documentation introduced by
$translateTitle->getTitle() is of type string, but the function expects a object<ValueObjects\String\String>.

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...
252
        $this->offerRepository->save($offer);
253
    }
254
255
    /**
256
     * @param AbstractTranslateDescription $translateDescription
257
     */
258
    private function handleTranslateDescription(AbstractTranslateDescription $translateDescription)
259
    {
260
        $offer = $this->load($translateDescription->getItemId());
261
        $offer->translateDescription($translateDescription->getLanguage(), $translateDescription->getDescription());
0 ignored issues
show
Documentation introduced by
$translateDescription->getDescription() is of type string, but the function expects a object<ValueObjects\String\String>.

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...
262
        $this->offerRepository->save($offer);
263
    }
264
265
    /**
266
     * Handle an add image command.
267
     * @param AbstractAddImage $addImage
268
     */
269
    public function handleAddImage(AbstractAddImage $addImage)
270
    {
271
        $offer = $this->load($addImage->getItemId());
272
        $offer->addImage($addImage->getImage());
273
        $this->offerRepository->save($offer);
274
    }
275
276
    /**
277
     * @param AbstractRemoveImage $removeImage
278
     */
279
    public function handleRemoveImage(AbstractRemoveImage $removeImage)
280
    {
281
        $offer = $this->load($removeImage->getItemId());
282
        $offer->removeImage($removeImage->getImage());
283
        $this->offerRepository->save($offer);
284
    }
285
286
    /**
287
     * @param AbstractUpdateImage $updateImage
288
     */
289
    public function handleUpdateImage(AbstractUpdateImage $updateImage)
290
    {
291
        $offer = $this->load($updateImage->getItemId());
292
        $offer->updateImage($updateImage);
293
        $this->offerRepository->save($offer);
294
    }
295
296
    /**
297
     * @param AbstractSelectMainImage $selectMainImage
298
     */
299
    public function handleSelectMainImage(AbstractSelectMainImage $selectMainImage)
300
    {
301
        $offer = $this->load($selectMainImage->getItemId());
302
        $offer->selectMainImage($selectMainImage->getImage());
303
        $this->offerRepository->save($offer);
304
    }
305
306
    /**
307
     * Handle the update of description on a place.
308
     * @param AbstractUpdateDescription $updateDescription
309
     */
310
    public function handleUpdateDescription(AbstractUpdateDescription $updateDescription)
311
    {
312
        $offer = $this->load($updateDescription->getItemId());
313
314
        $offer->updateDescription(
315
            $updateDescription->getDescription()
316
        );
317
318
        $this->offerRepository->save($offer);
319
320
    }
321
322
    /**
323
     * Handle the update of typical age range on a place.
324
     * @param AbstractUpdateTypicalAgeRange $updateTypicalAgeRange
325
     */
326
    public function handleUpdateTypicalAgeRange(AbstractUpdateTypicalAgeRange $updateTypicalAgeRange)
327
    {
328
        $offer = $this->load($updateTypicalAgeRange->getItemId());
329
330
        $offer->updateTypicalAgeRange(
331
            $updateTypicalAgeRange->getTypicalAgeRange()
332
        );
333
334
        $this->offerRepository->save($offer);
335
336
    }
337
338
    /**
339
     * Handle the deletion of typical age range on a place.
340
     * @param AbstractDeleteTypicalAgeRange $deleteTypicalAgeRange
341
     */
342
    public function handleDeleteTypicalAgeRange(AbstractDeleteTypicalAgeRange $deleteTypicalAgeRange)
343
    {
344
        $offer = $this->load($deleteTypicalAgeRange->getItemId());
345
346
        $offer->deleteTypicalAgeRange();
347
348
        $this->offerRepository->save($offer);
349
350
    }
351
352
    /**
353
     * Handle an update command to update organizer of a place.
354
     * @param AbstractUpdateOrganizer $updateOrganizer
355
     */
356
    public function handleUpdateOrganizer(AbstractUpdateOrganizer $updateOrganizer)
357
    {
358
        $offer = $this->load($updateOrganizer->getItemId());
359
        $this->loadOrganizer($updateOrganizer->getOrganizerId());
360
361
        $offer->updateOrganizer(
362
            $updateOrganizer->getOrganizerId()
363
        );
364
365
        $this->offerRepository->save($offer);
366
    }
367
368
    /**
369
     * Handle an update command to delete the organizer.
370
     * @param AbstractDeleteOrganizer $deleteOrganizer
371
     */
372
    public function handleDeleteOrganizer(AbstractDeleteOrganizer $deleteOrganizer)
373
    {
374
        $offer = $this->load($deleteOrganizer->getItemId());
375
376
        $offer->deleteOrganizer(
377
            $deleteOrganizer->getOrganizerId()
378
        );
379
380
        $this->offerRepository->save($offer);
381
    }
382
383
    /**
384
     * Handle an update command to updated the contact point.
385
     * @param AbstractUpdateContactPoint $updateContactPoint
386
     */
387
    public function handleUpdateContactPoint(AbstractUpdateContactPoint $updateContactPoint)
388
    {
389
        $offer = $this->load($updateContactPoint->getId());
390
391
        $offer->updateContactPoint(
392
            $updateContactPoint->getContactPoint()
393
        );
394
395
        $this->offerRepository->save($offer);
396
397
    }
398
399
    /**
400
     * Handle an update command to updated the booking info.
401
     * @param AbstractUpdateBookingInfo $updateBookingInfo
402
     */
403
    public function handleUpdateBookingInfo(AbstractUpdateBookingInfo $updateBookingInfo)
404
    {
405
        $offer = $this->load($updateBookingInfo->getItemId());
406
407
        $offer->updateBookingInfo(
408
            $updateBookingInfo->getBookingInfo()
409
        );
410
411
        $this->offerRepository->save($offer);
412
    }
413
414
    /**
415
     * @param AbstractUpdatePriceInfo $updatePriceInfo
416
     */
417
    private function handleUpdatePriceInfo(AbstractUpdatePriceInfo $updatePriceInfo)
418
    {
419
        $offer = $this->load($updatePriceInfo->getItemId());
420
421
        $offer->updatePriceInfo(
422
            $updatePriceInfo->getPriceInfo()
423
        );
424
425
        $this->offerRepository->save($offer);
426
    }
427
428
    /**
429
     * @param AbstractDeleteOffer $deleteOffer
430
     */
431
    private function handleDeleteOffer(AbstractDeleteOffer $deleteOffer)
432
    {
433
        $offer = $this->load($deleteOffer->getItemId());
434
        $offer->delete();
435
        $this->offerRepository->save($offer);
436
    }
437
438
    /**
439
     * @param AbstractPublish $publish
440
     */
441
    private function handlePublish(AbstractPublish $publish)
442
    {
443
        $offer = $this->load($publish->getItemId());
444
        $offer->publish($publish->getPublicationDate());
445
        $this->offerRepository->save($offer);
446
    }
447
448
    /**
449
     * @param AbstractApprove $approve
450
     */
451
    private function handleApprove(AbstractApprove $approve)
452
    {
453
        $offer = $this->load($approve->getItemId());
454
        $offer->approve();
455
        $this->offerRepository->save($offer);
456
    }
457
458
    /**
459
     * @param AbstractReject $reject
460
     */
461
    private function handleReject(AbstractReject $reject)
462
    {
463
        $offer = $this->load($reject->getItemId());
464
        $offer->reject($reject->getReason());
465
        $this->offerRepository->save($offer);
466
    }
467
468
    /**
469
     * @param AbstractFlagAsDuplicate $flagAsDuplicate
470
     */
471
    private function handleFlagAsDuplicate(AbstractFlagAsDuplicate $flagAsDuplicate)
472
    {
473
        $offer = $this->load($flagAsDuplicate->getItemId());
474
        $offer->flagAsDuplicate();
475
        $this->offerRepository->save($offer);
476
    }
477
478
    /**
479
     * @param AbstractFlagAsInappropriate $flagAsInappropriate
480
     */
481
    private function handleFlagAsInappropriate(AbstractFlagAsInappropriate $flagAsInappropriate)
482
    {
483
        $offer = $this->load($flagAsInappropriate->getItemId());
484
        $offer->flagAsInappropriate();
485
        $this->offerRepository->save($offer);
486
    }
487
488
    /**
489
     * Makes it easier to type-hint to Offer.
490
     *
491
     * @param string $id
492
     * @return Offer
493
     */
494
    private function load($id)
495
    {
496
        return $this->offerRepository->load($id);
497
    }
498
499
    /**
500
     * Makes it easier to type-hint to Organizer.
501
     *
502
     * @param string $id
503
     * @return Organizer
504
     */
505
    private function loadOrganizer($id)
506
    {
507
        return $this->organizerRepository->load($id);
508
509
    }
510
}
511