Completed
Pull Request — master (#68)
by
unknown
06:18
created

Card   F

Complexity

Total Complexity 113

Size/Duplication

Total Lines 846
Duplicated Lines 7.57 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 113
lcom 1
cbo 12
dl 64
loc 846
rs 1.754
c 0
b 0
f 0

73 Methods

Rating   Name   Duplication   Size   Complexity  
A getShortId() 0 4 1
A setName() 0 6 1
A getName() 0 4 1
A setDescription() 0 6 1
A getDescription() 0 4 1
A getDescriptionData() 0 4 1
A getUrl() 0 4 1
A getShortUrl() 0 4 1
A getShortLink() 0 4 1
A setPosition() 0 6 1
A getPosition() 0 4 1
A setDueDate() 0 6 1
A getDueDate() 0 8 2
A setEmail() 0 6 1
A getEmail() 0 4 1
A setClosed() 0 6 1
A isClosed() 0 4 1
A setSubscribed() 0 6 1
A isSubscribed() 0 4 1
A setCheckItemStates() 0 6 1
A getCheckItemStates() 0 4 1
A setBoardId() 0 6 1
A getBoardId() 0 4 1
A setBoard() 0 4 1
A getBoard() 0 4 1
A setListId() 0 6 1
A getListId() 0 4 1
A setList() 0 4 1
A getList() 0 4 1
A moveToList() 0 17 3
A setChecklistIds() 0 6 1
A getChecklistIds() 0 4 1
A setChecklists() 0 10 2
A getChecklists() 0 12 2
A getChecklist() 0 14 3
A hasChecklist() 0 14 4
A addChecklist() 0 32 5
B removeChecklist() 0 23 6
A setMemberIds() 0 6 1
A getMemberIds() 0 4 1
A hasMember() 0 4 1
A addMember() 14 14 2
A removeMember() 18 18 4
A setMembers() 0 10 2
A getMembers() 0 10 2
A setMembersVotedIds() 0 6 1
A getMembersVotedIds() 0 4 1
A hasMemberVoted() 0 4 1
A addMemberVoted() 14 14 2
A removeMemberVoted() 18 18 4
A setMembersVoted() 0 10 2
A getMembersVoted() 0 10 2
A addAttachment() 0 14 4
A setAttachmentCoverId() 0 6 1
A getAttachmentCoverId() 0 4 1
A setManualCoverAttachment() 0 6 1
A getManualCoverAttachment() 0 4 1
A setLabels() 0 6 1
A getLabelIds() 0 4 1
A getLabels() 0 4 1
A hasLabel() 0 4 1
A addLabel() 0 5 1
A removeLabel() 0 9 3
A setBadges() 0 6 1
A getBadges() 0 4 1
A getDateOfLastActivity() 0 4 1
A getActions() 0 4 1
A addComment() 0 6 1
A removeComment() 0 6 1
A setIdCardSource() 0 6 1
A setKeepFromSource() 0 6 1
A preSave() 0 7 2
A postSave() 0 17 4

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Card often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Card, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Trello\Model;
4
5
use Trello\Events;
6
use Trello\Exception\InvalidArgumentException;
7
use Trello\Exception\RuntimeException;
8
9
/**
10
 * @codeCoverageIgnore
11
 */
12
class Card extends AbstractObject implements CardInterface
13
{
14
    protected $apiName = 'card';
15
16
    protected $loadParams = array(
17
        'fields'          => 'all',
18
        'board'           => true,
19
        'list'            => true,
20
        'stickers'        => true,
21
        'members'         => true,
22
        'membersVoted'    => true,
23
        'attachments'     => true,
24
        'checklists'      => 'all',
25
        'checkItemStates' => true,
26
        'labels'          => true,
27
        'actions'         => Events::CARD_COMMENT,
28
    );
29
30
    protected $newChecklists = array();
31
    protected $newComments = array();
32
    protected $commentsToBeRemoved = array();
33
    protected $newAttachments = array();
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function getShortId()
39
    {
40
        return $this->data['idShort'];
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function setName($name)
47
    {
48
        $this->data['name'] = $name;
49
50
        return $this;
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function getName()
57
    {
58
        return $this->data['name'];
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function setDescription($desc)
65
    {
66
        $this->data['desc'] = $desc;
67
68
        return $this;
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74
    public function getDescription()
75
    {
76
        return $this->data['desc'];
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function getDescriptionData()
83
    {
84
        return $this->data['descData'];
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function getUrl()
91
    {
92
        return $this->data['url'];
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function getShortUrl()
99
    {
100
        return $this->data['shortUrl'];
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function getShortLink()
107
    {
108
        return $this->data['shortLink'];
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function setPosition($pos)
115
    {
116
        $this->data['pos'] = $pos;
117
118
        return $this;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function getPosition()
125
    {
126
        return $this->data['pos'];
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function setDueDate(\DateTime $due = null)
133
    {
134
        $this->data['due'] = $due;
135
136
        return $this;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142
    public function getDueDate()
143
    {
144
        if ($this->data['due'] instanceof \DateTime) {
145
            return $this->data['due'];
146
        }
147
148
        return new \DateTime($this->data['due']);
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public function setEmail($email)
155
    {
156
        $this->data['email'] = $email;
157
158
        return $this;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function getEmail()
165
    {
166
        return $this->data['email'];
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function setClosed($closed)
173
    {
174
        $this->data['closed'] = $closed;
175
176
        return $this;
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     */
182
    public function isClosed()
183
    {
184
        return $this->data['closed'];
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function setSubscribed($subscribed)
191
    {
192
        $this->data['subscribed'] = $subscribed;
193
194
        return $this;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function isSubscribed()
201
    {
202
        return $this->data['subscribed'];
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208
    public function setCheckItemStates(array $checkItemStates)
209
    {
210
        $this->data['checkItemStates'] = $checkItemStates;
211
212
        return $this;
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218
    public function getCheckItemStates()
219
    {
220
        return $this->data['checkItemStates'];
221
    }
222
223
    /**
224
     * {@inheritdoc}
225
     */
226
    public function setBoardId($boardId)
227
    {
228
        $this->data['idBoard'] = $boardId;
229
230
        return $this;
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     */
236
    public function getBoardId()
237
    {
238
        return $this->data['idBoard'];
239
    }
240
241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function setBoard(BoardInterface $board)
245
    {
246
        return $this->setBoardId($board->getId());
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252
    public function getBoard()
253
    {
254
        return new Board($this->client, $this->getBoardId());
255
    }
256
257
    /**
258
     * {@inheritdoc}
259
     */
260
    public function setListId($listId)
261
    {
262
        $this->data['idList'] = $listId;
263
264
        return $this;
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    public function getListId()
271
    {
272
        return $this->data['idList'];
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278
    public function setList(CardlistInterface $list)
279
    {
280
        return $this->setListId($list->getId());
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    public function getList()
287
    {
288
        return new Cardlist($this->client, $this->getListId());
289
    }
290
291
    public function moveToList($name)
292
    {
293
        foreach ($this->getBoard()->getLists() as $list) {
294
            if ($list->getName() === $name) {
295
                $this->setList($list);
296
297
                return $this;
298
            }
299
        }
300
301
        throw new InvalidArgumentException(sprintf(
302
            'Card "%s" could not be moved to list "%s" as no list with that name exists on the board named "%s"',
303
            $this->getName(),
304
            $name,
305
            $this->getBoard()->getName()
306
        ));
307
    }
308
309
    /**
310
     * {@inheritdoc}
311
     */
312
    public function setChecklistIds(array $checklistIds)
313
    {
314
        $this->data['idChecklists'] = $checklistIds;
315
316
        return $this;
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322
    public function getChecklistIds()
323
    {
324
        return $this->data['idChecklists'];
325
    }
326
327
    /**
328
     * {@inheritdoc}
329
     */
330
    public function setChecklists(array $checklists)
331
    {
332
        $ids = array();
333
334
        foreach ($checklists as $checklist) {
335
            $ids[] = $checklist->getId();
336
        }
337
338
        return $this->setChecklistIds($ids);
339
    }
340
341
    /**
342
     * {@inheritdoc}
343
     */
344
    public function getChecklists()
345
    {
346
        $checklists = array();
347
348
        foreach ($this->getChecklistIds() as $id) {
349
            $checklists[] = new Checklist($this->client, $id);
350
        }
351
352
        $checklists = array_merge($checklists, $this->newChecklists);
353
354
        return $checklists;
355
    }
356
357
    /**
358
     * {@inheritdoc}
359
     * @param string $name
360
     */
361
    public function getChecklist($name)
362
    {
363
        foreach ($this->getChecklists() as $checklist) {
364
            if ($checklist->getName() === $name) {
365
                return $checklist;
366
            }
367
        }
368
369
        throw new InvalidArgumentException(sprintf(
370
            'There is no checklist named "%s"  on this card (%s).',
371
            $name,
372
            $this->getName()
373
        ));
374
    }
375
376
    /**
377
     * {@inheritdoc}
378
     */
379
    public function hasChecklist($checklist)
380
    {
381
        if ($checklist instanceof ChecklistInterface) {
382
            return in_array($checklist->getId(), $this->data['idChecklists']);
383
        }
384
385
        foreach ($this->getChecklists() as $existingList) {
386
            if ($existingList->getName() === $checklist) {
387
                return true;
388
            }
389
        }
390
391
        return false;
392
    }
393
394
    /**
395
     * {@inheritdoc}
396
     */
397
    public function addChecklist($checklist)
398
    {
399
        if (!$this->id) {
400
            throw new RuntimeException("You can't add checklists to a new card, you have to save it first.");
401
        }
402
403
        if (!$checklist instanceof ChecklistInterface) {
404
            $name = $checklist;
405
            $checklist = new Checklist($this->client);
406
            $checklist->setName($name);
407
        }
408
409
        $checklist->setCard($this);
410
411
        if (!$checklist->getId()) {
412
            $this->newChecklists[] = $checklist;
413
414
            return $this;
415
        }
416
417
        if ($this->hasChecklist($checklist)) {
418
            throw new InvalidArgumentException(sprintf(
419
                'Checklist %s is already on this card (%s).',
420
                $checklist->getName(),
421
                $this->getName()
422
            ));
423
        }
424
425
        $this->data['idChecklists'][] = $checklist->getId();
426
427
        return $this;
428
    }
429
430
    /**
431
     * {@inheritdoc}
432
     */
433
    public function removeChecklist($checklist)
434
    {
435
        if (!$this->hasChecklist($checklist)) {
436
            throw new InvalidArgumentException(sprintf(
437
                "Checklist %s is not on this card (%s), so you can't remove it.",
438
                is_object($checklist) ? $checklist->getName() : $checklist,
439
                $this->getName()
440
            ));
441
        }
442
443
        if (!$checklist instanceof ChecklistInterface) {
444
            $checklist = $this->getChecklist($checklist);
445
        }
446
447
        foreach ($this->data['idChecklists'] as $key => $checklistId) {
448
            if ($checklistId === $checklist->getId()) {
449
                unset($this->data['idChecklists'][$key]);
450
                $checklist->remove();
451
            }
452
        }
453
454
        return $this;
455
    }
456
457
    /**
458
     * {@inheritdoc}
459
     */
460
    public function setMemberIds(array $memberIds)
461
    {
462
        $this->data['idMembers'] = $memberIds;
463
464
        return $this;
465
    }
466
467
    /**
468
     * {@inheritdoc}
469
     */
470
    public function getMemberIds()
471
    {
472
        return $this->data['idMembers'];
473
    }
474
475
    /**
476
     * {@inheritdoc}
477
     */
478
    public function hasMember(MemberInterface $member)
479
    {
480
        return in_array($member->getId(), $this->data['idMembers']);
481
    }
482
483
    /**
484
     * {@inheritdoc}
485
     */
486 View Code Duplication
    public function addMember(MemberInterface $member)
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...
487
    {
488
        if ($this->hasMember($member)) {
489
            throw new InvalidArgumentException(sprintf(
490
                'Member %s is already on this card (%s).',
491
                $member->getFullName(),
492
                $this->getName()
493
            ));
494
        }
495
496
        $this->data['idMembers'][] = $member->getId();
497
498
        return $this;
499
    }
500
501
    /**
502
     * {@inheritdoc}
503
     */
504 View Code Duplication
    public function removeMember(MemberInterface $member)
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...
505
    {
506
        if (!$this->hasMember($member)) {
507
            throw new InvalidArgumentException(sprintf(
508
                "Member %s is not on this card (%s), so you can't remove him.",
509
                $member->getFullName(),
510
                $this->getName()
511
            ));
512
        }
513
514
        foreach ($this->data['idMembers'] as $key => $memberArray) {
515
            if ($memberArray['id'] === $member->getId()) {
516
                unset($this->data['idMembers'][$key]);
517
            }
518
        }
519
520
        return $this;
521
    }
522
523
    /**
524
     * {@inheritdoc}
525
     */
526
    public function setMembers(array $members)
527
    {
528
        $ids = array();
529
530
        foreach ($members as $member) {
531
            $ids[] = $member->getId();
532
        }
533
534
        return $this->setMemberIds($ids);
535
    }
536
537
    /**
538
     * {@inheritdoc}
539
     */
540
    public function getMembers()
541
    {
542
        $members = array();
543
544
        foreach ($this->getMemberIds() as $id) {
545
            $members[] = new Member($this->client, $id);
546
        }
547
548
        return $members;
549
    }
550
551
    /**
552
     * {@inheritdoc}
553
     */
554
    public function setMembersVotedIds(array $membersVotedIds)
555
    {
556
        $this->data['idMembersVoted'] = $membersVotedIds;
557
558
        return $this;
559
    }
560
561
    /**
562
     * {@inheritdoc}
563
     */
564
    public function getMembersVotedIds()
565
    {
566
        return $this->data['idMembersVoted'];
567
    }
568
569
    /**
570
     * {@inheritdoc}
571
     */
572
    public function hasMemberVoted(MemberInterface $member)
573
    {
574
        return in_array($member->getId(), $this->data['idMembersVoted']);
575
    }
576
577
    /**
578
     * {@inheritdoc}
579
     */
580 View Code Duplication
    public function addMemberVoted(MemberInterface $member)
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...
581
    {
582
        if ($this->hasMemberVoted($member)) {
583
            throw new InvalidArgumentException(sprintf(
584
                'Member %s has already voted this card (%s).',
585
                $member->getFullName(),
586
                $this->getName()
587
            ));
588
        }
589
590
        $this->data['idMembersVoted'][] = $member->getId();
591
592
        return $this;
593
    }
594
595
    /**
596
     * {@inheritdoc}
597
     */
598 View Code Duplication
    public function removeMemberVoted(MemberInterface $member)
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...
599
    {
600
        if (!$this->hasMemberVoted($member)) {
601
            throw new InvalidArgumentException(sprintf(
602
                "Member %s hasn't voted this card (%s), so you can't remove his vote.",
603
                $member->getFullName(),
604
                $this->getName()
605
            ));
606
        }
607
608
        foreach ($this->data['idMembersVoted'] as $key => $memberArray) {
609
            if ($memberArray['id'] === $member->getId()) {
610
                unset($this->data['idMembersVoted'][$key]);
611
            }
612
        }
613
614
        return $this;
615
    }
616
617
    /**
618
     * {@inheritdoc}
619
     */
620
    public function setMembersVoted(array $members)
621
    {
622
        $ids = array();
623
624
        foreach ($members as $member) {
625
            $ids[] = $member->getId();
626
        }
627
628
        return $this->setMembersVotedIds($ids);
629
    }
630
631
    /**
632
     * {@inheritdoc}
633
     */
634
    public function getMembersVoted()
635
    {
636
        $members = array();
637
638
        foreach ($this->getMembersVotedIds() as $id) {
639
            $members[] = new Member($this->client, $id);
640
        }
641
642
        return $members;
643
    }
644
645
    public function addAttachment($url, $name = '')
646
    {
647
        foreach ($this->data['attachments'] as $existing) {
648
            if ($existing['url'] === $url && $existing['name'] === $name) {
649
                return $this;
650
            }
651
        }
652
        $this->newAttachments[] = [
653
            'url' => $url,
654
            'name' => $name
655
        ];
656
657
        return $this;
658
    }
659
660
    /**
661
     * {@inheritdoc}
662
     */
663
    public function setAttachmentCoverId($attachmentCoverId)
664
    {
665
        $this->data['idAttachmentCover'] = $attachmentCoverId;
666
667
        return $this;
668
    }
669
670
    /**
671
     * {@inheritdoc}
672
     */
673
    public function getAttachmentCoverId()
674
    {
675
        return $this->data['idAttachmentCover'];
676
    }
677
678
    /**
679
     * {@inheritdoc}
680
     */
681
    public function setManualCoverAttachment($coverAttachment)
682
    {
683
        $this->data['manualCoverAttachment'] = $coverAttachment;
684
685
        return $this;
686
    }
687
688
    /**
689
     * {@inheritdoc}
690
     */
691
    public function getManualCoverAttachment()
692
    {
693
        return $this->data['manualCoverAttachment'];
694
    }
695
696
    /**
697
     * {@inheritdoc}
698
     */
699
    public function setLabels(array $labels)
700
    {
701
        $this->data['idLabels'] = $labels;
702
703
        return $this;
704
    }
705
706
    /**
707
     * {@inheritdoc}
708
     */
709
    public function getLabelIds()
710
    {
711
        return $this->data['idLabels'];
712
    }
713
714
    /**
715
     * {@inheritdoc}
716
     */
717
    public function getLabels()
718
    {
719
        return $this->data['labels'];
720
    }
721
722
    /**
723
     * {@inheritdoc}
724
     */
725
    public function hasLabel(LabelInterface $label)
726
    {
727
        return in_array($label->getId(), $this->data['idLabels']);
728
    }
729
730
    /**
731
     * {@inheritdoc}
732
     */
733
    public function addLabel(LabelInterface $label)
734
    {
735
        $this->data['idLabels'][] = $label->getId();
736
        return $this;
737
    }
738
739
    /**
740
     * {@inheritdoc}
741
     */
742
    public function removeLabel(LabelInterface $label)
743
    {
744
        foreach ($this->data['idLabels'] as $key => $id) {
745
            if ($id === $label->getId()) {
746
                unset($this->data['idLabels'][$key]);
747
            }
748
        }
749
        return $this;
750
    }
751
752
    /**
753
     * {@inheritdoc}
754
     */
755
    public function setBadges(array $badges)
756
    {
757
        $this->data['badges'] = $badges;
758
759
        return $this;
760
    }
761
762
    /**
763
     * {@inheritdoc}
764
     */
765
    public function getBadges()
766
    {
767
        return $this->data['badges'];
768
    }
769
770
    /**
771
     * {@inheritdoc}
772
     */
773
    public function getDateOfLastActivity()
774
    {
775
        return new \DateTime($this->data['dateLastActivity']);
776
    }
777
778
    /**
779
     * {@inheritdoc}
780
     */
781
    public function getActions($params = array())
782
    {
783
        return $this->api->actions()->all($this->id, $params);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Trello\Api\ApiInterface as the method actions() does only exist in the following implementations of said interface: Trello\Api\Board, Trello\Api\Card, Trello\Api\Cardlist, Trello\Api\Member.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
784
    }
785
786
    /**
787
     * {@inheritdoc}
788
     */
789
    public function addComment($text)
790
    {
791
        $this->newComments[] = $text;
792
793
        return $this;
794
    }
795
796
    /**
797
     * {@inheritdoc}
798
     */
799
    public function removeComment($commentId)
800
    {
801
        $this->commentsToBeRemoved[] = $commentId;
802
803
        return $this;
804
    }
805
806
    /**
807
     * {@inheritdoc}
808
     */
809
    public function setIdCardSource($id)
810
    {
811
        $this->data['idCardSource'] = $id;
812
813
        return $this;
814
    }
815
816
    /**
817
     * {@inheritdoc}
818
     */
819
    public function setKeepFromSource($keep)
820
    {
821
        $this->data['keepFromSource'] = $keep;
822
823
        return $this;
824
    }
825
826
    /**
827
     * {@inheritdoc}
828
     */
829
    protected function preSave()
830
    {
831
        foreach ($this->newChecklists as $checklist) {
832
            $checklist->save();
833
            $this->addChecklist($checklist);
834
        }
835
    }
836
837
    /**
838
     * {@inheritdoc}
839
     */
840
    protected function postSave()
841
    {
842
        foreach ($this->newComments as $key => $text) {
843
            $this->api->actions()->addComment($this->id, $text);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Trello\Api\ApiInterface as the method actions() does only exist in the following implementations of said interface: Trello\Api\Board, Trello\Api\Card, Trello\Api\Cardlist, Trello\Api\Member.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
844
            unset($this->newComments[$key]);
845
        }
846
847
        foreach ($this->commentsToBeRemoved as $key => $commentId) {
848
            $this->api->actions()->removeComment($this->id, $commentId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Trello\Api\ApiInterface as the method actions() does only exist in the following implementations of said interface: Trello\Api\Board, Trello\Api\Card, Trello\Api\Cardlist, Trello\Api\Member.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
849
            unset($this->commentsToBeRemoved[$key]);
850
        }
851
852
        foreach ($this->newAttachments as $key => $attachment) {
853
            $this->api->attachments()->create($this->id, $attachment);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Trello\Api\ApiInterface as the method attachments() does only exist in the following implementations of said interface: Trello\Api\Card.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
854
            unset($this->newAttachments[$key]);
855
        }
856
    }
857
}
858