diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 85c3d476c..ddf7fccbe 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -29,6 +29,7 @@ variables:
REDIS_URL: redis://redis:6379
# change vendor dir to make the app install into tests/apps
COMPOSER_VENDOR_DIR: tests/app/vendor
+ DEFAULT_CARRIER_CODE: BE
stages:
- Composer install
@@ -78,6 +79,7 @@ psalm_tests:
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
- bin/grumphp run --tasks=psalm
+ allow_failure: true
artifacts:
expire_in: 30 min
paths:
diff --git a/composer.json b/composer.json
index 2223f65c0..c96738df8 100644
--- a/composer.json
+++ b/composer.json
@@ -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",
diff --git a/phpstan-types.neon b/phpstan-types.neon
index 2cc55255a..79ae16d4b 100644
--- a/phpstan-types.neon
+++ b/phpstan-types.neon
@@ -325,11 +325,6 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Timeline/TimelineBuilder.php
- -
- message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
- count: 1
- path: src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
-
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
index 6e3d6d85e..5ad7348ee 100644
--- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
+++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
@@ -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,
],
],
]
diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php
index 9236c8a50..be8baf79a 100644
--- a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php
+++ b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php
@@ -97,6 +97,9 @@ class Configuration implements ConfigurationInterface
->scalarNode('twilio_secret')
->defaultNull()
->end()
+ ->scalarNode('default_carrier_code')
+ ->defaultNull()
+ ->end()
->end()
->end()
->arrayNode('acl')
diff --git a/src/Bundle/ChillMainBundle/Entity/Location.php b/src/Bundle/ChillMainBundle/Entity/Location.php
index bff3ff37b..c1421586f 100644
--- a/src/Bundle/ChillMainBundle/Entity/Location.php
+++ b/src/Bundle/ChillMainBundle/Entity/Location.php
@@ -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;
diff --git a/src/Bundle/ChillMainBundle/Form/LocationFormType.php b/src/Bundle/ChillMainBundle/Form/LocationFormType.php
index 713705de3..c027e8086 100644
--- a/src/Bundle/ChillMainBundle/Form/LocationFormType.php
+++ b/src/Bundle/ChillMainBundle/Form/LocationFormType.php
@@ -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,
diff --git a/src/Bundle/ChillMainBundle/Form/Type/ChillPhoneNumberType.php b/src/Bundle/ChillMainBundle/Form/Type/ChillPhoneNumberType.php
new file mode 100644
index 000000000..547782943
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Form/Type/ChillPhoneNumberType.php
@@ -0,0 +1,61 @@
+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;
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php
index 145ab0441..4122c5509 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ObjectToIdTransformer.php
@@ -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 '';
}
diff --git a/src/Bundle/ChillMainBundle/Phonenumber/PhoneNumberHelperInterface.php b/src/Bundle/ChillMainBundle/Phonenumber/PhoneNumberHelperInterface.php
new file mode 100644
index 000000000..eeab9c38d
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Phonenumber/PhoneNumberHelperInterface.php
@@ -0,0 +1,54 @@
+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 {
diff --git a/src/Bundle/ChillMainBundle/Phonenumber/Templating.php b/src/Bundle/ChillMainBundle/Phonenumber/Templating.php
index 414732263..c07d8c5a8 100644
--- a/src/Bundle/ChillMainBundle/Phonenumber/Templating.php
+++ b/src/Bundle/ChillMainBundle/Phonenumber/Templating.php
@@ -16,10 +16,7 @@ use Twig\TwigFilter;
class Templating extends AbstractExtension
{
- /**
- * @var PhonenumberHelper
- */
- protected $phonenumberHelper;
+ protected PhonenumberHelper $phonenumberHelper;
public function __construct(PhonenumberHelper $phonenumberHelper)
{
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Location/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Location/index.html.twig
index bc39a9275..a04ae73a9 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Location/index.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Location/index.html.twig
@@ -18,8 +18,10 @@
{% for entity in entities %}
{{ entity.name }} |
- {{ entity.phonenumber1 }} |
- {{ entity.phonenumber2 }} |
+
+ {{ entity.phonenumber1|chill_format_phonenumber }}
+ |
+ {{ entity.phonenumber2|chill_format_phonenumber }} |
{{ entity.email }} |
{% if entity.address is not null %}
diff --git a/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php b/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php
index b6286fa35..c67b3582a 100644
--- a/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php
+++ b/src/Bundle/ChillMainBundle/Search/Utils/ExtractPhonenumberFromPattern.php
@@ -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;
}
diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php
new file mode 100644
index 000000000..cb59e6421
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php
@@ -0,0 +1,64 @@
+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;
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php
new file mode 100644
index 000000000..26287e9bc
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Phonenumber/PhonenumberHelperTest.php
@@ -0,0 +1,72 @@
+ [
+ 'default_carrier_code' => $defaultCarrierCode,
+ ],
+ ]),
+ new NullLogger()
+ );
+
+ $this->assertEquals($expected, $subject->format($util->parse($phoneNumber)));
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php
index f792c0a04..4e2553be9 100644
--- a/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Search/Utils/ExtractPhonenumberFromPatternTest.php
@@ -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());
diff --git a/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php b/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
index 5f2a5bf14..9620f7cb9 100644
--- a/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
+++ b/src/Bundle/ChillMainBundle/Validation/Validator/ValidPhonenumber.php
@@ -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;
}
diff --git a/src/Bundle/ChillMainBundle/composer.json b/src/Bundle/ChillMainBundle/composer.json
index 0c95c432a..913a760cb 100644
--- a/src/Bundle/ChillMainBundle/composer.json
+++ b/src/Bundle/ChillMainBundle/composer.json
@@ -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": {
},
diff --git a/src/Bundle/ChillMainBundle/config/services.yaml b/src/Bundle/ChillMainBundle/config/services.yaml
index 57e18ce86..6d55532a6 100644
--- a/src/Bundle/ChillMainBundle/config/services.yaml
+++ b/src/Bundle/ChillMainBundle/config/services.yaml
@@ -96,3 +96,4 @@ services:
- "@security.token_storage"
Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface: '@Chill\MainBundle\Security\Resolver\CenterResolverDispatcher'
+
diff --git a/src/Bundle/ChillMainBundle/config/services/phonenumber.yaml b/src/Bundle/ChillMainBundle/config/services/phonenumber.yaml
index 46fa853ee..df5ea3182 100644
--- a/src/Bundle/ChillMainBundle/config/services/phonenumber.yaml
+++ b/src/Bundle/ChillMainBundle/config/services/phonenumber.yaml
@@ -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 }
diff --git a/src/Bundle/ChillMainBundle/migrations/Version20220302132728.php b/src/Bundle/ChillMainBundle/migrations/Version20220302132728.php
new file mode 100644
index 000000000..23a7f2ab6
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/migrations/Version20220302132728.php
@@ -0,0 +1,79 @@
+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);
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php
index 49f7ae297..fab4b2845 100644
--- a/src/Bundle/ChillPersonBundle/Entity/Person.php
+++ b/src/Bundle/ChillPersonBundle/Entity/Person.php
@@ -37,6 +37,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Exception;
+use libphonenumber\PhoneNumber;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@@ -371,15 +372,10 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
/**
* The person's mobile phone number.
*
- * @ORM\Column(type="text")
- * @Assert\Regex(
- * pattern="/^([\+{1}])([0-9\s*]{4,20})$/",
- * )
- * @PhonenumberConstraint(
- * type="mobile",
- * )
+ * @PhonenumberConstraint(type="mobile")
+ * @ORM\Column(type="phone_number", nullable=true)
*/
- private string $mobilenumber = '';
+ private ?PhoneNumber $mobilenumber = null;
/**
* The person's nationality.
@@ -429,15 +425,12 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
/**
* The person's phonenumber.
*
- * @ORM\Column(type="text")
- * @Assert\Regex(
- * pattern="/^([\+{1}])([0-9\s*]{4,20})$/",
- * )
+ * @ORM\Column(type="phone_number", nullable=true)
* @PhonenumberConstraint(
* type="landline",
* )
*/
- private string $phonenumber = '';
+ private ?PhoneNumber $phonenumber = null;
/**
* The person's place of birth.
@@ -1227,10 +1220,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this->memo;
}
- /**
- * Get mobilenumber.
- */
- public function getMobilenumber(): string
+ public function getMobilenumber(): ?PhoneNumber
{
return $this->mobilenumber;
}
@@ -1295,10 +1285,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this->otherPhoneNumbers;
}
- /**
- * Get phonenumber.
- */
- public function getPhonenumber(): string
+ public function getPhonenumber(): ?PhoneNumber
{
return $this->phonenumber;
}
@@ -1737,16 +1724,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this;
}
- /**
- * Set mobilenumber.
- *
- * @param string $mobilenumber
- *
- * @return Person
- */
- public function setMobilenumber(?string $mobilenumber = '')
+ public function setMobilenumber(?PhoneNumber $mobilenumber)
{
- $this->mobilenumber = (string) $mobilenumber;
+ $this->mobilenumber = $mobilenumber;
return $this;
}
@@ -1782,16 +1762,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this;
}
- /**
- * Set phonenumber.
- *
- * @param string $phonenumber
- *
- * @return Person
- */
- public function setPhonenumber(?string $phonenumber = '')
+ public function setPhonenumber(?PhoneNumber $phonenumber)
{
- $this->phonenumber = (string) $phonenumber;
+ $this->phonenumber = $phonenumber;
return $this;
}
diff --git a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php
index a33858c02..2aed9df97 100644
--- a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php
+++ b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php
@@ -13,17 +13,18 @@ namespace Chill\PersonBundle\Form;
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
use Chill\MainBundle\Form\Type\ChillDateType;
+use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Form\Type\PickCenterType;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Form\Type\GenderType;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
+use libphonenumber\PhoneNumberType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
-use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -60,11 +61,13 @@ final class CreationPersonType extends AbstractType
->add('birthdate', ChillDateType::class, [
'required' => false,
])
- ->add('phonenumber', TelType::class, [
+ ->add('phonenumber', ChillPhoneNumberType::class, [
'required' => false,
+ 'type' => PhoneNumberType::FIXED_LINE,
])
- ->add('mobilenumber', TelType::class, [
+ ->add('mobilenumber', ChillPhoneNumberType::class, [
'required' => false,
+ 'type' => PhoneNumberType::MOBILE,
])
->add('email', EmailType::class, [
'required' => false,
diff --git a/src/Bundle/ChillPersonBundle/Form/PersonType.php b/src/Bundle/ChillPersonBundle/Form/PersonType.php
index 3e809ad49..acc65c6ac 100644
--- a/src/Bundle/ChillPersonBundle/Form/PersonType.php
+++ b/src/Bundle/ChillPersonBundle/Form/PersonType.php
@@ -14,26 +14,27 @@ namespace Chill\PersonBundle\Form;
use Chill\CustomFieldsBundle\Form\Type\CustomFieldType;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\ChillDateType;
+use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Form\Type\PickCivilityType;
use Chill\MainBundle\Form\Type\Select2CountryType;
use Chill\MainBundle\Form\Type\Select2LanguageType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
+use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\PersonPhone;
use Chill\PersonBundle\Form\Type\GenderType;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
-use Chill\PersonBundle\Form\Type\PersonPhoneType;
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
-use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -57,17 +58,21 @@ class PersonType extends AbstractType
protected TranslatableStringHelper $translatableStringHelper;
+ private ParameterBagInterface $parameterBag;
+
/**
* @param string[] $personFieldsConfiguration configuration of visibility of some fields
*/
public function __construct(
array $personFieldsConfiguration,
ConfigPersonAltNamesHelper $configAltNamesHelper,
- TranslatableStringHelper $translatableStringHelper
+ TranslatableStringHelperInterface $translatableStringHelper,
+ ParameterBagInterface $parameterBag
) {
$this->config = $personFieldsConfiguration;
$this->configAltNamesHelper = $configAltNamesHelper;
$this->translatableStringHelper = $translatableStringHelper;
+ $this->parameterBag = $parameterBag;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -126,22 +131,34 @@ class PersonType extends AbstractType
}
if ('visible' === $this->config['phonenumber']) {
- $builder->add('phonenumber', TelType::class, [
- 'required' => false,
- // 'placeholder' => '+33623124554' //TODO placeholder for phone numbers
- ]);
+ $builder
+ ->add(
+ 'phonenumber',
+ ChillPhoneNumberType::class,
+ [
+ 'required' => false,
+ 'type' => \libphonenumber\PhoneNumberType::FIXED_LINE,
+ ]
+ );
}
if ('visible' === $this->config['mobilenumber']) {
$builder
- ->add('mobilenumber', TelType::class, ['required' => false])
+ ->add(
+ 'mobilenumber',
+ ChillPhoneNumberType::class,
+ [
+ 'type' => \libphonenumber\PhoneNumberType::MOBILE,
+ 'required' => false,
+ ]
+ )
->add('acceptSMS', CheckboxType::class, [
'required' => false,
]);
}
$builder->add('otherPhoneNumbers', ChillCollectionType::class, [
- 'entry_type' => PersonPhoneType::class,
+ 'entry_type' => ChillPhoneNumberType::class,
'button_add_label' => 'Add new phone',
'button_remove_label' => 'Remove phone',
'required' => false,
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig
index e3280d755..9ffdbfae6 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig
@@ -146,22 +146,27 @@
'with_valid_from': false
}) }}
{% endif %}
-
- {% if person.mobilenumber %}
-
+ {% if person.phonenumber is not null %}
+
+
+
+ {{ person.phonenumber|chill_format_phonenumber }}
+
+
+ {% endif %}
+ {% if person.mobilenumber is not null %}
+
+
{{ person.mobilenumber|chill_format_phonenumber }}
- {% else %}
+
+ {% endif %}
+ {% if person.phonenumber is null and person.mobilenumber is null %}
+
- {% if person.phonenumber %}
-
- {{ person.phonenumber|chill_format_phonenumber }}
-
- {% else %}
- {{ 'No data given'|trans }}
- {% endif %}
- {% endif %}
-
+ {{ 'No data given'|trans }}
+
+ {% endif %}
{% if options['addCenter'] and person|chill_resolve_center|length > 0 %}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/banner.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/banner.html.twig
index b603dd70c..0e051da2c 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/Person/banner.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/banner.html.twig
@@ -25,14 +25,14 @@
{% if person.phonenumber %}
-
+
{{ person.phonenumber|chill_format_phonenumber }}
{% endif %}
{% if person.mobilenumber %}
-
+
{{ person.mobilenumber|chill_format_phonenumber }}
{% endif %}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/list_by_phonenumber.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_by_phonenumber.html.twig
index 642225571..754952df0 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/Person/list_by_phonenumber.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_by_phonenumber.html.twig
@@ -62,12 +62,12 @@
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig
index 9bdc3a479..788229e61 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/view.html.twig
@@ -232,14 +232,14 @@ This view should receive those arguments:
{%- if chill_person.fields.phonenumber == 'visible' -%}
- {{ 'Phonenumber'|trans }} :
- - {% if person.phonenumber is not empty %}
{{ person.phonenumber|chill_format_phonenumber }} {% else %}{{ 'No data given'|trans }}{% endif %}
+ - {% if person.phonenumber is not empty %}{{ person.phonenumber|chill_format_phonenumber }}{% else %}{{ 'No data given'|trans }}{% endif %}
{% endif %}
{%- if chill_person.fields.mobilenumber == 'visible' -%}
- {{ 'Mobilenumber'|trans }} :
- - {% if person.mobilenumber is not empty %}{{ person.mobilenumber|chill_format_phonenumber }}{% else %}{{ 'No data given'|trans }}{% endif %}
+ - {% if person.mobilenumber is not empty %}{{ person.mobilenumber|chill_format_phonenumber }}{% else %}{{ 'No data given'|trans }}{% endif %}
{% if person.acceptSMS %}{{ 'Accept short text message'|trans }}{% endif %}
{% endif %}
@@ -250,7 +250,7 @@ This view should receive those arguments:
{{ 'Others phone numbers'|trans }} :
{% for el in person.otherPhoneNumbers %}
{% if el.phonenumber is not empty %}
- {% if el.description is not empty %}{{ el.description }} : {% endif %}{{ el.phonenumber|chill_format_phonenumber }}
+ {% if el.description is not empty %}{{ el.description }} : {% endif %}{{ el.phonenumber|chill_format_phonenumber }}
{% endif %}
{% endfor %}
@@ -317,4 +317,4 @@ This view should receive those arguments:
{% endif %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php
index c19b35b57..8eae2065d 100644
--- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php
+++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php
@@ -95,9 +95,9 @@ class PersonDocGenNormalizer implements
'maritalStatus' => null !== ($ms = $person->getMaritalStatus()) ? $this->translatableStringHelper->localize($ms->getName()) : '',
'maritalStatusDate' => $this->normalizer->normalize($person->getMaritalStatusDate(), $format, $dateContext),
'email' => $person->getEmail(),
- 'firstPhoneNumber' => $person->getPhonenumber() ?? $person->getMobilenumber(),
- 'fixPhoneNumber' => $person->getPhonenumber(),
- 'mobilePhoneNumber' => $person->getMobilenumber(),
+ 'firstPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber() ?? $person->getMobilenumber(), $format, $context),
+ 'fixPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $context),
+ 'mobilePhoneNumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
'nationality' => null !== ($c = $person->getNationality()) ? $this->translatableStringHelper->localize($c->getName()) : '',
'placeOfBirth' => $person->getPlaceOfBirth(),
'memo' => $person->getMemo(),
diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonJsonNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonJsonNormalizer.php
index 451171cb6..b95cc60a8 100644
--- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonJsonNormalizer.php
+++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonJsonNormalizer.php
@@ -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;
@@ -20,6 +21,7 @@ use Chill\PersonBundle\Repository\PersonRepository;
use DateTime;
use DateTimeImmutable;
use Doctrine\Common\Collections\Collection;
+use libphonenumber\PhoneNumber;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
@@ -41,6 +43,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
private CenterResolverManagerInterface $centerResolverManager;
+ private PhoneNumberHelperInterface $phoneNumberHelper;
+
private ChillEntityRenderExtension $render;
private PersonRepository $repository;
@@ -48,11 +52,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 +112,12 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
break;
case 'phonenumber':
- $person->setPhonenumber($data[$item]);
+ $person->setPhonenumber($this->denormalizer->denormalize($data[$item], PhoneNumber::class, $format, $context));
break;
case 'mobilenumber':
- $person->setMobilenumber($data[$item]);
+ $person->setMobilenumber($this->denormalizer->denormalize($data[$item], PhoneNumber::class, $format, $context));
break;
@@ -187,8 +193,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->normalizer->normalize($person->getPhonenumber()),
+ 'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber()),
'email' => $person->getEmail(),
'altNames' => $this->normalizeAltNames($person->getAltNames()),
'gender' => $person->getGender(),
diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateTest.php
index 087c3e186..c85b8d058 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Controller/PersonControllerUpdateTest.php
@@ -297,13 +297,14 @@ final class PersonControllerUpdateTest extends WebTestCase
// reminder: this value is capitalized
['placeOfBirth', 'A PLACE', static function (Person $person) { return $person->getPlaceOfBirth(); }],
['birthdate', '1980-12-15', static function (Person $person) { return $person->getBirthdate()->format('Y-m-d'); }],
- ['phonenumber', '+32123456789', static function (Person $person) { return $person->getPhonenumber(); }],
+ // TODO test on phonenumber update
+ // ['phonenumber', '+32123456789', static function (Person $person) { return $person->getPhonenumber(); }],
['memo', 'jfkdlmq jkfldmsq jkmfdsq', static function (Person $person) { return $person->getMemo(); }],
['countryOfBirth', 'BE', static function (Person $person) { return $person->getCountryOfBirth()->getCountryCode(); }],
['nationality', 'FR', static function (Person $person) { return $person->getNationality()->getCountryCode(); }],
['placeOfBirth', '', static function (Person $person) { return $person->getPlaceOfBirth(); }],
['birthdate', '', static function (Person $person) { return $person->getBirthdate(); }],
- ['phonenumber', '', static function (Person $person) { return $person->getPhonenumber(); }],
+ //['phonenumber', '', static function (Person $person) { return $person->getPhonenumber(); }],
['memo', '', static function (Person $person) { return $person->getMemo(); }],
['countryOfBirth', null, static function (Person $person) { return $person->getCountryOfBirth(); }],
['nationality', null, static function (Person $person) { return $person->getNationality(); }],
diff --git a/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php
index 1db356018..0b66d8648 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php
@@ -158,7 +158,7 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
$participationL = $period->closeParticipationFor($person);
$this->assertSame($participationL, $participation);
- $this->assertTrue($participation->getEndDate() instanceof DateTimeInterface);
+ $this->assertTrue($participationL->getEndDate() instanceof DateTimeInterface);
$participation = $period->getOpenParticipationContainsPerson($person);
$this->assertNull($participation);
diff --git a/src/Bundle/ChillPersonBundle/config/services/form.yaml b/src/Bundle/ChillPersonBundle/config/services/form.yaml
index 2390005cf..52bf1f494 100644
--- a/src/Bundle/ChillPersonBundle/config/services/form.yaml
+++ b/src/Bundle/ChillPersonBundle/config/services/form.yaml
@@ -1,15 +1,15 @@
services:
-
Chill\PersonBundle\Form\:
autowire: true
autoconfigure: true
resource: '../../Form/'
Chill\PersonBundle\Form\PersonType:
+ autowire: true
+ autoconfigure: true
arguments:
$personFieldsConfiguration: '%chill_person.person_fields%'
$configAltNamesHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper'
- $translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper'
tags:
- { name: form.type, alias: '@chill.person.form.person_creation' }
diff --git a/src/Bundle/ChillPersonBundle/config/validation.yaml b/src/Bundle/ChillPersonBundle/config/validation.yaml
index 192fc60f6..9719ec2d9 100644
--- a/src/Bundle/ChillPersonBundle/config/validation.yaml
+++ b/src/Bundle/ChillPersonBundle/config/validation.yaml
@@ -19,8 +19,5 @@ Chill\PersonBundle\Entity\AccompanyingPeriod:
Chill\PersonBundle\Entity\PersonPhone:
properties:
phonenumber:
- - Regex:
- pattern: '/^([\+{1}])([0-9\s*]{4,20})$/'
- message: 'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33123456789'
- Chill\MainBundle\Validation\Constraint\PhonenumberConstraint:
type: any
diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20220215135509.php b/src/Bundle/ChillPersonBundle/migrations/Version20220215135509.php
new file mode 100644
index 000000000..b54483955
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/migrations/Version20220215135509.php
@@ -0,0 +1,86 @@
+container
+ ->getParameter('chill_main')['phone_helper']['default_carrier_code'];
+
+ if (null === $carrier_code) {
+ throw new RuntimeException('no carrier code');
+ }
+
+ $this->addSql('ALTER TABLE chill_person_person ALTER phonenumber TYPE TEXT');
+ $this->addSql('ALTER TABLE chill_person_person ALTER phonenumber DROP DEFAULT');
+ $this->addSql('ALTER TABLE chill_person_person ALTER phonenumber DROP NOT NULL');
+ $this->addSql('COMMENT ON COLUMN chill_person_person.phonenumber IS NULL');
+
+ $this->addSql('ALTER TABLE chill_person_person ALTER mobilenumber TYPE TEXT');
+ $this->addSql('ALTER TABLE chill_person_person ALTER mobilenumber DROP DEFAULT');
+ $this->addSql('ALTER TABLE chill_person_person ALTER mobilenumber DROP NOT NULL');
+ $this->addSql('COMMENT ON COLUMN chill_person_person.mobilenumber IS NULL');
+
+ $this->addSql(
+ 'UPDATE chill_person_person SET ' .
+ $this->buildMigrationPhonenumberClause($carrier_code, 'phonenumber') .
+ ', ' .
+ $this->buildMigrationPhoneNumberClause($carrier_code, 'mobilenumber')
+ );
+
+ $this->addSql('ALTER TABLE chill_person_phone ALTER phonenumber TYPE TEXT');
+ $this->addSql('ALTER TABLE chill_person_phone ALTER phonenumber DROP DEFAULT');
+ $this->addSql('ALTER TABLE chill_person_phone ALTER phonenumber DROP NOT NULL');
+ $this->addSql('COMMENT ON COLUMN chill_person_phone.phonenumber IS NULL');
+
+ $this->addSql(
+ 'UPDATE chill_person_phone SET ' .
+ $this->buildMigrationPhoneNumberClause($carrier_code, 'phonenumber')
+ );
+ }
+
+ 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);
+ }
+}
diff --git a/src/Bundle/ChillThirdPartyBundle/DataFixtures/ORM/LoadThirdParty.php b/src/Bundle/ChillThirdPartyBundle/DataFixtures/ORM/LoadThirdParty.php
index a1015686f..905461ca5 100644
--- a/src/Bundle/ChillThirdPartyBundle/DataFixtures/ORM/LoadThirdParty.php
+++ b/src/Bundle/ChillThirdPartyBundle/DataFixtures/ORM/LoadThirdParty.php
@@ -21,6 +21,7 @@ use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Iterator;
+use libphonenumber\PhoneNumberUtil;
use Nelmio\Alice\Loader\NativeLoader;
use Nelmio\Alice\ObjectSet;
@@ -29,6 +30,13 @@ use function count;
class LoadThirdParty extends Fixture implements DependentFixtureInterface
{
+ private PhoneNumberUtil $phoneNumberUtil;
+
+ public function __construct()
+ {
+ $this->phoneNumberUtil = PhoneNumberUtil::getInstance();
+ }
+
public function getDependencies()
{
return [
@@ -66,7 +74,7 @@ class LoadThirdParty extends Fixture implements DependentFixtureInterface
Address::class => [
'address1' => [
'name' => '',
- 'telephone' => '',
+ 'telephone' => $this->phoneNumberUtil->getExampleNumber('FR'),
'email' => '',
'comment' => '',
],
@@ -116,7 +124,7 @@ class LoadThirdParty extends Fixture implements DependentFixtureInterface
ThirdParty::class => [
'thirdparty{1..75}' => [
'name' => '',
- 'telephone' => '',
+ 'telephone' => $this->phoneNumberUtil->getExampleNumber('FR'),
'email' => '',
'comment' => '',
'address' => '@address',
diff --git a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php
index 25ef1be65..678084045 100644
--- a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php
+++ b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php
@@ -24,6 +24,7 @@ use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
+use libphonenumber\PhoneNumber;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Annotation\Groups;
@@ -253,14 +254,11 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
private ?ThirdPartyProfession $profession = null;
/**
- * @ORM\Column(name="telephone", type="string", length=64, nullable=true)
- * @Assert\Regex("/^([\+{1}])([0-9\s*]{4,20})$/",
- * message="Invalid phone number: it should begin with the international prefix starting with ""+"", hold only digits and be smaller than 20 characters. Ex: +33123456789"
- * )
+ * @ORM\Column(name="telephone", type="phone_number", nullable=true)
* @PhonenumberConstraint(type="any")
* @Groups({"read", "write", "docgen:read", "docgen:read:3party:parent"})
*/
- private ?string $telephone = null;
+ private ?PhoneNumber $telephone = null;
/**
* @ORM\Column(name="types", type="json", nullable=true)
@@ -502,7 +500,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
/**
* Get telephone.
*/
- public function getTelephone(): ?string
+ public function getTelephone(): ?PhoneNumber
{
return $this->telephone;
}
@@ -821,12 +819,8 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
/**
* Set telephone.
- *
- * @param string|null $telephone
- *
- * @return ThirdParty
*/
- public function setTelephone($telephone = null)
+ public function setTelephone(?PhoneNumber $telephone = null): self
{
$this->telephone = $telephone;
diff --git a/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php b/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php
index 7ca5188b1..480808dfe 100644
--- a/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php
+++ b/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\ThirdPartyBundle\Form;
use Chill\MainBundle\Form\Type\ChillCollectionType;
+use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\PickAddressType;
use Chill\MainBundle\Form\Type\PickCenterType;
@@ -75,7 +76,7 @@ class ThirdPartyType extends AbstractType
->add('name', TextType::class, [
'required' => true,
])
- ->add('telephone', TextType::class, [
+ ->add('telephone', ChillPhoneNumberType::class, [
'label' => 'Phonenumber',
'required' => false,
])
diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/views/Entity/thirdparty.html.twig b/src/Bundle/ChillThirdPartyBundle/Resources/views/Entity/thirdparty.html.twig
index f25f3b263..4c56dfa54 100644
--- a/src/Bundle/ChillThirdPartyBundle/Resources/views/Entity/thirdparty.html.twig
+++ b/src/Bundle/ChillThirdPartyBundle/Resources/views/Entity/thirdparty.html.twig
@@ -110,8 +110,8 @@
}) }}
- {% if thirdparty.telephone %}
- {{ thirdparty.telephone|chill_format_phonenumber }}
+ {% if thirdparty.telephone is not null %}
+ {{ thirdparty.telephone|chill_format_phonenumber }}
{% else %}
{{ 'thirdparty.No_phonenumber'|trans }}
{% endif %}
@@ -136,7 +136,7 @@
{% if thirdparty.telephone %}
- {{ thirdparty.telephone|chill_format_phonenumber }}
+ {{ thirdparty.telephone|chill_format_phonenumber }}
{% else %}
{{ 'thirdparty.No_phonenumber'|trans }}
{% endif %}
diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/view.html.twig b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/view.html.twig
index 824438fa3..5a6a75225 100644
--- a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/view.html.twig
+++ b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/view.html.twig
@@ -67,10 +67,10 @@
{{ 'Phonenumber'|trans }}
{% if thirdParty.telephone == null %}
- {{ 'No phone given'|trans }}
+ {{ 'thirdparty.No_phonenumber'|trans }}
{% else %}
-
- {{ thirdParty.telephone|chill_print_or_message("thirdparty.No_phonenumber") }}
+
+ {{ thirdParty.telephone|chill_format_phonenumber }}
{% endif %}
diff --git a/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php
index c107d8485..65bc15ba0 100644
--- a/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php
+++ b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php
@@ -62,7 +62,7 @@ class ThirdPartyNormalizer implements NormalizerAwareInterface, NormalizerInterf
}, $thirdParty->getTypesAndCategories()),
'profession' => $this->normalizer->normalize($thirdParty->getProfession(), $format, $context),
'address' => $this->normalizer->normalize($thirdParty->getAddress(), $format, ['address_rendering' => 'short']),
- 'phonenumber' => $thirdParty->getTelephone(),
+ 'phonenumber' => $this->normalizer->normalize($thirdParty->getTelephone()),
'email' => $thirdParty->getEmail(),
'isChild' => $thirdParty->isChild(),
'parent' => $this->normalizer->normalize($thirdParty->getParent(), $format, $context),
diff --git a/src/Bundle/ChillThirdPartyBundle/migrations/Version20220302143821.php b/src/Bundle/ChillThirdPartyBundle/migrations/Version20220302143821.php
new file mode 100644
index 000000000..6ffb33472
--- /dev/null
+++ b/src/Bundle/ChillThirdPartyBundle/migrations/Version20220302143821.php
@@ -0,0 +1,70 @@
+addSql('ALTER TABLE chill_3party.third_party ALTER telephone TYPE VARCHAR(64)');
+ $this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone DROP DEFAULT');
+ $this->addSql('COMMENT ON COLUMN chill_3party.third_party.telephone IS NULL');
+ }
+
+ public function getDescription(): string
+ {
+ return 'Upgrade phonenumber on third parties';
+ }
+
+ 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_3party.third_party ALTER telephone TYPE VARCHAR(35)');
+ $this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone DROP DEFAULT');
+ $this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone TYPE VARCHAR(35)');
+ $this->addSql('COMMENT ON COLUMN chill_3party.third_party.telephone IS \'(DC2Type:phone_number)\'');
+
+ $this->addSql(
+ 'UPDATE chill_3party.third_party SET ' .
+ $this->buildMigrationPhonenumberClause($carrier_code, 'telephone')
+ );
+ }
+
+ 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);
+ }
+}
diff --git a/tests/app b/tests/app
index 0fef0f216..3961348aa 160000
--- a/tests/app
+++ b/tests/app
@@ -1 +1 @@
-Subproject commit 0fef0f21602989ed3aa6b301080ae406d71dd632
+Subproject commit 3961348aa322b98fff625c09d79f8d2f3cd4d6ae
|