TokenCollection   C
last analyzed

Complexity

Total Complexity 55

Size/Duplication

Total Lines 365
Duplicated Lines 12.05 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 86.29%

Importance

Changes 0
Metric Value
wmc 55
lcom 1
cbo 2
dl 44
loc 365
ccs 107
cts 124
cp 0.8629
rs 6.8
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A getIgnoreUnknownFilters() 0 4 1
A setIgnoreUnknownFilters() 0 5 1
A getIterator() 0 4 1
A hasSourceHash() 0 4 1
A getSourceHash() 0 7 2
A setSourceHash() 0 5 1
A isEmpty() 0 4 1
A getCount() 0 4 1
A add() 0 6 1
A import() 0 9 2
A remove() 0 5 1
A clear() 0 5 1
A has() 0 4 1
A get() 0 4 1
A getArray() 0 4 1
A getNames() 0 9 2
B findByName() 0 19 9
A findResolved() 11 11 3
A findResolvedAndNotInjected() 11 11 4
A findUnresolved() 11 11 3
A hasUnresolved() 0 10 3
A findWithUnresolvedFilters() 11 11 3
C resolve() 0 22 9

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 TokenCollection 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 TokenCollection, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ConfigToken;
4
5
use ConfigToken\TokenFilter\Exception\UnknownFilterException;
6
use ConfigToken\TokenResolver\Exception\OutOfScopeException;
7
use ConfigToken\TokenResolver\Exception\ScopeTokenValueSerializationException;
8
use ConfigToken\TokenResolver\Exception\TokenFormatException;
9
use ConfigToken\TokenResolver\Exception\UnknownTokenException;
10
use ConfigToken\TokenResolver\TokenResolverInterface;
11
12
/**
13
 * Generic token collection class used in conjunction with a given token resolver instance to resolve
14
 * tokens to values and apply the given filters.
15
 */
