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

JBZoo / CI-Report-Converter / 8319938202

28 Jan 2024 02:03PM UTC coverage: 94.125%. Remained the same
8319938202

push

github

web-flow
Update version of jbzoo/cli dependency (#49)

1426 of 1515 relevant lines covered (94.13%)

45.89 hits per line

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

83.33
/src/Formats/TeamCity/Helper.php
1
<?php
2

3
/**
4
 * JBZoo Toolbox - CI-Report-Converter.
5
 *
6
 * This file is part of the JBZoo Toolbox project.
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license    MIT
11
 * @copyright  Copyright (C) JBZoo.com, All rights reserved.
12
 * @see        https://github.com/JBZoo/CI-Report-Converter
13
 */
14

15
declare(strict_types=1);
16

17
namespace JBZoo\CIReportConverter\Formats\TeamCity;
18

19
final class Helper
20
{
21
    public const PREDEFINED_METRICS = [
22
        'ArtifactsSize',
23
        'VisibleArtifactsSize',
24
        'buildStageDuration:artifactsPublishing',
25
        'buildStageDuration:buildStepRunner_<N>',
26
        'buildStageDuration:sourcesUpdate',
27
        'buildStageDuration:dependenciesResolving',
28
        'BuildDuration',
29
        'BuildDurationNetTime',
30
        'CodeCoverageB',
31
        'CodeCoverageC',
32
        'CodeCoverageL',
33
        'CodeCoverageM',
34
        'CodeCoverageR',
35
        'CodeCoverageS',
36
        'CodeCoverageAbsBCovered',
37
        'CodeCoverageAbsBTotal',
38
        'CodeCoverageAbsCCovered',
39
        'CodeCoverageAbsCTotal',
40
        'CodeCoverageAbsLCovered',
41
        'CodeCoverageAbsLTotal',
42
        'CodeCoverageAbsMCovered',
43
        'CodeCoverageAbsMTotal',
44
        'CodeCoverageAbsRCovered',
45
        'CodeCoverageAbsRTotal',
46
        'CodeCoverageAbsSCovered',
47
        'CodeCoverageAbsSTotal',
48
        'DuplicatorStats',
49
        'TotalTestCount',
50
        'PassedTestCount',
51
        'FailedTestCount',
52
        'IgnoredTestCount',
53
        'InspectionStatsE',
54
        'InspectionStatsW',
55
        'SuccessRate',
56
        'TimeSpentInQueue',
57
    ];
58
    private const TIMESTAMP_FORMAT = 'Y-m-d\TH:i:s.uO';
59

60
    public static function printEvent(string $eventName, array $params = []): string
61
    {
62
        self::ensureValidJavaId($eventName);
132✔
63

64
        $result = "\n##teamcity[{$eventName}";
132✔
65

66
        foreach ($params as $propertyName => $propertyValue) {
132✔
67
            $escapedValue = self::escapeValue((string)$propertyValue);
132✔
68
            if (\is_int($propertyName)) {
132✔
69
                $result .= " '{$escapedValue}'"; // Value without name; skip the key and dump just the value
×
70
            } else {
71
                self::ensureValidJavaId($propertyName);
132✔
72
                $result .= " {$propertyName}='{$escapedValue}'"; // Classic name=value pair
132✔
73
            }
74
        }
75

76
        $result .= "]\n";
132✔
77

78
        return $result;
132✔
79
    }
80

81
    /**
82
     * Checks if given value is valid Java ID.
83
     * Valid Java ID starts with alpha-character and continues with mix of alphanumeric characters and `-`.
84
     */
85
    public static function ensureValidJavaId(string $value): void
86
    {
87
        if (\preg_match('/^[a-z][-a-z0-9]+$/i', $value) === 0) {
132✔
88
            throw new Exception("Value \"{$value}\" is not valid Java ID.");
×
89
        }
90
    }
91

92
    /**
93
     * @param null|\DateTime $datetime either date with timestamp or `NULL` for now
94
     */
95
    public static function formatTimestamp(?\DateTime $datetime = null): string
96
    {
97
        $datetime ??= new \DateTime();
132✔
98
        $formatted = $datetime->format(self::TIMESTAMP_FORMAT);
132✔
99

100
        // We need to pass only 3 microsecond digits.
101
        // 2000-01-01T12:34:56.123450+0100 <- before
102
        // 2000-01-01T12:34:56.123+0100 <- after
103
        return \substr($formatted, 0, 23) . \substr($formatted, 26);
132✔
104
    }
105

106
    private static function escapeValue(?string $value): ?string
107
    {
108
        if ($value === null) {
132✔
109
            return null;
×
110
        }
111

112
        $escapeCharacterMap = [
132✔
113
            '\'' => '|\'',
132✔
114
            "\n" => '|n',
132✔
115
            "\r" => '|r',
132✔
116
            '|'  => '||',
132✔
117
            '['  => '|[',
132✔
118
            ']'  => '|]',
132✔
119
        ];
132✔
120

121
        return \preg_replace_callback(
132✔
122
            '/([\'\n\r|[\]])|\\\\u(\d{4})/',
132✔
123
            static function (array $matches) use ($escapeCharacterMap) {
132✔
124
                if ($matches[1] !== '') {
78✔
125
                    return $escapeCharacterMap[$matches[1]];
78✔
126
                }
127

128
                if ($matches[2] !== '') {
×
129
                    return '|0x' . $matches[2];
×
130
                }
131

132
                throw new Exception('Unexpected match combination.');
×
133
            },
132✔
134
            $value,
132✔
135
        );
132✔
136
    }
137
}
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

© 2025 Coveralls, Inc