Skip to content

Commit 18496ee

Browse files
committed
improve Domain modifier methods
1 parent 7db81b1 commit 18496ee

11 files changed

+149
-124
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ All Notable changes to `PHP Domain Parser` **5.x** series will be documented in
66

77
### Added
88

9-
- `Pdp\SectionInterface` interface implemented by `Pdp\Rules` and `Pdp\PublicSuffix`
9+
- `Pdp\PublicSuffixListSection` interface implemented by `Pdp\Rules` and `Pdp\PublicSuffix`
1010
- `Pdp\DomainInterface` interface implemented by `Pdp\Domain` and `Pdp\PublicSuffix`
1111
- `Pdp\Domain` implements the `Countable` interface.
1212
- `Pdp\Domain::getContent` returns the Domain name value replaces `Pdp\Domain::getDomain`

src/Converter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* @author Jeremy Kendall <[email protected]>
2222
* @author Ignace Nyamagana Butera <[email protected]>
2323
*/
24-
final class Converter implements SectionInterface
24+
final class Converter implements PublicSuffixListSection
2525
{
2626
use IDNAConverterTrait;
2727

src/Domain.php

Lines changed: 86 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,7 @@ private function setPublicSuffix(PublicSuffix $publicSuffix): PublicSuffix
9999
throw new Exception(sprintf('The domain `%s` can not contain a public suffix', $this->domain));
100100
}
101101

102-
static $pattern = '/[^\x20-\x7f]/';
103-
if (preg_match($pattern, $this->domain)) {
104-
$publicSuffix = $publicSuffix->toUnicode();
105-
}
106-
102+
$publicSuffix = $this->normalize($publicSuffix);
107103
$publicSuffixContent = $publicSuffix->getContent();
108104
if ($this->domain === $publicSuffixContent) {
109105
throw new Exception(sprintf('The public suffix `%s` can not be equal to the domain name `%s`', $publicSuffixContent, $this->domain));
@@ -116,6 +112,23 @@ private function setPublicSuffix(PublicSuffix $publicSuffix): PublicSuffix
116112
return $publicSuffix;
117113
}
118114

115+
/**
116+
* Normalize the domain name encoding content.
117+
*
118+
* @param mixed $domain
119+
*
120+
* @return mixed
121+
*/
122+
private function normalize($domain)
123+
{
124+
static $pattern = '/[^\x20-\x7f]/';
125+
if (null !== $this->domain && preg_match($pattern, $this->domain)) {
126+
return $domain->toUnicode();
127+
}
128+
129+
return $domain->toAscii();
130+
}
131+
119132
/**
120133
* Computes the registrable domain part.
121134
*/
@@ -358,8 +371,8 @@ public function toUnicode()
358371
* are: be, ac.be, ulb.ac.be, or the null public suffix. Any other public
359372
* suffix will throw an Exception.
360373
*
361-
* This method does not change the domain conent it only updates/changes/removes
362-
* its public suffix information.
374+
* This method MUST retain the state of the current instance, and return
375+
* an instance that contains the modified Public Suffix Information.
363376
*
364377
* @param mixed $publicSuffix
365378
*
@@ -371,11 +384,7 @@ public function resolve($publicSuffix): self
371384
$publicSuffix = new PublicSuffix($publicSuffix);
372385
}
373386

374-
static $pattern = '/[^\x20-\x7f]/';
375-
if (null !== $this->domain && preg_match($pattern, $this->domain)) {
376-
$publicSuffix = $publicSuffix->toUnicode();
377-
}
378-
387+
$publicSuffix = $this->normalize($publicSuffix);
379388
if ($this->publicSuffix == $publicSuffix) {
380389
return $this;
381390
}
@@ -392,7 +401,7 @@ public function resolve($publicSuffix): self
392401
* Returns an instance with the specified sub domain added.
393402
*
394403
* This method MUST retain the state of the current instance, and return
395-
* an instance that contains the modified domain with the new sub domain
404+
* an instance that contains the new sub domain
396405
*
397406
* @param mixed $subDomain the subdomain to add
398407
*
@@ -407,33 +416,30 @@ public function withSubDomain($subDomain): self
407416
}
408417

409418
if (null === $this->publicSuffix->getContent()) {
410-
throw new Exception('A subdomain can not be added to domain without a public suffix.');
411-
}
412-
413-
static $pattern = '/[^\x20-\x7f]/';
414-
$subDomain = $subDomain->toAscii();
415-
if (null !== $this->domain && preg_match($pattern, $this->domain)) {
416-
$subDomain = $subDomain->toUnicode();
419+
throw new Exception('A subdomain can not be added to a domain without a public suffix part.');
417420
}
418421

