Skip to content

Commit

Permalink
Merge pull request #91 from milwad-dev/feat/add-dynamic-phone-validator
Browse files Browse the repository at this point in the history
[1.x] Feat/add dynamic phone validator
  • Loading branch information
milwad-dev authored Jun 9, 2024
2 parents 938550a + 0fb2786 commit cada6e7
Show file tree
Hide file tree
Showing 26 changed files with 321 additions and 165 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ composer.lock
.phpunit.result.cache
phpunit.xml
coverage
.phpunit.cache
2 changes: 1 addition & 1 deletion .phpunit.cache/test-results

Large diffs are not rendered by default.

41 changes: 35 additions & 6 deletions config/laravel-validate.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
<?php

use Milwad\LaravelValidate\Rules\ValidBase64;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\DEPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\ENPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\ESPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\FRPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\GRPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\IDPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\INPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\IRPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\ITPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\JAPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\KOPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\NEPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\RUPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\SAPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\SEPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\TRPhoneValidator;
use Milwad\LaravelValidate\Utils\CountryPhoneValidator\ZHPhoneValidator;

return [
'rules' => [
'base-64' => [
'name' => 'base64',
'class' => ValidBase64::class,
],
'phone-country' => [
'DE' => DEPhoneValidator::class,
'EN' => ENPhoneValidator::class,
'ES' => ESPhoneValidator::class,
'FR' => FRPhoneValidator::class,
'GR' => GRPhoneValidator::class,
'ID' => IDPhoneValidator::class,
'IN' => INPhoneValidator::class,
'IR' => IRPhoneValidator::class,
'IT' => ITPhoneValidator::class,
'JA' => JAPhoneValidator::class,
'KO' => KOPhoneValidator::class,
'NE' => NEPhoneValidator::class,
'RU' => RUPhoneValidator::class,
'SA' => SAPhoneValidator::class,
'SE' => SEPhoneValidator::class,
'TR' => TRPhoneValidator::class,
'ZH' => ZHPhoneValidator::class,
],
];
15 changes: 15 additions & 0 deletions src/LaravelValidateServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Milwad\LaravelValidate;

use Illuminate\Support\ServiceProvider;
use Milwad\LaravelValidate\Utils\CountryPhoneCallback;

class LaravelValidateServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -73,4 +74,18 @@ private function publishConfigFile(): void
__DIR__.'/../config/laravel-validate.php' => config_path('laravel-validate.php'),
], 'laravel-validate-config');
}

