Merge branch '20-update-telephone-type-new-approach' into 'master'

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

See merge request Chill-Projet/chill-bundles!322
This commit is contained in:
2022-03-02 20:39:52 +00:00
44 changed files with 711 additions and 254 deletions

View File

@@ -39,6 +39,7 @@ use Chill\MainBundle\Form\LocationTypeType;
use Chill\MainBundle\Form\UserJobType;
use Chill\MainBundle\Form\UserType;
use Exception;
use Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType;
use Ramsey\Uuid\Doctrine\UuidType;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -235,6 +236,7 @@ class ChillMainExtension extends Extension implements
'dateinterval' => NativeDateIntervalType::class,
'point' => PointType::class,
'uuid' => UuidType::class,
'phone_number' => PhoneNumberType::class,
],
],
]

View File

@@ -97,6 +97,9 @@ class Configuration implements ConfigurationInterface
->scalarNode('twilio_secret')
->defaultNull()
->end()
->scalarNode('default_carrier_code')
->defaultNull()
->end()
->end()
->end()
->arrayNode('acl')

View File

@@ -18,9 +18,9 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint;
use DateTimeImmutable;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use libphonenumber\PhoneNumber;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Table(name="chill_main_location")
@@ -90,20 +90,18 @@ class Location implements TrackCreationInterface, TrackUpdateInterface
private ?string $name = null;
/**
* @ORM\Column(type="string", length=64, nullable=true)
* @ORM\Column(type="phone_number", nullable=true)
* @Serializer\Groups({"read", "write", "docgen:read"})
* @Assert\Regex(pattern="/^([\+{1}])([0-9\s*]{4,20})$/")
* @PhonenumberConstraint(type="any")
*/
private ?string $phonenumber1 = null;
private ?PhoneNumber $phonenumber1 = null;
/**
* @ORM\Column(type="string", length=64, nullable=true)
* @ORM\Column(type="phone_number", nullable=true)
* @Serializer\Groups({"read", "write", "docgen:read"})
* @Assert\Regex(pattern="/^([\+{1}])([0-9\s*]{4,20})$/")
* @PhonenumberConstraint(type="any")
*/
private ?string $phonenumber2 = null;
private ?PhoneNumber $phonenumber2 = null;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
@@ -162,12 +160,12 @@ class Location implements TrackCreationInterface, TrackUpdateInterface
return $this->name;
}
public function getPhonenumber1(): ?string
public function getPhonenumber1(): ?PhoneNumber
{
return $this->phonenumber1;
}
public function getPhonenumber2(): ?string
public function getPhonenumber2(): ?PhoneNumber
{
return $this->phonenumber2;
}
@@ -238,14 +236,14 @@ class Location implements TrackCreationInterface, TrackUpdateInterface
return $this;
}
public function setPhonenumber1(?string $phonenumber1): self
public function setPhonenumber1(?PhoneNumber $phonenumber1): self
{
$this->phonenumber1 = $phonenumber1;
return $this;
}
public function setPhonenumber2(?string $phonenumber2): self
public function setPhonenumber2(?PhoneNumber $phonenumber2): self
{
$this->phonenumber2 = $phonenumber2;

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Form;
use Chill\MainBundle\Entity\LocationType as EntityLocationType;
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Form\Type\PickAddressType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
@@ -46,8 +47,8 @@ final class LocationFormType extends AbstractType
},
])
->add('name', TextType::class)
->add('phonenumber1', TextType::class, ['required' => false])
->add('phonenumber2', TextType::class, ['required' => false])
->add('phonenumber1', ChillPhoneNumberType::class, ['required' => false])
->add('phonenumber2', ChillPhoneNumberType::class, ['required' => false])
->add('email', TextType::class, ['required' => false])
->add('address', PickAddressType::class, [
'required' => false,

View File

@@ -0,0 +1,61 @@
<?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\Form\Type;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use Misd\PhoneNumberBundle\Form\Type\PhoneNumberType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use function array_key_exists;
class ChillPhoneNumberType extends AbstractType
{
private string $defaultCarrierCode;
private PhoneNumberUtil $phoneNumberUtil;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->defaultCarrierCode = $parameterBag->get('chill_main')['phone_helper']['default_carrier_code'];
$this->phoneNumberUtil = PhoneNumberUtil::getInstance();
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('default_region', $this->defaultCarrierCode)
->setDefault('format', PhoneNumberFormat::NATIONAL)
->setDefault('type', \libphonenumber\PhoneNumberType::FIXED_LINE_OR_MOBILE)
->setNormalizer('attr', function (Options $options, $value) {
if (array_key_exists('placeholder', $value)) {
return $value;
}
$examplePhoneNumber = $this->phoneNumberUtil->getExampleNumberForType($this->defaultCarrierCode, $options['type']);
return array_merge(
$value,
[
'placeholder' => PhoneNumberUtil::getInstance()->format($examplePhoneNumber, $options['format']),
]
);
});
}
public function getParent()
{
return PhoneNumberType::class;
}
}

View File

@@ -38,7 +38,7 @@ class ObjectToIdTransformer implements DataTransformerInterface
*/
public function reverseTransform($id)
{
if (!$id) {
if (null === $id) {
return null;
}
@@ -46,7 +46,7 @@ class ObjectToIdTransformer implements DataTransformerInterface
->getRepository($this->class)
->find($id);
if (!$object) {
if (null === $object) {
throw new TransformationFailedException();
}
@@ -62,7 +62,7 @@ class ObjectToIdTransformer implements DataTransformerInterface
*/
public function transform($object)
{
if (!$object) {
if (null === $object) {
return '';
}

View File

@@ -0,0 +1,54 @@
<?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;
use libphonenumber\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 format(PhoneNumber $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;
}

View File

@@ -15,8 +15,12 @@ use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
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,32 @@ 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 PhonenumberUtil $phoneNumberUtil;
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)
@@ -72,11 +68,19 @@ class PhonenumberHelper
]);
$this->isConfigured = true;
}
$this->phoneNumberUtil = PhoneNumberUtil::getInstance();
}
public function format($phonenumber)
/**
* @param string $phoneNumber A national phone number starting with +
*
* @throws NumberParseException
*/
public function format(PhoneNumber $phoneNumber): string
{
return $this->performTwilioFormat($phonenumber);
return $this->phoneNumberUtil
->formatOutOfCountryCallingNumber($phoneNumber, $this->config['default_carrier_code']);
}
/**
@@ -137,7 +141,7 @@ class PhonenumberHelper
}
/**
* REturn true if the phoennumber is a mobile phone. Return always true
* REturn true if the phonenumber is a mobile phone. Return always true
* if the validation is not configured.
*
* @param string $phonenumber
@@ -157,68 +161,7 @@ class PhonenumberHelper
return 'mobile' === $validation;
}
protected function performTwilioFormat($phonenumber)
{
if (false === $this->isPhonenumberValidationConfigured()) {
return $phonenumber;
}
// filter only number
$filtered = preg_replace('/[^0-9]/', '', $phonenumber);
$item = $this->cachePool->getItem('pnum_format_nat_' . $filtered);
if ($item->isHit()) {
return $item->get();
}
try {
$response = $this->twilioClient->get(sprintf(self::FORMAT_URI, '+' . $filtered), [
'http_errors' => true,
]);
} catch (ClientException $e) {
$response = $e->getResponse();
$this->logger->error('[phonenumber helper] Could not format number '
. 'due to client error', [
'message' => $response->getBody()->getContents(),
'status_code' => $response->getStatusCode(),
'phonenumber' => $phonenumber,
]);
return $phonenumber;
} catch (ServerException $e) {
$response = $e->getResponse();
$this->logger->error('[phonenumber helper] Could not format number '
. 'due to server error', [
'message' => $response->getBody()->getContents(),
'status_code' => $response->getStatusCode(),
'phonenumber' => $phonenumber,
]);
return null;
} catch (ConnectException $e) {
$this->logger->error('[phonenumber helper] Could not format number '
. 'due to connect error', [
'message' => $e->getMessage(),
'phonenumber' => $phonenumber,
]);
return null;
}
$format = json_decode($response->getBody()->getContents())->national_format;
$item
->set($format)
// expires after 3d
->expiresAfter(3600 * 24 * 3);
$this->cachePool->save($item);
return $format;
}
protected function performTwilioLookup($phonenumber)
private function performTwilioLookup($phonenumber)
{
if (false === $this->isPhonenumberValidationConfigured()) {
return null;
@@ -230,7 +173,7 @@ class PhonenumberHelper
$item = $this->cachePool->getItem('pnum_' . $filtered);
if ($item->isHit()) {
//return $item->get();
return $item->get();
}
try {

View File

@@ -16,10 +16,7 @@ use Twig\TwigFilter;
class Templating extends AbstractExtension
{
/**
* @var PhonenumberHelper
*/
protected $phonenumberHelper;
protected PhonenumberHelper $phonenumberHelper;
public function __construct(PhonenumberHelper $phonenumberHelper)
{

View File

@@ -18,8 +18,10 @@
{% for entity in entities %}
<tr>
<td>{{ entity.name }}</td>
<td>{{ entity.phonenumber1 }}</td>
<td>{{ entity.phonenumber2 }}</td>
<td>
{{ entity.phonenumber1|chill_format_phonenumber }}
</td>
<td>{{ entity.phonenumber2|chill_format_phonenumber }}</td>
<td>{{ entity.email }}</td>
<td>
{% if entity.address is not null %}

View File

@@ -11,8 +11,10 @@ declare(strict_types=1);
namespace Chill\MainBundle\Search\Utils;
use libphonenumber\PhoneNumberUtil;
use LogicException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use function count;
use function implode;
use function preg_match;
@@ -24,6 +26,13 @@ class ExtractPhonenumberFromPattern
{
private const PATTERN = '([\\+]{0,1}[0-9\\ ]{5,})';
private string $defaultCarrierCode;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->defaultCarrierCode = $parameterBag->get('chill_main')['phone_helper']['default_carrier_code'];
}
public function extractPhonenumber(string $subject): SearchExtractionResult
{
$matches = [];
@@ -35,11 +44,21 @@ class ExtractPhonenumberFromPattern
foreach (str_split(trim($matches[0])) as $key => $char) {
switch ($char) {
case '+':
if (0 === $key) {
$phonenumber[] = $char;
} else {
throw new LogicException('should not match not alnum character');
}
break;
case '0':
$length++;
if (0 === $key) {
$phonenumber[] = '+32';
$util = PhoneNumberUtil::getInstance();
$phonenumber[] = '+' . $util->getCountryCodeForRegion($this->defaultCarrierCode);
} else {
$phonenumber[] = $char;
}

View File

@@ -0,0 +1,64 @@
<?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\Serializer\Normalizer;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberUtil;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterface
{
private string $defaultCarrierCode;
private PhoneNumberUtil $phoneNumberUtil;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->defaultCarrierCode = $parameterBag->get('chill_main')['phone_helper']['default_carrier_code'];
$this->phoneNumberUtil = PhoneNumberUtil::getInstance();
}
/**
* @param mixed $data
* @param mixed $type
* @param null|mixed $format
*
* @throws UnexpectedValueException
*/
public function denormalize($data, $type, $format = null, array $context = [])
{
try {
return $this->phoneNumberUtil->parse($data, $this->defaultCarrierCode);
} catch (NumberParseException $e) {
throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e);
}
}
public function normalize($object, ?string $format = null, array $context = []): string
{
return $this->phoneNumberUtil->formatOutOfCountryCallingNumber($object, $this->defaultCarrierCode);
}
public function supportsDenormalization($data, $type, $format = null)
{
return 'libphonenumber\PhoneNumber' === $type;
}
public function supportsNormalization($data, ?string $format = null)
{
return $data instanceof PhoneNumber;
}
}

View File

@@ -0,0 +1,72 @@
<?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\Tests\Routing\Loader;
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
use libphonenumber\PhoneNumberUtil;
use Psr\Log\NullLogger;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
* @internal
* @coversNothing
*/
final class PhonenumberHelperTest extends KernelTestCase
{
public function formatPhonenumbers()
{
yield [
'BE',
'+3281136917',
'081 13 69 17',
];
yield [
'FR',
'+33 6 23 12 45 54',
'06 23 12 45 54',
];
yield [
'FR',
'+32 81 13 69 17',
'00 32 81 13 69 17',
];
yield [
'BE',
'+33 6 23 12 45 54',
'00 33 6 23 12 45 54',
];
}
/**
* @dataProvider formatPhonenumbers
*/
public function testFormatPhonenumbers(string $defaultCarrierCode, string $phoneNumber, string $expected)
{
$util = PhoneNumberUtil::getInstance();
$subject = new PhonenumberHelper(
new ArrayAdapter(),
new ParameterBag([
'chill_main.phone_helper' => [
'default_carrier_code' => $defaultCarrierCode,
],
]),
new NullLogger()
);
$this->assertEquals($expected, $subject->format($util->parse($phoneNumber)));
}
}

View File

@@ -13,6 +13,7 @@ namespace Search\Utils;
use Chill\MainBundle\Search\Utils\ExtractPhonenumberFromPattern;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
* @internal
@@ -22,17 +23,25 @@ final class ExtractPhonenumberFromPatternTest extends KernelTestCase
{
public function provideData()
{
yield ['Diallo', 0, [], 'Diallo', 'no phonenumber'];
yield ['BE', 'Diallo', 0, [], 'Diallo', 'no phonenumber'];
yield ['Diallo 15/06/2021', 0, [], 'Diallo 15/06/2021', 'no phonenumber and a date'];
yield ['BE', 'Diallo 15/06/2021', 0, [], 'Diallo 15/06/2021', 'no phonenumber and a date'];
yield ['Diallo 0486 123 456', 1, ['+32486123456'], 'Diallo', 'a phonenumber and a name'];
yield ['BE', 'Diallo 0486 123 456', 1, ['+32486123456'], 'Diallo', 'a phonenumber and a name'];
yield ['Diallo 123 456', 1, ['123456'], 'Diallo', 'a number and a name, without leadiing 0'];
yield ['BE', 'Diallo 123 456', 1, ['123456'], 'Diallo', 'a number and a name, without leadiing 0'];
yield ['123 456', 1, ['123456'], '', 'only phonenumber'];
yield ['BE', '123 456', 1, ['123456'], '', 'only phonenumber'];
yield ['0123 456', 1, ['+32123456'], '', 'only phonenumber with a leading 0'];
yield ['BE', '0123 456', 1, ['+32123456'], '', 'only phonenumber with a leading 0'];
yield ['FR', '123 456', 1, ['123456'], '', 'only phonenumber'];
yield ['FR', '0123 456', 1, ['+33123456'], '', 'only phonenumber with a leading 0'];
yield ['FR', 'Diallo 0486 123 456', 1, ['+33486123456'], 'Diallo', 'a phonenumber and a name'];
yield ['FR', 'Diallo +32486 123 456', 1, ['+32486123456'], 'Diallo', 'a phonenumber and a name'];
}
/**
@@ -44,9 +53,11 @@ final class ExtractPhonenumberFromPatternTest extends KernelTestCase
* @param mixed $filteredSubject
* @param mixed $msg
*/
public function testExtract($subject, $expectedCount, $expected, $filteredSubject, $msg)
public function testExtract(string $defaultCarrierCode, $subject, $expectedCount, $expected, $filteredSubject, $msg)
{
$extractor = new ExtractPhonenumberFromPattern();
$extractor = new ExtractPhonenumberFromPattern(new ParameterBag(['chill_main' => [
'phone_helper' => ['default_carrier_code' => $defaultCarrierCode],
]]));
$result = $extractor->extractPhonenumber($subject);
$this->assertCount($expectedCount, $result->getFound());

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;
@@ -46,7 +43,7 @@ class ValidPhonenumber extends ConstraintValidator
return;
}
if (empty($value)) {
if ('' === $value) {
return;
}

View File

@@ -26,7 +26,8 @@
],
"require": {
"league/csv": "^9.6",
"phpoffice/phpspreadsheet": "~1.2"
"phpoffice/phpspreadsheet": "~1.2",
"odolbeau/phone-number-bundle": "^3.6"
},
"require-dev": {
},

View File

@@ -96,3 +96,4 @@ services:
- "@security.token_storage"
Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface: '@Chill\MainBundle\Security\Resolver\CenterResolverDispatcher'

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\PhoneNumberHelperInterface: '@Chill\MainBundle\Phonenumber\PhonenumberHelper'
Chill\MainBundle\Phonenumber\Templating:
arguments:
$phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper'
tags:
- { name: twig.extension }
Chill\MainBundle\Phonenumber\PhonenumberHelper: ~
Chill\MainBundle\Phonenumber\Templating: ~
Chill\MainBundle\Validation\Validator\ValidPhonenumber:
arguments:
$phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper'
tags:
- { name: validator.constraint_validator }

View File

@@ -0,0 +1,79 @@
<?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\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use libphonenumber\PhoneNumberUtil;
use RuntimeException;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
final class Version20220302132728 extends AbstractMigration implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber1 TYPE VARCHAR(64)');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber1 DROP DEFAULT');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber2 TYPE VARCHAR(64)');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber2 DROP DEFAULT');
$this->addSql('COMMENT ON COLUMN chill_main_location.phonenumber1 IS NULL');
$this->addSql('COMMENT ON COLUMN chill_main_location.phonenumber2 IS NULL');
}
public function getDescription(): string
{
return 'Upgrade phonenumber on location';
}
public function up(Schema $schema): void
{
$carrier_code = $this->container
->getParameter('chill_main')['phone_helper']['default_carrier_code'];
if (null === $carrier_code) {
throw new RuntimeException('no carrier code');
}
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber1 TYPE VARCHAR(35)');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber1 DROP DEFAULT');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber1 TYPE VARCHAR(35)');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber2 TYPE VARCHAR(35)');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber2 DROP DEFAULT');
$this->addSql('ALTER TABLE chill_main_location ALTER phonenumber2 TYPE VARCHAR(35)');
$this->addSql('COMMENT ON COLUMN chill_main_location.phonenumber1 IS \'(DC2Type:phone_number)\'');
$this->addSql('COMMENT ON COLUMN chill_main_location.phonenumber2 IS \'(DC2Type:phone_number)\'');
$this->addSql(
'UPDATE chill_main_location SET ' .
$this->buildMigrationPhonenumberClause($carrier_code, 'phonenumber1') .
', ' .
$this->buildMigrationPhoneNumberClause($carrier_code, 'phonenumber2')
);
}
private function buildMigrationPhoneNumberClause(string $defaultCarriercode, string $field): string
{
$util = PhoneNumberUtil::getInstance();
$countryCode = $util->getCountryCodeForRegion($defaultCarriercode);
return sprintf('%s=CASE
WHEN %s = \'\' THEN NULL
WHEN LEFT(%s, 1) = \'0\'
THEN \'+%s\' || replace(replace(substr(%s, 2), \'(0)\', \'\'), \' \', \'\')
ELSE replace(replace(%s, \'(0)\', \'\'),\' \', \'\')
END', $field, $field, $field, $countryCode, $field, $field);
}
}