Completed
Push — master ( 787b87...c59397 )
by Demonchaux
13s
created

Hydrator::getMethodCoveredLines()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 0
cts 13
cp 0
rs 9.2728
c 0
b 0
f 0
cc 5
nc 5
nop 1
crap 30
1
<?php
2
3
/**
4
 * This file is part of the Clover to Html package.
5
 *
6
 * (c) Stéphane Demonchaux <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace CloverToHtml;
12
13
class Hydrator
14
{
15
    /**
16
     * @param \SimpleXMLElement $xml
17
     * @param Root              $root
18
     *
19
     * @return Root
20
     */
21
    public function xmlToDto(\SimpleXMLElement $xml, Root $root): Root
22
    {
23
        foreach ($xml as $data) {
24
            foreach ($data->package as $package) {
25
                $root = $this->hydrateFiles($package, $root);
26
            }
27
            $root = $this->hydrateFiles($data, $root);
28
        }
29
30
        $root->setBasePath($this->calBasePath($root));
31
32
        return $this->hydrateDirectory($root);
33
    }
34
35
    /**
36
     * @param Root $root
37
     *
38
     * @return Root
39
     */
40
    private function hydrateDirectory(Root $root): Root
41
    {
42
        $basePath = $root->getBasePath();
43
44
        foreach ($root->getFileCollection() as $file) {
45
            $dirPath = $file->getDirectory($basePath);
46
            if ($root->hasDirectory($dirPath)) {
47
                $directory = $root->getDirectoryByName($dirPath);
48
            } else {
49
                $directory = new Directory();
50
                $directory->setPath($dirPath);
51
            }
52
53
            $directory->addFile($file);
54
55
            $root->addDirectory($directory);
56
        }
57
58
        return $root;
59
    }
60
61
    /**
62
     * @param Root $root
63
     *
64
     * @return string
65
     */
66
    private function calBasePath(Root $root): string
67
    {
68
        $pathCollection = array();
69
        foreach ($root->getFileCollection() as $file) {
70
            $pathCollection[] = $file->getName();
71
        }
72
73
        return $this->getCommonPath($pathCollection) . '/';
74
    }
75
76
    /**
77
     * @see http://rosettacode.org/wiki/Find_common_directory_path#PHP
78
     *
79
     * @param array $paths
80
     *
81
     * @return string
82
     */
83
    private function getCommonPath(array $paths): string
84
    {
85
        $lastOffset = 1;
86
        $common     = '/';
87
88
        while (($index = strpos($paths[0], '/', $lastOffset)) !== false) {
89
            $dirLen = $index - $lastOffset + 1;
90
            $dir    = substr($paths[0], $lastOffset, $dirLen);
91
92
            foreach ($paths as $path) {
93
                if (substr($path, $lastOffset, $dirLen) !== $dir) {
94
                    return $common;
95
                }
96
            }
97
98
            $common    .= $dir;
99
            $lastOffset = $index + 1;
100
        }
101
102
        return substr($common, 0, -1);
103
    }
104
105
    /**
106
     * @param \SimpleXMLElement $data
107
     * @param Root              $root
108
     *
109
     * @return Root
110
     */
111
    private function hydrateFiles(\SimpleXMLElement $data, Root $root): Root
112
    {
113
        foreach ($data->file as $fileXml) {
114
            $root->addFile($this->hydrateFile($fileXml));
115
        }
116
117
        return $root;
118
    }
119
120
    /**
121
     * @param \SimpleXMLElement $fileXml
122
     *
123
     * @return File
124
     */
125
    private function hydrateFile(\SimpleXMLElement $fileXml): File