16
class TokenCollection implements \IteratorAggregate
17
{
18
    /** @var Token[] */
19
    protected $tokens =array ();
20
21
    /** @var string */
22
    protected $sourceHash;
23
24
    /** @var boolean */
25
    protected $ignoreUnknownFilters = True;
26
27
    /**
28
     * @param Token[] $tokens Array of Token with tokenString as keys.
29
     */
30 15
    public function __construct(array $tokens = null)
31
    {
32 15
        if (isset($tokens)) {
33 1
            $this->tokens = $tokens;
34 1
        }
35 15
    }
36
37
    /**
38
     * Get the ignore unknown filters flag.
39
     *
40
     * @return boolean
41
     */
42
    public function getIgnoreUnknownFilters()
43
    {
44
        return $this->ignoreUnknownFilters;
45
    }
46
47
    /**
48
     * Set the ignore unknown filters flag.
49
     *
50
     * @param boolean $ignoreUnknownFilters The new value for the ignore unknown filters flag.
51
     * @return $this
52
     */
53
    public function setIgnoreUnknownFilters($ignoreUnknownFilters)
54
    {
55
        $this->ignoreUnknownFilters = $ignoreUnknownFilters;
56
        return $this;
57
    }
58
59
    /**
60
     * (PHP 5 &gt;= 5.0.0)<br/>
61
     * Retrieve an external iterator
62
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
63
     * @return \Traversable An instance of an object implementing <b>Iterator</b> or <b>Traversable</b>
64
     */
65
    public function getIterator()
66
    {
67
        return new \ArrayIterator($this->tokens);
68
    }
69
70
71
    /**
72
     * Check if the source hash was set.
73
     *
74
     * @return boolean
75
     */
76 1
    public function hasSourceHash()
77
    {
78 1
        return isset($this->sourceHash);
79
    }
80
81
    /**
82
     * Get the source hash.
83
     *
84
     * @return string|null
85
     */
86 1
    public function getSourceHash()
87
    {
88 1
        if (!$this->hasSourceHash()) {
89
            return null;
90
        }
91 1
        return $this->sourceHash;
92
    }
93
94
    /**
95
     * Set the source hash.
96
     *
97
     * @param string $value The new value.
98
     * @return $this
99
     */
100 14
    public function setSourceHash($value)
101
    {
102 14
        $this->sourceHash = $value;
103 14
        return $this;
104
    }
105
106
    /**
107
     * Check if the list of tokens is empty.
108
     *
109
     * @return boolean
110
     */
111 6
    public function isEmpty()
112
    {
113 6
        return count($this->tokens) == 0;
114
    }
115
116
    /**
117
     * Get the number of tokens in the list
118
     *
119
     * @return integer
120
     */
121 1
    public function getCount()
122
    {
123 1
        return count($this->tokens);
124
    }
125
126
    /**
127
     * Add a new token to the list.
128
     * If another token already exists with the same tokenString then it will be overwritten.
129
     *
130
     * @param Token $token
131
     * @return $this
132
     */
133 14
    public function add(Token $token)
134
    {
135 14
        $this->tokens[$token->getTokenString()] = $token;
136
137 14
        return $this;
138
    }
139
140
    /**
141
     * Import add all tokens from another list.
142
     * Existing tokens will be overwritten. The hash will be unset.
143
     *
144
     * @param TokenCollection $tokens
145
     * @return $this
146
     */
147 1
    public function import(TokenCollection $tokens)
148
    {
149 1
        foreach ($tokens->tokens as $tokenString => $token) {
150 1
            $this->tokens[$tokenString] = $token;
151 1
        }
152 1
        $this->sourceHash = null;
153
154 1
        return $this;
155
    }
156
157
    /**
158
     * Remove the given token from the list.
159
     *
160
     * @param Token $token
161
     * @return $this
162
     */
163 1
    public function remove(Token $token)
164
    {
165 1
        unset($this->tokens[$token->getTokenString()]);
166 1
        return $this;
167
    }
168
169
    /**
170
     * Clear the list of tokens.
171
     *
172
     * @return $this
173
     */
174 1
    public function clear()
175
    {
176 1
        $this->tokens = array();
177 1
        return $this;
178
    }
179
180
    /**
181
     * Check if a token with the given token string is in this list.
182
     *
183
     * @param string $tokenString
184
     * @return boolean
185
     */
186 14
    public function has($tokenString)
187
    {
188 14
        return isset($this->tokens[$tokenString]);
189
    }
190
191
    /**
192
     * Get a token from this list having the given token string.
193
     *
194
     * @param string $tokenString
195
     * @return Token
196
     */
197 2
    public function get($tokenString)
198
    {
199 2
        return $this->tokens[$tokenString];
200
    }
201
202
    /**
203
     * Get the list of tokens as an associative array of Token with tokenString as keys.
204
     *
205
     * @return Token[]
206
     */
207 7
    public function getArray()
208
    {
209 7
        return $this->tokens;
210
    }
211
212
    /**
213
     * Get all token names.
214
     *
215
     * @return string[]
216
     */
217
    public function getNames()
218
    {
219
        $result = array();
220
        foreach ($this->tokens as $token) {
221
            $tokenName = $token->getTokenName();
222
            $result[$tokenName] = $tokenName;
223
        }
224
        return $result;
225
    }
226
227
    /**
228
     * Find tokens having the given token name.
229
     *
230
     * @param string|string[]|null $tokenNameToFind Null to find all. String to find a certain token. Array of strings
231
     *                                              To find multiple tokens.
232
     * @return Token[]|array Array of Token if $tokenNameToFind is string, Array of arrays of Token with token names
233
     *                       as keys if $tokenNameToFind is string[] or null.
234
     */
235 1
    public function findByName($tokenNameToFind = null)
236
    {
237 1
        $result = array();
238 1
        foreach ($this->tokens as $tokenString => $token)
239
        {
240 1
            $tokenName = $token->getTokenName();
241 1
            if ((!isset($tokenNameToFind)) || (is_array($tokenNameToFind) && in_array($tokenName, $tokenNameToFind)) ||
242 1
                ($tokenName == $tokenNameToFind)) {
243 1
                if (!isset($result[$tokenName])) {
244 1
                    $result[$tokenName] = array();
245 1
                }
246 1
                $result[$tokenName][$tokenString] = $token;
247 1
            }
248 1
        }
249 1
        if (isset($tokenNameToFind) && isset($result[$tokenNameToFind])) {
250 1
            return $result[$tokenNameToFind];
251
        }
252 1
        return $result;
253
    }
254
255
    /**
256
     * Find all resolved tokens.
257
     *
258
     * @return Token[]
259
     */
260 1 View Code Duplication
    public function findResolved()
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...
261
    {
262 1
        $result = array();
263 1
        foreach ($this->tokens as $tokenString => $token)
264
        {
265 1
            if ($token->getIsResolved()) {
266 1
                $result[$tokenString] = $token;
267 1
            }
268 1
        }
269 1
        return $result;
270
    }
271
272
    /**
273
     * Find all tokens resolved but not yet injected.
274
     *
275
     * @return Token[]
276
     */
277 1 View Code Duplication
    public function findResolvedAndNotInjected()
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...
278
    {
279 1
        $result = array();
280 1
        foreach ($this->tokens as $tokenString => $token)
281
        {
282 1
            if ($token->getIsResolved() && (!$token->getIsInjected())) {
283 1
                $result[$tokenString] = $token;
284 1
            }
285 1
        }
286 1
        return $result;
287
    }
288
289
    /**
290
     * Find all unresolved tokens.
291
     *
292
     * @return Token[]
293
     */
294 1 View Code Duplication
    public function findUnresolved()
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...
295
    {
296 1
        $result = array();
297 1
        foreach ($this->tokens as $tokenString => $token)
298
        {
299 1
            if (!$token->getIsResolved()) {
300 1
                $result[$tokenString] = $token;
301 1
            }
302 1
        }
303 1
        return $result;
304
    }
305
306
    /**
307
     * Check if at least one unresolved token exists in the list.
308
     *
309
     * @return boolean
310
     */
311 1
    public function hasUnresolved()
312
    {
313 1
        foreach ($this->tokens as $tokenString => $token)
314
        {
315 1
            if (!$token->getIsResolved()) {
316 1
                return True;
317
            }
318 1
        }
319
        return False;
320
    }
321
322
    /**
323
     * Find all tokens with unresolved filters.
324
     *
325
     * @return Token[]
326
     */
327 1 View Code Duplication
    public function findWithUnresolvedFilters()
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...
328
    {
329 1
        $result = array();
330 1
        foreach ($this->tokens as $tokenString => $token)
331
        {
332 1
            if ($token->hasUnresolvedFilters()) {
333 1
                $result[$tokenString] = $token;
334 1
            }
335 1
        }
336 1
        return $result;
337
    }
338
339
    /**
340
     * Attempt to resolve the values for all tokens in the list.
341
     *
342
     * @param TokenResolverInterface $tokenResolver
343
     * @param boolean|null $ignoreUnknownTokens Null to use token resolver option.
344
     * @param boolean|null $ignoreUnknownFilters Null to use collection option.
345
     * @throws UnknownFilterException
346
     *
347
     * If using RegisteredTokenResolver:
348
     * @throws UnknownTokenException If the token name was not registered and set not to ignore unknown tokens.
349
     *
350
     * If using ScopeTokenResolver:
351
     * @throws UnknownTokenException
352
     * @throws OutOfScopeException
353
     * @throws ScopeTokenValueSerializationException
354
     * @throws TokenFormatException
355
     * @return $this
356
     */
357 14
    public function resolve(TokenResolverInterface $tokenResolver,
358
                            $ignoreUnknownTokens = null, $ignoreUnknownFilters = null)
359
    {
360 14
        if (is_null($ignoreUnknownTokens)) {
361 10
            $ignoreUnknownTokens = $tokenResolver->getIgnoreUnknownTokens();
362 10
        }
363 14
        if (is_null($ignoreUnknownFilters)) {
364 14
            $ignoreUnknownFilters = $this->ignoreUnknownFilters;
365 14
        }
366 14
        foreach ($this->tokens as $tokenString => $token) {
367 14
            if ($token->getIsResolved() && (!$token->hasUnresolvedFilters())) {
368
                continue;
369
            }
370 14
            if (!$token->getIsResolved()) {
371 14
                $token->resolveUnfilteredValue($tokenResolver, $ignoreUnknownTokens);
372 10
            }
373 10
            if ($token->hasFilters() && $token->hasUnfilteredTokenValue()) {
374 3
                $token->applyFilters($ignoreUnknownFilters);
375 3
            }
376 10
        }
377 8
        return $this;
378
    }
379
380
}