• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemsdk / phpcpd / #12

13 Apr 2025 04:42PM UTC coverage: 75.711%. Remained the same
#12

push

DKravtsov
phpcpd 8.1.1 release. Available installation via composer.

692 of 914 relevant lines covered (75.71%)

3.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.42
/src/Log/PMD.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Systemsdk\PhpCPD\Log;
6

7
use DOMElement;
8
use DOMException;
9
use DOMNode;
10
use Systemsdk\PhpCPD\CodeCloneMap;
11
use Systemsdk\PhpCPD\Exceptions\LoggerException;
12

13
use function is_object;
14
use function sprintf;
15

16
final class PMD extends AbstractXmlLogger
17
{
18
    private const string CPD_ELEMENT_NAME = 'pmd-cpd';
19
    private const string DUPLICATION_ELEMENT_NAME = 'duplication';
20
    private const string FILE_ELEMENT_NAME = 'file';
21
    private const string CODE_FRAGMENT_ELEMENT_NAME = 'codefragment';
22
    private const string ATTRIBUTE_LINES_NAME = 'lines';
23
    private const string ATTRIBUTE_TOKENS_NAME = 'tokens';
24
    private const string ATTRIBUTE_PATH_NAME = 'path';
25
    private const string ATTRIBUTE_LINE_NAME = 'line';
26
    private const string ACTION_CREATE_ELEMENT = 'create-element';
27
    private const string ACTION_APPEND_CHILD = 'append-child';
28
    private const string ACTION_SET_ATTRIBUTE = 'set-attribute';
29

30
    /**
31
     * @throws LoggerException
32
     */
33
    public function processClones(CodeCloneMap $clones): void
34
    {
35
        try {
36
            $cpd = $this->document->createElement(self::CPD_ELEMENT_NAME);
1✔
37
            $this->checkResult($cpd, self::CPD_ELEMENT_NAME, self::ACTION_CREATE_ELEMENT);
1✔
38

39
            $result = $this->document->appendChild($cpd);
1✔
40
            $this->checkResult($result, self::CPD_ELEMENT_NAME, self::ACTION_APPEND_CHILD);
1✔
41

42
            foreach ($clones as $clone) {
1✔
43
                $duplicationEl = $this->document->createElement(self::DUPLICATION_ELEMENT_NAME);
1✔
44
                $this->checkResult($duplicationEl, self::DUPLICATION_ELEMENT_NAME, self::ACTION_CREATE_ELEMENT);
1✔
45

46
                $duplication = $cpd->appendChild($duplicationEl);
1✔
47
                $this->checkResult($duplication, self::DUPLICATION_ELEMENT_NAME, self::ACTION_APPEND_CHILD);
1✔
48

49
                /** @var DOMElement $duplication */
50
                $result1 = $duplication->setAttribute(self::ATTRIBUTE_LINES_NAME, (string)$clone->numberOfLines());
1✔
51
                $this->checkResult($result1, self::ATTRIBUTE_LINES_NAME, self::ACTION_SET_ATTRIBUTE);
1✔
52

53
                $result2 = $duplication->setAttribute(self::ATTRIBUTE_TOKENS_NAME, (string)$clone->numberOfTokens());
1✔
54
                $this->checkResult($result2, self::ATTRIBUTE_TOKENS_NAME, self::ACTION_SET_ATTRIBUTE);
1✔
55

56
                foreach ($clone->files() as $codeCloneFile) {
1✔
57
                    $fileEl = $this->document->createElement(self::FILE_ELEMENT_NAME);
1✔
58
                    $this->checkResult($fileEl, self::FILE_ELEMENT_NAME, self::ACTION_CREATE_ELEMENT);
1✔
59

60
                    $file = $duplication->appendChild($fileEl);
1✔
61
                    $this->checkResult($file, self::FILE_ELEMENT_NAME, self::ACTION_APPEND_CHILD);
1✔
62

63
                    /** @var DOMElement $file */
64
                    $result1 = $file->setAttribute(self::ATTRIBUTE_PATH_NAME, $codeCloneFile->name());
1✔
65
                    $this->checkResult($result1, self::ATTRIBUTE_PATH_NAME, self::ACTION_SET_ATTRIBUTE);
1✔
66

67
                    $result2 = $file->setAttribute(self::ATTRIBUTE_LINE_NAME, (string)$codeCloneFile->startLine());
1✔
68
                    $this->checkResult($result2, self::ATTRIBUTE_LINE_NAME, self::ACTION_SET_ATTRIBUTE);
1✔
69
                }
70

71
                $codeFragmentEl = $this->document->createElement(
1✔
72
                    self::CODE_FRAGMENT_ELEMENT_NAME,
1✔
73
                    $this->escapeForXml($clone->lines())
1✔
74
                );
1✔
75
                $this->checkResult($codeFragmentEl, self::CODE_FRAGMENT_ELEMENT_NAME, self::ACTION_CREATE_ELEMENT);
1✔
76

77
                $codeFragment = $duplication->appendChild($codeFragmentEl);
1✔
78
                $this->checkResult($codeFragment, self::CODE_FRAGMENT_ELEMENT_NAME, self::ACTION_APPEND_CHILD);
1✔
79
            }
80

81
            $this->flush();
1✔
82
        } catch (DOMException $exception) {
×
83
            throw new LoggerException($exception->getMessage());
×
84
        }
85
    }
86

87
    /**
88
     * @throws LoggerException
89
     */
90
    private function checkResult(DOMNode|false $result, string $name, string $type): void
91
    {
92
        if (is_object($result)) {
1✔
93
            return;
1✔
94
        }
95

96
        $error = 'Unknown action: %s';
×
97

98
        if ($type === self::ACTION_CREATE_ELEMENT) {
×
99
            $error = 'Can not create element: %s';
×
100
        } elseif ($type === self::ACTION_APPEND_CHILD) {
×
101
            $error = 'Can not add new child at the end: %s';
×
102
        } elseif ($type === self::ACTION_SET_ATTRIBUTE) {
×
103
            $error = 'Can not set attribute: %s';
×
104
        }
105

106
        $this->generateException($error, $name);
×
107
    }
108

109
    /**
110
     * @throws LoggerException
111
     */
112
    private function generateException(string $error, string $name): void
113
    {
114
        throw new LoggerException(sprintf($error, $name));
×
115
    }
116
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc