Skip to content

Commit 1f28803

Browse files
committed
Use RegisteredName to improve ResolvedDomain
1 parent 3130723 commit 1f28803

File tree

9 files changed

+99
-66
lines changed

9 files changed

+99
-66
lines changed

src/Domain.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function keys(string $label = null): array
8383
}
8484

8585
/**
86-
* @return array<int, string>
86+
* @return list<string>
8787
*/
8888
public function labels(): array
8989
{
@@ -112,20 +112,20 @@ public function toUnicode(): self
112112
/**
113113
* @throws CannotProcessHost
114114
*/
115-
public function prepend(DomainNameProvider|Host|string|Stringable|null $label): self
115+
public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self
116116
{
117117
return $this->newInstance($this->registeredName->prepend($label));
118118
}
119119

120120
/**
121121
* @throws CannotProcessHost
122122
*/
123-
public function append(DomainNameProvider|Host|string|Stringable|null $label): self
123+
public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self
124124
{
125125
return $this->newInstance($this->registeredName->append($label));
126126
}
127127

128-
public function withLabel(int $key, DomainNameProvider|Host|string|Stringable|null $label): self
128+
public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self
129129
{
130130
return $this->newInstance($this->registeredName->withLabel($key, $label));
131131
}

src/DomainName.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function label(int $key): ?string;
3737
/**
3838
* Returns the object labels.
3939
*
40-
* @return array<int, string>
40+
* @return list<string>
4141
*/
4242
public function labels(): array;
4343

@@ -47,7 +47,7 @@ public function labels(): array;
4747
* If a value is specified only the keys associated with
4848
* the given value will be returned
4949
*
50-
* @return array<int>
50+
* @return list<int>
5151
*/
5252
public function keys(string $label = null): array;
5353

@@ -64,14 +64,14 @@ public function getIterator(): Iterator;
6464
*
6565
* @see ::withLabel
6666
*/
67-
public function prepend(DomainNameProvider|Host|string|Stringable|null $label): self;
67+
public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self;
6868

6969
/**
7070
* Appends a label to the domain.
7171
*
7272
* @see ::withLabel
7373
*/
74-
public function append(DomainNameProvider|Host|string|Stringable|null $label): self;
74+
public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self;
7575

7676
/**
7777
* Returns an instance with the specified label added at the specified key.
@@ -82,12 +82,12 @@ public function append(DomainNameProvider|Host|string|Stringable|null $label): s
8282
* If $key is non-negative, the added label will be the label at $key position from the start.
8383
* If $key is negative, the added label will be the label at $key position from the end.
8484
*
85-
* @param string|null|Stringable|Host|DomainNameProvider $label a domain label
85+
* @param DomainNameProvider|Host|Stringable|string|int|null $label a domain label
8686
*
8787
* @throws CannotProcessHost If the key is out of bounds
8888
* @throws CannotProcessHost If the label is converted to the NULL value
8989
*/
90-
public function withLabel(int $key, DomainNameProvider|Host|string|Stringable|null $label): self;
90+
public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self;
9191

9292
/**
9393
* Returns an instance with the label at the specified key removed.

src/RegisteredName.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ final class RegisteredName implements DomainName
3737
^(?:(?&reg_name)\.){0,126}(?&reg_name)\.?$/ix';
3838
private const REGEXP_URI_DELIMITERS = '/[:\/?#\[\]@ ]/';
3939

40-
/** @var array<int, string> */
40+
/** @var list<string> */
4141
private readonly array $labels;
4242
private readonly ?string $domain;
4343

@@ -200,7 +200,7 @@ public function keys(string $label = null): array
200200
}
201201