419-
$subDomain = $subDomain->getContent();
420-
if ($subDomain === $this->subDomain) {
422+
$subDomain = $this->normalize($subDomain);
423+
if ($this->subDomain === $subDomain->getContent()) {
421424
return $this;
422425
}
423426

424-
$newDomain = $this->registrableDomain;
425-
if (null !== $subDomain) {
426-
$newDomain = $subDomain.'.'.$newDomain;
427-
}
427+
$clone = clone $this;
428+
$clone->labels = array_merge(
429+
array_slice($this->labels, 0, count($this->publicSuffix) + 1),
430+
iterator_to_array($subDomain)
431+
);
432+
$clone->domain = implode('.', array_reverse($clone->labels));
433+
$clone->subDomain = $subDomain->getContent();
428434

429-
return new Domain($newDomain, $this->publicSuffix);
435+
return $clone;
430436
}
431437

432438
/**
433439
* Returns an instance with the specified public suffix added.
434440
*
435441
* This method MUST retain the state of the current instance, and return
436-
* an instance that contains the modified component with the new public suffix
442+
* an instance that contains the new public suffix
437443
*
438444
* @param mixed $publicSuffix
439445
*
@@ -451,33 +457,31 @@ public function withPublicSuffix($publicSuffix): self
451457
throw new Exception('A public suffix can not be added to domain without a public suffix.');
452458
}
453459

454-
static $pattern = '/[^\x20-\x7f]/';
455-
$publicSuffix = $publicSuffix->toAscii();
456-
if (null !== $this->domain && preg_match($pattern, $this->domain)) {
457-
$publicSuffix = $publicSuffix->toUnicode();
458-
}
459-
460+
$publicSuffix = $this->normalize($publicSuffix);
460461
if ($this->publicSuffix == $publicSuffix) {
461462
return $this;
462463
}
463464

464-
$newDomain = $this->labels[count($this->publicSuffix)];
465-
if (null !== $this->subDomain) {
466-
$newDomain = $this->subDomain.'.'.$newDomain;
467-
}
468-
469-
if (null !== $publicSuffix->getContent()) {
470-
$newDomain .= '.'.$publicSuffix->getContent();
471-
}
465+
$clone = clone $this;
466+
$clone->labels = array_merge(
467+
iterator_to_array($publicSuffix),
468+
array_slice($this->labels, count($this->publicSuffix))
469+
);
470+
$clone->domain = implode('.', array_reverse($clone->labels));
471+
$clone->publicSuffix = $publicSuffix;
472+
$clone->registrableDomain = $this->labels[count($this->publicSuffix)].'.'.$publicSuffix->getContent();
472473

473-
return new Domain($newDomain, $publicSuffix);
474+
return $clone;
474475
}
475476

476477
/**
477478
* Returns an instance with the specified label added at the specified key.
478479
*
479480
* This method MUST retain the state of the current instance, and return
480-
* an instance that contains the modified domain with the new label
481+
* an instance that contains the new label
482+
*
483+
* If $key is non-negative, the added label will be the label at $key position from the start.
484+
* If $key is negative, the added label will be the label at $key position from the end.
481485
*
482486
* @param int $key
483487
* @param mixed $label
@@ -493,45 +497,52 @@ public function withLabel(int $key, $label): self
493497
$label = new PublicSuffix($label);
494498
}
495499

496-
if (null === $label->getContent() || 1 !== count($label)) {
500+
if (1 !== count($label)) {
497501
throw new Exception(sprintf('The label `%s` is invalid', $label->getContent()));
498502
}
499503

500-
static $pattern = '/[^\x20-\x7f]/';
501-
$label = $label->toAscii();
502-
if (null !== $this->domain && preg_match($pattern, $this->domain)) {
503-
$label = $label->toUnicode();
504-
}
505-
506-
$label = $label->getContent();
507504
$nb_labels = count($this->labels);
508505
$offset = filter_var($key, FILTER_VALIDATE_INT, ['options' => ['min_range' => - $nb_labels - 1, 'max_range' => $nb_labels]]);
509506
if (false === $offset) {
510507
throw new Exception(sprintf('the given key `%s` is invalid', $key));
511508
}
512509

513-
if ($offset < 0) {
510+
if (0 > $offset) {
514511
$offset = $nb_labels + $offset;
515512
}
516513

514+
$label = $this->normalize($label)->getContent();
517515
if ($label === ($this->labels[$offset] ?? null)) {
518516
return $this;
519517
}
520518

521-
$labels = $this->labels;
522-
$labels[$offset] = $label;
519+
$clone = clone $this;
520+
$clone->labels[$offset] = $label;
521+
ksort($clone->labels);
522+
$clone->labels = array_values($clone->labels);
523+
$clone->domain = implode('.', array_reverse($clone->labels));
524+
if (null !== $this->publicSuffix->getLabel($offset)) {
525+
$clone->publicSuffix = new PublicSuffix();
526+
$clone->registrableDomain = null;
527+
$clone->subDomain = null;
523528

524-
return new Domain(
525-
implode('.', array_reverse($labels)),
526-
$offset < 0 || null === $this->publicSuffix->getLabel($offset) ? $this->publicSuffix : null
527-
);
529+
return $clone;
530+
}
531+
532+
$clone->registrableDomain = $clone->setRegistrableDomain();
533+
$clone->subDomain = $clone->setSubDomain();
534+
535+
return $clone;
528536
}
529537

530538
/**
531539
* Returns an instance with the label at the specified key removed.
532540
*
533541
* This method MUST retain the state of the current instance, and return
534-
* an instance that contains the modified domain with the label removed
542+
* an instance without the specified label
543+
*
544+
* If $key is non-negative, the removed label will be the label at $key position from the start.
545+
* If $key is negative, the removed label will be the label at $key position from the end.
535546
*
536547
* @param int $key
537548
*
@@ -547,16 +558,24 @@ public function withoutLabel(int $key): self
547558
throw new Exception(sprintf('the given key `%s` is invalid', $key));
548559
}
549560

550-
if ($offset < 0) {
561+
if (0 > $offset) {
551562
$offset = $nb_labels + $offset;
552563
}
553564

554-
$labels = $this->labels;
555-
unset($labels[$offset]);
565+
$clone = clone $this;
566+
unset($clone->labels[$offset]);
567+
$clone->domain = implode('.', array_reverse($clone->labels));
568+
if (null !== $this->publicSuffix->getLabel($offset)) {
569+
$clone->publicSuffix = new PublicSuffix();
570+
$clone->registrableDomain = null;
571+
$clone->subDomain = null;
572+
573+
return $clone;
574+
}
575+
576+
$clone->registrableDomain = $clone->setRegistrableDomain();
577+
$clone->subDomain = $clone->setSubDomain();
556578

557-
return new Domain(
558-
implode('.', array_reverse($labels)),
559-
$offset < 0 || null == $this->publicSuffix->getLabel($offset) ? $this->publicSuffix : null
560-
);
579+
return $clone;
561580
}
562581
}

src/DomainInterface.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ public function getContent();
3535
/**
3636
* Retrieves a single domain label.
3737
*
38-
* If $offset is non-negative, the returned value will be the label at $offset position.
39-
* If $offset is negative, the returned value will be the label at $offset position from the end.
38+
* If $key is non-negative, the returned value will be the label at $key position from the start.
39+
* If $key is negative, the returned value will be the label at $key position from the end.
4040
*
41-
* If no label is found the submitted $offset the returned value will be null.
41+
* If no label is found the submitted $key the returned value will be null.
4242
*
43-
* @param int $offset the label offset
43+
* @param int $key the label offset
4444
*
4545
* @return string|null
4646
*/
47-
public function getLabel(int $offset);
47+
public function getLabel(int $key);
4848