/**
* Boot applications.
*
* @throws \Throwable
*/
public function boot(): void
{
$countries = config('laravel-validate.phone-country', []);

foreach ($countries as $code => $country) {
CountryPhoneCallback::addValidator($code, $country);
}
}
}
2 changes: 1 addition & 1 deletion src/Rules/ValidPhoneNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __construct(protected ?string $code = null)
public function passes($attribute, $value): bool
{
if (is_string($this->code)) {
$passes = (new CountryPhoneCallback($value, $this->code))->callPhoneValidator();
$passes = CountryPhoneCallback::callPhoneValidator($this->code, $value);

return collect($passes)->some(fn ($passe) => $passe);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Utils/Country.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Country

public const CHAD = 'TD';

public const CHINA = 'zh';
public const CHINA = 'ZH';

public const COMOROS = 'KM';

Expand Down
173 changes: 19 additions & 154 deletions src/Utils/CountryPhoneCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,174 +2,39 @@

namespace Milwad\LaravelValidate\Utils;

use Milwad\LaravelValidate\Utils\CountryPhoneValidator\CountryPhoneValidator;
use RuntimeException;

class CountryPhoneCallback
{
/**
* Create a new phone validator instance.
*/
public function __construct(private mixed $value, private string $code, ?string $attribute = null)
{
}

// TODO: Add a feature to add validate method for your own country!

/**
* Validate Iran phone number.
* Country Validate classes.
*/
protected function validateIR(): false|int
{
return preg_match('/^(\+98|0)?9\d{9}$/', $this->value);
}
protected static array $validators = [];

/**
* Validate Iran phone number.
*/
protected function validateEN(): false|int
{
return preg_match('/^(?:\+44|0)7\d{9}$/', $this->value);
}

/**
* Validate Nigeria phone number.
*/
protected function validateNE(): false|int
{
return preg_match('/^(\+227|00227|227)?\d{8}$/', $this->value);
}

/**
* Validate Saudi Arabia phone number.
*/
protected function validateSA(): false|int
{
return preg_match('/^((\+966)|0)?5\d{8}$/', $this->value);
}

/**
* Validate Germany phone number.
*/
protected function validateDE(): false|int
{
return preg_match('/^((\+49)|(0))(1|15|16|17|19|30|31|32|33|34|40|41|42|43|44|49|151|152|153|155|156|157|159|160|162|163|180|181|182|183|184|185|186|187|188|170|171|172|173|174|175|176|177|178|179)\d{7,8}$/', $this->value);
}

/**
* Validate Greece phone number.
*/
protected function validateGR(): false|int
{
return preg_match('/^\+30[2-9]\d{2}\d{3}\d{4}$/', $this->value);
}

/**
* Validate Spain phone number.
*/
protected function validateES(): false|int
{
return preg_match('/^(?:\+34|0034|34)?[6789]\d{8}$/', $this->value);
}

/**
* Validate France phone number.
*/
protected function validateFR(): false|int
{
return preg_match('/^(?:\+33|0033|0)(?:[1-9](?:\d{2}){4}|[67]\d{8})$/', $this->value);
}

/**
* Validate India phone number.
*/
protected function validateIN(): false|int
{
return preg_match('/^(?:(?:\+|0{0,2})91(\s|-)?)?[6789]\d{9}$/', $this->value);
}

/**
* Validate Indonesia phone number.
*/
protected function validateID(): false|int
{
return preg_match('/^(?:\+62|0)(?:\d{2,3}\s?){1,2}\d{4,8}$/', $this->value);
}

/**
* Validate Italy phone number.
*/
protected function validateIT(): false|int
{
return preg_match('/^\+39\d{8,10}$/', $this->value);
}

/**
* Validate Japanese phone number.
*/
protected function validateJA(): false|int
{
return preg_match('/(\d{2,3})-?(\d{3,4})-?(\d{4})/', $this->value);
}

/**
* Validate Korean phone number.
*/
protected function validateKO(): false|int
{
return preg_match('/^(?:\+82|0)(?:10|1[1-9])-?\d{3,4}-?\d{4}$/', $this->value);
}

/**
* Validate Russian phone number.
*/
protected function validateRU(): false|int
{
return preg_match('/^(?:\+7|8)(?:\s?\(?\d{3}\)?\s?\d{3}(?:-?\d{2}){2}|\s?\d{2}(?:\s?\d{2}){3})$/', $this->value);
}

/**
* Validate Sweden phone number.
*/
protected function validateSE(): false|int
{
return preg_match('/^(?:\+46|0) ?(?:[1-9]\d{1,2}-?\d{2}(?:\s?\d{2}){2}|7\d{2}-?\d{2}(?:\s?\d{2}){2})$/', $this->value);
}

/**
* Validate Turkey phone number.
* Add new country validator.
*
* @throws \Throwable
*/
protected function validateTR(): false|int
public static function addValidator(string $code, string $validator): void
{
return preg_match('/^(?:\+90|0)(?:\s?[1-9]\d{2}\s?\d{3}\s?\d{2}\s?\d{2}|[1-9]\d{2}-?\d{3}-?\d{2}-?\d{2})$/', $this->value);
}
if (! new $validator instanceof CountryPhoneValidator) {
throw new RuntimeException('The validator is not instance of CountryPhoneValidator');
}

/**
* Validate Chinese phone number.
*/
protected function validateZH(): false|int
{
return preg_match('/^(?:\+86)?1[3-9]\d{9}$/', $this->value);
self::$validators[$code] = $validator;
}

/**
* Call the phone validator method for each country code and return the results.
*
* @throws \BadMethodCallException if the validator method for a country code does not exist.
* Call country validate class.
*/
public function callPhoneValidator(): array
public static function callPhoneValidator(string $code, $value)
{
$results = [];
$codes = explode(',', $this->code);
$codes = array_map('strtoupper', $codes);

foreach ($codes as $code) {
$methodName = 'validate'.$code;

if (method_exists($this, $methodName)) {
$results[$code] = $this->{$methodName}();
} else {
throw new \BadMethodCallException("Validator method '{$methodName}' does not exist.");
}
if (isset(self::$validators[$code])) {
return (new self::$validators[$code])->validate($value);
} else {
throw new \BadMethodCallException("Validator method for '$code' does not exist.");
}

return $results;
}
}
8 changes: 8 additions & 0 deletions src/Utils/CountryPhoneValidator/CountryPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

interface CountryPhoneValidator
{
public function validate($value): bool;
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/DEPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class DEPhoneValidator implements CountryPhoneValidator
{
/**
* Validate Iran phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^((\+49)|(0))(1|15|16|17|19|30|31|32|33|34|40|41|42|43|44|49|151|152|153|155|156|157|159|160|162|163|180|181|182|183|184|185|186|187|188|170|171|172|173|174|175|176|177|178|179)\d{7,8}$/', $value);
}
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/ENPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class ENPhoneValidator implements CountryPhoneValidator
{
/**
* Validate English phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^(?:\+44|0)7\d{9}$/', $value);
}
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/ESPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class ESPhoneValidator implements CountryPhoneValidator
{
/**
* Validate Spain phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^(?:\+34|0034|34)?[6789]\d{8}$/', $value);
}
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/FRPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class FRPhoneValidator implements CountryPhoneValidator
{
/**
* Validate France phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^(?:\+33|0033|0)(?:[1-9](?:\d{2}){4}|[67]\d{8})$/', $value);
}
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/GRPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class GRPhoneValidator implements CountryPhoneValidator
{
/**
* Validate Greece phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^\+30[2-9]\d{2}\d{3}\d{4}$/', $value);
}
}
14 changes: 14 additions & 0 deletions src/Utils/CountryPhoneValidator/IDPhoneValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Milwad\LaravelValidate\Utils\CountryPhoneValidator;

class IDPhoneValidator implements CountryPhoneValidator
{
/**
* Validate Indonesia phone numbers.
*/
public function validate($value): bool
{
return preg_match('/^(?:\+62|0)(?:\d{2,3}\s?){1,2}\d{4,8}$/', $value);
}
}
Loading

0 comments on commit cada6e7

Please sign in to comment.