<?php
//----------------------------------------------------------------------
// src/Services/Communication/SmsProviderTools.php
//----------------------------------------------------------------------
namespace App\Services\Communication;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Routing\RouterInterface;
use Twilio\Rest\Client as TwilioClient;
use Twilio\Exceptions\TwilioException;
use App\Entity\SocietyGroup;
use App\Entity\Communication\Sms\Sms;
use App\Entity\Communication\Sms\SmsPhoneNumber;
use App\Entity\Communication\Sms\SmsStatus;
use App\Entity\Communication\SmsProviders\SmsProvider;
use App\Entity\Communication\SmsProviders\SmsMode;
use App\Entity\Communication\SmsProviders\SmsModeStatus;
use App\Entity\Communication\SmsProviders\SmsTwilio;
use App\Entity\Communication\SmsProviders\SmsTwilioStatus;
use App\Entity\Config\Config;
use App\Services\LogTools;
use App\Services\Platform\ExternalMessageTools;
use App\Services\Security\PasswordTools;
/**
* For now all this code works under the assumption that only one SmsProvider is active.
*
* Naming conventions :
* $smsProvider can be an object of type
* SmsProvider::SmsMode
* SmsProvider::SmsTwilio
* $sms is an object of type Sms::Sms
*
* Error logging should be done with both errorlog and smsLogDebug
* $msg = "my amazing and unexpected error";
* $this->logTools->errorlog($msg);
* $this->logTools->smsLogDebug($msg, $activeSmsProvider);
*/
class SmsProviderTools
{
public function __construct(ManagerRegistry $doctrine, LogTools $logTools, PasswordTools $passwordTools, RouterInterface $router, ExternalMessageTools $externalMessageTools, string $smsModeAPIKey)
{
$this->em = $doctrine->getManager();
$this->logTools = $logTools;
$this->passwordTools = $passwordTools;
$this->externalMessageTools = $externalMessageTools;
$this->router = $router;
$this->smsModeAPIKey = $smsModeAPIKey;
$this->debug = true;
}
/**
* Is SmsMode the currently active SmsProvider ?
*
* @return boolean
*/
public function isActiveSmsMode()
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Get the active SmsProvider
if ($activeSmsProvider === null)
{
return false;
}
return $activeSmsProvider->isSmsMode();
}
/**
* Is Twilio the currently active SmsProvider ?
*
* @return boolean
*/
public function isActiveSmsTwilio()
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Get the active SmsProvider
if ($activeSmsProvider === null)
{
return false;
}
return $activeSmsProvider->isSmsTwilio();
}
/**
* Get the currently active SmsProvider
* Note : Only one SmsProvider should be active
*
* @return null|SmsProvider
*/
public function getActiveSmsProvider()
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
return $activeSmsProvider;
}
/**
* Returns the default SmsStatus depending on the active SmsProvider
* Note : Only one SmsProvider should be active
*
* @return null|SmsStatus
*/
public function getDefaultSmsStatus()
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Get the active SmsProvider
$provider = $activeSmsProvider;
if ($provider === null)
{
$msg = "No active SmsProvider";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg);
return null;
}
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: getDefaultSmsStatus] Active provider is ".$provider->displayForLog());
// Get the DefaultStatus for the active SmsProvider
$providerStatus = null;
switch ($provider->getName())
{
case SmsProvider::CODE_TWILIOSMS:
$providerStatus = $this->em->getRepository(SmsTwilioStatus::class)->findOneBy(array(
'defaultValue' => 1,
));
break;
case SmsProvider::CODE_SMSMODE:
$providerStatus = $this->em->getRepository(SmsModeStatus::class)->findOneBy(array(
'defaultValue' => 1,
));
break;
}
if ($providerStatus === null)
{
$msg = "No default status for the currently active SmsProvider";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// Based on the code of the SmsProvider's status, get the corresponding SmsStatus
$code = $providerStatus->getCode();
$status = $this->em->getRepository(SmsStatus::class)->findOneByCode($code);
if ($status === null)
{
$msg = "No SmsStatus found for code ".$code;
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: getDefaultSmsStatus] SmsProvider.DefaultStatus : ".$providerStatus->displayForLog());
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: getDefaultSmsStatus] SmsStatus : ".$status->displayForLog());
return $status;
}
/**
* Creates an object of type SmsTwilio or SmsMode
* depending on the active SmsProvider
* Note : Only one SmsProvider should be active
*
* @see \App\Entity\Communication\SmsProviders\SmsProvider for the documentation of the SMSProvider
*
* @uses \App\Services\Communication\SmsProviderTools::craftSmsTwilioProvider() to craft the SmsProvider depending on the active SmsProvider
* @uses \App\Services\Communication\SmsProviderTools::craftSmsModeProvider() to craft the SmsProvider depending on the active SmsProvider
*
* @param Sms $sms
* @return null|(SmsTwilio|SmsMode)
*/
public function craftSmsProvider(Sms $sms)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Get the active SmsProvider
$provider = $activeSmsProvider;
if ($provider === null)
{
$msg = "No active SmsProvider";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg);
return null;
}
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: craftSmsProvider] Active provider is ".$provider->displayForLog());
// Get the DefaultStatus for the active SmsProvider
$smsProvider = null;
switch ($provider->getName())
{
case SmsProvider::CODE_TWILIOSMS:
$smsProvider = $this->craftSmsTwilioProvider($sms);
break;
case SmsProvider::CODE_SMSMODE:
$smsProvider = $this->craftSmsModeProvider($sms);
break;
}
return $smsProvider;
}
/**
* Creates an object of type SmsTwilio
*
* @param Sms $sms
* @return null|SmsTwilio
*/
private function craftSmsTwilioProvider(Sms $sms)
{
$smsProvider = new SmsTwilio();
// Generate CODE for url callback
$code = $this->passwordTools->generateUniqId();
$smsProvider->setCode($code);
$smsProvider->setClient($sms->getClient());
$smsProvider->setHumanResource($sms->getHumanResource());
$smsProvider->setAuthor($sms->getAuthor());
$smsProvider->setEmitter($sms->getEmitter());
$smsProvider->setRecipient($sms->getRecipient());
$smsProvider->setSociety($sms->getSociety());
$smsProvider->setSocietyGroup($sms->getSocietyGroup());
$smsProvider->setSubject($sms->getSubject());
$smsProvider->setBody($sms->getBody());
$status = $this->em->getRepository(SmsTwilioStatus::class)->findOneByCode($sms->getStatus()->getCode());
$smsProvider->setStatus($status);
// Link the two objects
$smsProvider->setSms($sms);
$this->em->persist($smsProvider);
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: craftSmsTwilioProvider] New SmsTwilio object created");
return $smsProvider;
}
/**
* Creates an object of type SmsMode
*
* @param Sms $sms
* @return null|SmsTwilio
*/
private function craftSmsModeProvider(Sms $sms)
{
$smsProvider = new SmsMode();
$smsProvider->setClient($sms->getClient());
$smsProvider->setHumanResource($sms->getHumanResource());
$smsProvider->setAuthor($sms->getAuthor());
$smsProvider->setEmitter($sms->getEmitter());
$smsProvider->setRecipient($sms->getRecipient());
$smsProvider->setSociety($sms->getSociety());
$smsProvider->setSocietyGroup($sms->getSocietyGroup());
$smsProvider->setSubject($sms->getSubject());
$smsProvider->setBody($sms->getBody());
$status = $this->em->getRepository(SmsModeStatus::class)->findOneByCode($sms->getStatus()->getCode());
$smsProvider->setStatus($status);
// Link the two objects
$smsProvider->setSms($sms);
$this->em->persist($smsProvider);
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: craftSmsModeProvider] New SmsMode object created");
return $smsProvider;
}
/**
* Sends a sms using the active SmsProvider
* Note : Only one SmsProvider should be active
*
* @uses \App\Services\Communication\SmsProviderTools::sendSmsTwilio() depending on the active SmsProvider
* @uses \App\Services\Communication\SmsProviderTools::sendSmsMode() depending on the active SmsProvider
*
* @param SmsTwilio|SmsMode $smsProvider
* @param string $callbackUrl
* @return true|false
*/
public function sendSms($smsProvider)
{
if ($smsProvider instanceof SmsTwilio)
{
return $this->sendSmsTwilio($smsProvider);
}
if ($smsProvider instanceof SmsMode)
{
return $this->sendSmsMode($smsProvider);
}
return null;
}
/**
* Sends a sms using SmsTwilio
*
*
* @param SmsTwilio $smsProvider
* @param string $callbackUrl
* @return true|false
*/
private function sendSmsTwilio($smsProvider)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$configRepository = $this->em->getRepository(Config::class);
$twilioId = $configRepository->findOneByName(Config::TWILIO_SMS_ACCOUNT_ID);
$twilioToken = $configRepository->findOneByName(Config::TWILIO_SMS_AUTH_TOKEN);
$code = $smsProvider->getCode();
$body = $smsProvider->getBody();
$to = $smsProvider->getRecipient();
$from = $smsProvider->getEmitter();
if (in_array(null, [$twilioId, $twilioToken, $code, $body, $to, $from]))
{
return false;
}
$urlConfig = $configRepository->findOneByName(Config::URL);
if ($urlConfig === null)
{
$msg = "Config::URL not found";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$callbackUrl = $urlConfig->getValue() . $this->router->generate('icod_twilio_sms_callback', array('id' => $code));
$twilioClient = new TwilioClient($twilioId->getValue(), $twilioToken->getValue());
try
{
$message = $twilioClient->messages->create($to, array(
'from' => $from,
'body' => $body,
'statusCallback' => $callbackUrl,
));
}
catch (TwilioException $e)
{
$msg = $e->getMessage();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$twilioSid = $message->sid;
$numberSegment = $message->numSegments;
if ($twilioSid !== null)
{
$smsProvider->setTwilioSid($twilioSid);
}
if ($numberSegment !== null)
{
$smsProvider->setTwilioNumberSegment($numberSegment);
$smsProvider->getSms()->setNumberSegment($numberSegment);
}
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: sendSmsTwilio] SmsTwilio sent ".$smsProvider->displayForLog());
return true;
}
/**
* Sends a sms using SmsMode
*
* @param SmsMode $smsProvider
* @param string $callbackUrl
* @return true|false
*/
private function sendSmsMode($smsProvider, $sentDate = null)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Get required params
$body = $smsProvider->getBody();
$to = $smsProvider->getRecipient();
$from = $smsProvider->getEmitter();
$societyGroup = $smsProvider->getSocietyGroup();
if (in_array(null, [$body, $to, $from, $societyGroup]))
{
return false;
}
$configRepository = $this->em->getRepository(Config::class);
// Get the SmsMode Api URL
$url = $configRepository->findOneByName(Config::SMS_MODE_URL);
if ($url === null)
{
$msg = "Config::SMS_MODE_URL not found";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$url = $url->getValue();
// Get the Platform URL, used to craft callback url
$urlConfig = $configRepository->findOneByName(Config::URL);
if ($urlConfig === null)
{
$msg = "Config::URL not found";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$urlConfig = $urlConfig->getValue();
// Craft callback urls
$callbackUrl = $urlConfig . $this->router->generate('icod_smsmode_sms_callback');
$callbackUrlResponse = $urlConfig . $this->router->generate('icod_smsmode_sms_response');
// Get the senderDisplay for the given SocietyGroup
$senderDisplay = $this->getSmsModeSenderDisplay($societyGroup);
// Detect Encoding SMSMode
$encoding = $this->detectEncodingSmsMode($body);
// Curl json bod
$curlPostBody = array(
"recipient" => array("to" => $to), // e.164 format
//"from" => "36034", // https://ui.smsmode.com/settings/senders default sender is used if not specified here
"from" => $senderDisplay, // we can specify what we want here
"body" => array(
"text" => $body,
"encoding" => $encoding // Encoding of the message GSM7 | UNICODE - Detected with detectEncodingSmsMode algo
),
// "refClient" => "ref client : " . uniqid(),
'callbackUrlStatus' => $callbackUrl,
'callbackUrlMo' => $callbackUrlResponse,
);
// Encode the body array into Json to bes included in curl call
$curlPostBody = json_encode($curlPostBody);
// If no sent date provided, use now +30 secs. This gap can be used to unsend the SMS ?
// If it's not needed, just remove sentDate from $curlPostBody, the sms will be sent asap
if ($sentDate === null)
{
$sentDate = new \DateTime('NOW');
$sentDate->modify('+30 seconds');
}
// format provided sent date in ISO8601 without timezone
$sentDate = $sentDate->format('Y-m-d\TH:i:s');
// Disable for now
// $curlPostBody["sentDate"] = $sentDate;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPostBody);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"X-Api-Key: " . $this->smsModeAPIKey,
"Accept: application/json",
"content-Type: application/json"
));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curlResult = curl_exec($ch);
if (curl_errno($ch))
{
$msg = "curl_exec.error ".curl_error($ch);
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$result = json_decode($curlResult);
if (!$result)
{
$msg = "JSON decode failed";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
// Task plan.io #4013
// If Success, smsMode return 201 else 4xx/5xx
// Doc : https://dev.smsmode.com/sms/v1/message
$codeReturned = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($codeReturned != 201)
{
$errorMessage = $result?->message . " - " . $result?->detail;
$this->logTools->errorlog($errorMessage);
$this->logTools->smsLogDebug($errorMessage, $activeSmsProvider);
return false;
}
$messageId = $result?->messageId;
$acceptedAt = $result?->acceptedAt;
$sentTo = $result?->recipient?->to;
$from = $result?->from;
$encoding = $result?->body?->encoding;
$messagePartCount = $result?->body?->messagePartCount;
$statusValue = $result?->status?->value;
$statusDeliveryDate= $result?->status?->deliveryDate;
$rawJson = $curlResult;
$smsProvider->setRawData($curlResult);
if (!empty($messageId))
{
$smsProvider->setMessageId($messageId);
}
if (!empty($messagePartCount))
{
$smsProvider->setMessagePartCount($messagePartCount);
$smsProvider->getSms()->setNumberSegment($messagePartCount);
}
$this->logTools->sms_debug($this->debug, "[SmsProviderTools :: sendSmsMode] SmsMode sent ".$smsProvider->displayForLog());
return true;
}
/**
* @param SocietyGroup $societyGroup
* @return string
*/
public function getSmsModeSenderDisplay(SocietyGroup $societyGroup)
{
$defaultSenderDisplay = SmsMode::DEFAULT_SHORTCODE;
$senderDisplay = null;
$smsPhoneNumber = $this->em->getRepository(SmsPhoneNumber::class)->findOneBy(array(
'societyGroup' => $societyGroup,
));
if ($smsPhoneNumber !== null)
{
$senderDisplay = $smsPhoneNumber->getSenderDisplay();
if (!empty($senderDisplay))
{
return $senderDisplay;
}
}
return $defaultSenderDisplay;
}
public function detectEncodingSmsMode(string $body)
{
$gsm7 = array(
"!", '"', "#", "$", "%", "&", "'", "(", ")", ")", ")", "*", "+", ",", "-",
".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<",
"=", ">", "?", "@", "\r", "\n", " ", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
"s", "t", "u", "v", "w", "x", "y", "z", "¡", "£", "¤", "¥", "§", "¿", "Ä", "Å", "Æ", "Ç",
"É", "Ñ", "Ö", "Ø", "Ü", "ß", "à ", "ä", "å", "æ", "è", "é", "ì", "ñ", "ò", "ö", "ø", "ù",
"ü", "Γ", "Θ", "Λ", "Ξ", "Π", "Σ", "Φ", "Ψ", "Ω", "∆"
);
$gsm7Extended = array("€", "{", "|", "}", "~", "[", "]", "^", "\f");
$encoding = "GSM7";
foreach(mb_str_split($body) as $char)
{
if(!in_array($char, $gsm7) && !in_array($char, $gsm7Extended))
{
$encoding = "UNICODE";
break;
}
}
return $encoding;
}
/**
* Creates a SmsTwilioStatus|SmsModeStatus for a given value
* depending on the active SmsProvider
* Note : Only one SmsProvider should be active
*
* @uses \App\Services\Communication\SmsProviderTools::createSmsTwilioStatus() depending on the active SmsProvider
* @uses \App\Services\Communication\SmsProviderTools::createSmsModeStatus() depending on the active SmsProvider
*
* @param SmsTwilio|SmsMode $smsProvider
* @param string $value
* @return true|false
*/
public function createSmsStatus($smsProvider, $value)
{
$smsProviderStatus = null;
if ($smsProvider instanceof SmsTwilio)
{
$smsProviderStatus = $this->createSmsTwilioStatus($value);
}
if ($smsProvider instanceof SmsMode)
{
$smsProviderStatus = $this->createSmsModeStatus($value);
}
if ($smsProviderStatus === null)
{
return null;
}
$status = new SmsStatus();
$status->setValue($value);
$status->setCode($smsProviderStatus->getCode());
$this->em->persist($status);
return array(
'smsStatus' => $status,
'smsProviderStatus' => $smsProviderStatus,
);
}
/**
* Creates a SmsTwilioStatus for a given value
* Can be called from outside of the service
*
* @param string $value
* @return null|SmsTwilioStatus
*/
private function createSmsTwilioStatus($value)
{
$lastCode = $this->em
->getRepository(SmsTwilioStatus::class)
->findOneBy(
array(),
array('code' => 'DESC')
);
$code = 1;
if ($lastCode !== null)
{
$code = $lastCode->getCode() + 1;
}
$status = new SmsTwilioStatus();
$status->setStatusTwilio($value);
$status->setValue($value);
$status->setCode($code);
$this->em->persist($status);
return $status;
}
/**
* Can be called from outside of the service
* Creates a SmsModeStatus for a given value
*
* @param string $value
* @return null|SmsModeStatus
*/
private function createSmsModeStatus($value)
{
$lastCode = $this->em
->getRepository(SmsModeStatus::class)
->findOneBy(
array(),
array('code' => 'DESC')
);
$code = 1;
if ($lastCode !== null)
{
$code = $lastCode->getCode() + 1;
}
$status = new SmsModeStatus();
$status->setStatusSmsMode($value);
$status->setValue($value);
$status->setCode($code);
$this->em->persist($status);
return $status;
}
/**
* Tries to find a SmsTwilioStatus|SmsModeStatus with the given value (statusValue)
* depending on the active SmsProvider.
* If the status is not found, one is created for the given value.
* In both cases, the corresponding SmsStatus is also returned.
* Note : Only one SmsProvider should be active
*
* @uses \App\Services\Communication\SmsProviderTools::handleSmsTwilioStatus() depending on the active SmsProvider
* @uses \App\Services\Communication\SmsProviderTools::handleSmsModeStatus() depending on the active SmsProvider
*
* @param Sms $sms
* @param string $value
* @return null|array
*/
public function handleSmsStatus(Sms $sms, $statusValue)
{
$smsProvider = $sms->getProvider();
if ($smsProvider === null)
{
return null;
}
if ($smsProvider->isSmsTwilio())
{
return $this->handleSmsTwilioStatus($smsProvider, $statusValue);
}
if ($smsProvider->isSmsMode())
{
return $this->handleSmsModeStatus($smsProvider, $statusValue);
}
// if ($smsProvider instanceof SmsTwilio)
// {
// return $this->handleSmsTwilioStatus($smsProvider, $statusValue);
// }
// if ($smsProvider instanceof SmsMode)
// {
// return $this->handleSmsModeStatus($smsProvider, $statusValue);
// }
return null;
}
/**
* Tries to find a SmsTwilioStatus with the given value (statusValue).
* If the status is not found, one is created for the given value.
* In both cases, the corresponding SmsStatus is also returned.
*
* Can be called from outside of the service
*
* @param SmsProvider $smsProvider
* @param string $value
* @return null|array
*/
public function handleSmsTwilioStatus(SmsProvider $smsProvider, $statusValue)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$smsProviderStatus = $this->em
->getRepository(SmsTwilioStatus::class)
->findOneByStatusTwilio($statusValue);
if ($smsProviderStatus === null)
{
// Create unknown status
$statusData = $this->createSmsStatus($smsProvider, $statusValue);
if ($statusData === null)
{
$msg = "SmsTwilioStatus not found and creation of a new custom status failed";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$smsStatus = $statusData['smsStatus'];
$smsProviderStatus = $statusData['smsProviderStatus'];
}
else
{
$code = $smsProviderStatus->getCode();
$smsStatus = $this->em->getRepository(SmsStatus::class)->findOneByCode($code);
if ($smsStatus === null)
{
$msg = "SmsStatus not found for code $code";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
}
return array(
'smsStatus' => $smsStatus,
'smsProviderStatus' => $smsProviderStatus,
);
}
/**
* Tries to find a SmsModeStatus with the given value (statusValue).
* If the status is not found, one is created for the given value.
* In both cases, the corresponding SmsStatus is also returned.
*
* Can be called from outside of the service
*
* @param string $value
* @return null|array
*/
public function handleSmsModeStatus(SmsProvider $smsProvider, $statusValue)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$smsProviderStatus = $this->em
->getRepository(SmsModeStatus::class)
->findOneByStatusSmsMode($statusValue);
if ($smsProviderStatus === null)
{
// Create unknown status
$statusData = $this->createSmsStatus($smsProvider, $statusValue);
if ($statusData === null)
{
$msg = "SmsModeStatus not found and creation of a new custom status failed";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$smsStatus = $statusData['smsStatus'];
$smsProviderStatus = $statusData['smsProviderStatus'];
}
else
{
$code = $smsProviderStatus->getCode();
$smsStatus = $this->em->getRepository(SmsStatus::class)->findOneByCode($code);
if ($smsStatus === null)
{
$msg = "SmsStatus not found for code $code";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
}
return array(
'smsStatus' => $smsStatus,
'smsProviderStatus' => $smsProviderStatus,
);
}
/**
* Creates Sms, SmsTwilio, ExternalMessage for the given data.
* Objects are properly linked.
* In case of success returns an array containing the three objects.
*
* Called by SmsTwilioController :: smsResponse
* when someone answers to the Twilio sms they received
*
* @uses \App\Services\Platform\ExternalMessageTools::createExternalMessageForSmsChild()
*
* @param SmsTwilio $parentSmsProvider
* @param string $value
* @return null|array
*/
public function craftObjectsFromTwilioData(SmsTwilio $parentSmsProvider, $twilioData)
{
// Get the active SmsProvider
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$smsProviderTwilio = $this->em->getRepository(SmsProvider::class)->findOneByName(SmsProvider::CODE_TWILIOSMS);
if ($smsProviderTwilio === null)
{
$msg = "SmsProvider not found for name ".SmsProvider::CODE_TWILIOSMS;
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// Handle Status for both Sms and TwilioSms
$statusValue = $twilioData["SmsStatus"];
$statusData = $this->handleSmsTwilioStatus($smsProviderTwilio, $statusValue);
if ($statusData === null)
{
$msg = "SmsTwilioStatus not found and creation of a new custom status failed";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$smsStatus = $statusData['smsStatus'];
$smsProviderStatus = $statusData['smsProviderStatus'];
// Get the SmsParent
$parentSms = $parentSmsProvider->getSms();
if ($parentSms === null)
{
$msg = "ParentSms not found for parentSmsProvider ".$parentSmsProvider->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// At this point nothing can go wrong any more, start creating data
//----------------------------------------------------------------------
// PART ONE : Create the SmsTwilio
$smsProvider = new SmsTwilio();
$smsProvider->setAuthor($parentSmsProvider->getAuthor());
$smsProvider->setClient($parentSmsProvider->getClient());
$smsProvider->setSocietyGroup($parentSmsProvider->getSocietyGroup());
$smsProvider->setSociety($parentSmsProvider->getSociety());
$smsProvider->setTwilioTo($twilioData["To"]);
$smsProvider->setEmitter($twilioData["From"]);
$smsProvider->setRecipient($twilioData["To"]);
$smsProvider->setSubject($parentSmsProvider->getSubject());
$smsProvider->setBody($twilioData["Body"]);
$smsProvider->setTwilioSid($twilioData["SmsMessageSid"]);
$smsProvider->setTwilioNumberSegment($twilioData["NumSegments"]);
$smsProvider->setCallbackDate(new \DateTime());
$smsProvider->setTwilioRaw(json_encode($twilioData));
$smsProvider->setStatus($smsProviderStatus);
$uniqueCode = $this->passwordTools->generateUniqId();
$smsProvider->setCode($uniqueCode);
//----------------------------------------------------------------------
// PART TWO : Create the Sms
$sms = new Sms();
$sms->setCreationDate($smsProvider->getCreationDate());
$sms->setRecipient($smsProvider->getRecipient());
$sms->setEmitter($smsProvider->getEmitter());
$sms->setSubject($smsProvider->getSubject());
$sms->setBody($smsProvider->getBody());
$sms->setError($smsProvider->getError());
$sms->setPrice($smsProvider->getPrice());
$sms->setNumberSegment($smsProvider->getTwilioNumberSegment());
$sms->setAuthor($smsProvider->getAuthor());
$sms->setClient($smsProvider->getClient());
$sms->setHumanResource($smsProvider->getHumanResource());
$sms->setSociety($smsProvider->getSociety());
$sms->setSocietyGroup($smsProvider->getSocietyGroup());
$sms->setStatus($smsStatus);
$sms->setMission($parentSms->getMission());
// smsProviderTwilio = SmsProvider :: class -> SmsProvider::CODE_TWILIOSMS
$sms->setProvider($smsProviderTwilio);
//----------------------------------------------------------------------
// PART THREE : Link objects (part.one)
// This is needed to create the ExternalMessage
// Sms : Link the parent and child Sms
$sms->setParent($parentSms);
// SmsProvider : Link the parent and child
$smsProvider->setParent($parentSmsProvider);
// Make the link between the Sms and TwilioSms
$smsProvider->setSms($sms);
//----------------------------------------------------------------------
// PART FOUR : Create the ExternalMessage
$externalMessage = $this->externalMessageTools->createExternalMessageForSmsChild($sms);
if ($externalMessage === null)
{
// Error is logged in ExternalMessageTools
return null;
}
// At this point the ExternalMessage and the Sms are already linked (done in ExternalMessageTools)
// $externalMessage->setSms($sms);
//----------------------------------------------------------------------
// PART FIVE : Persist data
$this->em->persist($sms);
$this->em->persist($smsProvider);
return array(
'sms' => $sms,
'smsProvider' => $smsProvider,
'externalMessage' => $externalMessage,
);
}
}