mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 09:18:24 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			451-activi
			...
			dune
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cef00005c5 | |||
| 127803a94c | |||
| 2d76294c26 | |||
| 82f95d2745 | |||
| 2f4f1f2c55 | |||
|  | 068b269af9 | ||
|  | 756ed616b6 | ||
|  | 50d686f086 | 
| @@ -26,146 +26,168 @@ use Psr\Cache\CacheItemPoolInterface; | ||||
|  | ||||
| /** | ||||
|  * Helper to some task linked to phonenumber. | ||||
|  *  | ||||
|  * Currently, only Twilio is supported (https://www.twilio.com/lookup). A method  | ||||
|  * | ||||
|  * 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 | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      * @var Client  | ||||
|      * Twilio client | ||||
|      */ | ||||
|     protected $twilioClient; | ||||
|     protected Client $twilioClient; | ||||
|      | ||||
|     /** | ||||
|      * | ||||
|      * @var LoggerInterface | ||||
|      * TRUE if the client is properly configured | ||||
|      */ | ||||
|     protected $logger; | ||||
|      | ||||
|     /** | ||||
|      * | ||||
|      * @var CacheItemPoolInterface | ||||
|      */ | ||||
|     protected $cachePool; | ||||
|      | ||||
|     protected bool $isConfigured = false; | ||||
|  | ||||
|     protected LoggerInterface $logger; | ||||
|  | ||||
|     protected CacheItemPoolInterface $cachePool; | ||||
|  | ||||
|     const LOOKUP_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s'; | ||||
|     const FORMAT_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s'; | ||||
|      | ||||
|      | ||||
|  | ||||
|     public function __construct( | ||||
|         CacheItemPoolInterface $cachePool, | ||||
|         $config,  | ||||
|         $config, | ||||
|         LoggerInterface $logger | ||||
|     ) { | ||||
|         $this->logger = $logger; | ||||
|         $this->cachePool = $cachePool; | ||||
|          | ||||
|         if (\array_key_exists('twilio_sid', $config)  | ||||
|  | ||||
|         if (\array_key_exists('twilio_sid', $config) | ||||
|             && !empty($config['twilio_sid']) | ||||
|             && \array_key_exists('twilio_secret', $config)  | ||||
|             && !empty($config['twilio_secret'])) { | ||||
|              | ||||
|             && strlen($config['twilio_sid']) > 2 | ||||
|             && \array_key_exists('twilio_secret', $config) | ||||
|             && !empty($config['twilio_secret']) | ||||
|             && strlen($config['twilio_secret']) > 2 | ||||
|             ) { | ||||
|  | ||||
|             $this->twilioClient = new Client([ | ||||
|                 'auth' => [ $config['twilio_sid'], $config['twilio_secret'] ] | ||||
|             ]); | ||||
|         }  | ||||
|             $this->isConfigured = TRUE; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Return true if the validation is configured and available. | ||||
|      *  | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isPhonenumberValidationConfigured() : bool | ||||
|     { | ||||
|         return NULL !== $this->twilioClient; | ||||
|         return $this->isConfigured; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * REturn true if the phoennumber is a mobile phone. Return always false  | ||||
|      * REturn true if the phoennumber is a mobile phone. Return always true | ||||
|      * if the validation is not configured. | ||||
|      *  | ||||
|      * | ||||
|      * @param string $phonenumber | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isValidPhonenumberMobile($phonenumber) : bool | ||||
|     { | ||||
|         $validation = $this->performTwilioLookup($phonenumber); | ||||
|          | ||||
|         if (NULL === $validation) { | ||||
|             return false; | ||||
|         if (FALSE === $this->isPhonenumberValidationConfigured()) { | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         $validation = $this->performTwilioLookup($phonenumber); | ||||
|  | ||||
|         if (NULL === $validation) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return $validation === 'mobile'; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Return true if the phonenumber is a landline or voip phone.  Return always false  | ||||
|      * Return true if the phonenumber is a landline or voip phone.  Return always true | ||||
|      * if the validation is not configured. | ||||
|      *  | ||||
|      * | ||||
|      * @param string $phonenumber | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isValidPhonenumberLandOrVoip($phonenumber) : bool | ||||
|     { | ||||
|         $validation = $this->performTwilioLookup($phonenumber); | ||||
|          | ||||
|         if (NULL === $validation) { | ||||
|             return false; | ||||
|         if (FALSE === $this->isPhonenumberValidationConfigured()) { | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         $validation = $this->performTwilioLookup($phonenumber); | ||||
|  | ||||
|         if (NULL === $validation) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return \in_array($validation, [ 'landline', 'voip' ]); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Return true if the phonenumber is a landline or voip phone.  Return always false  | ||||
|      * Return true if the phonenumber is a landline or voip phone.  Return always true | ||||
|      * if the validation is not configured. | ||||
|      *  | ||||
|      * | ||||
|      * @param string $phonenumber | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isValidPhonenumberAny($phonenumber) : bool | ||||
|     { | ||||
|         if (FALSE === $this->isPhonenumberValidationConfigured()) { | ||||
|             return true; | ||||
|         } | ||||
|         $validation = $this->performTwilioLookup($phonenumber); | ||||
|          | ||||
| ; | ||||
|         if (NULL === $validation) { | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         return \in_array($validation, [ 'landline', 'voip', 'mobile' ]); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Get type (mobile, landline, ...) for phone number | ||||
|      * | ||||
|      * @param string $phonenumber | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getType(string $phonenumber): string | ||||
|     { | ||||
|         return $this->performTwilioLookup($phonenumber) ?? 'unknown'; | ||||
|     } | ||||
|  | ||||
|     public function format($phonenumber) | ||||
|     { | ||||
|         return $this->performTwilioFormat($phonenumber); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     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 " | ||||
| @@ -174,7 +196,7 @@ class PhonenumberHelper | ||||
|                 "status_code" => $response->getStatusCode(), | ||||
|                 "phonenumber" => $phonenumber | ||||
|             ]); | ||||
|              | ||||
|  | ||||
|             return $phonenumber; | ||||
|         } catch (ServerException $e) { | ||||
|             $response = $e->getResponse(); | ||||
| @@ -184,7 +206,7 @@ class PhonenumberHelper | ||||
|                 "status_code" => $response->getStatusCode(), | ||||
|                 "phonenumber" => $phonenumber | ||||
|             ]); | ||||
|              | ||||
|  | ||||
|             return null; | ||||
|         } catch (ConnectException $e) { | ||||
|             $this->logger->error("[phonenumber helper] Could not format number " | ||||
| @@ -192,38 +214,38 @@ class PhonenumberHelper | ||||
|                 "message" => $e->getMessage(), | ||||
|                 "phonenumber" => $phonenumber | ||||
|             ]); | ||||
|              | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         $format = \json_decode($response->getBody())->national_format; | ||||
|          | ||||
|  | ||||
|         $item | ||||
|             ->set($format) | ||||
|             // expires after 3d | ||||
|             ->expiresAfter(3600 * 24 * 3) | ||||
|             ; | ||||
|          | ||||
|  | ||||
|         $this->cachePool->save($item); | ||||
|          | ||||
|  | ||||
|         return $format; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     protected function performTwilioLookup($phonenumber) | ||||
|     { | ||||
|         if (FALSE === $this->isPhonenumberValidationConfigured()) { | ||||
|             return null; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         // filter only number | ||||
|         $filtered = \preg_replace("/[^0-9]/", "", $phonenumber); | ||||
|          | ||||
|  | ||||
|         $item = $this->cachePool->getItem('pnum_'.$filtered); | ||||
|          | ||||
|  | ||||
|         if ($item->isHit()) { | ||||
|             return $item->get(); | ||||
|             //return $item->get(); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         try { | ||||
|             $response = $this->twilioClient->get(sprintf(self::LOOKUP_URI, '+'.$filtered), [ | ||||
|                 'http_errors' => true, | ||||
| @@ -241,7 +263,7 @@ class PhonenumberHelper | ||||
|                 "status_code" => $response->getStatusCode(), | ||||
|                 "phonenumber" => $phonenumber | ||||
|             ]); | ||||
|              | ||||
|  | ||||
|             return null; | ||||
|         } catch (ConnectException $e) { | ||||
|             $this->logger->error("[phonenumber helper] Could not format number " | ||||
| @@ -249,20 +271,20 @@ class PhonenumberHelper | ||||
|                 "message" => $e->getMessage(), | ||||
|                 "phonenumber" => $phonenumber | ||||
|             ]); | ||||
|              | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         $validation = \json_decode($response->getBody())->carrier->type; | ||||
|          | ||||
|  | ||||
|         $item | ||||
|             ->set($validation) | ||||
|             // expires after 12h | ||||
|             ->expiresAfter(3600 * 12) | ||||
|             ; | ||||
|          | ||||
|  | ||||
|         $this->cachePool->save($item); | ||||
|          | ||||
|  | ||||
|         return $validation; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -148,7 +148,6 @@ form { | ||||
|    li { | ||||
|       label { | ||||
|          display: inline-block; | ||||
|          font-weight: normal; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|   | ||||
| @@ -51,25 +51,24 @@ class PersonController extends AbstractController | ||||
|      * @var SimilarPersonMatcher | ||||
|      */ | ||||
|     protected $similarPersonMatcher; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @var TranslatorInterface | ||||
|      */ | ||||
|     protected $translator; | ||||
|      | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @var EventDispatcherInterface | ||||
|      */ | ||||
|     protected $eventDispatcher; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @var PersonRepository; | ||||
|      */ | ||||
|     protected $personRepository; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @var ConfigPersonAltNamesHelper | ||||
| @@ -120,13 +119,13 @@ class PersonController extends AbstractController | ||||
|             throw $this->createNotFoundException("Person with id $person_id not" | ||||
|                     . " found on this server"); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person, | ||||
|                 "You are not allowed to see this person."); | ||||
|          | ||||
|  | ||||
|         $event = new PrivacyEvent($person); | ||||
|         $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); | ||||
|          | ||||
|  | ||||
|         return $this->render('ChillPersonBundle:Person:view.html.twig', | ||||
|             array( | ||||
|                 "person" => $person, | ||||
| @@ -293,7 +292,7 @@ class PersonController extends AbstractController | ||||
|             $r->setStatusCode(400); | ||||
|             return $r; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         $form = $this->createForm( | ||||
|                 //CreationPersonType::NAME, | ||||
|                 CreationPersonType::class, | ||||
| @@ -306,7 +305,7 @@ class PersonController extends AbstractController | ||||
|         $form->handleRequest($request); | ||||
|  | ||||
|         $person = $this->_bindCreationForm($form); | ||||
|          | ||||
|  | ||||
|         $errors = $this->_validatePersonAndAccompanyingPeriod($person); | ||||
|         $this->logger->info(sprintf('Person created with %d errors ', count($errors))); | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,7 @@ class Person implements HasCenterInterface | ||||
|      * @ORM\Column(type="string", length=255) | ||||
|      */ | ||||
|     private $lastName; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @var Collection | ||||
|      * | ||||
| @@ -177,6 +177,18 @@ class Person implements HasCenterInterface | ||||
|      */ | ||||
|     private $mobilenumber = ''; | ||||
|  | ||||
|     /** | ||||
|      * @var Collection | ||||
|      * | ||||
|      * @ORM\OneToMany( | ||||
|      *     targetEntity="Chill\PersonBundle\Entity\PersonPhone", | ||||
|      *     mappedBy="person", | ||||
|      *     cascade={"persist", "remove", "merge", "detach"}, | ||||
|      *     orphanRemoval=true | ||||
|      * ) | ||||
|      */ | ||||
|     private $otherPhoneNumbers; | ||||
|  | ||||
|     //TO-ADD caseOpeningDate | ||||
|     //TO-ADD nativeLanguag | ||||
|  | ||||
| @@ -248,15 +260,14 @@ class Person implements HasCenterInterface | ||||
|      * @ORM\OrderBy({"validFrom" = "DESC"}) | ||||
|      */ | ||||
|     private $addresses; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      * | ||||
|      * @ORM\Column(type="text", nullable=true) | ||||
|      */ | ||||
|     private $fullnameCanonical; | ||||
|      | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Person constructor. | ||||
|      * | ||||
| @@ -268,6 +279,7 @@ class Person implements HasCenterInterface | ||||
|         $this->spokenLanguages = new ArrayCollection(); | ||||
|         $this->addresses = new ArrayCollection(); | ||||
|         $this->altNames = new ArrayCollection(); | ||||
|         $this->otherPhoneNumbers = new ArrayCollection(); | ||||
|  | ||||
|         if ($opening === null) { | ||||
|             $opening = new \DateTime(); | ||||
| @@ -285,7 +297,7 @@ class Person implements HasCenterInterface | ||||
|         $accompanyingPeriod->setPerson($this); | ||||
|         $this->accompanyingPeriods->add($accompanyingPeriod); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param AccompanyingPeriod $accompanyingPeriod | ||||
|      */ | ||||
| @@ -476,7 +488,7 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->lastName; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -484,7 +496,7 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->altNames; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $altNames | ||||
|      * @return $this | ||||
| @@ -492,10 +504,10 @@ class Person implements HasCenterInterface | ||||
|     public function setAltNames(Collection $altNames) | ||||
|     { | ||||
|         $this->altNames = $altNames; | ||||
|          | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param PersonAltName $altName | ||||
|      * @return $this | ||||
| @@ -506,24 +518,24 @@ class Person implements HasCenterInterface | ||||
|             $this->altNames->add($altName); | ||||
|             $altName->setPerson($this); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param PersonAltName $altName | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function removeAltName(PersonAltName $altName)  | ||||
|     public function removeAltName(PersonAltName $altName) | ||||
|     { | ||||
|         if ($this->altNames->contains($altName)) { | ||||
|             $altName->setPerson(null); | ||||
|             $this->altNames->removeElement($altName); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Set birthdate | ||||
|      * | ||||
| @@ -760,7 +772,7 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->nationality; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
| @@ -863,7 +875,53 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->mobilenumber; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getOtherPhoneNumbers(): Collection | ||||
|     { | ||||
|         return $this->otherPhoneNumbers; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $otherPhoneNumbers | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setOtherPhoneNumbers(Collection $otherPhoneNumbers) | ||||
|     { | ||||
|         $this->otherPhoneNumbers = $otherPhoneNumbers; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PersonPhone $otherPhoneNumber | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function addOtherPhoneNumber(PersonPhone $otherPhoneNumber) | ||||
|     { | ||||
|         if (false === $this->otherPhoneNumbers->contains($otherPhoneNumber)) { | ||||
|             $otherPhoneNumber->setPerson($this); | ||||
|             $this->otherPhoneNumbers->add($otherPhoneNumber); | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PersonPhone $otherPhoneNumber | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function removeOtherPhoneNumber(PersonPhone $otherPhoneNumber) | ||||
|     { | ||||
|         if ($this->otherPhoneNumbers->contains($otherPhoneNumber)) { | ||||
|             $this->otherPhoneNumbers->removeElement($otherPhoneNumber); | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
| @@ -894,7 +952,7 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->spokenLanguages; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param Address $address | ||||
|      * @return $this | ||||
| @@ -905,7 +963,7 @@ class Person implements HasCenterInterface | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param Address $address | ||||
|      */ | ||||
| @@ -924,7 +982,7 @@ class Person implements HasCenterInterface | ||||
|     { | ||||
|         return $this->addresses; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * @param \DateTime|null $date | ||||
|      * @return null | ||||
|   | ||||
							
								
								
									
										115
									
								
								src/Bundle/ChillPersonBundle/Entity/PersonPhone.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/Bundle/ChillPersonBundle/Entity/PersonPhone.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\PersonBundle\Entity; | ||||
|  | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\ORM\Mapping as ORM; | ||||
|  | ||||
| /** | ||||
|  * Person Phones | ||||
|  * | ||||
|  * @ORM\Entity() | ||||
|  * @ORM\Table(name="chill_person_phone") | ||||
|  */ | ||||
| class PersonPhone | ||||
| { | ||||
|     /** | ||||
|      * @ORM\Id | ||||
|      * @ORM\Column(name="id", type="integer") | ||||
|      * @ORM\GeneratedValue(strategy="AUTO") | ||||
|      */ | ||||
|     private ?int $id; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\ManyToOne( | ||||
|      *  targetEntity="Chill\PersonBundle\Entity\Person", | ||||
|      *  inversedBy="otherPhoneNumbers" | ||||
|      * ) | ||||
|      */ | ||||
|     private Person $person; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\Column(type="text", length=40, nullable=true) | ||||
|      */ | ||||
|     private ?string $type; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\Column(type="text", length=40, nullable=false) | ||||
|      */ | ||||
|     private string $phonenumber = ''; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\Column(type="text", nullable=true) | ||||
|      */ | ||||
|     private ?string $description = null; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\Column(type="datetime", nullable=false) | ||||
|      */ | ||||
|     private \DateTime $date; | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->date = new \DateTime(); | ||||
|     } | ||||
|  | ||||
|     public function getId(): int | ||||
|     { | ||||
|         return $this->id; | ||||
|     } | ||||
|  | ||||
|     public function getPerson(): Person | ||||
|     { | ||||
|         return $this->person; | ||||
|     } | ||||
|  | ||||
|     public function setPerson(Person $person): void | ||||
|     { | ||||
|         $this->person = $person; | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return $this->type; | ||||
|     } | ||||
|  | ||||
|     public function setType(string $type): void | ||||
|     { | ||||
|         $this->type = $type; | ||||
|     } | ||||
|  | ||||
|     public function getPhonenumber(): string | ||||
|     { | ||||
|         return $this->phonenumber; | ||||
|     } | ||||
|  | ||||
|     public function setPhonenumber(string $phonenumber): void | ||||
|     { | ||||
|         $this->phonenumber = $phonenumber; | ||||
|     } | ||||
|  | ||||
|     public function getDescription(): ?string | ||||
|     { | ||||
|         return $this->description; | ||||
|     } | ||||
|  | ||||
|     public function setDescription(?string $description): void | ||||
|     { | ||||
|         $this->description = $description; | ||||
|     } | ||||
|  | ||||
|     public function getDate(): \DateTime | ||||
|     { | ||||
|         return $this->date; | ||||
|     } | ||||
|  | ||||
|     public function setDate(\DateTime $date): void | ||||
|     { | ||||
|         $this->date = $date; | ||||
|     } | ||||
|      | ||||
|     public function isEmpty(): bool | ||||
|     { | ||||
|         return empty($this->getDescription()) && empty($this->getPhonenumber()); | ||||
|     } | ||||
| } | ||||
| @@ -21,21 +21,24 @@ | ||||
|  | ||||
| namespace Chill\PersonBundle\Form; | ||||
|  | ||||
| use Chill\CustomFieldsBundle\Form\Type\CustomFieldType; | ||||
| use Chill\MainBundle\Form\Type\ChillCollectionType; | ||||
| use Chill\MainBundle\Form\Type\ChillTextareaType; | ||||
| use Chill\MainBundle\Form\Type\Select2CountryType; | ||||
| use Chill\MainBundle\Form\Type\Select2LanguageType; | ||||
| use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; | ||||
| use Chill\PersonBundle\Form\Type\GenderType; | ||||
| use Chill\PersonBundle\Form\Type\PersonAltNameType; | ||||
| use Chill\PersonBundle\Form\Type\PersonPhoneType; | ||||
| use Chill\PersonBundle\Entity\PersonPhone; | ||||
| use Chill\PersonBundle\Form\Type\Select2MaritalStatusType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| use Symfony\Component\Form\Extension\Core\Type\TextType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\DateType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\EmailType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\TelType; | ||||
| use Chill\PersonBundle\Form\Type\GenderType; | ||||
| use Chill\MainBundle\Form\Type\Select2CountryType; | ||||
| use Chill\MainBundle\Form\Type\Select2LanguageType; | ||||
| use Chill\CustomFieldsBundle\Form\Type\CustomFieldType; | ||||
| use Chill\PersonBundle\Form\Type\Select2MaritalStatusType; | ||||
| use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; | ||||
| use Chill\PersonBundle\Form\Type\PersonAltNameType; | ||||
| use Chill\MainBundle\Form\Type\ChillTextareaType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\TextType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
|  | ||||
| class PersonType extends AbstractType | ||||
| { | ||||
| @@ -48,7 +51,7 @@ class PersonType extends AbstractType | ||||
|      * @var string[] | ||||
|      */ | ||||
|     protected $config = array(); | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @var ConfigPersonAltNamesHelper | ||||
| @@ -80,13 +83,13 @@ class PersonType extends AbstractType | ||||
|             ->add('gender', GenderType::class, array( | ||||
|                 'required' => true | ||||
|             )); | ||||
|          | ||||
|  | ||||
|         if ($this->configAltNamesHelper->hasAltNames()) { | ||||
|             $builder->add('altNames', PersonAltNameType::class, [ | ||||
|                 'by_reference' => false | ||||
|             ]); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         if ($this->config['memo'] === 'visible') { | ||||
|             $builder | ||||
|                 ->add('memo', ChillTextareaType::class, array('required' => false)) | ||||
| @@ -104,11 +107,25 @@ class PersonType extends AbstractType | ||||
|         if ($this->config['phonenumber'] === 'visible') { | ||||
|             $builder->add('phonenumber', TelType::class, array('required' => false)); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         if ($this->config['mobilenumber'] === 'visible') { | ||||
|             $builder->add('mobilenumber', TelType::class, array('required' => false)); | ||||
|         } | ||||
|  | ||||
|         $builder->add('otherPhoneNumbers', ChillCollectionType::class, [ | ||||
|             'entry_type' => PersonPhoneType::class, | ||||
|             'button_add_label' => 'Add new phone', | ||||
|             'button_remove_label' => 'Remove phone', | ||||
|             'required' => false, | ||||
|             'allow_add' => true, | ||||
|             'allow_delete' => true, | ||||
|             'by_reference' => false, | ||||
|             'label' => false, | ||||
|             'delete_empty' => function(PersonPhone $pp = null) { | ||||
|                 return NULL === $pp || $pp->isEmpty(); | ||||
|             } | ||||
|         ]); | ||||
|  | ||||
|         if ($this->config['email'] === 'visible') { | ||||
|             $builder->add('email', EmailType::class, array('required' => false)); | ||||
|         } | ||||
| @@ -153,7 +170,7 @@ class PersonType extends AbstractType | ||||
|     { | ||||
|         $resolver->setDefaults(array( | ||||
|             'data_class' => 'Chill\PersonBundle\Entity\Person', | ||||
|             'validation_groups' => array('general', 'creation') | ||||
|             'validation_groups' => array('general', 'creation'), | ||||
|         )); | ||||
|  | ||||
|         $resolver->setRequired(array( | ||||
|   | ||||
							
								
								
									
										65
									
								
								src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\PersonBundle\Form\Type; | ||||
|  | ||||
| use Chill\MainBundle\Phonenumber\PhonenumberHelper; | ||||
| use Chill\PersonBundle\Entity\PersonPhone; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\TelType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\TextType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Component\Form\FormEvent; | ||||
| use Symfony\Component\Form\FormEvents; | ||||
| use Symfony\Component\Form\FormInterface; | ||||
| use Symfony\Component\Form\FormView; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
|  | ||||
| class PersonPhoneType extends AbstractType | ||||
| { | ||||
|     private PhonenumberHelper $phonenumberHelper; | ||||
|  | ||||
|     private EntityManagerInterface $em; | ||||
|  | ||||
|     public function __construct(PhonenumberHelper $phonenumberHelper, EntityManagerInterface $em) | ||||
|     { | ||||
|         $this->phonenumberHelper = $phonenumberHelper; | ||||
|         $this->em = $em; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder, array $options) | ||||
|     { | ||||
|         $builder->add('phonenumber', TelType::class, [ | ||||
|             'label' => 'Other phonenumber', | ||||
|             'required' => true, | ||||
|         ]); | ||||
|  | ||||
|         $builder->add('description', TextType::class, [ | ||||
|             'required' => false, | ||||
|         ]); | ||||
|  | ||||
|         $builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) { | ||||
|             if (NULL === $event->getData()) { | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             $oldPersonPhone = $this->em->getUnitOfWork() | ||||
|                 ->getOriginalEntityData($event->getData()); | ||||
|  | ||||
|             if ($oldPersonPhone['phonenumber'] ?? null !== $event->getForm()->getData()->getPhonenumber()) { | ||||
|                 $type = $this->phonenumberHelper->getType($event->getData()->getPhonenumber()); | ||||
|                 $event->getData()->setType($type); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $resolver | ||||
|             ->setDefaults([ | ||||
|                 'data_class' => PersonPhone::class, | ||||
|                 'validation_groups' => ['general', 'creation'], | ||||
|             ]) | ||||
|         ; | ||||
|     } | ||||
| } | ||||
| @@ -83,6 +83,9 @@ | ||||
|     {%- if form.mobilenumber is defined -%} | ||||
|     {{ form_row(form.mobilenumber, {'label': 'Mobilenumber'}) }} | ||||
|     {%- endif -%} | ||||
|     {%- if form.otherPhoneNumbers is defined -%} | ||||
|         {{ form_widget(form.otherPhoneNumbers) }} | ||||
|     {%- endif -%} | ||||
|     {%- if form.contactInfo is defined -%} | ||||
|     {{ form_row(form.contactInfo, {'label': 'Notes on contact information'}) }} | ||||
|     {%- endif -%} | ||||
|   | ||||
| @@ -227,6 +227,17 @@ This view should receive those arguments: | ||||
|                 <dd>{% if person.mobilenumber is not empty %}<a href="tel:{{ person.mobilenumber }}"><pre>{{ person.mobilenumber|chill_format_phonenumber }}</pre></a>{% else %}<span class="chill-no-data-statement">{{ 'No data given'|trans }}{% endif %}</dd> | ||||
|             </dl> | ||||
|             {% endif %} | ||||
|             {% for pp in person.otherPhoneNumbers %} | ||||
|                 <dt>{{ 'Other phonenumber'|trans }} :</dt> | ||||
|                 <dd> | ||||
|                     <a href="tel:{{ pp.phoneNumber }}"><pre>{{ pp.phoneNumber|chill_format_phonenumber }}</pre></a> | ||||
|                     {% if pp.description is not empty %} | ||||
|                     <blockquote class="chill-user-quote"> | ||||
|                     {{ pp.description|nl2br }} | ||||
|                     {% endif %} | ||||
|                     </blockquote> | ||||
|                 </dd> | ||||
|             {% endfor %} | ||||
|             {%- if chill_person.fields.contact_info == 'visible' -%} | ||||
|             <dl> | ||||
|                 <dt>{{ 'Notes on contact information'|trans }} :</dt> | ||||
|   | ||||
| @@ -22,7 +22,7 @@ services: | ||||
|             $closingMotiveRepository: '@Chill\PersonBundle\Repository\ClosingMotiveRepository' | ||||
|         tags: | ||||
|             - { name: form.type, alias: closing_motive } | ||||
|              | ||||
|  | ||||
|     Chill\PersonBundle\Form\AccompanyingPeriodType: | ||||
|         arguments: | ||||
|             $config: "%chill_person.accompanying_period_fields%" | ||||
| @@ -39,10 +39,17 @@ services: | ||||
|             - '@Symfony\Component\Translation\TranslatorInterface' | ||||
|         tags: | ||||
|             - { name: form.type } | ||||
|              | ||||
|  | ||||
|     Chill\PersonBundle\Form\Type\PersonAltNameType: | ||||
|         arguments: | ||||
|             $configHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper' | ||||
|             $translatableStringHelper: '@chill.main.helper.translatable_string' | ||||
|         tags: | ||||
|             - { name: form.type } | ||||
|  | ||||
|     Chill\PersonBundle\Form\Type\PersonPhoneType: | ||||
|         arguments: | ||||
|             $phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper' | ||||
|             $em: '@Doctrine\ORM\EntityManagerInterface' | ||||
|         tags: | ||||
|             - { name: form.type } | ||||
|   | ||||
| @@ -51,8 +51,9 @@ Chill\PersonBundle\Entity\Person: | ||||
|              - Chill\MainBundle\Validation\Constraint\PhonenumberConstraint: | ||||
|                   type: mobile | ||||
|                   groups: [ general, creation ] | ||||
|  | ||||
|  | ||||
|         otherPhoneNumbers: | ||||
|             -   Valid: | ||||
|                     traverse: true | ||||
|     constraints: | ||||
|           - Callback: | ||||
|                   callback: isAccompanyingPeriodValid | ||||
| @@ -77,3 +78,14 @@ Chill\PersonBundle\Entity\AccompanyingPeriod: | ||||
|     constraints: | ||||
|           - Callback: | ||||
|               callback: isDateConsistent | ||||
|  | ||||
| Chill\PersonBundle\Entity\PersonPhone: | ||||
|     properties: | ||||
|         phonenumber: | ||||
|             - Regex: | ||||
|                 pattern: '/^([\+{1}])([0-9\s*]{4,20})$/' | ||||
|                 groups: [ general, creation ] | ||||
|                 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 | ||||
|                 groups: [ general, creation ] | ||||
|   | ||||
| @@ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\Migrations\Person; | ||||
|  | ||||
| use Doctrine\DBAL\Schema\Schema; | ||||
| use Doctrine\Migrations\AbstractMigration; | ||||
|  | ||||
| /** | ||||
|  * Auto-generated Migration: Please modify to your needs! | ||||
|  */ | ||||
| final class Version20210318095831 extends AbstractMigration | ||||
| { | ||||
|     public function getDescription() : string | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     public function up(Schema $schema) : void | ||||
|     { | ||||
|         // this up() migration is auto-generated, please modify it to your needs | ||||
|  | ||||
|         $this->addSql('CREATE SEQUENCE chill_person_phone_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); | ||||
|         $this->addSql('CREATE TABLE chill_person_phone (id INT NOT NULL, person_id INT DEFAULT NULL, phonenumber TEXT NOT NULL, description TEXT DEFAULT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))'); | ||||
|         $this->addSql('CREATE INDEX IDX_72C1F87217BBB47 ON chill_person_phone (person_id)'); | ||||
|         $this->addSql('ALTER TABLE chill_person_phone ADD CONSTRAINT FK_72C1F87217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); | ||||
|     } | ||||
|  | ||||
|     public function down(Schema $schema) : void | ||||
|     { | ||||
|         // this down() migration is auto-generated, please modify it to your needs | ||||
|         $this->addSql('DROP SEQUENCE chill_person_phone_id_seq CASCADE'); | ||||
|         $this->addSql('DROP TABLE chill_person_phone'); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\Migrations\Person; | ||||
|  | ||||
| use Doctrine\DBAL\Schema\Schema; | ||||
| use Doctrine\Migrations\AbstractMigration; | ||||
|  | ||||
| /** | ||||
|  * Auto-generated Migration: Please modify to your needs! | ||||
|  */ | ||||
| final class Version20210325141540 extends AbstractMigration | ||||
| { | ||||
|     public function getDescription() : string | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     public function up(Schema $schema) : void | ||||
|     { | ||||
|         // this up() migration is auto-generated, please modify it to your needs | ||||
|         $this->addSql('ALTER TABLE chill_person_phone ADD type TEXT DEFAULT NULL'); | ||||
|     } | ||||
|  | ||||
|     public function down(Schema $schema) : void | ||||
|     { | ||||
|         // this down() migration is auto-generated, please modify it to your need | ||||
|         $this->addSql('ALTER TABLE chill_person_phone DROP type'); | ||||
|     } | ||||
| } | ||||
| @@ -40,6 +40,10 @@ Phonenumber: 'Numéro de téléphone' | ||||
| phonenumber: numéro de téléphone | ||||
| Mobilenumber: 'Numéro de téléphone portable' | ||||
| mobilenumber: numéro de téléphone portable | ||||
| Other phonenumber: Autre numéro de téléphone | ||||
| Description: description | ||||
| Add new phone: Ajouter un numéro de téléphone | ||||
| Remove phone: Supprimer | ||||
| 'Notes on contact information': 'Remarques sur les informations de contact' | ||||
| 'Remarks': 'Remarques' | ||||
| '{0} Born the %date% | {1} Born the %date%': '{0} Né le %date% | {1} Née le %date%' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user