Completed
Push — master ( 11a376...8d38b3 )
by Andrii
03:54
created

History   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 2

Test Coverage

Coverage 66.4%

Importance

Changes 0
Metric Value
wmc 51
c 0
b 0
f 0
lcom 3
cbo 2
dl 0
loc 256
ccs 83
cts 125
cp 0.664
rs 8.3206

34 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A isInitTag() 0 4 1
A isLastTag() 0 4 1
A setProject() 0 4 1
A getProject() 0 8 3
A detectProject() 0 8 3
A addHeader() 0 4 1
A addHeaders() 0 6 2
A setHeaders() 0 5 1
A getHeaders() 0 4 1
A hasLink() 0 4 1
A removeLink() 0 4 1
A addLink() 0 4 1
A addLinks() 0 6 2
A setLinks() 0 4 1
A getLinks() 0 4 1
A hasHash() 0 4 1
A addHash() 0 4 1
A addHashes() 0 6 2
A setHashes() 0 5 1
A getHashes() 0 4 1
A getFirstTag() 0 4 1
A setFirstTag() 0 4 1
A countTags() 0 4 1
A initTags() 0 6 2
A getTags() 0 4 1
A addTags() 0 6 2
A setTags() 0 5 1
B findTag() 0 12 5
A hasTag() 0 4 1
A removeTag() 0 10 3
A addTag() 0 4 1
A merge() 0 6 1
A mergeTags() 0 12 3

How to fix   Complexity   

Complex Class

Complex classes like History 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 History, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Changelog keeper
4
 *
5
 * @link      https://github.com/hiqdev/chkipper
6
 * @package   chkipper
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2016-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\chkipper\history;
12
13
/**
14
 * History class.
15
 *
16
 * @property array $headers: header => header
17
 * @property array $hashes:  hash => hash
18
 * @property array $links:   link => href
19
 * @property array $tags:    tag name => tag object
20
 *
21
 * @author Andrii Vasyliev <[email protected]>
22
 */