126
    {
127
        $file = new File();
128
        $file->setName($this->findAttributeByName($fileXml, 'name'));
129
        $methodNumber = 0;
130
131
        foreach ($fileXml->class as $classXml) {
132
            $class = new ClassDto();
133
            $class->setName($this->findAttributeByName($classXml, 'name'));
134
            $class->setLineCount($this->findAttributeByName($fileXml->metrics, 'statements'));
135
            $class->setLineCoveredCount($this->findAttributeByName($fileXml->metrics, 'coveredstatements'));
136
            $class->setMethodCount($this->findAttributeByName($fileXml->metrics, 'methods'));
137
            $class->setMethodCoveredCount($this->findAttributeByName($fileXml->metrics, 'coveredmethods'));
138
            $class->setElementCount($this->findAttributeByName($fileXml->metrics, 'elements'));
139
            $class->setElementCoveredCount($this->findAttributeByName($fileXml->metrics, 'coveredelements'));
140
            $class->setConditionalCount($this->findAttributeByName($fileXml->metrics, 'conditionals'));
141
            $class->setConditionalCoveredCount($this->findAttributeByName($fileXml->metrics, 'coveredconditionals'));
142
            $class = $this->hydrateMethod($fileXml, $class, $methodNumber);
143
144
            $file->addClass($class);
145
        }
146
147
        foreach ($fileXml->line as $lineXml) {
148
            $file->addLine(
149
                $this->findAttributeByName($lineXml, 'num'),
150
                $this->findAttributeByName($lineXml, 'type'),
151
                (bool) $this->findAttributeByName($lineXml, 'count')
152
            );
153
        }
154
155
        return $file;
156
    }
157
158
    /**
159
     * @param \SimpleXMLElement $fileXml
160
     *
161
     * @return array
162
     */
163
    private function getMethodCoveredLines(\SimpleXMLElement $fileXml): array
164
    {
165
        $coveredLines = [];
166
        $totalLines = [];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
167
        $methodName = null;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
168
        foreach ($fileXml->line as $lineXml) {
169
            $type = $this->findAttributeByName($lineXml, 'type');
170
171
            // Must add method to class
172
            if ($type === 'method') {
173
                $methodName = $this->findAttributeByName($lineXml, 'name');
174
            }
175
176
            if ($methodName !== null && $type === 'stmt') {
177
                $coveredLines[$methodName] += (int) $this->findAttributeByName($lineXml, 'count');
178
                $totalLines[$methodName]++;
179
            }
180
        }
181
182
        return [$coveredLines, $totalLines];
183
    }
184
185
    /**
186
     * @param \SimpleXMLElement $fileXml
187
     * @param ClassDto $class
188
     * @param $methodNumber
189
     *
190
     * @return ClassDto
191
     */
192
    private function hydrateMethod(\SimpleXMLElement $fileXml, ClassDto $class, &$methodNumber): ClassDto
193
    {
194
        $methodCoveredLines = $this->getMethodCoveredLines($fileXml)[0];
195
        $methodLines = $this->getMethodCoveredLines($fileXml)[1];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
196
197
        foreach ($fileXml->line as $lineXml) {
198
            $type = $this->findAttributeByName($lineXml, 'type');
199
200
            // Must add method to class
201
            if ($type === 'method') {
202
                $methodName = $this->findAttributeByName($lineXml, 'name');
203
                $class->addMethod(
204
                    $methodName,
205
                    $this->findAttributeByName($lineXml, 'crap'),
206
                    $methodLines[$methodName],
207
                    $methodCoveredLines[$methodName],
208
                    $this->findAttributeByName($lineXml, 'num')
209
                );
210
                ++$methodNumber;
211
            }
212
213
            if ($class->getMethodCount() === $methodNumber) {
214
                break;
215
            }
216
        }
217
218
        return $class;
219
    }
220
221
    /**
222
     * @param \SimpleXMLElement $element
223
     * @param string            $name
224
     *
225
     * @throws \InvalidArgumentException
226
     *
227
     * @return string
228
     */
229
    private function findAttributeByName(\SimpleXMLElement $element, $name): string
230
    {
231
        foreach ($element->attributes() as $attrName => $attValue) {
232
            if ($attrName === $name) {
233
                return (string) $attValue;
234
            }
235
        }
236
237
        throw new \InvalidArgumentException(sprintf('Attribute "%s" not found', $name));
238
    }
239
}
240