@@ -82,32 +82,62 @@ final class Domain implements DomainInterface, JsonSerializable
82
82
* @var string|null
83
83
*/
84
84
private $ subDomain ;
85
-
85
+
86
+ /**
87
+ * @var int
88
+ */
89
+ private $ asciiIDNAOption = IDNA_DEFAULT ;
90
+
91
+ /**
92
+ * @var int
93
+ */
94
+ private $ unicodeIDNAOption = IDNA_DEFAULT ;
95
+
96
+ /**
97
+ * @var bool
98
+ */
99
+ private $ isTransitionalDifferent ;
100
+
86
101
/**
87
102
* {@inheritdoc}
88
103
*/
89
104
public static function __set_state (array $ properties ): self
90
105
{
91
- return new self ($ properties ['domain ' ], $ properties ['publicSuffix ' ]);
106
+ return new self (
107
+ $ properties ['domain ' ],
108
+ $ properties ['publicSuffix ' ],
109
+ $ properties ['asciiIDNAOption ' ] ?? IDNA_DEFAULT ,
110
+ $ properties ['unicodeIDNAOption ' ] ?? IDNA_DEFAULT
111
+ );
92
112
}
93
-
113
+
94
114
/**
95
115
* New instance.
96
- *
97
116
* @param null|mixed $domain
98
117
* @param null|PublicSuffix $publicSuffix
99
- */
100
- public function __construct ($ domain = null , PublicSuffix $ publicSuffix = null )
101
- {
102
- $ this ->labels = $ this ->setLabels ($ domain );
118
+ * @param int $asciiIDNAOption
119
+ * @param int $unicodeIDNAOption
120
+ */
121
+ public function __construct (
122
+ $ domain = null ,
123
+ PublicSuffix $ publicSuffix = null ,
124
+ int $ asciiIDNAOption = IDNA_DEFAULT ,
125
+ int $ unicodeIDNAOption = IDNA_DEFAULT
126
+ ) {
127
+ $ this ->asciiIDNAOption = $ asciiIDNAOption ;
128
+ $ this ->unicodeIDNAOption = $ unicodeIDNAOption ;
129
+ $ this ->labels = $ this ->setLabels ($ domain , $ asciiIDNAOption , $ unicodeIDNAOption );
130
+ $ this ->isTransitionalDifferent = $ this ->hasTransitionalDifference ($ domain );
103
131
if ([] !== $ this ->labels ) {
104
132
$ this ->domain = implode ('. ' , array_reverse ($ this ->labels ));
105
133
}
106
- $ this ->publicSuffix = $ this ->setPublicSuffix ($ publicSuffix ?? new PublicSuffix ());
134
+ $ this ->publicSuffix = $ this ->setPublicSuffix (
135
+ $ publicSuffix ?? new PublicSuffix (null , '' , $ asciiIDNAOption , $ unicodeIDNAOption )
136
+ );
107
137
$ this ->registrableDomain = $ this ->setRegistrableDomain ();
108
138
$ this ->subDomain = $ this ->setSubDomain ();
109
139
}
110
-
140
+
111
141
/**
112
142
* Sets the public suffix domain part.
113
143
*
@@ -224,7 +254,7 @@ public function jsonSerialize()
224
254
*/
225
255
public function __debugInfo ()
226
256
{
227
- return [
257
+ return [
228
258
'domain ' => $ this ->domain ,
229
259
'registrableDomain ' => $ this ->registrableDomain ,
230
260
'subDomain ' => $ this ->subDomain ,
@@ -388,12 +418,12 @@ public function toAscii()
388
418
return $ this ;
389
419
}
390
420
391
- $ domain = $ this ->idnToAscii ($ this ->domain );
421
+ $ domain = $ this ->idnToAscii ($ this ->domain , $ this -> asciiIDNAOption );
392
422
if ($ domain === $ this ->domain ) {
393
423
return $ this ;
394
424
}
395
425
396
- return new self ($ domain , $ this ->publicSuffix );
426
+ return new self ($ domain , $ this ->publicSuffix , $ this -> getAsciiIDNAOption (), $ this -> getUnicodeIDNAOption () );
397
427
}
398
428
399
429
/**
@@ -405,7 +435,12 @@ public function toUnicode()
405
435
return $ this ;
406
436
}
407
437
408
- return new self ($ this ->idnToUnicode ($ this ->domain ), $ this ->publicSuffix );
438
+ return new self (
439
+ $ this ->idnToUnicode ($ this ->domain , $ this ->unicodeIDNAOption ),
440
+ $ this ->publicSuffix ,
441
+ $ this ->getAsciiIDNAOption (),
442
+ $ this ->getUnicodeIDNAOption ()
443
+ );
409
444
}
410
445
411
446
/**
@@ -426,15 +461,20 @@ public function toUnicode()
426
461
public function resolve ($ publicSuffix ): self
427
462
{
428
463
if (!$ publicSuffix instanceof PublicSuffix) {
429
- $ publicSuffix = new PublicSuffix ($ publicSuffix );
464
+ $ publicSuffix = new PublicSuffix (
465
+ $ publicSuffix ,
466
+ '' ,
467
+ $ this ->getAsciiIDNAOption (),
468
+ $ this ->getUnicodeIDNAOption ()
469
+ );
430
470
}
431
471
432
472
$ publicSuffix = $ this ->normalize ($ publicSuffix );
433
473
if ($ this ->publicSuffix == $ publicSuffix ) {
434
474
return $ this ;
435
475
}
436
476
437
- return new self ($ this ->domain , $ publicSuffix );
477
+ return new self ($ this ->domain , $ publicSuffix, $ this -> getAsciiIDNAOption (), $ this -> getUnicodeIDNAOption () );
438
478
}
439
479
440
480
/**
@@ -453,7 +493,12 @@ public function resolve($publicSuffix): self
453
493
public function withPublicSuffix ($ publicSuffix ): self
454
494
{
455
495
if (!$ publicSuffix instanceof PublicSuffix) {
456
- $ publicSuffix = new PublicSuffix ($ publicSuffix );
496
+ $ publicSuffix = new PublicSuffix (
497
+ $ publicSuffix ,
498
+ '' ,
499
+ $ this ->getAsciiIDNAOption (),
500
+ $ this ->getUnicodeIDNAOption ()
501
+ );
457
502
}
458
503
459
504
$ publicSuffix = $ this ->normalize ($ publicSuffix );
@@ -463,10 +508,15 @@ public function withPublicSuffix($publicSuffix): self
463
508
464
509
$ domain = implode ('. ' , array_reverse (array_slice ($ this ->labels , count ($ this ->publicSuffix ))));
465
510
if (null === $ publicSuffix ->getContent ()) {
466
- return new self ($ domain );
511
+ return new self ($ domain, null , $ this -> getAsciiIDNAOption (), $ this -> getUnicodeIDNAOption () );
467
512
}
468
513
469
- return new self ($ domain .'. ' .$ publicSuffix ->getContent (), $ publicSuffix );
514
+ return new self (
515
+ $ domain .'. ' .$ publicSuffix ->getContent (),
516
+ $ publicSuffix ,
517
+ $ this ->getAsciiIDNAOption (),
518
+ $ this ->getUnicodeIDNAOption ()
519
+ );
470
520
}
471
521
472
522
@@ -494,10 +544,20 @@ public function withSubDomain($subDomain): self
494
544
}
495
545
496
546
if (null === $ subDomain ) {
497
- return new self ($ this ->registrableDomain , $ this ->publicSuffix );
547
+ return new self (
548
+ $ this ->registrableDomain ,
549
+ $ this ->publicSuffix ,
550
+ $ this ->getAsciiIDNAOption (),
551
+ $ this ->getUnicodeIDNAOption ()
552
+ );
498
553
}
499
554
500
- return new self ($ subDomain .'. ' .$ this ->registrableDomain , $ this ->publicSuffix );
555
+ return new self (
556
+ $ subDomain .'. ' .$ this ->registrableDomain ,
557
+ $ this ->publicSuffix ,
558
+ $ this ->getAsciiIDNAOption (),
559
+ $ this ->getUnicodeIDNAOption ()
560
+ );
501
561
}
502
562
503
563
/**
@@ -529,10 +589,10 @@ private function normalizeContent($domain)
529
589
}
530
590
531
591
if (preg_match (self ::REGEXP_IDN_PATTERN , $ this ->domain )) {
532
- return $ this ->idnToUnicode ($ domain );
592
+ return $ this ->idnToUnicode ($ domain, $ this -> unicodeIDNAOption );
533
593
}
534
594
535
- return $ this ->idnToAscii ($ domain );
595
+ return $ this ->idnToAscii ($ domain, $ this -> asciiIDNAOption );
536
596
}
537
597
538
598
/**
@@ -605,10 +665,20 @@ public function withLabel(int $key, $label): self
605
665
ksort ($ labels );
606
666
607
667
if (null !== $ this ->publicSuffix ->getLabel ($ key )) {
608
- return new self (implode ('. ' , array_reverse ($ labels )));
668
+ return new self (
669
+ implode ('. ' , array_reverse ($ labels )),
670
+ null ,
671
+ $ this ->getAsciiIDNAOption (),
672
+ $ this ->getUnicodeIDNAOption ()
673
+ );
609
674
}
610
675
611
- return new self (implode ('. ' , array_reverse ($ labels )), $ this ->publicSuffix );
676
+ return new self (
677
+ implode ('. ' , array_reverse ($ labels )),
678
+ $ this ->publicSuffix ,
679
+ $ this ->getAsciiIDNAOption (),
680
+ $ this ->getUnicodeIDNAOption ()
681
+ );
612
682
}
613
683
614
684
/**
@@ -651,15 +721,47 @@ public function withoutLabel(int $key, int ...$keys): self
651
721
}
652
722
653
723
if ([] === $ labels ) {
654
- return new self ();
724
+ return new self (null , null , $ this -> getAsciiIDNAOption (), $ this -> getUnicodeIDNAOption () );
655
725
}
656
726
657
727
$ domain = implode ('. ' , array_reverse ($ labels ));
658
728
$ psContent = $ this ->publicSuffix ->getContent ();
659
729
if (null === $ psContent || '. ' .$ psContent !== substr ($ domain , - strlen ($ psContent ) - 1 )) {
660
- return new self ($ domain );
730
+ return new self ($ domain, null , $ this -> getAsciiIDNAOption (), $ this -> getUnicodeIDNAOption () );
661
731
}
662
732
663
- return new self ($ domain , $ this ->publicSuffix );
733
+ return new self ($ domain , $ this ->publicSuffix , $ this ->getAsciiIDNAOption (), $ this ->getUnicodeIDNAOption ());
734
+ }
735
+
736
+
737
+ public function getAsciiIDNAOption (): int
738
+ {
739
+ return $ this ->asciiIDNAOption ;
740
+ }
741
+
742
+ public function getUnicodeIDNAOption (): int
743
+ {
744
+ return $ this ->unicodeIDNAOption ;
745
+ }
746
+ /**
747
+ * Set IDNA_* options for functions idn_to_ascii, idn_to_utf.
748
+ * @see https://www.php.net/manual/en/intl.constants.php
749
+ * @param int $forAscii
750
+ * @param int $forUnicode
751
+ * @return $this
752
+ */
753
+ public function withIDNAOptions (int $ forAscii , int $ forUnicode )
754
+ {
755
+ return new self ($ this ->domain , $ this ->publicSuffix , $ forAscii , $ forUnicode );
756
+ }
757
+
758
+ /**
759
+ * return true if domain contains deviation characters.
760
+ * @see http://unicode.org/reports/tr46/#Transition_Considerations
761
+ * @return bool
762
+ **/
763
+ public function isTransitionalDifferent (): bool
764
+ {
765
+ return $ this ->isTransitionalDifferent ;
664
766
}
665
767
}
0 commit comments