diff --git a/src/PhoneServiceProvider.php b/src/PhoneServiceProvider.php index 7438f53..e50cb35 100644 --- a/src/PhoneServiceProvider.php +++ b/src/PhoneServiceProvider.php @@ -4,8 +4,10 @@ use Illuminate\Support\ServiceProvider; use Illuminate\Validation\Factory; +use Illuminate\Validation\InvokableValidationRule; use Illuminate\Validation\Rule; use libphonenumber\PhoneNumberUtil; +use Propaganistas\LaravelPhone\Rules\Phone; class PhoneServiceProvider extends ServiceProvider { @@ -28,10 +30,9 @@ public function registerValidator(): void { $this->callAfterResolving('validator', function (Factory $validator) { $validator->extendDependent('phone', function ($attribute, $value, array $parameters, $validator) { - return (new Rules\Phone) - ->setValidator($validator) - ->setParameters($parameters) - ->passes($attribute, $value); + return InvokableValidationRule::make( + (new Phone)->setData($validator->getData())->setParameters($parameters) + )->setValidator($validator)->passes($attribute, $value); }); }); diff --git a/src/Rules/Phone.php b/src/Rules/Phone.php index da69361..d2f0ae5 100644 --- a/src/Rules/Phone.php +++ b/src/Rules/Phone.php @@ -2,10 +2,10 @@ namespace Propaganistas\LaravelPhone\Rules; -use Illuminate\Contracts\Validation\Rule; -use Illuminate\Contracts\Validation\ValidatorAwareRule; +use Closure; +use Illuminate\Contracts\Validation\DataAwareRule; +use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Support\Arr; -use Illuminate\Validation\Validator; use libphonenumber\PhoneNumberType as libPhoneNumberType; use Propaganistas\LaravelPhone\Concerns\PhoneNumberCountry; use Propaganistas\LaravelPhone\Concerns\PhoneNumberType; @@ -13,9 +13,9 @@ use Propaganistas\LaravelPhone\Exceptions\NumberParseException; use Propaganistas\LaravelPhone\PhoneNumber; -class Phone implements Rule, ValidatorAwareRule +class Phone implements ValidationRule, DataAwareRule { - protected Validator $validator; + protected array $data; protected ?string $countryField = null; @@ -29,8 +29,21 @@ class Phone implements Rule, ValidatorAwareRule protected bool $lenient = false; - public function passes($attribute, $value) + public function setData(array $data) { + $this->data = $data; + + return $this; + } + + public function validate(string $attribute, mixed $value, Closure $fail): void + { + if (! $this->passes($attribute, $value)) { + $fail('validation.phone')->translate(); + } + } + + protected function passes(string $attribute, mixed $value) { $countries = PhoneNumberCountry::sanitize([ $this->getCountryFieldValue($attribute), ...$this->countries, @@ -132,13 +145,13 @@ public function international() protected function getCountryFieldValue(string $attribute) { // Using Arr::get() enables support for nested data. - return Arr::get($this->validator->getData(), $this->countryField ?: $attribute.'_country'); + return Arr::get($this->data, $this->countryField ?: $attribute.'_country'); } protected function isDataKey($attribute): bool { // Using Arr::has() enables support for nested data. - return Arr::has($this->validator->getData(), $attribute); + return Arr::has($this->data, $attribute); } public function setParameters($parameters) @@ -171,16 +184,4 @@ public function setParameters($parameters) return $this; } - - public function setValidator($validator) - { - $this->validator = $validator; - - return $this; - } - - public function message() - { - return trans('validation.phone'); - } } diff --git a/tests/RuleTest.php b/tests/RuleTest.php index 813db3a..3ccb6f8 100644 --- a/tests/RuleTest.php +++ b/tests/RuleTest.php @@ -114,28 +114,10 @@ public function it_sets_international_mode() $this->assertTrue($this->getProtectedProperty($rule, 'international')); } - #[Test] - public function it_returns_default_validation_message() - { - app('translator')->setLocale('xx'); - - app('translator')->setLoaded([ - '*' => [ - 'validation' => [ - 'xx' => [ - 'phone' => 'foo', - ], - ], - ], - ]); - - $this->assertEquals('foo', (new Phone)->message()); - } - #[Test] public function it_converts_string_validation_parameters() { - $base = (new Phone)->setValidator(validator(['foo' => null])); + $base = (new Phone)->setData(['foo' => null]); $rule = (clone $base)->setParameters('lenient'); $this->assertTrue($this->getProtectedProperty($rule, 'lenient')); @@ -185,7 +167,7 @@ public function it_converts_string_validation_parameters() #[Test] public function it_treats_string_validation_parameters_case_insensitive() { - $base = (new Phone)->setValidator(validator(['foo' => null])); + $base = (new Phone)->setData(['foo' => null]); $rule = (clone $base)->setParameters('LeNIent'); $this->assertTrue($this->getProtectedProperty($rule, 'lenient')); @@ -203,12 +185,12 @@ public function it_treats_string_validation_parameters_case_insensitive() #[Test] public function it_treats_coinciding_field_names_as_parameters() { - $base = (new Phone)->setValidator(validator([ + $base = (new Phone)->setData([ 'mobile' => null, 'fixed_line' => null, 'lenient' => null, 'international' => null, - ])); + ]); $rule = (clone $base)->setParameters(['mobile', 'fixed_line', 'lenient', 'international']); @@ -223,7 +205,7 @@ public function it_treats_coinciding_field_names_as_parameters() #[Test] public function it_ignores_invalid_string_validation_parameters() { - $base = (new Phone)->setValidator(validator([])); + $base = (new Phone)->setData([]); $rule = (clone $base)->setParameters(['xyz', 'foo']); $this->assertEquals([], $this->getProtectedProperty($rule, 'countries')); diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 0e6ac82..3d6afb7 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -2,6 +2,7 @@ namespace Propaganistas\LaravelPhone\Tests; +use Illuminate\Validation\Rule; use Illuminate\Validation\Validator; use libphonenumber\PhoneNumberType; use PHPUnit\Framework\Attributes\Test; @@ -561,4 +562,47 @@ public function it_validates_libphonenumber_specific_regions_as_country() ['field' => [(new Phone)->country('AC')]] )->passes()); } + + #[Test] + public function it_validates_with_validator_alias() + { + $this->assertTrue($this->validate( + ['field' => '0470123456'], + ['field' => ['phone:be,mobile']] + )->passes()); + } + + #[Test] + public function it_validates_with_rule_macro() + { + $this->assertTrue($this->validate( + ['field' => '0470123456'], + ['field' => [Rule::phone()->country('BE')->type('mobile')]] + )->passes()); + } + + #[Test] + public function it_translates_validation_message() + { + app('translator')->setLocale('xx'); + + app('translator')->setLoaded([ + '*' => [ + 'validation' => [ + 'xx' => [ + 'phone' => 'foo', + ], + ], + ], + ]); + + $message = $this->validate(['field' => '003212345678'], ['field' => new Phone])->errors()->first('field'); + $this->assertEquals('foo', $message); + + $message = $this->validate(['field' => '003212345678'], ['field' => 'phone'])->errors()->first('field'); + $this->assertEquals('foo', $message); + + $message = $this->validate(['field' => '003212345678'], ['field' => Rule::phone()])->errors()->first('field'); + $this->assertEquals('foo', $message); + } }