ErrorCPD::getCpdDescription()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 3
nop 2
dl 0
loc 19
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copy paste detection
5
 *
6
 * PHP Version 5.2.6
7
 *
8
 * Copyright (c) 2007-2009, Mayflower GmbH
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 *
15
 *   * Redistributions of source code must retain the above copyright
16
 *     notice, this list of conditions and the following disclaimer.
17
 *
18
 *   * Redistributions in binary form must reproduce the above copyright
19
 *     notice, this list of conditions and the following disclaimer in
20
 *     the documentation and/or other materials provided with the
21
 *     distribution.
22
 *
23
 *   * Neither the name of Mayflower GmbH nor the names of his
24
 *     contributors may be used to endorse or promote products derived
25
 *     from this software without specific prior written permission.
26
 *
27
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
 * POSSIBILITY OF SUCH DAMAGE.
39
 *
40
 * @category PHP_CodeBrowser
41
 *
42
 * @author Elger Thiele <[email protected]>
43
 * @author Michel Hartmann <[email protected]>
44
 *
45
 * @copyright 2007-2010 Mayflower GmbH
46
 *
47
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
48
 *
49
 * @version SVN: $Id$
50
 *
51
 * @link http://www.phpunit.de/
52
 *
53
 * @since File available since  0.1.0
54
 */
55
56
namespace PHPCodeBrowser\Plugins;
57
58
use DOMElement;
59
use DOMNodeList;
60
use PHPCodeBrowser\AbstractPlugin;
61
use PHPCodeBrowser\Issue;
62
63
/**
64
 * ErrorCPD
65
 *
66
 * @category PHP_CodeBrowser
67
 *
68
 * @author Elger Thiele <[email protected]>
69
 * @author Michel Hartmann <[email protected]>
70
 *
71
 * @copyright 2007-2010 Mayflower GmbH
72
 *
73
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
74
 *
75
 * @version Release: @package_version@
76
 *
77
 * @link http://www.phpunit.de/
78
 *
79
 * @since Class available since  0.1.0
80
 */
81
class ErrorCPD extends AbstractPlugin
82
{
83
    /**
84
     * @var string $pluginName
85
     */
86
    protected $pluginName = 'pmd-cpd';
87
88
    /**
89
     * Mapper method for this plugin.
90
     *
91
     * @param \DOMNode $element  The XML plugin node with its errors
92
     * @param string   $filename
93
     *
94
     * @return array<Issue>
95
     */
96
    public function mapIssues(\DOMNode $element, string $filename): array
97
    {
98
        /** @var DOMElement $parentNode */
99
        $parentNode = $element->parentNode;
100
        $files      = $this->issueXml->query(
101
            'file[@path="'.$filename.'"]',
102
            $parentNode
103
        );
104
        $lineCount  = (int) $parentNode->getAttribute('lines');
105
106
        $result = [];
107
108
        foreach ($files as $file) {
109
            if (!($file instanceof DOMElement)) {
110
                continue;
111
            }
112
113
            $result[] = new Issue(
114
                $file->getAttribute('path'),
115
                (int) $file->getAttribute('line'),
116
                (int) $file->getAttribute('line') + $lineCount,
117
                'Duplication',
118
                \htmlentities($this->getCpdDescription($parentNode->childNodes, $file), ENT_COMPAT),
119
                'notice'
120
            );
121
        }
122
123
        return $result;
124
    }
125
126
    /**
127
     * @return array
128
     */
129
    public function getFilesWithIssues(): array
130
    {
131
        $fileNames = [];
132
        $nodes     = $this->issueXml->query(
133
            '/*/'.$this->pluginName.'/*/file[@path]'
134
        );
135
136
        foreach ($nodes as $node) {
137
            if (!($node instanceof DOMElement)) {
138
                continue;
139
            }
140
141
            $fileNames[] = $node->getAttribute('path');
142
        }
143
144
        return \array_unique($fileNames);
145
    }
146
147
    /**
148
     * Get all DOMNodes that represent issues for a specific file.
149
     *
150
     * @param string $filename Name of the file to get nodes for.
151
     *
152
     * @return DOMNodeList
153
     */
154
    protected function getIssueNodes(string $filename): DOMNodeList
155
    {
156
        return $this->issueXml->query(
157
            '/*/'.$this->pluginName.'/*/file[@path="'.$filename.'"]'
158
        );
159
    }
160
161
    /**
162
     * We need another version of getDescription, as we need $allNodes
163
     * to find duplicates.
164
     *
165
     * @param DOMNodeList $allNodes
166
     * @param DOMElement  $currentNode
167
     *
168
     * @return string
169
     */
170
    protected function getCpdDescription(DOMNodeList $allNodes, DOMElement $currentNode): string
171
    {
172
        $source = [];
173
174
        foreach ($allNodes as $node) {
175
            if (!($node instanceof DOMElement)
176
                || $node->isSameNode($currentNode)
177
            ) {
178
                continue;
179
            }
180
181
            $source[] = \sprintf(
182
                '%s (%d)',
183
                $node->getAttribute('path'),
184
                $node->getAttribute('line')
185
            );
186
        }
187
188
        return "Copy paste from:\n".\implode("\n", $source);
189
    }
190
}
191