fix: Use odolbeau/phone-number-bundle for formatting phone number type fields.

There is no need to use the bundle, we could have used the library instead. However, this idea is to switch to that bundle at some point.
This commit is contained in:
Pol Dellaiera 2022-02-01 16:20:45 +01:00
parent 822f0aa737
commit 4822acb6fb
No known key found for this signature in database
GPG Key ID: D476DFE9C67467CA
7 changed files with 112 additions and 53 deletions

View File

@ -22,6 +22,7 @@
"league/csv": "^9.7.1",
"nyholm/psr7": "^1.4",
"ocramius/package-versions": "^1.10",
"odolbeau/phone-number-bundle": "^3.6",
"phpoffice/phpspreadsheet": "^1.16",
"ramsey/uuid-doctrine": "^1.7",
"sensio/framework-extra-bundle": "^5.5",

View File

@ -0,0 +1,56 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Phonenumber;
/**
* Helper to some task linked to phonenumber.
*
* Currently, only Twilio is supported (https://www.twilio.com/lookup). A method
* allow to check if the helper is configured for validation. This should be used
* before doing some validation.
*/
interface PhoneNumberHelperInterface
{
public function denormalize(string $phoneNumber): string;
public function format(string $phonenumber): string;
/**
* Get type (mobile, landline, ...) for phone number.
*/
public function getType(string $phonenumber): string;
/**
* Return true if the validation is configured and available.
*/
public function isPhonenumberValidationConfigured(): bool;
/**
* Return true if the phonenumber is a landline or voip phone. Return always true
* if the validation is not configured.
*/
public function isValidPhonenumberAny(string $phonenumber): bool;
/**
* Return true if the phonenumber is a landline or voip phone. Return always true
* if the validation is not configured.
*/
public function isValidPhonenumberLandOrVoip(string $phonenumber): bool;
/**
* REturn true if the phoennumber is a mobile phone. Return always true
* if the validation is not configured.
*/
public function isValidPhonenumberMobile(string $phonenumber): bool;
public function normalize(string $phoneNumber): string;
}

View File

