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

systemsdk / phpcpd / #4

30 Dec 2024 04:42PM UTC coverage: 75.789%. Remained the same
#4

push

DKravtsov
phpcpd 8.0.0 release. Made codebase refactoring. Updated requirements php 8.3, updated composer dependencies, updated tests to the PHPUnit 11. Updated dev environment to the php 8.4, Phing 3.0, added code quality tools: ecs, phpstan.

271 of 379 new or added lines in 20 files covered. (71.5%)

65 existing lines in 13 files now uncovered.

648 of 855 relevant lines covered (75.79%)

2.18 hits per line

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

60.0
/src/Log/AbstractXmlLogger.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Systemsdk\PhpCPD\Log;
6

7
use DOMDocument;
8
use Systemsdk\PhpCPD\CodeCloneMap;
9
use Systemsdk\PhpCPD\Exceptions\LoggerException;
10

11
use function file_put_contents;
12
use function htmlspecialchars;
13
use function mb_convert_encoding;
14
use function ord;
15
use function preg_replace;
16
use function strlen;
17

18
use const ENT_COMPAT;
19

20
abstract class AbstractXmlLogger
21
{
22
    protected DOMDocument $document;
23

24
    public function __construct(
25
        private readonly string $filename
26
    ) {
27
        $this->document = new DOMDocument('1.0', 'UTF-8');
1✔
28
        $this->document->formatOutput = true;
1✔
29
    }
30

31
    abstract public function processClones(CodeCloneMap $clones): void;
32

33
    /**
34
     * @throws LoggerException
35
     */
36
    protected function flush(): void
37
    {
38
        $xml = $this->document->saveXML();
1✔
39

40
        if ($xml === false) {
1✔
NEW
41
            throw new LoggerException('Can not dump the internal xml tree back into a string');
×
42
        }
43

44
        $results = file_put_contents($this->filename, $xml);
1✔
45

46
        if ($results === false) {
1✔
NEW
47
            throw new LoggerException('Can not save log file');
×
48
        }
49
    }
50

51
    /**
52
     * @throws LoggerException
53
     */
54
    protected function convertToUtf8(string $string): string
55
    {
56
        if (!$this->isUtf8($string)) {
1✔
57
            /** @var string|false $string */
58
            $string = mb_convert_encoding($string, 'UTF-8');
×
59

NEW
60
            if ($string === false) {
×
NEW
61
                throw new LoggerException('Cannot convert to UTF-8');
×
62
            }
63
        }
64

65
        return (string)$string;
1✔
66
    }
67

68
    protected function isUtf8(string $string): bool
69
    {
70
        $length = strlen($string);
1✔
71

72
        for ($i = 0; $i < $length; $i++) {
1✔
73
            if (ord($string[$i]) < 0x80) {
1✔
74
                $n = 0;
1✔
UNCOV
75
            } elseif ((ord($string[$i]) & 0xE0) === 0xC0) {
×
76
                $n = 1;
×
77
            } elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
×
UNCOV
78
                $n = 2;
×
UNCOV
79
            } elseif ((ord($string[$i]) & 0xF0) === 0xF0) {
×
UNCOV
80
                $n = 3;
×
81
            } else {
UNCOV
82
                return false;
×
83
            }
84

85
            for ($j = 0; $j < $n; $j++) {
1✔
UNCOV
86
                if ((++$i === $length) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
×
UNCOV
87
                    return false;
×
88
                }
89
            }
90
        }
91

92
        return true;
1✔
93
    }
94

95
    /**
96
     * @throws LoggerException
97
     */
98
    protected function escapeForXml(string $string): string
99
    {
100
        $string = $this->convertToUtf8($string);
1✔
101
        $string = (string)preg_replace(
1✔
102
            '/[^\x09\x0A\x0D\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]/u',
1✔
103
            "\xEF\xBF\xBD",
1✔
104
            $string
1✔
105
        );
1✔
106

107
        return htmlspecialchars($string, ENT_COMPAT);
1✔
108
    }
109
}
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