Skip to content

Commit

Permalink
Use PHP Domain Parser to validate domains
Browse files Browse the repository at this point in the history
  • Loading branch information
henriquemoody committed Jan 17, 2025
1 parent c096fb0 commit 2a683be
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 60 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"require-dev": {
"egulias/email-validator": "^4.0",
"giggsey/libphonenumber-for-php-lite": "^8.13",
"jeremykendall/php-domain-parser": "^6.0",
"malukenho/docheader": "^1.0",
"mikey179/vfsstream": "^1.6",
"nette/php-generator": "^4.1",
Expand All @@ -48,6 +49,7 @@
"ext-fileinfo": "File Information",
"ext-mbstring": "Multibyte String Functions",
"egulias/email-validator": "Improves the Email rule if available",
"jeremykendall/php-domain-parser": "Allows validating domains",
"giggsey/libphonenumber-for-php-lite": "Enables the phone rule if available",
"sokil/php-isocodes": "Enable rules that validate ISO codes",
"sokil/php-isocodes-db-only": "Enable rules that validate ISO codes"
Expand Down
81 changes: 22 additions & 59 deletions library/Rules/Domain.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,88 +9,51 @@

namespace Respect\Validation\Rules;

use Attribute;
use Pdp\Domain as PdpDomain;
use Respect\Validation\Exceptions\MissingComposerDependencyException;
use Respect\Validation\Message\Template;
use Respect\Validation\Result;
use Respect\Validation\Rule;
use Respect\Validation\Rules\Core\Standard;
use Throwable;

use function array_pop;
use function class_exists;
use function count;
use function explode;
use function mb_substr_count;
use function is_string;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
#[Template(
'{{name}} must be a valid domain',
'{{name}} must not be a valid domain',
)]
final class Domain extends Standard
{
private readonly Rule $genericRule;

private readonly Rule $tldRule;

private readonly Rule $partsRule;

public function __construct(bool $tldCheck = true)
{
$this->genericRule = $this->createGenericRule();
$this->tldRule = $this->createTldRule($tldCheck);
$this->partsRule = $this->createPartsRule();
public function __construct(
private readonly bool $requireTld = true,

Check failure on line 30 in library/Rules/Domain.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Property Respect\Validation\Rules\Domain::$requireTld is never read, only written.
) {
if (!class_exists(PdpDomain::class)) {
throw new MissingComposerDependencyException(
'Domain rule requires PHP Domain Parser',
'jeremykendall/php-domain-parser',
);
}
}

public function evaluate(mixed $input): Result
{
$genericResult = $this->genericRule->evaluate($input);
if (!$genericResult->isValid) {
if (!is_string($input)) {
return Result::failed($input, $this);
}

$parts = explode('.', (string) $input);
if (count($parts) >= 2) {
$childResult = $this->tldRule->evaluate(array_pop($parts));
if (!$childResult->isValid) {
try {
$domain = \Pdp\Domain::fromIDNA2008($input);
if (count($domain->labels()) === 1) {
return Result::failed($input, $this);
}
}

return new Result($this->partsRule->evaluate($parts)->isValid, $input, $this);
}

private function createGenericRule(): Circuit
{
return new Circuit(
new StringType(),
new NoWhitespace(),
new Contains('.'),
new Length(new GreaterThanOrEqual(3))
);
}

private function createTldRule(bool $realTldCheck): Rule
{
if ($realTldCheck) {
return new Tld();
$domain->label(0);
} catch (Throwable) {
return Result::failed($input, $this);
}

return new Circuit(new Not(new StartsWith('-')), new Length(new GreaterThanOrEqual(2)));
}

private function createPartsRule(): Rule
{
return new Each(
new Circuit(
new Alnum('-'),
new Not(new StartsWith('-')),
new AnyOf(
new Not(new Contains('--')),
new Callback(static function ($str) {
return mb_substr_count($str, '--') == 1;
})
),
new Not(new EndsWith('-'))
)
);
return Result::passed($input, $this);
}
}
2 changes: 1 addition & 1 deletion tests/unit/Rules/DomainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public static function providerForDomainWithRealTopLevelDomain(): array
['mail.xn--bcher-kva.ch'],
['example-hyphen.com'],
['example--valid.com'],
['xn--bcher--kva.ch'],
['std--a.com'],
['r--w.com'],
];
Expand All @@ -79,7 +80,6 @@ public static function providerForInvalidDomains(): array
['2222222domain.local'],
['-example-invalid.com'],
['example.invalid.-com'],
['xn--bcher--kva.ch'],
['example.invalid-.com'],
['1.2.3.256'],
['1.2.3.4'],
Expand Down

0 comments on commit 2a683be

Please sign in to comment.