@ -15,8 +15,12 @@ use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use function array_key_exists;
use function in_array;
@ -24,40 +28,30 @@ use function json_decode;
use function preg_replace;
use function strlen;
/**
* Helper to some task linked to phonenumber.
*
* Currently, only Twilio is supported (https://www.twilio.com/lookup). A method
* allow to check if the helper is configured for validation. This should be used
* before doing some validation.
*/
class PhonenumberHelper
final class PhonenumberHelper implements PhoneNumberHelperInterface
{
public const FORMAT_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s';
public const LOOKUP_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s';
protected CacheItemPoolInterface $cachePool;
private CacheItemPoolInterface $cachePool;
/**
* TRUE if the client is properly configured.
*/
protected bool $isConfigured = false;
private array $config;
protected LoggerInterface $logger;
private bool $isConfigured = false;
/**
* Twilio client.
*/
protected Client $twilioClient;
private LoggerInterface $logger;
private Client $twilioClient;
public function __construct(
CacheItemPoolInterface $cachePool,
$config,
CacheItemPoolInterface $cacheUserData,
ParameterBagInterface $parameterBag,
LoggerInterface $logger
) {
$this->logger = $logger;
$this->cachePool = $cachePool;
$this->cachePool = $cacheUserData;
$this->config = $config = $parameterBag->get('chill_main.phone_helper');
if (
array_key_exists('twilio_sid', $config)
@ -74,9 +68,17 @@ class PhonenumberHelper
}
}
public function format($phonenumber)
public function denormalize(string $phoneNumber): string
{
return $this->performTwilioFormat($phonenumber);
$phoneUtil = PhoneNumberUtil::getInstance();
$phoneNumber = $phoneUtil->parse($phoneNumber);
return $phoneUtil->format($phoneNumber, PhoneNumberFormat::NATIONAL);
}
public function format(string $phonenumber): string
{
return $this->normalize($phonenumber);
}
/**
@ -157,7 +159,15 @@ class PhonenumberHelper
return 'mobile' === $validation;
}
protected function performTwilioFormat($phonenumber)
public function normalize(string $phoneNumber): string
{
$phoneUtil = PhoneNumberUtil::getInstance();
$phoneNumber = $phoneUtil->parse($phoneNumber, $this->config['default_carrier_code']);
return $phoneUtil->formatNationalNumberWithPreferredCarrierCode($phoneNumber, $this->config['default_carrier_code']);
}
private function performTwilioFormat($phonenumber)
{
if (false === $this->isPhonenumberValidationConfigured()) {
return $phonenumber;
@ -218,7 +228,7 @@ class PhonenumberHelper
return $format;
}
protected function performTwilioLookup($phonenumber)
private function performTwilioLookup($phonenumber)
{
if (false === $this->isPhonenumberValidationConfigured()) {
return null;

View File

@ -14,19 +14,16 @@ namespace Chill\MainBundle\Phonenumber;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class Templating extends AbstractExtension
final class Templating extends AbstractExtension
{
/**
* @var PhonenumberHelper
*/
protected $phonenumberHelper;
protected PhoneNumberHelperInterface $phonenumberHelper;
public function __construct(PhonenumberHelper $phonenumberHelper)
public function __construct(PhoneNumberHelperInterface $phonenumberHelper)
{
$this->phonenumberHelper = $phonenumberHelper;
}
public function formatPhonenumber($phonenumber)
public function formatPhonenumber(string $phonenumber): string
{
return $this->phonenumberHelper->format($phonenumber) ?? $phonenumber;
}

View File

@ -11,24 +11,21 @@ declare(strict_types=1);
namespace Chill\MainBundle\Validation\Validator;
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
use LogicException;
use Psr\Log\LoggerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class ValidPhonenumber extends ConstraintValidator
final class ValidPhonenumber extends ConstraintValidator
{
protected $logger;
private LoggerInterface $logger;
/**
* @var PhonenumberHelper
*/
protected $phonenumberHelper;
private PhoneNumberHelperInterface $phonenumberHelper;
public function __construct(
LoggerInterface $logger,
PhonenumberHelper $phonenumberHelper
PhoneNumberHelperInterface $phonenumberHelper
) {
$this->phonenumberHelper = $phonenumberHelper;
$this->logger = $logger;

View File

@ -3,19 +3,12 @@ services:
autowire: true
autoconfigure: true
Chill\MainBundle\Phonenumber\PhonenumberHelper:
arguments:
$config: '%chill_main.phone_helper%'
$cachePool: '@cache.user_data'
Chill\MainBundle\Phonenumber\PhonenumberHelper: ~
Chill\MainBundle\Phonenumber\Templating:
arguments:
$phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper'
tags:
- { name: twig.extension }
Chill\MainBundle\Validation\Validator\ValidPhonenumber:
arguments:
$phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper'
tags:
- { name: validator.constraint_validator }

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
use Chill\PersonBundle\Entity\Person;
@ -41,6 +42,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
private CenterResolverManagerInterface $centerResolverManager;
private PhoneNumberHelperInterface $phoneNumberHelper;
private ChillEntityRenderExtension $render;
private PersonRepository $repository;
@ -48,11 +51,13 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
public function __construct(
ChillEntityRenderExtension $render,
PersonRepository $repository,
CenterResolverManagerInterface $centerResolverManager
CenterResolverManagerInterface $centerResolverManager,
PhoneNumberHelperInterface $phoneNumberHelper
) {
$this->render = $render;
$this->repository = $repository;
$this->centerResolverManager = $centerResolverManager;
$this->phoneNumberHelper = $phoneNumberHelper;
}
public function denormalize($data, $type, $format = null, array $context = [])
@ -106,12 +111,12 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
break;
case 'phonenumber':
$person->setPhonenumber($data[$item]);
$person->setPhonenumber($this->phoneNumberHelper->denormalize($data[$item]));
break;
case 'mobilenumber':
$person->setMobilenumber($data[$item]);
$person->setMobilenumber($this->phoneNumberHelper->denormalize($data[$item]));
break;
@ -187,8 +192,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
'deathdate' => $this->normalizer->normalize($person->getDeathdate(), $format, $context),
'age' => $this->normalizer->normalize($person->getAge(), $format, $context),
'centers' => $this->normalizer->normalize($this->centerResolverManager->resolveCenters($person), $format, $context),
'phonenumber' => $person->getPhonenumber(),
'mobilenumber' => $person->getMobilenumber(),
'phonenumber' => $this->phoneNumberHelper->normalize($person->getPhonenumber()),
'mobilenumber' => $this->phoneNumberHelper->normalize($person->getMobilenumber()),
'email' => $person->getEmail(),
'altNames' => $this->normalizeAltNames($person->getAltNames()),
'gender' => $person->getGender(),