├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE ├── UPGRADING.md ├── composer.json ├── config └── domain-parser.php ├── docs ├── 10-getting-started.md └── 20-usage.md ├── phpunit.xml └── src ├── Commands └── RefreshCacheCommand.php ├── Directives.php ├── DomainParser.php ├── DomainParserConfig.php ├── Facades ├── DomainParser.php ├── Rules.php └── TopLevelDomains.php ├── Http └── RequestFactory.php ├── ServiceProvider.php └── ValidatorWrapper.php /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__.'/src') 5 | ->in(__DIR__.'/tests/src') 6 | ->ignoreVCSIgnored(true); 7 | 8 | return (new \DistortedFusion\PhpCsFixerConfig\Config())->setFinder($finder); 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All Notable changes will be documented in this file 4 | 5 | ## 1.1.0 - 2022-02-15 6 | 7 | ### Added 8 | 9 | - Support for Laravel 9.x 10 | 11 | ### Fixed 12 | 13 | - None 14 | 15 | ### Removed 16 | 17 | - Dropped support for older PHP version below 8.x 18 | 19 | ## 1.0.0 - 2021-03-30 20 | 21 | ### Added 22 | 23 | - Upgraded to [PHP Domain Parser](https://github.com/jeremykendall/php-domain-parser) 6.0, please refer to the [upgrading guide](UPGRADING.md) for breaking changes. 24 | 25 | ### Fixed 26 | 27 | - None 28 | 29 | ### Removed 30 | 31 | - Support for PHP 7.3 and below has been dropped. 32 | - Support for custom HTTP clients has been dropped, please refer to the [upgrading guide](UPGRADING.md). 33 | - Various namespace and config changes, please refer to the [upgrading guide](UPGRADING.md). 34 | 35 | ## 0.5.1 - 2021-01-12 36 | 37 | ### Added 38 | 39 | - None 40 | 41 | ### Fixed 42 | 43 | - Fixed #14: Made sure the config file is suffixed with .php when publishing the config. 44 | 45 | ### Removed 46 | 47 | - None 48 | 49 | ## 0.5.0 - 2020-12-15 50 | 51 | ### Added 52 | 53 | - Experimental support for Laravel 8.x on both PHP 7.4 and PHP 8.x. 54 | 55 | ### Fixed 56 | 57 | - None 58 | 59 | ### Removed 60 | 61 | - None 62 | 63 | ## 0.4.0 - 2020-09-08 64 | 65 | - Added support for Laravel 6.x and 7.x. 66 | 67 | ## 0.3.0 - 2018-12-13 68 | 69 | - Added Blade directive `domain_to_ascii` 70 | - Added Blade directive `domain_to_unicode` 71 | - Rename `Constraints` to `Directives` 72 | - Bug fix validation error messages. 73 | - Improve `ServiceProvider` 74 | 75 | ## 0.2.0 - 2018-12-12 76 | 77 | - Rename `Factory` to `Adapter` 78 | - Improve patch to Laravel bug [#26674](https://github.com/laravel/framework/issues/26674) 79 | - Improve `RefreshCacheCommand` 80 | - Added missing typehinting where possible 81 | 82 | ## 0.1.0 - 2018-12-07 83 | 84 | - first release 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Kevin Dierkx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Laravel Domain Parser Upgrade Guide 2 | 3 | Please refer to the [jeremykendall/php-domain-parser upgrading guide](https://github.com/jeremykendall/php-domain-parser/blob/develop/UPGRADING.md) for a complete overview of all internal changes. 4 | 5 | ## Upgrading to 1.x 6 | 7 | In order to stay compatible with the base package, this package dropped all support for PHP versions before and including 7.3. The minimum supported PHP version is now PHP 7.4 and the minimum supported Laravel version is 8.x. 8 | 9 | ### Backwards compatibility changes 10 | 11 | The following changes might directly impact you installation. 12 | 13 | #### Namespace and class changes 14 | 15 | - The `Adapter` class has been replaced with the `DomainParser` class and is now registered in the Laravel IOC container: 16 | 17 | ```diff 18 | env('CACHE_DRIVER', 'file'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Cache TTL 25 | |-------------------------------------------------------------------------- 26 | | 27 | | The cache TTL determines how long, in minutes, the PSL and TLD lists are 28 | | kept in cache before fetching new lists. 29 | | 30 | | Expected: int|null 31 | | 32 | */ 33 | 34 | 'cache_ttl' => 3600, 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | HTTP Client Options 39 | |-------------------------------------------------------------------------- 40 | | 41 | | These are optional GuzzleHttp Client configurations. For a full list of 42 | | available options please refer to the official docs: https://docs.guzzlephp.org/en/7.0/quickstart.html 43 | | 44 | | Expected: array 45 | | 46 | */ 47 | 48 | 'http_client_options' => [], 49 | 50 | /* 51 | |-------------------------------------------------------------------------- 52 | | Public Suffix List URI 53 | |-------------------------------------------------------------------------- 54 | | 55 | | This option controls the default location the package will use to fetch 56 | | a fresh PSL list. 57 | | 58 | | Expected: string|null 59 | | 60 | */ 61 | 62 | 'uri_public_suffix_list' => 'https://publicsuffix.org/list/public_suffix_list.dat', 63 | 64 | /* 65 | |-------------------------------------------------------------------------- 66 | | Top Level Domain list URI 67 | |-------------------------------------------------------------------------- 68 | | 69 | | This option controls the default location the package will use to fetch 70 | | a fresh TLD list. 71 | | 72 | | Expected: string|null 73 | | 74 | */ 75 | 76 | 'uri_top_level_domain_list' => 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt', 77 | ]; 78 | -------------------------------------------------------------------------------- /docs/10-getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | This Laravel package eases [PHP Domain Parser](https://github.com/jeremykendall/php-domain-parser) _(PDP)_ integration in your Laravel application. 4 | 5 | PHP Domain Parser is a resource based domain parser implemented in PHP. With it you can easily parse a domain into its component subdomain, registrable domain, second level domain and public suffix parts using the Public Suffix List or IANA Top Level Domain List. 6 | 7 | This package doesn't intent to replace or reinvent the API offered by PDP, instead it offers you various entry points to PDP which can be used to validate or process your domain. 8 | 9 | ## Installation 10 | 11 | The package can be installed via composer: 12 | 13 | ```bash 14 | composer require bakame/laravel-domain-parser 15 | ``` 16 | 17 | *This package implements Laravel's Package Discovery, no further changes are needed to your application configurations. For more information [please refer to the Laravel documentation](https://laravel.com/docs/packages#package-discovery).* 18 | 19 | ## Version Compatibility 20 | 21 | | Laravel | PHP | Package | PDP | 22 | | ------- | -------------- | ------- | ---- | 23 | | 9.x | ^8.0 | >= 1.1 | ^6.0 | 24 | | 10.x | ^8.1 | >= 1.2 | ^6.2 | 25 | | 11.x | ^8.2 | >= 1.3 | ^6.2 | 26 | 27 | *Only the currently supported PHP versions are listed. Please [refer to previous releases of this package](https://github.com/kevindierkx/laravel-domain-parser/tags) for support for older PHP or Laravel versions.* 28 | 29 | ## Configuration 30 | 31 | In order to edit the default configuration you need to publish the package configuration to your application config directory: 32 | 33 | ```bash 34 | php artisan vendor:publish --provider="Bakame\Laravel\Pdp\ServiceProvider" --tag=config 35 | ``` 36 | 37 | The configuration file will be published to `config/domain-parser.php` in your application directory. Please refer to the [config file](https://github.com/kevindierkx/laravel-domain-parser/blob/master/config/domain-parser.php) for an overview of the available options. 38 | 39 | ## Maintenance 40 | 41 | ### Refresh Cache Command 42 | 43 | You can warm and/or update the cache information using the bundled refresh cache command manually. 44 | 45 | You can choose to refresh: 46 | 47 | - The Public Suffix List 48 | 49 | ```bash 50 | php artisan domain-parser:refresh --rules 51 | ``` 52 | 53 | - The IANA Root Zone Database 54 | 55 | ```bash 56 | php artisan domain-parser:refresh --tlds 57 | ``` 58 | 59 | - Both data sets in a single call (default) 60 | 61 | ```bash 62 | php artisan domain-parser:refresh 63 | ``` 64 | 65 | ### Scheduling 66 | 67 | It is recommended to schedule the refresh command so you don't have to manually run `domain-parser:refresh` every time you need to update your cache. 68 | 69 | The command can be scheduled in Laravel's console kernel, just like any other command. 70 | 71 | ```php 72 | // app/Console/Kernel.php 73 | protected function schedule(Schedule $schedule) 74 | { 75 | $schedule->command('domain-parser:refresh')->daily()->at('04:00'); 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/20-usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | This package provides some useful Laravel implementations in the form of validation rules, Blade directives and Blade conditionals. Additionally it provides a bridge with the [PHP Domain Parser](https://github.com/jeremykendall/php-domain-parser) base package, please refer to the [base documentation](https://github.com/jeremykendall/php-domain-parser#documentation) for an overview of all functionality. 4 | 5 | ## Facades 6 | 7 | - `DomainParser` is a Laravel Facade for the `\Bakame\Laravel\Pdp\DomainParser` instance and contains helper methods for interacting with the [PHP Domain Parser](https://github.com/jeremykendall/php-domain-parser) base package. 8 | 9 | - `Rules` is a Laravel Facade for the `\Pdp\PublicSuffixList` instance, also available as `pdp.rules` from the IOC container. 10 | 11 | - `TopLevelDomains` is a Laravel Facade for the `\Pdp\TopLevelDomainsList` instance, also available as `pdp.tld` from the IOC container. 12 | 13 | *Please note:* By default all facades will be registered during package discovery. In the following examples we will use these facades directly. 14 | 15 | ## Validation rules 16 | 17 | | Rules | Description | 18 | | ------------------- | ----------- | 19 | | `is_domain_name` | Tells whether the submitted value represents a Domain Name | 20 | | `is_tld` | Tells whether the submitted value is a TLD | 21 | | `contains_tld` | Tells whether the submitted value is a Domain Name with a known TLD | 22 | | `is_known_suffix` | Tells whether the submitted value is a Domain Name with a known suffix | 23 | | `is_icann_suffix` | Tells whether the submitted value is a Domain Name with an ICANN suffix | 24 | | `is_private_suffix` | Tells whether the submitted value is a Domain Name with a Private suffix | 25 | 26 | ```php 27 | $validator = Validator::make($request->all(), [ 28 | 'tld' => 'is_tld', 29 | 'domain' => 'is_icann_suffix', 30 | ]); 31 | ``` 32 | 33 | ## Blade if statement directives 34 | 35 | | If statement | Description | 36 | | ---------------- | ----------- | 37 | | `domain_name` | Tells whether the submitted value represents a Domain Name | 38 | | `tld` | Tells whether the submitted value is a TLD | 39 | | `contains_tld` | Tells whether the submitted value is a Domain Name with a known TLD | 40 | | `known_suffix` | Tells whether the submitted value is a Domain Name with a Known suffix | 41 | | `icann_suffix` | Tells whether the submitted value is a Domain Name with an ICANN suffix | 42 | | `private_suffix` | Tells whether the submitted value is a Domain Name with a Private suffix | 43 | 44 | ```php 45 | @contains_tld('example.localhost') 46 | OK 47 | @else 48 | KO 49 | @endcontains_tld 50 | {{-- KO --}} 51 | ``` 52 | 53 | ## Blade directives 54 | 55 | | directive | Description | 56 | | ------------------- | ----------- | 57 | | `domain_to_unicode` | Converts the hostname into its Unicode representation | 58 | | `domain_to_ascii` | Converts the hostname into its Ascii representation | 59 | 60 | ```php 61 | @domain_to_unicode('www.xn--85x722f.xn--55qx5d.cn') {{-- www.食狮.公司.cn --}} 62 | @domain_to_ascii('www.食狮.公司.cn') {{-- www.xn--85x722f.xn--55qx5d.cn --}} 63 | ``` 64 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | tests 16 | 17 | 18 | 19 | 20 | 21 | src 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Commands/RefreshCacheCommand.php: -------------------------------------------------------------------------------- 1 | info('Refreshing PHP Domain Parser lists cache...'); 37 | 38 | $refreshRulesList = $this->option('rules'); 39 | $refreshTldList = $this->option('tlds'); 40 | 41 | // Refresh both lists by default when no specific list is specified. 42 | if (! $refreshRulesList && ! $refreshTldList) { 43 | $refreshRulesList = true; 44 | $refreshTldList = true; 45 | } 46 | 47 | try { 48 | if ($refreshRulesList) { 49 | $this->updatePublicSuffixList(); 50 | } 51 | 52 | if ($refreshTldList) { 53 | $this->updateTldList(); 54 | } 55 | } catch (Throwable $e) { 56 | $this->error('The PHP Domain Parser lists cache could not be updated.'); 57 | $this->error('An error occurred during the update.'); 58 | $this->error('----- Error Message -----'); 59 | $this->error($e->getMessage()); 60 | 61 | return 1; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | /** 68 | * Update the public suffix list. 69 | * 70 | * @return bool 71 | */ 72 | protected function updatePublicSuffixList(): bool 73 | { 74 | $this->info('Updating the Public Suffix list cache.'); 75 | 76 | DomainParser::getRules(true); 77 | 78 | $this->info('The Public Suffix List cache is updated.'); 79 | 80 | return true; 81 | } 82 | 83 | /** 84 | * Update the TLD list. 85 | * 86 | * @return bool 87 | */ 88 | protected function updateTldList(): bool 89 | { 90 | $this->info('Updating the IANA Root Zone Database cache.'); 91 | 92 | DomainParser::getTopLevelDomains(true); 93 | 94 | $this->info('The IANA Root Zone Database cache is updated.'); 95 | 96 | return true; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Directives.php: -------------------------------------------------------------------------------- 1 | toAscii()->toString()) { 31 | return true; 32 | } 33 | } 34 | 35 | return false; 36 | } 37 | 38 | /** 39 | * Determine if the domain is a valid domain name. 40 | * 41 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 42 | * 43 | * @return bool 44 | */ 45 | public static function isDomain($domain): bool 46 | { 47 | try { 48 | Rules::getICANNDomain($domain); 49 | 50 | return true; 51 | } catch (Throwable $e) { 52 | return false; 53 | } 54 | } 55 | 56 | /** 57 | * Determine if the domain contains an ICANN suffix. 58 | * 59 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 60 | * 61 | * @return bool 62 | */ 63 | public static function isICANNSuffix($domain): bool 64 | { 65 | return Rules::resolve($domain)->suffix()->isICANN(); 66 | } 67 | 68 | /** 69 | * Determine if the domain contains a private suffix. 70 | * 71 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 72 | * 73 | * @return bool 74 | */ 75 | public static function isPrivateSuffix($domain): bool 76 | { 77 | return Rules::resolve($domain)->suffix()->isPrivate(); 78 | } 79 | 80 | /** 81 | * Determine if the domain contains a known suffix. 82 | * 83 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 84 | * 85 | * @return bool 86 | */ 87 | public static function isKnownSuffix($domain): bool 88 | { 89 | return Rules::resolve($domain)->suffix()->isKnown(); 90 | } 91 | 92 | /** 93 | * Determine if the domain contains a known Top Level Domain suffix. 94 | * 95 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 96 | * 97 | * @return bool 98 | */ 99 | public static function containsTLD($domain): bool 100 | { 101 | return TopLevelDomains::resolve($domain)->suffix()->isKnown(); 102 | } 103 | 104 | /** 105 | * Convert the domain into its ASCII form. 106 | * 107 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 108 | * 109 | * @return mixed 110 | */ 111 | public static function toAscii($domain) 112 | { 113 | return Rules::resolve($domain)->toAscii()->toString() ?: $domain; 114 | } 115 | 116 | /** 117 | * Convert the domain into its unicode form. 118 | * 119 | * @param int|DomainNameProvider|Host|string|Stringable|null $domain 120 | * 121 | * @return mixed 122 | */ 123 | public static function toUnicode($domain) 124 | { 125 | return Rules::resolve($domain)->toUnicode()->toString() ?: $domain; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/DomainParser.php: -------------------------------------------------------------------------------- 1 | config = $config; 32 | } 33 | 34 | /** 35 | * Get the Public Suffix List instance. 36 | * 37 | * @param bool $fresh 38 | * 39 | * @return PublicSuffixList 40 | */ 41 | public function getRules(bool $fresh = false): PublicSuffixList 42 | { 43 | $uri = $this->config->uriPublicSuffixList ?: $this->getDefaultPublicSuffixListUri(); 44 | $ttl = $this->convertTtlToDateTime($this->config->cacheTtl); 45 | 46 | $factory = $this->getStorageFactory(); 47 | $storage = $factory->createPublicSuffixListStorage('', $ttl); 48 | 49 | if ($fresh) { 50 | $storage->delete($uri); 51 | } 52 | 53 | return $storage->get($uri); 54 | } 55 | 56 | /** 57 | * Get the Top Level Domains List instance. 58 | * 59 | * @param bool $fresh 60 | * 61 | * @return TopLevelDomainList 62 | */ 63 | public function getTopLevelDomains(bool $fresh = false): TopLevelDomainList 64 | { 65 | $uri = $this->config->uriTopLevelDomainList ?: $this->getDefaultTopLevelDomainListUri(); 66 | $ttl = $this->convertTtlToDateTime($this->config->cacheTtl); 67 | 68 | $factory = $this->getStorageFactory(); 69 | $storage = $factory->createTopLevelDomainListStorage('', $ttl); 70 | 71 | if ($fresh) { 72 | $storage->delete($uri); 73 | } 74 | 75 | return $storage->get($uri); 76 | } 77 | 78 | /** 79 | * Resolve the PDP storage factory instance. 80 | * 81 | * @return PsrStorageFactory 82 | */ 83 | private function getStorageFactory(): PsrStorageFactory 84 | { 85 | return new PsrStorageFactory( 86 | $this->getCacheInstance(), 87 | $this->getHttpClientInstance(), 88 | new RequestFactory() 89 | ); 90 | } 91 | 92 | /** 93 | * Resolve the cache instance that should be used by PDP. 94 | * 95 | * @return CacheInterface 96 | */ 97 | private function getCacheInstance(): CacheInterface 98 | { 99 | return Cache::store($this->config->cacheDriver); 100 | } 101 | 102 | /** 103 | * Resolve the HTTP client instance that should be used by PDP. 104 | * 105 | * @return ClientInterface 106 | */ 107 | private function getHttpClientInstance(): ClientInterface 108 | { 109 | return new \GuzzleHttp\Client($this->config->httpClientOptions); 110 | } 111 | 112 | /** 113 | * Get the default URI used to fetch the public suffix list. 114 | * 115 | * @return string 116 | */ 117 | public function getDefaultPublicSuffixListUri(): string 118 | { 119 | return ResourceUri::PUBLIC_SUFFIX_LIST_URI; 120 | } 121 | 122 | /** 123 | * Get the default URI used to fetch the Top Level Domain list. 124 | * 125 | * @return string 126 | */ 127 | public function getDefaultTopLevelDomainListUri(): string 128 | { 129 | return ResourceUri::TOP_LEVEL_DOMAIN_LIST_URI; 130 | } 131 | 132 | /** 133 | * Convert a TTL into a date time object. 134 | * 135 | * @param int|null $ttl 136 | * 137 | * @return DateTime 138 | */ 139 | protected function convertTtlToDateTime(?int $ttl = null): ?DateTime 140 | { 141 | if (is_null($ttl)) { 142 | return null; 143 | } 144 | 145 | return (new DateTime())->modify("+{$ttl} minutes"); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/DomainParserConfig.php: -------------------------------------------------------------------------------- 1 | cacheDriver = $properties['cache_driver'] ?? null; 16 | $this->cacheTtl = $properties['cache_ttl'] ?? null; 17 | $this->httpClientOptions = $properties['http_client_options'] ?? []; 18 | $this->uriPublicSuffixList = $properties['uri_public_suffix_list'] ?? null; 19 | $this->uriTopLevelDomainList = $properties['uri_top_level_domain_list'] ?? null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Facades/DomainParser.php: -------------------------------------------------------------------------------- 1 | mergeConfigFrom( 22 | $this->basePath().'/config/domain-parser.php', 'domain-parser' 23 | ); 24 | 25 | $this->app->singleton('pdp.parser', function ($app) { 26 | $config = new DomainParserConfig($app->make('config')->get('domain-parser')); 27 | 28 | return new DomainParser($config); 29 | }); 30 | 31 | $this->app->singleton('pdp.rules', function ($app) { 32 | return $app->make('pdp.parser')->getRules(); 33 | }); 34 | $this->app->singleton('pdp.tld', function ($app) { 35 | return $app->make('pdp.parser')->getTopLevelDomains(); 36 | }); 37 | } 38 | 39 | /** 40 | * Bootstrap any application services. 41 | * 42 | * @return void 43 | */ 44 | public function boot(): void 45 | { 46 | $this->offerPublishing(); 47 | 48 | if ($this->app->runningInConsole()) { 49 | $this->commands([Commands\RefreshCacheCommand::class]); 50 | } 51 | 52 | $is_domain = [Directives::class, 'isDomain']; 53 | $is_tld = [Directives::class, 'isTLD']; 54 | $contains_tld = [Directives::class, 'containsTLD']; 55 | $is_known_suffix = [Directives::class, 'isKnownSuffix']; 56 | $is_icann_suffix = [Directives::class, 'isICANNSuffix']; 57 | $is_private_suffix = [Directives::class, 'isPrivateSuffix']; 58 | $domain_to_unicode = static function ($expression) { 59 | return ''; 60 | }; 61 | $domain_to_ascii = static function ($expression) { 62 | return ''; 63 | }; 64 | 65 | Blade::directive('domain_to_unicode', $domain_to_unicode); 66 | Blade::directive('domain_to_ascii', $domain_to_ascii); 67 | 68 | Blade::if('domain_name', Closure::fromCallable($is_domain)); 69 | Blade::if('tld', Closure::fromCallable($is_tld)); 70 | Blade::if('contains_tld', Closure::fromCallable($contains_tld)); 71 | Blade::if('known_suffix', Closure::fromCallable($is_known_suffix)); 72 | Blade::if('icann_suffix', Closure::fromCallable($is_icann_suffix)); 73 | Blade::if('private_suffix', Closure::fromCallable($is_private_suffix)); 74 | 75 | Validator::extend( 76 | 'is_domain_name', 77 | Closure::fromCallable(new ValidatorWrapper($is_domain)), 78 | 'The :attribute field is not a valid domain name.' 79 | ); 80 | Validator::extend( 81 | 'is_tld', 82 | Closure::fromCallable(new ValidatorWrapper($is_tld)), 83 | 'The :attribute field is not a top level domain.' 84 | ); 85 | Validator::extend( 86 | 'contains_tld', 87 | Closure::fromCallable(new ValidatorWrapper($contains_tld)), 88 | 'The :attribute field does end with a top level domain.' 89 | ); 90 | Validator::extend( 91 | 'is_known_suffix', 92 | Closure::fromCallable(new ValidatorWrapper($is_known_suffix)), 93 | 'The :attribute field is not a domain with an known suffix.' 94 | ); 95 | Validator::extend( 96 | 'is_icann_suffix', 97 | Closure::fromCallable(new ValidatorWrapper($is_icann_suffix)), 98 | 'The :attribute field is not a domain with an ICANN suffix.' 99 | ); 100 | Validator::extend( 101 | 'is_private_suffix', 102 | Closure::fromCallable(new ValidatorWrapper($is_private_suffix)), 103 | 'The :attribute field is not a domain with a private suffix.' 104 | ); 105 | } 106 | 107 | /** 108 | * Define the configuration publishing. 109 | * 110 | * @return void 111 | */ 112 | protected function offerPublishing(): void 113 | { 114 | if ($this->app->runningInConsole()) { 115 | $this->publishes([ 116 | $this->basePath().'/config/domain-parser.php' => config_path('domain-parser.php'), 117 | ], 'config'); 118 | } 119 | } 120 | 121 | private function basePath(): string 122 | { 123 | return realpath(rtrim(__DIR__, '/').'/../') ?: '/../'; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/ValidatorWrapper.php: -------------------------------------------------------------------------------- 1 | callable = $callable; 26 | } 27 | 28 | /** 29 | * @param string $attribute 30 | * @param mixed $value 31 | * @param array $params 32 | * @param Validator $validator 33 | */ 34 | public function __invoke(string $attribute, $value, array $params, Validator $validator): bool 35 | { 36 | return ($this->callable)($value); 37 | } 38 | } 39 | --------------------------------------------------------------------------------