4949
/**
5050
* Returns the associated key for each label.

src/PublicSuffix.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
* @author Ignace Nyamagana Butera <[email protected]>
2828
*/
29-
final class PublicSuffix implements DomainInterface, JsonSerializable, SectionInterface
29+
final class PublicSuffix implements DomainInterface, JsonSerializable, PublicSuffixListSection
3030
{
3131
use IDNAConverterTrait;
3232

src/SectionInterface.php renamed to src/PublicSuffixListSection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @author Ignace Nyamagana Butera <[email protected]>
1818
*/
19-
interface SectionInterface
19+
interface PublicSuffixListSection
2020
{
2121
const ALL_DOMAINS = 'ALL_DOMAINS';
2222
const ICANN_DOMAINS = 'ICANN_DOMAINS';

src/Rules.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @author Jeremy Kendall <[email protected]>
1818
* @author Ignace Nyamagana Butera <[email protected]>
1919
*/
20-
final class Rules implements SectionInterface
20+
final class Rules implements PublicSuffixListSection
2121
{
2222
/**
2323
* PSL rules as a multidimentional associative array.

tests/CacheTest.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,6 @@ public function testDeleteMultipleGenerator()
480480
$this->assertEquals([], $expected);
481481
}
482482

483-
/**
484-
* @expectException \Psr\SimpleCache\InvalidArgumentException
485-
*/
486483
public function testDeleteMultipleInvalidArg()
487484
{
488485
$this->expectException(InvalidArgumentException::class);

0 commit comments

Comments
 (0)