Checklist   B
last analyzed

Complexity

Total Complexity 38

Size/Duplication

Total Lines 261
Duplicated Lines 3.83 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 38
lcom 1
cbo 6
dl 10
loc 261
rs 8.3999
c 1
b 1
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A setName() 0 6 1
A getName() 0 4 1
A setBoardId() 0 6 1
A getBoardId() 0 4 1
A setBoard() 0 4 1
A getBoard() 0 4 1
A setCardId() 0 6 1
A getCardId() 0 4 1
A setCard() 0 4 1
A getCard() 0 4 1
A setPosition() 0 6 1
A getPosition() 0 4 1
A getItems() 0 4 1
B hasItem() 5 10 5
B getItemKey() 5 14 5
A removeItem() 0 12 2
A setItem() 0 20 3
A setItemChecked() 0 7 1
A isItemChecked() 0 6 1
A postRefresh() 0 6 2
B preSave() 0 19 5

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 Trello\Model;
4
5
use Trello\Exception\InvalidArgumentException;
6
use Trello\ClientInterface;
7
8
/**
9
 * @codeCoverageIgnore
10
 */
11
class Checklist extends AbstractObject implements ChecklistInterface
12
{
13
    protected $apiName = 'checklist';
14
15
    protected $loadParams = array(
16
        'fields' => 'all',
17
        'checkItems' => 'all',
18
        'checkItem_fields' => 'all',
19
    );
20
21
    protected $itemsToBeRemoved = array();
22
23
    public function __construct(ClientInterface $client, $id = null)
24
    {
25
        $this->data = array(
26
            'name' => null,
27
            'checkItems' => array(),
28
        );
29
30
        parent::__construct($client, $id);
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function setName($name)
37
    {
38
        $this->data['name'] = $name;
39
40
        return $this;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function getName()
47
    {
48
        return $this->data['name'];
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function setBoardId($boardId)
55
    {
56
        $this->data['idBoard'] = $boardId;
57
58
        return $this;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function getBoardId()
65
    {
66
        return $this->data['idBoard'];
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72
    public function setBoard(BoardInterface $board)
73
    {
74
        return $this->setBoardId($board->getId());
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function getBoard()
81
    {
82
        return new Board($this->client, $this->getBoardId());
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function setCardId($cardId)
89
    {
90
        $this->data['idCard'] = $cardId;
91
92
        return $this;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function getCardId()
99
    {
100
        return $this->data['idCard'];
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function setCard(CardInterface $card)
107
    {
108
        return $this->setCardId($card->getId());
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function getCard()
115
    {
116
        return new Card($this->client, $this->getCardId());
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    public function setPosition($pos)
123
    {
124
        $this->data['pos'] = $pos;
125
126
        return $this;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function getPosition()
133
    {
134
        return $this->data['pos'];
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    public function getItems()
141
    {
142
        return $this->data['checkItems'];
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     * @param string $nameOrId
148
     */
149
    public function hasItem($nameOrId)
150
    {
151 View Code Duplication
        foreach ($this->getItems() as $item) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
152
            if ($item['name'] === $nameOrId || (isset($item['id']) && $item['id'] === $nameOrId)) {
153
                return true;
154
            }
155
        }
156
157
        return false;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function getItemKey($nameOrId)
164
    {
165 View Code Duplication
        foreach ($this->getItems() as $key => $item) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
166
            if ($item['name'] === $nameOrId || (isset($item['id']) && $item['id'] === $nameOrId)) {
167
                return $key;
168
            }
169
        }
170
171
        throw new InvalidArgumentException(sprintf(
172
            'Checklist "%s" does not have an item with name or id "%s"',
173
            $this->getName(),
174
            $nameOrId
175
        ));
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function removeItem($nameOrId)
182
    {
183
        $key = $this->getItemKey($nameOrId);
184
185
        if (isset($this->data['checkItems'][$key]['id'])) {
186
            $this->itemsToBeRemoved[] = $this->data['checkItems'][$key]['id'];
187
        }
188
189
        unset($this->data['checkItems'][$key]);
190
191
        return $this;
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function setItem($nameOrId, $checked = null, $position = null)
198
    {
199
        if ($this->hasItem($nameOrId)) {
200
            $key = $this->getItemKey($nameOrId);
201
202
            $this->data['checkItems'][$key]['state'] = $checked;
203
204
            if (isset($position)) {
205
                $this->data['checkItems'][$key]['position'] = $position;
206
            }
207
        } else {
208
            $this->data['checkItems'][] = array(
209
                'name'     => $nameOrId,
210
                'state'    => $checked,
211
                'position' => $position,
212
            );
213
        }
214
215
        return $this;
216
    }
217
218
    /**
219
     * {@inheritdoc}
220
     */
221
    public function setItemChecked($nameOrId, $bool)
222
    {
223
        $key = $this->getItemKey($nameOrId);
224
        $this->data['checkItems'][$key]['state'] = $bool;
225
226
        return $this;
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232
    public function isItemChecked($nameOrId)
233
    {
234
        $key = $this->getItemKey($nameOrId);
235
236
        return $this->data['checkItems'][$key]['state'];
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242
    protected function postRefresh()
243
    {
244
        foreach ($this->data['checkItems'] as $key => $item) {
245
            $this->data['checkItems'][$key]['state'] = in_array($item['state'], array(true, 'complete', 'true'));
246
        }
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252
    protected function preSave()
253
    {
254
        $items = $this->data['checkItems'];
255
256
        if (!$this->id) {
257
            $this->create();
258
        }
259
260
        foreach ($this->itemsToBeRemoved as $itemId) {
261
            $this->api->items()->remove($this->id, $itemId);
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 items() does only exist in the following implementations of said interface: Trello\Api\Checklist.

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...
262
        }
263
        foreach ($items as $item) {
264
            if (isset($item['id'])) {
265
                $this->api->items()->update($this->id, $item['id'], $item);
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 items() does only exist in the following implementations of said interface: Trello\Api\Checklist.

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...
266
            } else {
267
                $this->api->items()->create($this->id, $item['name'], $item['state'], $item);
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 items() does only exist in the following implementations of said interface: Trello\Api\Checklist.

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...
268
            }
269
        }
270
    }
271
}
272