202202
/**
203-
* @return array<int, string>
203+
* @return list<string>
204204
*/
205205
public function labels(): array
206206
{
@@ -238,7 +238,7 @@ public function toUnicode(): self
238238
/**
239239
* Filter a subdomain to update the domain part.
240240
*/
241-
private function normalize(DomainNameProvider|Host|Stringable|string|null $domain): ?string
241+
private function normalize(DomainNameProvider|Host|Stringable|string|int|null $domain): ?string
242242
{
243243
if ($domain instanceof DomainNameProvider) {
244244
$domain = $domain->domain();
@@ -264,20 +264,20 @@ private function normalize(DomainNameProvider|Host|Stringable|string|null $domai
264264
/**
265265
* @throws CannotProcessHost
266266
*/
267-
public function prepend(DomainNameProvider|Host|string|Stringable|null $label): self
267+
public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self
268268
{
269269
return $this->withLabel(count($this->labels), $label);
270270
}
271271

272272
/**
273273
* @throws CannotProcessHost
274274
*/
275-
public function append(DomainNameProvider|Host|string|Stringable|null $label): self
275+
public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self
276276
{
277277
return $this->withLabel(- count($this->labels) - 1, $label);
278278
}
279279

280-
public function withLabel(int $key, DomainNameProvider|Host|string|Stringable|null $label): self
280+
public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self
281281
{
282282
$nbLabels = count($this->labels);
283283
if ($key < - $nbLabels - 1 || $key > $nbLabels) {

src/ResolvedDomain.php

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ final class ResolvedDomain implements ResolvedDomainName
1313
private readonly DomainName $registrableDomain;
1414
private readonly DomainName $subDomain;
1515

16+
/**
17+
* @throws CannotProcessHost
18+
*/
1619
private function __construct(
1720
private readonly DomainName $domain,
1821
private readonly EffectiveTopLevelDomain $suffix
@@ -24,28 +27,40 @@ private function __construct(
2427
] = $this->parse();
2528
}
2629

27-
public static function fromICANN(int|DomainNameProvider|Host|string|Stringable|null $domain, int $suffixLength): self
30+
/**
31+
* @throws CannotProcessHost
32+
*/
33+
public static function fromICANN(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength): self
2834
{
2935
$domain = self::setDomainName($domain);
3036

3137
return new self($domain, Suffix::fromICANN($domain->slice(0, $suffixLength)));
3238
}
3339

34-
public static function fromPrivate(int|DomainNameProvider|Host|string|Stringable|null $domain, int $suffixLength): self
40+
/**
41+
* @throws CannotProcessHost
42+
*/
43+
public static function fromPrivate(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength): self
3544
{
3645
$domain = self::setDomainName($domain);
3746

3847
return new self($domain, Suffix::fromPrivate($domain->slice(0, $suffixLength)));
3948
}
4049

41-
public static function fromIANA(int|DomainNameProvider|Host|string|Stringable|null $domain): self
50+
/**
51+
* @throws CannotProcessHost
52+
*/
53+
public static function fromIANA(DomainNameProvider|Host|Stringable|string|int|null $domain): self
4254
{
4355
$domain = self::setDomainName($domain);
4456

4557
return new self($domain, Suffix::fromIANA($domain->label(0)));
4658
}
4759

48-
public static function fromUnknown(int|DomainNameProvider|Host|string|Stringable|null $domain, int $suffixLength = 0): self
60+
/**
61+
* @throws CannotProcessHost
62+
*/
63+
public static function fromUnknown(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength = 0): self
4964
{
5065
$domain = self::setDomainName($domain);
5166

@@ -60,19 +75,19 @@ public static function __set_state(array $properties): self
6075
return new self($properties['domain'], $properties['suffix']);
6176
}
6277

63-
private static function setDomainName(int|DomainNameProvider|Host|string|Stringable|null $domain): DomainName
78+
private static function setDomainName(DomainNameProvider|Host|Stringable|string|int|null $domain): DomainName
6479
{
6580
return match (true) {
6681
$domain instanceof DomainNameProvider => $domain->domain(),
6782
$domain instanceof DomainName => $domain,
68-
default => Domain::fromIDNA2008($domain),
83+
default => RegisteredName::fromIDNA2008($domain),
6984
};
7085
}
7186

7287
/**
7388
* Make sure the Value Object is always in a valid state.
7489
*
75-
* @throws UnableToResolveDomain If the suffix can not be attached to the domain
90+
* @throws UnableToResolveDomain|CannotProcessHost If the suffix can not be attached to the domain
7691
*
7792
* @return array{registrableDomain: DomainName, secondLevelDomain: DomainName, subDomain: DomainName}
7893
*/
@@ -116,39 +131,39 @@ public function domain(): DomainName
116131
return $this->domain;
117132
}
118133

119-
public function jsonSerialize(): ?string
134+
public function registrableDomain(): DomainName
120135
{
121-
return $this->domain->jsonSerialize();
136+
return $this->registrableDomain;
122137
}
123138

124-
public function value(): ?string
139+
public function secondLevelDomain(): DomainName
125140
{
126-
return $this->domain->value();
141+
return $this->secondLevelDomain;
127142
}
128143

129-
public function toString(): string
144+
public function subDomain(): DomainName
130145
{
131-
return $this->domain->toString();
146+
return $this->subDomain;
132147
}
133148

134-
public function registrableDomain(): DomainName
149+
public function suffix(): EffectiveTopLevelDomain
135150
{
136-
return $this->registrableDomain;
151+
return $this->suffix;
137152
}
138153

139-
public function secondLevelDomain(): DomainName
154+
public function jsonSerialize(): ?string
140155
{
141-
return $this->secondLevelDomain;
156+
return $this->domain->jsonSerialize();
142157
}
143158

144-
public function subDomain(): DomainName
159+
public function value(): ?string
145160
{
146-
return $this->subDomain;
161+
return $this->domain->value();
147162
}
148163

149-
public function suffix(): EffectiveTopLevelDomain
164+
public function toString(): string
150165
{
151-
return $this->suffix;
166+
return $this->domain->toString();
152167
}
153168

154169
public function toAscii(): self
@@ -161,7 +176,7 @@ public function toUnicode(): self
161176
return new self($this->domain->toUnicode(), $this->suffix->toUnicode());
162177
}
163178

164-
public function withSuffix(int|DomainNameProvider|Host|string|Stringable|null $suffix): self
179+
public function withSuffix(DomainNameProvider|Host|Stringable|string|int|null $suffix): self
165180
{
166181
if (!$suffix instanceof EffectiveTopLevelDomain) {
167182
$suffix = Suffix::fromUnknown($suffix);
@@ -173,30 +188,27 @@ public function withSuffix(int|DomainNameProvider|Host|string|Stringable|null $s
173188
);
174189
}
175190

176-
public function withSubDomain(int|DomainNameProvider|Host|string|Stringable|null $subDomain): self
191+
public function withSubDomain(DomainNameProvider|Host|Stringable|string|int|null $subDomain): self
177192
{
178193
if (null === $this->suffix->value()) {
179194
throw UnableToResolveDomain::dueToMissingRegistrableDomain($this->domain);
180195
}
181196

182-
$subDomain = $this->domain->clear()->append(self::setDomainName($subDomain));
197+
$subDomain = RegisteredName::fromIDNA2008($subDomain);
183198
if ($this->subDomain->value() === $subDomain->value()) {
184199
return $this;
185200
}
186201

187202
return new self($this->registrableDomain->prepend($subDomain), $this->suffix);
188203
}
189204

190-
/**
191-
* @param int|DomainNameProvider|Host|string|Stringable|null $label the second level domain
192-
*/
193-
public function withSecondLevelDomain($label): self
205+
public function withSecondLevelDomain(DomainNameProvider|Host|Stringable|string|int|null $label): self
194206
{
195207
if (null === $this->suffix->value()) {
196208
throw UnableToResolveDomain::dueToMissingRegistrableDomain($this->domain);
197209
}
198210

199-
$label = self::setDomainName($label);
211+
$label = RegisteredName::fromIDNA2008($label);
200212
if (1 !== count($label)) {
201213
throw UnableToResolveDomain::dueToInvalidSecondLevelDomain($label);
202214
}

src/ResolvedDomainName.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ public function secondLevelDomain(): DomainName;
2222
public function registrableDomain(): DomainName;
2323

2424
/**
25-
* Returns the sub domain component.
25+
* Returns the subdomain component.
2626
*/
2727
public function subDomain(): DomainName;
2828

2929
/**
30-
* Returns an instance with the specified sub domain added.
30+
* Returns an instance with the specified subdomain added.
3131
*
3232
* This method MUST retain the state of the current instance, and return
33-
* an instance that contains the new sub domain
33+
* an instance that contains the new subdomain
3434
*
3535
* @throws CannotProcessHost If the Sub domain can not be added to the current Domain
3636
*/

src/ResolvedDomainTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,4 +553,20 @@ public function testItReturnsTheInstanceWhenTheSLDIsEqual(): void
553553

554554
self::assertEquals($domain->withSecondLevelDomain('ulb'), $domain);
555555
}
556+
557+
public function testSubDomainCanHandleIpLikeValue(): void
558+
{
559+
self::assertSame(
560+
'1.1.1.1.cloudflare-dns.com',
561+
ResolvedDomain::fromICANN('cloudflare-dns.com', 1)->withSubDomain('1.1.1.1')->toString()
562+
);
563+
}
564+
565+
public function testSuffixCanHandleIpLikeValue(): void
566+
{
567+
self::assertSame(
568+
'cloudflare-dns.com.1.1.1.1',
569+
ResolvedDomain::fromICANN('cloudflare-dns.com.1.1.1.1', 4)->toString()
570+
);
571+
}
556572
}

0 commit comments

Comments
 (0)