diff --git a/src/Illuminate/Validation/Rule.php b/src/Illuminate/Validation/Rule.php index c15772bba7d5..37ead70af8a3 100644 --- a/src/Illuminate/Validation/Rule.php +++ b/src/Illuminate/Validation/Rule.php @@ -20,6 +20,7 @@ use Illuminate\Validation\Rules\ProhibitedIf; use Illuminate\Validation\Rules\RequiredIf; use Illuminate\Validation\Rules\Unique; +use Illuminate\Validation\Rules\Url; class Rule { @@ -243,4 +244,12 @@ public static function numeric() { return new Numeric; } + + /** + * @param string[]|\Illuminate\Contracts\Support\Arrayable|null $protocols + */ + public static function url($protocols = null) + { + return new Url(...func_get_args()); + } } diff --git a/src/Illuminate/Validation/Rules/Url.php b/src/Illuminate/Validation/Rules/Url.php new file mode 100644 index 000000000000..d251cdb57724 --- /dev/null +++ b/src/Illuminate/Validation/Rules/Url.php @@ -0,0 +1,73 @@ +protocols(...func_get_args()); + } + + public function active(bool $active) + { + $this->active = $active; + + return $this; + } + + /** + * @param string[]|\Illuminate\Contracts\Support\Arrayable|null $protocols + */ + public function protocols($protocols = null) + { + $this->protocols = match (true) { + $protocols instanceof Arrayable => $protocols->toArray(), + ! is_array($protocols) => func_get_args(), + default => $protocols, + }; + + return $this; + } + + public function protocol(string $protocol) + { + $this->protocols = array_unique([...$this->protocols, $protocol]); + + return $this; + } + + /** + * Convert the rule to a validation string. + * + * @return string + */ + public function __toString() + { + if ($this->active) { + return 'active_url'; + } + + if ($this->protocols === []) { + return 'url'; + } + + return 'url:'.implode(',', $this->protocols); + } +} diff --git a/tests/Validation/ValidationUrlRuleTest.php b/tests/Validation/ValidationUrlRuleTest.php new file mode 100644 index 000000000000..77585a4256ae --- /dev/null +++ b/tests/Validation/ValidationUrlRuleTest.php @@ -0,0 +1,69 @@ +assertSame('url', (string) $rule); + } + + #[TestWith([true, 'active_url'])] + #[TestWith([false, 'url'])] + public function testActiveUrlRuleStringification(bool $active, string $output) + { + $rule = Rule::url()->active($active); + + $this->assertSame($output, (string) $rule); + } + + public function testUrlRuleConstructorProtocolsStringification() + { + $rule = Rule::url('http', 'https'); + + $this->assertSame('url:http,https', (string) $rule); + + $rule = Rule::url(['http', 'https']); + + $this->assertSame('url:http,https', (string) $rule); + + $rule = Rule::url(collect(['http', 'https'])); + + $this->assertSame('url:http,https', (string) $rule); + } + + public function testUrlRuleProtocolsStringification() + { + $rule = Rule::url()->protocols('http', 'https'); + + $this->assertSame('url:http,https', (string) $rule); + + $rule = Rule::url()->protocols(['http', 'https']); + + $this->assertSame('url:http,https', (string) $rule); + + $rule = Rule::url()->protocols(collect(['http', 'https'])); + + $this->assertSame('url:http,https', (string) $rule); + + $rule = Rule::url('ftp')->protocols(collect(['http', 'https'])); + + $this->assertSame('url:http,https', (string) $rule); + } + + #[TestWith(['http', 'url:http,https'])] + #[TestWith(['ftp', 'url:http,https,ftp'])] + public function testUrlRuleProtocolStringification(string $input, string $output) + { + $rule = Rule::url('http', 'https')->protocol($input); + + $this->assertSame($output, (string) $rule); + } +}