Skip to content

Commit ac9c3fa

Browse files
committed
Rules::resolve and Rules::getPublicSuffix allow wider type parameters
1 parent 7e42d27 commit ac9c3fa

File tree

7 files changed

+107
-38
lines changed

7 files changed

+107
-38
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ final class Rules
6363
public static function createFromPath(string $path, $context = null): self
6464
public static function createFromString(string $content): self
6565
public function __construct(array $rules)
66-
public function getPublicSuffix(string $domain = null, string $section = self::ALL_DOMAINS): PublicSuffix
67-
public function resolve(string $domain = null, string $section = self::ALL_DOMAINS): Domain
66+
public function getPublicSuffix($domain = null, string $section = self::ALL_DOMAINS): PublicSuffix
67+
public function resolve($domain = null, string $section = self::ALL_DOMAINS): Domain
6868
}
6969
~~~
7070

@@ -104,6 +104,7 @@ But also enable returns informations about the domain parts and its public suffi
104104

105105
final class Domain implements DomainInterface, JsonSerializable
106106
{
107+
public function __construct($domain = null, PublicSuffix $publicSuffix = null)
107108
public function getPublicSuffix(): ?string
108109
public function getRegistrableDomain(): ?string
109110
public function getSubDomain(); ?string
@@ -188,6 +189,7 @@ The `Rules::getPublicSuffix` method expects the same arguments as `Rules::resolv
188189

189190
final class PublicSuffix implements DomainInterface, JsonSerializable
190191
{
192+
public function __construct($publicSuffix = null)
191193
public function isKnown(): bool;
192194
public function isICANN(): bool;
193195
public function isPrivate(): bool;

bin/update-psl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#!/usr/bin/env php
22
<?php
33

4-
use Pdp;
5-
64
require dirname(__DIR__).'/src/Installer.php';
75

8-
Installer::updateLocalCache();
6+
Pdp\Installer::updateLocalCache();

src/Domain.php

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ public static function __set_state(array $properties): self
6767
/**
6868
* New instance.
6969
*
70-
* @param string|null $domain
70+
* @param mixed $domain
7171
* @param PublicSuffix $publicSuffix
7272
*/
73-
public function __construct(string $domain = null, PublicSuffix $publicSuffix = null)
73+
public function __construct($domain = null, PublicSuffix $publicSuffix = null)
7474
{
7575
list($this->domain, $this->labels) = $this->setDomain($domain);
7676
$this->publicSuffix = $this->setPublicSuffix($publicSuffix ?? new PublicSuffix());
@@ -125,11 +125,10 @@ private function setRegistrableDomain()
125125
return null;
126126
}
127127

128-
$labels = explode('.', $this->domain);
129-
$countLabels = count($labels);
130-
$countPublicSuffixLabels = count($this->publicSuffix);
131-
132-
return implode('.', array_slice($labels, $countLabels - $countPublicSuffixLabels - 1));
128+
return implode('.', array_slice(
129+
explode('.', $this->domain),
130+
count($this->labels) - count($this->publicSuffix) - 1
131+
));
133132
}
134133

135134
/**
@@ -143,14 +142,17 @@ private function setSubDomain()
143142
return null;
144143
}
145144

146-
$labels = explode('.', $this->domain);
147-
$countLabels = count($labels);
148-
$countLabelsToRemove = count(explode('.', $this->registrableDomain));
149-
if ($countLabels === $countLabelsToRemove) {
145+
$nbLabels = count($this->labels);
146+
$nbRegistrableLabels = count($this->publicSuffix) + 1;
147+
if ($nbLabels === $nbRegistrableLabels) {
150148
return null;
151149
}
152150

153-
return implode('.', array_slice($labels, 0, $countLabels - $countLabelsToRemove));
151+
return implode('.', array_slice(
152+
explode('.', $this->domain),
153+
0,
154+
$nbLabels - $nbRegistrableLabels
155+
));
154156
}
155157

156158
/**

src/IDNAConverterTrait.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Pdp;
1313

14+
use TypeError;
15+
1416
/**
1517
* @internal Domain name validator
1618
*
@@ -113,14 +115,18 @@ private function idnToUnicode(string $domain): string
113115
*
114116
* For example: setDomain('wWw.uLb.Ac.be') should return ['www.ulb.ac.be', ['be', 'ac', 'ulb', 'www']];
115117
*
116-
* @param string|null $domain
118+
* @param mixed $domain
117119
*
118120
* @throws Exception If the domain is invalid
119121
*
120122
* @return array
121123
*/
122-
private function setDomain(string $domain = null): array
124+
private function setDomain($domain = null): array
123125
{
126+
if ($domain instanceof DomainInterface) {
127+
return [$domain->getContent(), iterator_to_array($domain, false)];
128+
}
129+
124130
if (null === $domain) {
125131
return [$domain, []];
126132
}
@@ -129,6 +135,11 @@ private function setDomain(string $domain = null): array
129135
return [$domain, ['']];
130136
}
131137

138+
if (!is_scalar($domain) && !method_exists($domain, '__toString')) {
139+
throw new TypeError(sprintf('The domain must be a scalar, a stringable object, a DomainInterface object or null; `%s` given', gettype($domain)));
140+
}
141+
142+
$domain = (string) $domain;
132143
if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
133144
throw new Exception(sprintf('The domain `%s` is invalid: this is an IPv4 host', $domain));
134145
}

src/PublicSuffix.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ public static function __set_state(array $properties): self
5656
/**
5757
* New instance.
5858
*
59-
* @param string|null $publicSuffix
60-
* @param string $section
59+
* @param mixed $publicSuffix
60+
* @param string $section
6161
*/
62-
public function __construct(string $publicSuffix = null, string $section = '')
62+
public function __construct($publicSuffix = null, string $section = '')
6363
{
6464
list($this->publicSuffix, $this->labels) = $this->setDomain($publicSuffix);
6565
$this->section = $this->setSection($section);

src/Rules.php

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ public function __construct(array $rules)
9292
/**
9393
* Determines the public suffix for a given domain.
9494
*
95-
* @param string|null $domain
96-
* @param string $section
95+
* @param mixed $domain
96+
* @param string $section
9797
*
9898
* @throws Exception
9999
* If the Domain is invalid or malformed
@@ -102,20 +102,21 @@ public function __construct(array $rules)
102102
*
103103
* @return PublicSuffix
104104
*/
105-
public function getPublicSuffix(string $domain = null, string $section = self::ALL_DOMAINS): PublicSuffix
105+
public function getPublicSuffix($domain = null, string $section = self::ALL_DOMAINS): PublicSuffix
106106
{
107107
$this->validateSection($section);
108-
if (!$this->isMatchable($domainObj = new Domain($domain))) {
109-
throw new Exception(sprintf('The domain `%s` can not contain a public suffix', $domain));
108+
$domain = $domain instanceof Domain ? $domain : new Domain($domain);
109+
if (!$this->isMatchable($domain)) {
110+
throw new Exception(sprintf('The domain `%s` can not contain a public suffix', $domain->getContent()));
110111
}
111112

112-
$publicSuffix = $this->findPublicSuffix($domainObj, $section);
113+
$publicSuffix = $this->findPublicSuffix($domain, $section);
113114
if (null === $publicSuffix->getContent()) {
114-
$publicSuffix = new PublicSuffix($domainObj->getLabel(0));
115+
$publicSuffix = new PublicSuffix($domain->getLabel(0));
115116
}
116117

117118
static $pattern = '/[^\x20-\x7f]/';
118-
if (preg_match($pattern, $domainObj->getContent())) {
119+
if (preg_match($pattern, $domain->getContent())) {
119120
return $publicSuffix->toUnicode();
120121
}
121122

@@ -125,16 +126,16 @@ public function getPublicSuffix(string $domain = null, string $section = self::A
125126
/**
126127
* Returns PSL info for a given domain.
127128
*
128-
* @param string|null $domain
129-
* @param string $section
129+
* @param mixed $domain
130+
* @param string $section
130131
*
131132
* @return Domain
132133
*/
133-
public function resolve(string $domain = null, string $section = self::ALL_DOMAINS): Domain
134+
public function resolve($domain = null, string $section = self::ALL_DOMAINS): Domain
134135
{
135136
$this->validateSection($section);
136137
try {
137-
$domain = new Domain($domain);
138+
$domain = $domain instanceof Domain ? $domain : new Domain($domain);
138139
if (!$this->isMatchable($domain)) {
139140
return $domain;
140141
}

tests/RulesTest.php

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
use Pdp\Domain;
1010
use Pdp\Exception;
1111
use Pdp\Manager;
12+
use Pdp\PublicSuffix;
1213
use Pdp\Rules;
1314
use PHPUnit\Framework\TestCase;
15+
use TypeError;
1416

1517
/**
1618
* @coversDefaultClass Pdp\Rules
@@ -72,13 +74,25 @@ public function testDomainInternalPhpMethod()
7274
* @covers \Pdp\PublicSuffix::setSection
7375
* @covers \Pdp\PublicSuffix::isKnown
7476
* @covers \Pdp\Domain::isKnown
77+
* @covers \Pdp\IDNAConverterTrait::setDomain
7578
*/
7679
public function testNullWillReturnNullDomain()
7780
{
7881
$domain = $this->rules->resolve('COM');
7982
$this->assertFalse($domain->isKnown());
8083
}
8184

85+
86+
/**
87+
* @covers ::resolve
88+
* @covers \Pdp\IDNAConverterTrait::setDomain
89+
*/
90+
public function testThrowsTypeErrorOnWrongInput()
91+
{
92+
$this->expectException(TypeError::class);
93+
$this->rules->resolve(date_create());
94+
}
95+
8296
/**
8397
* @covers ::resolve
8498
* @covers ::validateSection
@@ -98,6 +112,7 @@ public function testResolveThrowsExceptionOnWrongDomainType()
98112
* @covers \Pdp\PublicSuffix::setSection
99113
* @covers \Pdp\PublicSuffix::isKnown
100114
* @covers \Pdp\Domain::isKnown
115+
* @covers \Pdp\IDNAConverterTrait::setDomain
101116
*/
102117
public function testIsSuffixValidFalse()
103118
{
@@ -119,6 +134,7 @@ public function testIsSuffixValidFalse()
119134
* @covers \Pdp\Domain::isKnown
120135
* @covers \Pdp\Domain::isICANN
121136
* @covers \Pdp\Domain::isPrivate
137+
* @covers \Pdp\IDNAConverterTrait::setDomain
122138
*/
123139
public function testIsSuffixValidTrue()
124140
{
@@ -142,6 +158,7 @@ public function testIsSuffixValidTrue()
142158
* @covers \Pdp\Domain::isKnown
143159
* @covers \Pdp\Domain::isICANN
144160
* @covers \Pdp\Domain::isPrivate
161+
* @covers \Pdp\IDNAConverterTrait::setDomain
145162
*/
146163
public function testIsSuffixValidFalseWithPunycoded()
147164
{
@@ -165,6 +182,7 @@ public function testIsSuffixValidFalseWithPunycoded()
165182
* @covers \Pdp\Domain::isKnown
166183
* @covers \Pdp\Domain::isICANN
167184
* @covers \Pdp\Domain::isPrivate
185+
* @covers \Pdp\IDNAConverterTrait::setDomain
168186
*/
169187
public function testSubDomainIsNull()
170188
{
@@ -177,7 +195,7 @@ public function testSubDomainIsNull()
177195
/**
178196
* @covers ::resolve
179197
* @covers ::validateSection
180-
* @covers \Pdp\Domain::setDomain
198+
* @covers \Pdp\IDNAConverterTrait::setDomain
181199
*/
182200
public function testWithInvalidDomainName()
183201
{
@@ -191,6 +209,7 @@ public function testWithInvalidDomainName()
191209
* @covers ::findPublicSuffix
192210
* @covers ::findPublicSuffixFromSection
193211
* @covers \Pdp\PublicSuffix::setSection
212+
* @covers \Pdp\IDNAConverterTrait::setDomain
194213
*/
195214
public function testWithPrivateDomain()
196215
{
@@ -207,6 +226,7 @@ public function testWithPrivateDomain()
207226
* @covers ::findPublicSuffix
208227
* @covers ::findPublicSuffixFromSection
209228
* @covers \Pdp\PublicSuffix::setSection
229+
* @covers \Pdp\IDNAConverterTrait::setDomain
210230
*/
211231
public function testWithPrivateDomainInvalid()
212232
{
@@ -224,6 +244,7 @@ public function testWithPrivateDomainInvalid()
224244
* @covers ::findPublicSuffix
225245
* @covers ::findPublicSuffixFromSection
226246
* @covers \Pdp\PublicSuffix::setSection
247+
* @covers \Pdp\IDNAConverterTrait::setDomain
227248
*/
228249
public function testWithPrivateDomainValid()
229250
{
@@ -241,6 +262,7 @@ public function testWithPrivateDomainValid()
241262
* @covers ::findPublicSuffix
242263
* @covers ::findPublicSuffixFromSection
243264
* @covers \Pdp\PublicSuffix::setSection
265+
* @covers \Pdp\IDNAConverterTrait::setDomain
244266
*/
245267
public function testWithICANNDomainInvalid()
246268
{
@@ -252,6 +274,37 @@ public function testWithICANNDomainInvalid()
252274
$this->assertSame('ac.be', $domain->getPublicSuffix());
253275
}
254276

277+
/**
278+
* @covers ::resolve
279+
* @covers ::validateSection
280+
* @covers ::findPublicSuffix
281+
* @covers ::findPublicSuffixFromSection
282+
* @covers \Pdp\PublicSuffix::setSection
283+
* @covers \Pdp\IDNAConverterTrait::setDomain
284+
*/
285+
public function testWithDomainObject()
286+
{
287+
$domain = new Domain('private.ulb.ac.be', new PublicSuffix('ac.be', Rules::ICANN_DOMAINS));
288+
$newDomain = $this->rules->resolve($domain);
289+
$this->assertSame('private.ulb.ac.be', $domain->getDomain());
290+
$this->assertTrue($domain->isKnown());
291+
$this->assertTrue($domain->isICANN());
292+
$this->assertFalse($domain->isPrivate());
293+
$this->assertSame('ac.be', $domain->getPublicSuffix());
294+
$this->assertSame($domain, $newDomain);
295+
}
296+
297+
/**
298+
* @covers ::getPublicSuffix
299+
* @covers \Pdp\IDNAConverterTrait::setDomain
300+
*/
301+
public function testWithDomainInterfaceObject()
302+
{
303+
$publicSuffix = new PublicSuffix('ac.be', Rules::ICANN_DOMAINS);
304+
$psl = $this->rules->getPublicSuffix($publicSuffix);
305+
$this->assertEquals($publicSuffix, $psl);
306+
}
307+
255308
/**
256309
* @dataProvider parseDataProvider
257310
* @param mixed $publicSuffix
@@ -274,6 +327,7 @@ public function testGetRegistrableDomain($publicSuffix, $registrableDomain, $dom
274327
* @param mixed $domain
275328
* @param mixed $expectedDomain
276329
* @covers ::resolve
330+
* @covers \Pdp\IDNAConverterTrait::setDomain
277331
* @covers \Pdp\Domain::setPublicSuffix
278332
* @covers \Pdp\Domain::getPublicSuffix
279333
*/
@@ -289,8 +343,8 @@ public function testGetPublicSuffix($publicSuffix, $registrableDomain, $domain,
289343
* @param mixed $domain
290344
* @param mixed $expectedDomain
291345
* @covers ::resolve
346+
* @covers \Pdp\IDNAConverterTrait::setDomain
292347
* @covers \Pdp\Domain::withPublicSuffix
293-
* @covers \Pdp\Domain::setDomain
294348
* @covers \Pdp\Domain::getContent
295349
*/
296350
public function testGetDomain($publicSuffix, $registrableDomain, $domain, $expectedDomain)
@@ -331,8 +385,8 @@ public function parseDataProvider()
331385
*
332386
* @covers ::getPublicSuffix
333387
* @covers ::validateSection
334-
* @covers \Pdp\Domain::setDomain
335388
* @covers ::isMatchable
389+
* @covers \Pdp\IDNAConverterTrait::setDomain
336390
*/
337391
public function testGetPublicSuffixThrowsException($domain, $section)
338392
{
@@ -360,7 +414,7 @@ public function invalidParseProvider()
360414
* @covers ::getPublicSuffix
361415
* @covers ::validateSection
362416
* @covers ::isMatchable
363-
* @covers \Pdp\PublicSuffix::setDomain
417+
* @covers \Pdp\IDNAConverterTrait::setDomain
364418
* @dataProvider validPublicSectionProvider
365419
*
366420
* @param string|null $domain
@@ -419,6 +473,7 @@ public function checkPublicSuffix($input, $expected)
419473
* @covers ::findPublicSuffixFromSection
420474
* @covers \Pdp\Domain::withPublicSuffix
421475
* @covers \Pdp\Domain::getRegistrableDomain
476+
* @covers \Pdp\IDNAConverterTrait::setDomain
422477
*/
423478
public function testPublicSuffixSpec()
424479
{

0 commit comments

Comments
 (0)