23
class History
24
{
25
    public $lastTag = 'Under development';
26
27
    public $initTag = 'Development started';
28
29
    protected $_config;
30
    protected $_project;
31
    protected $_headers = [];
32
    protected $_hashes  = [];
33
    protected $_links   = [];
34
    protected $_tags    = [];
35
36 3
    public function __construct(ConfigInterface $config)
37
    {
38 3
        $this->_config = $config;
39 3
    }
40
41 2
    public function isInitTag($tag)
42
    {
43 2
        return $tag === $this->initTag;
44
    }
45
46 2
    public function isLastTag($tag)
47
    {
48 2
        return $tag === $this->lastTag;
49
    }
50
51 1
    public function setProject($value)
52
    {
53 1
        $this->_project = $value;
54 1
    }
55
56 2
    public function getProject()
57
    {
58 2
        if ($this->_project === null) {
59 1
            $this->_project = $this->_config->getName() ?: $this->detectProject();
60 1
        }
61
62 2
        return $this->_project;
63
    }
64
65 1
    public function detectProject()
66
    {
67 1
        foreach ($this->getHeaders() as $line) {
68 1
            if (preg_match('/\b([a-z0-9._-]{2,}\/[a-z0-9._-]{2,})\b/i', $line, $m)) {
69 1
                return $m[1];
70
            }
71
        }
72
    }
73
74 2
    public function addHeader($str)
75
    {
76 2
        $this->_headers[$str] = $str;
77 2
    }
78
79 1
    public function addHeaders(array $headers)
80
    {
81 1
        foreach ($headers as $header) {
82 1
            $this->addHeader($header);
83 1
        }
84 1
    }
85
86 1
    public function setHeaders(array $headers)
87
    {
88 1
        $this->_headers = [];
89 1
        $this->addHeaders($headers);
90 1
    }
91
92 2
    public function getHeaders()
93
    {
94 2
        return $this->_headers;
95
    }
96
97 2
    public function hasLink($link)
98
    {
99 2
        return isset($this->_links[$link]);
100
    }
101
102
    public function removeLink($link)
103
    {
104
        unset($this->_links[$link]);
105
    }
106
107 3
    public function addLink($link, $href)
108
    {
109 3
        $this->_links[$link] = $href;
110 3
    }
111
112
    public function addLinks(array $links)
113
    {
114
        foreach ($links as $link => $href) {
115
            $this->addLink($link, $href);
116
        }
117
    }
118
119 1
    public function setLinks(array $links)
120
    {
121 1
        $this->_links = $links;
122 1
    }
123
124 2
    public function getLinks()
125
    {
126 2
        return $this->_links;
127
    }
128
129 2
    public function hasHash($hash)
130
    {
131 2
        return isset($this->_hashes[(string) $hash]);
132
    }
133
134 3
    public function addHash($hash)
135
    {
136 3
        $this->_hashes[(string) $hash] = $hash;
137 3
    }
138
139
    public function addHashes(array $hashes)
140
    {
141
        foreach ($hashes as $hash) {
142
            $this->addHash($hash);
143
        }
144
    }
145
146
    public function setHashes(array $hashes)
147
    {
148
        $this->_hashes = [];
149
        $this->addHashes($hashes);
150
    }
151
152 2
    public function getHashes()
153
    {
154 2
        return $this->_hashes;
155
    }
156
157 2
    public function getFirstTag()
158
    {
159 2
        return reset($this->_tags);
160
    }
161
162
    public function setFirstTag($name)
163
    {
164
        $this->getFirstTag()->setName($name);
165
    }
166
167 3
    public function countTags()
168
    {
169 3
        return count($this->_tags);
170
    }
171
172 3
    public function initTags()
173
    {
174 3
        if (!$this->countTags()) {
175 3
            $this->addTag(new Tag($this->lastTag));
176 3
        }
177 3
    }
178
179 2
    public function getTags()
180
    {
181 2
        return $this->_tags;
182
    }
183
184
    /**
185
     * Adds given tags to the history.
186
     * @param Tag[] $tags
187
     * @param boolean $prependNotes default is append
188
     */
189 1
    public function addTags(array $tags, $prependNotes = false)
190
    {
191 1
        foreach ($tags as $name => $tag) {
192 1
            $this->addTag($tag, $prependNotes);
193 1
        }
194 1
    }
195
196 1
    public function setTags(array $tags)
197
    {
198 1
        $this->_tags = [];
199 1
        $this->addTags($tags);
200 1
    }
201
202
    /**
203
     * Returns tag by name.
204
     * Creates if not exists.
205
     * Returns first tag when given empty name.
206
     * @param string|Tag $tag tag name or tag object
207
     * @return Tag
208
     */
209 3
    public function findTag($tag)
210
    {
211 3
        if (!$tag) {
212 1
            $tag = reset($this->_tags) ?: $this->lastTag;
213 1
        }
214 3
        $name = $tag instanceof Tag ? $tag->getName() : $tag;
215 3
        if (!$this->hasTag($name)) {
216 3
            $this->_tags[$name] = new Tag($name);
217 3
        }
218
219 3
        return $this->_tags[$name];
220
    }
221
222 3
    public function hasTag($tag)
223
    {
224 3
        return isset($this->_tags[$tag]);
225
    }
226
227
    public function removeTag($name)
228
    {
229
        foreach ($this->_tags as $k => $tag) {
230
            if ($tag->getName() === $name) {
231
                unset($this->_tags[$k]);
232
233
                return;
234
            }
235
        }
236
    }
237
238
    /**
239
     * Adds tag.
240
     * @param Tag $tag
241
     * @param boolean $prependNotes default is append
242
     * @return Tag the added tag
243
     */
244 3
    public function addTag(Tag $tag, $prependNotes = false)
245
    {
246 3
        return $this->findTag($tag->getName())->setDate($tag->getDate())->addNotes($tag->getNotes(), $prependNotes);
247
    }
248
249
    /**
250
     * Merges given history into the current.
251
     * @param History $history
252
     * @param boolean $prependNotes default is append
253
     */
254
    public function merge(History $history, $prependNotes = false)
255
    {
256
        $this->mergeTags($history->getTags(), $prependNotes);
257
        $this->addLinks($history->getLinks());
258
        $this->addHashes($history->getHashes());
259
    }
260
261
    /**
262
     * Merge given tags into the current history.
263
     * @param Tag[] $tags
264
     * @param boolean $prependNotes default is append
265
     */
266
    public function mergeTags(array $tags, $prependNotes = false)
267
    {
268
        foreach ($tags as $tag) {
269
            foreach ($tag->getNotes() as $note) {
270
                $note->removeCommits($this->getHashes());
271
            }
272
        }
273
        $this->addTags($tags, $prependNotes);
274
        //$olds = $this->getTags();
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
275
        //$this->_tags = $tags;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
276
        //$this->addTags($$olds);
0 ignored issues
show
Unused Code Comprehensibility introduced by
88% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
277
    }
278
}
279