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

smartemailing / types / 16907400834

12 Aug 2025 11:24AM UTC coverage: 92.527% (-0.07%) from 92.595%
16907400834

push

github

web-flow
add url type get fragment method (#144)

Co-authored-by: Roman Veselý <vesely@xproduction.cz>

0 of 1 new or added line in 1 file covered. (0.0%)

1263 of 1365 relevant lines covered (92.53%)

0.93 hits per line

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

89.47
/src/UrlType.php
1
<?php
2

3
declare(strict_types = 1);
4

5
namespace SmartEmailing\Types;
6

7
use Nette\Http\Url;
8
use Nette\InvalidArgumentException;
9
use Nette\Utils\Validators;
10
use SmartEmailing\Types\Comparable\ComparableInterface;
11
use SmartEmailing\Types\Comparable\StringComparableTrait;
12
use SmartEmailing\Types\ExtractableTraits\StringExtractableTrait;
13
use SmartEmailing\Types\Helpers\StringHelpers;
14

15
final class UrlType implements ToStringInterface, ComparableInterface
16
{
17

18
        use StringExtractableTrait;
19
        use ToStringTrait;
20
        use StringComparableTrait;
21

22
        private Url $url;
23

24
        private function __construct(
25
                string $value
26
        )
27
        {
28
                $value = StringHelpers::sanitize($value);
1✔
29
                $value = \strtr(
1✔
30
                        $value,
1✔
31
                        [
32
                                ' ' => '%20',
33
                        ]
34
                );
35

36
                // urlencode non-ascii chars
37
                $value = (string) \preg_replace_callback(
1✔
38
                        '/[^\x20-\x7f]/',
39
                        static fn ($match): string => \urlencode($match[0]),
1✔
40
                        $value
1✔
41
                );
42

43
                // Nette\Utils 2.4 has a bug, URLs without slash in empty path are treated as invalid
44
                $value = $this->addSlashToPathOrFail($value) ?? $value;
1✔
45

46
                if (!Validators::isUrl($value)) {
1✔
47
                        throw new InvalidTypeException('Invalid URL or missing protocol: ' . $value);
1✔
48
                }
49

50
                try {
51
                        $this->url = new Url($value);
1✔
52
                } catch (InvalidArgumentException $e) {
×
53
                        throw new InvalidTypeException('Invalid URL or missing protocol: ' . $value);
×
54
                }
55
        }
1✔
56

57
        public function getAuthority(): string
58
        {
59
                return $this->url->getAuthority();
1✔
60
        }
61

62
        public function getHost(): string
63
        {
64
                return $this->url->getHost();
1✔
65
        }
66

67
        public function getQueryString(): string
68
        {
69
                return $this->url->getQuery();
1✔
70
        }
71

72
    public function getFragment(): string
73
    {
NEW
74
        return $this->url->getFragment();
×
75
    }
76

77
        public function getPath(): string
78
        {
79
                return $this->url->getPath();
1✔
80
        }
81

82
        public function getAbsoluteUrl(): string
83
        {
84
                return $this->getValue();
1✔
85
        }
86

87
        /**
88
         * @deprecated use getQueryParameter instead
89
         */
90
        public function getParameter(
91
                string $name
92
        ): ?string
93
        {
94
                return $this->url->getQueryParameter($name) ?? null;
1✔
95
        }
96

97
        public function getBaseUrl(): string
98
        {
99
                return $this->url->getBaseUrl();
1✔
100
        }
101

102
        /**
103
         * @deprecated use getValue or (string) type cast
104
         */
105
        public function toString(): string
106
        {
107
                return (string) $this->url;
1✔
108
        }
109

110
        public function getScheme(): string
111
        {
112
                return $this->url->getScheme();
1✔
113
        }
114

115
        /**
116
         * @param array<string> $names
117
         */
118
        public function hasParameters(
119
                array $names
120
        ): bool
121
        {
122
                $parameters = \array_keys($this->url->getQueryParameters());
1✔
123

124
                foreach ($names as $name) {
1✔
125
                        if (!\in_array($name, $parameters, true)) {
1✔
126
                                return false;
1✔
127
                        }
128
                }
129

130
                return true;
1✔
131
        }
132

133
        /**
134
         * @return array<mixed>
135
         */
136
        public function getParameters(): array
137
        {
138
                return $this->url->getQueryParameters();
1✔
139
        }
140

141
        public function withQueryParameter(
142
                string $name,
143
                mixed $value
144
        ): self
145
        {
146
                $dolly = clone $this;
1✔
147
                $dolly->url->setQueryParameter(
1✔
148
                        $name,
149
                        $value
150
                );
151

152
                return $dolly;
1✔
153
        }
154

155
        /**
156
         * @deprecated use withHostName
157
         */
158
        public function withHost(
159
                Domain $host
160
        ): self
161
        {
162
                $dolly = clone $this;
1✔
163
                $dolly->url->setHost(
1✔
164
                        $host->getValue()
1✔
165
                );
166

167
                return $dolly;
1✔
168
        }
169

170
        public function withHostName(
171
                HostName $host
172
        ): self
173
        {
174
                $dolly = clone $this;
1✔
175
                $dolly->url->setHost(
1✔
176
                        $host->getValue()
1✔
177
                );
178

179
                return $dolly;
1✔
180
        }
181

182
        public function withScheme(
183
                string $scheme
184
        ): self
185
        {
186
                $dolly = clone $this;
1✔
187
                $dolly->url->setScheme(
1✔
188
                        $scheme
189
                );
190

191
                return $dolly;
1✔
192
        }
193

194
        public function withPath(
195
                string $path
196
        ): self
197
        {
198
                $dolly = clone $this;
1✔
199
                $dolly->url->setPath(
1✔
200
                        $path
201
                );
202

203
                return $dolly;
1✔
204
        }
205

206
        public function getQueryParameter(
207
                string $name,
208
                mixed $default = null
209
        ): mixed
210
        {
211
                return $this->url->getQueryParameter($name) ?? $default;
1✔
212
        }
213

214
        public function getValue(): string
215
        {
216
                return $this->url->getAbsoluteUrl();
1✔
217
        }
218

219
        private function addSlashToPathOrFail(
220
                string $value
221
        ): ?string
222
        {
223
                $urlParts = \parse_url($value);
1✔
224

225
                if ($urlParts === false) {
1✔
226
                        return null;
×
227
                }
228

229
                return $this->buildUrl($urlParts);
1✔
230
        }
231

232
        /**
233
         * @param array<string, string|int> $urlParts
234
         */
235
        private function buildUrl(
236
                array $urlParts
237
        ): string
238
        {
239
                $scheme = isset($urlParts['scheme'])
1✔
240
                        ? $urlParts['scheme'] . '://'
1✔
241
                        : '';
1✔
242
                $host = $urlParts['host'] ?? '';
1✔
243
                $port = isset($urlParts['port'])
1✔
244
                        ? ':' . $urlParts['port']
×
245
                        : '';
1✔
246
                $user = $urlParts['user'] ?? '';
1✔
247
                $pass = isset($urlParts['pass'])
1✔
248
                        ? ':' . $urlParts['pass']
×
249
                        : '';
1✔
250
                $pass = $user !== '' || $pass !== ''
1✔
251
                        ? $pass . '@'
×
252
                        : '';
1✔
253
                $path = $urlParts['path'] ?? '/';
1✔
254
                $query = isset($urlParts['query'])
1✔
255
                        ? '?' . $urlParts['query']
1✔
256
                        : '';
1✔
257
                $fragment = isset($urlParts['fragment'])
1✔
258
                        ? '#' . $urlParts['fragment']
×
259
                        : '';
1✔
260

261
                return $scheme . $user . $pass . $host . $port . $path . $query . $fragment;
1✔
262
        }
263

264
        public function __clone()
265
        {
266
                $this->url = clone $this->url;
1✔
267
        }
1✔
268

269
}
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