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

dg / texy / 21345922688

26 Jan 2026 04:05AM UTC coverage: 92.426% (+0.04%) from 92.382%
21345922688

push

github

dg
HtmlElement: removed toHtml() & toText()

18 of 19 new or added lines in 5 files covered. (94.74%)

28 existing lines in 7 files now uncovered.

2404 of 2601 relevant lines covered (92.43%)

0.92 hits per line

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

89.19
/src/Texy/Regexp.php
1
<?php
2

3
/**
4
 * This file is part of the Texy! (https://texy.nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Texy;
11

12
use JetBrains\PhpStorm\Language;
13
use function array_keys, array_values, is_array, preg_last_error, preg_last_error_msg, preg_match, preg_match_all, preg_replace, preg_replace_callback, preg_split, strlen;
14
use const PREG_OFFSET_CAPTURE, PREG_SET_ORDER, PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE;
15

16

17
/**
18
 * Regular expression utilities with error handling.
19
 */
20
class Regexp
21
{
22
        /**
23
         * Splits string by a regular expression. Subpatterns in parentheses will be captured and returned as well.
24
         * @return ($captureOffset is true ? list<array{string, int}> : list<string>)
25
         */
26
        public static function split(
1✔
27
                string $subject,
28
                #[Language('PhpRegExpXTCommentMode')]
29
                string $pattern,
30
                bool $captureOffset = false,
31
                bool $skipEmpty = false,
32
                int $limit = -1,
33
        ): array
34
        {
35
                $flags = ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0);
1✔
36
                return self::pcre('preg_split', [$pattern . 'ux', $subject, $limit, $flags | PREG_SPLIT_DELIM_CAPTURE]);
1✔
37
        }
38

39

40
        /**
41
         * Searches the string for the part matching the regular expression and returns
42
         * an array with the found expression and individual subexpressions, or null.
43
         * @return ($captureOffset is true ? array<int|string, array{string|null, int}> : array<int|string, string|null>)|null
44
         */
45
        public static function match(
1✔
46
                string $subject,
47
                #[Language('PhpRegExpXTCommentMode')]
48
                string $pattern,
49
                bool $captureOffset = false,
50
                int $offset = 0,
51
        ): ?array
52
        {
53
                $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | PREG_UNMATCHED_AS_NULL;
1✔
54
                if ($offset > strlen($subject)) {
1✔
55
                        return null;
×
56
                }
57

58
                $m = [];
1✔
59
                return self::pcre('preg_match', [$pattern . 'ux', $subject, &$m, $flags, $offset])
1✔
60
                        ? $m
1✔
61
                        : null;
1✔
62
        }
63

64

65
        /**
66
         * Searches the string for all occurrences matching the regular expression and
67
         * returns an array of arrays containing the found expression and each subexpression.
68
         * @return ($captureOffset is true ? list<array<int|string, array{string|null, int}>> : list<array<int|string, string|null>>)
69
         */
70
        public static function matchAll(
1✔
71
                string $subject,
72
                #[Language('PhpRegExpXTCommentMode')]
73
                string $pattern,
74
                bool $captureOffset = false,
75
                int $offset = 0,
76
        ): array
77
        {
78
                if ($offset > strlen($subject)) {
1✔
UNCOV
79
                        return [];
×
80
                }
81

82
                $m = [];
1✔
83
                $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | PREG_UNMATCHED_AS_NULL | PREG_SET_ORDER;
1✔
84
                self::pcre('preg_match_all', [$pattern . 'ux', $subject, &$m, $flags, $offset]);
1✔
85
                return $m;
1✔
86
        }
87

88

89
        /**
90
         * Replaces all occurrences matching regular expression $pattern which can be string or array in the form `pattern => replacement`.
91
         * @param  string|string[]  $pattern
92
         * @param  string|\Closure(string[]): string  $replacement
93
         */
94
        public static function replace(
1✔
95
                string $subject,
96
                #[Language('PhpRegExpXTCommentMode')]
97
                string|array $pattern,
98
                string|\Closure $replacement = '',
99
                int $limit = -1,
100
                bool $captureOffset = false,
101
        ): string
102
        {
103
                if (is_array($pattern) && is_string(key($pattern))) {
1✔
104
                        $patterns = array_map(static fn($p) => $p . 'ux', array_keys($pattern));
1✔
105
                        return self::pcre('preg_replace', [$patterns, array_values($pattern), $subject, $limit]);
1✔
106
                }
107

108
                $pattern = is_array($pattern)
1✔
UNCOV
109
                        ? array_map(static fn($p) => $p . 'ux', $pattern)
×
110
                        : $pattern . 'ux';
1✔
111

112
                if ($replacement instanceof \Closure) {
1✔
113
                        $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | PREG_UNMATCHED_AS_NULL;
1✔
114
                        return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit, 0, $flags]);
1✔
115
                } else {
116
                        return self::pcre('preg_replace', [$pattern, $replacement, $subject, $limit]);
1✔
117
                }
118
        }
119

120

121
        public static function quote(string $s): string
1✔
122
        {
123
                return addcslashes($s, "\x00..\x20-.\\+*?[^]$(){}=!<>|:-#");
1✔
124
        }
125

126

127
        /**
128
         * @internal
129
         * @param  array<mixed>  $args
130
         */
131
        public static function pcre(string $func, array $args): mixed
1✔
132
        {
133
                assert(is_callable($func));
134
                $res = @$func(...$args);
1✔
135
                if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars
1✔
136
                        && ($res === null || !in_array($func, ['preg_replace_callback', 'preg_replace'], true))
1✔
137
                ) {
UNCOV
138
                        throw new RegexpException(preg_last_error_msg() . ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code);
×
139
                }
140

141
                return $res;
1✔
142
        }
143
}
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