Compare commits
13 Commits
fd1e7b5519
...
85b64ada1a
Author | SHA1 | Date |
---|---|---|
osaajani | 85b64ada1a | |
osaajani | f9e64aee65 | |
osaajani | 59d3e28489 | |
osaajani | fdbc6a0878 | |
osaajani | 4f0c585f78 | |
osaajani | 55fe91619b | |
osaajani | 47b81c1af3 | |
osaajani | 715afd79ec | |
osaajani | 9b7907ad18 | |
osaajani | 69619d0bef | |
osaajani | 6353d5115b | |
osaajani | fb58802240 | |
osaajani | 298bba0c39 |
|
@ -119,9 +119,9 @@ interface AdapterInterface
|
|||
* @param array $medias : Array of medias to link to the MMS, [['http_url' => HTTP public url of the media et 'local_uri' => local uri to media file]]
|
||||
*
|
||||
* @return array : [
|
||||
* bool 'error' => false if no error, true else
|
||||
* ?string 'error_message' => null if no error, else error message
|
||||
* array 'uid' => Uid of the sms created on success
|
||||
* bool 'error' => false if no error, true else,
|
||||
* ?string 'error_message' => null if no error, else error message,
|
||||
* array 'uid' => Uid of the sms created on success,
|
||||
* ]
|
||||
*/
|
||||
public function send(string $destination, string $text, bool $flash = false, bool $mms = false, array $medias = []): array;
|
||||
|
|
|
@ -311,7 +311,8 @@ footer img
|
|||
}
|
||||
|
||||
/* SCHEDULEDS */
|
||||
.add-number-button
|
||||
.add-number-button,
|
||||
.add-phone-limit-button
|
||||
{
|
||||
display: inline-block;
|
||||
color: #DADFE1;
|
||||
|
@ -319,7 +320,8 @@ footer img
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
.add-number-button:hover
|
||||
.add-number-button:hover,
|
||||
.add-phone-limit-button:hover
|
||||
{
|
||||
color: #3498DB;
|
||||
cursor: pointer;
|
||||
|
@ -373,7 +375,8 @@ footer img
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.scheduleds-number-groupe
|
||||
.scheduleds-number-groupe,
|
||||
.phone-limits-group
|
||||
{
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
|
@ -383,7 +386,8 @@ footer img
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.scheduleds-number-groupe-remove
|
||||
.scheduleds-number-groupe-remove,
|
||||
.phone-limits-group-remove
|
||||
{
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
|
@ -391,7 +395,8 @@ footer img
|
|||
color: #888;
|
||||
}
|
||||
|
||||
.scheduleds-number-groupe-remove:hover
|
||||
.scheduleds-number-groupe-remove:hover,
|
||||
.phone-limits-group-remove:hover
|
||||
{
|
||||
color: #555;
|
||||
}
|
||||
|
@ -466,6 +471,16 @@ footer img
|
|||
color: #9b2420;
|
||||
}
|
||||
|
||||
/* PREVIEW CONTACT */
|
||||
.preview-contact-name
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.preview-contact-number
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* PHONE */
|
||||
#adapter-data-container
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
"symfony/yaml": "^5.0",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"xantios/mimey": ">=2.1",
|
||||
"kreait/firebase-php": "^5.14"
|
||||
},
|
||||
"require-dev": {
|
||||
"kreait/firebase-php": "^5.14",
|
||||
"benmorel/gsm-charset-converter": "^0.3.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,21 +73,6 @@ namespace controllers\internals;
|
|||
return $this->get_model()->insert($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets events for a type, since a date and eventually until a date (both included).
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param string $type : Event type we want
|
||||
* @param \DateTime $since : Date to get events since
|
||||
* @param ?\DateTime $until (optional) : Date until wich we want events, if not specified no limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_events_by_type_and_date_for_user(int $id_user, string $type, \DateTime $since, ?\DateTime $until = null)
|
||||
{
|
||||
$this->get_model()->get_events_by_type_and_date_for_user($id_user, $type, $since, $until);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model for the Controller.
|
||||
*/
|
||||
|
|
|
@ -44,11 +44,6 @@ class ExpressionProvider implements ExpressionFunctionProviderInterface
|
|||
return sprintf('isset(%1$s) && is_a(%1$s, \'DateTime\') && %1$s->format(\'m-d\') == (new \\DateTime())->format(\'m-d\')', $birthdate);
|
||||
}, function ($arguments, DateTime $birthdate)
|
||||
{
|
||||
if (!($birthdate ?? false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $birthdate->format('m-d') == (new DateTime())->format('m-d');
|
||||
});
|
||||
|
||||
|
|
|
@ -44,15 +44,15 @@ namespace controllers\internals;
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a phone by his name.
|
||||
* Return a list of phone limits
|
||||
*
|
||||
* @param string $name : Phone name
|
||||
* @param int $id_phone : Phone id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_by_name(string $name)
|
||||
public function get_limits(int $id_phone)
|
||||
{
|
||||
return $this->get_model()->get_by_name($name);
|
||||
return $this->get_model()->get_limits($id_phone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,19 +137,46 @@ namespace controllers\internals;
|
|||
* @param string $name : The name of the phone
|
||||
* @param string $adapter : The adapter to use the phone
|
||||
* @param string json $adapter_data : A JSON string representing adapter's data (for example credentials for an api)
|
||||
* @param int $priority : Priority with which to use phone to send SMS. Default 0.
|
||||
* @param array $limits : An array of limits for this phone. Each limit must be an array with a key volume and a key startpoint
|
||||
*
|
||||
* @return bool|int : false on error, new id on success
|
||||
*/
|
||||
public function create(int $id_user, string $name, string $adapter, string $adapter_data)
|
||||
public function create(int $id_user, string $name, string $adapter, string $adapter_data, int $priority = 0, array $limits = [])
|
||||
{
|
||||
$phone = [
|
||||
'id_user' => $id_user,
|
||||
'name' => $name,
|
||||
'priority' => $priority,
|
||||
'adapter' => $adapter,
|
||||
'adapter_data' => $adapter_data,
|
||||
];
|
||||
|
||||
return $this->get_model()->insert($phone);
|
||||
//Use transaction to garanty atomicity
|
||||
$this->bdd->beginTransaction();
|
||||
|
||||
$new_phone_id = $this->get_model()->insert($phone);
|
||||
if (!$new_phone_id)
|
||||
{
|
||||
$this->bdd->rollBack();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$limit_id = $this->get_model()->insert_phone_limit($new_phone_id, $limit['volume'], $limit['startpoint']);
|
||||
|
||||
if (!$limit_id)
|
||||
{
|
||||
$this->bdd->rollBack();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$success = $this->bdd->commit();
|
||||
return ($success ? $new_phone_id : false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,20 +186,54 @@ namespace controllers\internals;
|
|||
* @param int $id : Phone id
|
||||
* @param string $name : The name of the phone
|
||||
* @param string $adapter : The adapter to use the phone
|
||||
* @param array $adapter_data : An array of the data of the adapter (for example credentials for an api)
|
||||
* @param string json $adapter_data : A JSON string representing adapter's data (for example credentials for an api)
|
||||
* @param int $priority : Priority with which to use phone to send SMS. Default 0.
|
||||
* @param array $limits : An array of limits for this phone. Each limit must be an array with a key volume and a key startpoint
|
||||
*
|
||||
* @return bool : false on error, true on success
|
||||
*/
|
||||
public function update_for_user(int $id_user, int $id, string $name, string $adapter, array $adapter_data): bool
|
||||
public function update_for_user(int $id_user, int $id, string $name, string $adapter, string $adapter_data, int $priority = 0, array $limits = []): bool
|
||||
{
|
||||
$phone = [
|
||||
'id_user' => $id_user,
|
||||
'name' => $name,
|
||||
'adapter' => $adapter,
|
||||
'adapter_data' => json_encode($adapter_data),
|
||||
'adapter_data' => $adapter_data,
|
||||
'priority' => $priority,
|
||||
];
|
||||
|
||||
return (bool) $this->get_model()->update_for_user($id_user, $id, $phone);
|
||||
//Use transaction to garanty atomicity
|
||||
$this->bdd->beginTransaction();
|
||||
|
||||
$nb_delete = $this->get_model()->delete_phone_limits($id);
|
||||
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$limit_id = $this->get_model()->insert_phone_limit($id, $limit['volume'], $limit['startpoint']);
|
||||
|
||||
if (!$limit_id)
|
||||
{
|
||||
$this->bdd->rollBack();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$nb_update = $this->get_model()->update_for_user($id_user, $id, $phone);
|
||||
|
||||
$success = $this->bdd->commit();
|
||||
|
||||
if (!$success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($nb_update == 0 && count($limits) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -274,236 +274,6 @@ use Monolog\Logger;
|
|||
return $this->get_model()->gets_after_date_for_number_and_user($id_user, $date, $number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all messages to send and the number to use to send theme.
|
||||
*
|
||||
* @return array : List of smss to send at this time per scheduled id ['1' => [['id_scheduled', 'text', 'id_phone', 'destination', 'flash', 'mms', 'medias'], ...], ...]
|
||||
*/
|
||||
public function get_smss_to_send()
|
||||
{
|
||||
$smss_to_send_per_scheduled = [];
|
||||
|
||||
$internal_templating = new \controllers\internals\Templating();
|
||||
$internal_setting = new \controllers\internals\Setting($this->bdd);
|
||||
$internal_group = new \controllers\internals\Group($this->bdd);
|
||||
$internal_conditional_group = new \controllers\internals\ConditionalGroup($this->bdd);
|
||||
$internal_phone = new \controllers\internals\Phone($this->bdd);
|
||||
$internal_smsstop = new \controllers\internals\SmsStop($this->bdd);
|
||||
|
||||
$users_smsstops = [];
|
||||
$users_settings = [];
|
||||
$users_phones = [];
|
||||
$users_mms_phones = [];
|
||||
|
||||
$now = new \DateTime();
|
||||
$now = $now->format('Y-m-d H:i:s');
|
||||
$scheduleds = $this->get_model()->gets_before_date($now);
|
||||
foreach ($scheduleds as $scheduled)
|
||||
{
|
||||
$smss_to_send_per_scheduled[$scheduled['id']] = [];
|
||||
|
||||
if (!isset($users_settings[$scheduled['id_user']]))
|
||||
{
|
||||
$users_settings[$scheduled['id_user']] = [];
|
||||
|
||||
$settings = $internal_setting->gets_for_user($scheduled['id_user']);
|
||||
foreach ($settings as $name => $value)
|
||||
{
|
||||
$users_settings[$scheduled['id_user']][$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($users_smsstops[$scheduled['id_user']]) && $users_settings[$scheduled['id_user']]['smsstop'])
|
||||
{
|
||||
$users_smsstops[$scheduled['id_user']] = [];
|
||||
|
||||
$smsstops = $internal_smsstop->gets_for_user($scheduled['id_user']);
|
||||
foreach ($smsstops as $smsstop)
|
||||
{
|
||||
$users_smsstops[$scheduled['id_user']][] = $smsstop['number'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($users_phones[$scheduled['id_user']]))
|
||||
{
|
||||
$phones = $internal_phone->gets_for_user($scheduled['id_user']);
|
||||
$mms_phones = $internal_phone->gets_phone_supporting_mms_for_user($scheduled['id_user'], $internal_phone::MMS_SENDING);
|
||||
$users_phones[$scheduled['id_user']] = $phones ?: [];
|
||||
$users_mms_phones[$scheduled['id_user']] = $mms_phones ?: [];
|
||||
}
|
||||
|
||||
//Add medias to mms
|
||||
$scheduled['medias'] = [];
|
||||
if ($scheduled['mms'])
|
||||
{
|
||||
$internal_media = new Media($this->bdd);
|
||||
$scheduled['medias'] = $internal_media->gets_for_scheduled($scheduled['id']);
|
||||
}
|
||||
|
||||
$phone_to_use = null;
|
||||
foreach ($users_phones[$scheduled['id_user']] as $phone)
|
||||
{
|
||||
if ($phone['id'] !== $scheduled['id_phone'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$phone_to_use = $phone;
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
//Add messages for numbers
|
||||
$numbers = $this->get_numbers($scheduled['id']);
|
||||
foreach ($numbers as $number)
|
||||
{
|
||||
if (null === $phone_to_use)
|
||||
{
|
||||
if ($scheduled['mms'] && count($users_mms_phones))
|
||||
{
|
||||
$rnd_key = array_rand($users_mms_phones[$scheduled['id_user']]);
|
||||
$random_phone = $users_mms_phones[$scheduled['id_user']][$rnd_key];
|
||||
}
|
||||
else
|
||||
{
|
||||
$rnd_key = array_rand($users_phones[$scheduled['id_user']]);
|
||||
$random_phone = $users_phones[$scheduled['id_user']][$rnd_key];
|
||||
}
|
||||
}
|
||||
|
||||
$message = [
|
||||
'id_user' => $scheduled['id_user'],
|
||||
'id_scheduled' => $scheduled['id'],
|
||||
'id_phone' => $phone_to_use['id'] ?? $random_phone['id'],
|
||||
'destination' => $number['number'],
|
||||
'flash' => $scheduled['flash'],
|
||||
'mms' => $scheduled['mms'],
|
||||
'medias' => $scheduled['medias'],
|
||||
];
|
||||
|
||||
if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
|
||||
{
|
||||
$number['data'] = json_decode($number['data'] ?? '[]', true);
|
||||
|
||||
$metas = ['number' => $number['number']];
|
||||
$data = ['contact' => $number['data'], 'contact_metas' => $metas];
|
||||
|
||||
$render = $internal_templating->render($scheduled['text'], $data);
|
||||
|
||||
if (!$render['success'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$message['text'] = $render['result'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$message['text'] = $scheduled['text'];
|
||||
}
|
||||
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
//Add messages for contacts
|
||||
$contacts = $this->get_contacts($scheduled['id']);
|
||||
|
||||
$groups = $this->get_groups($scheduled['id']);
|
||||
foreach ($groups as $group)
|
||||
{
|
||||
$contacts_to_add = $internal_group->get_contacts($group['id']);
|
||||
$contacts = array_merge($contacts, $contacts_to_add);
|
||||
}
|
||||
|
||||
$conditional_groups = $this->get_conditional_groups($scheduled['id']);
|
||||
foreach ($conditional_groups as $conditional_group)
|
||||
{
|
||||
$contacts_to_add = $internal_conditional_group->get_contacts_for_condition_and_user($scheduled['id_user'], $conditional_group['condition']);
|
||||
$contacts = array_merge($contacts, $contacts_to_add);
|
||||
}
|
||||
|
||||
$added_contacts = [];
|
||||
foreach ($contacts as $contact)
|
||||
{
|
||||
if ($added_contacts[$contact['id']] ?? false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$added_contacts[$contact['id']] = true;
|
||||
|
||||
if (null === $phone_to_use)
|
||||
{
|
||||
if ($scheduled['mms'] && count($users_mms_phones))
|
||||
{
|
||||
$rnd_key = array_rand($users_mms_phones[$scheduled['id_user']]);
|
||||
$random_phone = $users_mms_phones[$scheduled['id_user']][$rnd_key];
|
||||
}
|
||||
else
|
||||
{
|
||||
$rnd_key = array_rand($users_phones[$scheduled['id_user']]);
|
||||
$random_phone = $users_phones[$scheduled['id_user']][$rnd_key];
|
||||
}
|
||||
}
|
||||
|
||||
$message = [
|
||||
'id_user' => $scheduled['id_user'],
|
||||
'id_scheduled' => $scheduled['id'],
|
||||
'id_phone' => $phone_to_use['id'] ?? $random_phone['id'],
|
||||
'destination' => $contact['number'],
|
||||
'flash' => $scheduled['flash'],
|
||||
'mms' => $scheduled['mms'],
|
||||
'medias' => $scheduled['medias'],
|
||||
];
|
||||
|
||||
if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
|
||||
{
|
||||
$contact['data'] = json_decode($contact['data'], true);
|
||||
|
||||
//Add metas of contact by adding contact without data
|
||||
$metas = $contact;
|
||||
unset($metas['data'], $metas['id_user']);
|
||||
|
||||
$data = ['contact' => $contact['data'], 'contact_metas' => $metas];
|
||||
|
||||
$render = $internal_templating->render($scheduled['text'], $data);
|
||||
|
||||
if (!$render['success'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$message['text'] = $render['result'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$message['text'] = $scheduled['text'];
|
||||
}
|
||||
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
foreach ($messages as $message)
|
||||
{
|
||||
//Remove empty messages
|
||||
if ('' === trim($message['text']) && !$message['medias'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//Remove messages to smsstops numbers
|
||||
if (($users_smsstops[$scheduled['id_user']] ?? false) && in_array($message['destination'], $users_smsstops[$scheduled['id_user']]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$smss_to_send_per_scheduled[$scheduled['id']][] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
return $smss_to_send_per_scheduled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a CSV file of numbers, potentially associated with datas.
|
||||
*
|
||||
|
@ -627,4 +397,292 @@ use Monolog\Logger;
|
|||
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all messages to send and the number to use to send theme.
|
||||
*
|
||||
* @return array : List of smss to send at this time per scheduled id ['1' => [['id_scheduled', 'text', 'id_phone', 'destination', 'flash', 'mms', 'medias'], ...], ...]
|
||||
*/
|
||||
public function get_smss_to_send()
|
||||
{
|
||||
$sms_per_scheduled = [];
|
||||
|
||||
$internal_templating = new \controllers\internals\Templating();
|
||||
$internal_setting = new \controllers\internals\Setting($this->bdd);
|
||||
$internal_group = new \controllers\internals\Group($this->bdd);
|
||||
$internal_conditional_group = new \controllers\internals\ConditionalGroup($this->bdd);
|
||||
$internal_phone = new \controllers\internals\Phone($this->bdd);
|
||||
$internal_smsstop = new \controllers\internals\SmsStop($this->bdd);
|
||||
$internal_sended = new \controllers\internals\Sended($this->bdd);
|
||||
|
||||
$users_smsstops = [];
|
||||
$users_settings = [];
|
||||
$users_phones = [];
|
||||
$users_mms_phones = [];
|
||||
|
||||
$now = new \DateTime();
|
||||
$now = $now->format('Y-m-d H:i:s');
|
||||
$scheduleds = $this->get_model()->gets_before_date($now);
|
||||
foreach ($scheduleds as $scheduled)
|
||||
{
|
||||
$id_scheduled = $scheduled['id'];
|
||||
$id_user = $scheduled['id_user'];
|
||||
|
||||
$sms_per_scheduled[$id_scheduled] = [];
|
||||
|
||||
// Forge cache of data about users, sms stops, phones, etc.
|
||||
if (!isset($users_settings[$id_user]))
|
||||
{
|
||||
$users_settings[$id_user] = [];
|
||||
|
||||
$settings = $internal_setting->gets_for_user($id_user);
|
||||
foreach ($settings as $name => $value)
|
||||
{
|
||||
$users_settings[$id_user][$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($users_smsstops[$id_user]) && $users_settings[$id_user]['smsstop'])
|
||||
{
|
||||
$users_smsstops[$id_user] = [];
|
||||
|
||||
$smsstops = $internal_smsstop->gets_for_user($id_user);
|
||||
foreach ($smsstops as $smsstop)
|
||||
{
|
||||
$users_smsstops[$id_user][] = $smsstop['number'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($users_phones[$id_user]))
|
||||
{
|
||||
$users_phones[$id_user] = [];
|
||||
$users_mms_phones[$id_user] = [];
|
||||
|
||||
$phones = $internal_phone->gets_for_user($id_user);
|
||||
foreach ($phones as &$phone)
|
||||
{
|
||||
$limits = $internal_phone->get_limits($phone['id']);
|
||||
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $internal_sended->count_since_for_phone_and_user($id_user, $phone['id'], $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
|
||||
$phone['remaining_volume'] = $remaining_volume;
|
||||
$users_phones[$id_user][$phone['id']] = $phone;
|
||||
}
|
||||
|
||||
$mms_phones = $internal_phone->gets_phone_supporting_mms_for_user($id_user, $internal_phone::MMS_SENDING);
|
||||
foreach ($mms_phones as &$mms_phone)
|
||||
{
|
||||
$limits = $internal_phone->get_limits($mms_phone['id']);
|
||||
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $internal_sended->count_since_for_phone_and_user($id_user, $mms_phone['id'], $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
|
||||
$mms_phone['remaining_volume'] = $remaining_volume;
|
||||
$users_mms_phones[$id_user][$mms_phone['id']] = $mms_phone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Add medias to mms
|
||||
$scheduled['medias'] = [];
|
||||
if ($scheduled['mms'])
|
||||
{
|
||||
$internal_media = new Media($this->bdd);
|
||||
$scheduled['medias'] = $internal_media->gets_for_scheduled($id_scheduled);
|
||||
}
|
||||
|
||||
$phone_to_use = null;
|
||||
if ($scheduled['id_phone'])
|
||||
{
|
||||
$phone_to_use = $users_phones[$id_user][$scheduled['id_phone']] ?? null;
|
||||
}
|
||||
|
||||
|
||||
// We turn all contacts, groups and conditional groups into just contacts
|
||||
$contacts = $this->get_contacts($id_scheduled);
|
||||
|
||||
$groups = $this->get_groups($id_scheduled);
|
||||
foreach ($groups as $group)
|
||||
{
|
||||
$contacts_to_add = $internal_group->get_contacts($group['id']);
|
||||
$contacts = array_merge($contacts, $contacts_to_add);
|
||||
}
|
||||
|
||||
$conditional_groups = $this->get_conditional_groups($id_scheduled);
|
||||
foreach ($conditional_groups as $conditional_group)
|
||||
{
|
||||
$contacts_to_add = $internal_conditional_group->get_contacts_for_condition_and_user($id_user, $conditional_group['condition']);
|
||||
$contacts = array_merge($contacts, $contacts_to_add);
|
||||
}
|
||||
|
||||
|
||||
// We turn all numbers and contacts into simple targets with number, data and meta so we can forge all messages from onlye one data source
|
||||
$targets = [];
|
||||
|
||||
$numbers = $this->get_numbers($id_scheduled);
|
||||
foreach ($numbers as $number)
|
||||
{
|
||||
$metas = ['number' => $number['number']];
|
||||
$targets[] = [
|
||||
'number' => $number['number'],
|
||||
'data' => $number['data'],
|
||||
'metas' => $metas,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($contacts as $contact)
|
||||
{
|
||||
$metas = $contact;
|
||||
unset($metas['data'], $metas['id_user']);
|
||||
|
||||
$targets[] = [
|
||||
'number' => $contact['number'],
|
||||
'data' => $contact['data'],
|
||||
'metas' => $metas,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// Pass on all targets to deduplicate destinations, remove number in sms stops, etc.
|
||||
$used_destinations = [];
|
||||
foreach ($targets as $key => $target)
|
||||
{
|
||||
if (in_array($target['number'], $used_destinations))
|
||||
{
|
||||
unset($targets[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Remove messages to smsstops numbers
|
||||
if (($users_smsstops[$id_user] ?? false) && in_array($target['number'], $users_smsstops[$id_user]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$used_destinations[] = $target['number'];
|
||||
}
|
||||
|
||||
|
||||
// Finally, we forge all messages and select phone to use
|
||||
foreach ($targets as $target)
|
||||
{
|
||||
// Forge message if templating enable
|
||||
$text = $scheduled['text'];
|
||||
if ((int) ($users_settings[$id_user]['templating'] ?? false)) // Cast to int because it is more reliable than bool on strings
|
||||
{
|
||||
$target['data'] = json_decode($target['data'], true);
|
||||
$data = ['contact' => $target['data'], 'contact_metas' => $target['metas']];
|
||||
|
||||
$render = $internal_templating->render($scheduled['text'], $data);
|
||||
|
||||
if (!$render['success'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = $render['result'];
|
||||
}
|
||||
|
||||
// Ignore empty messages
|
||||
if ('' === trim($text) && !$scheduled['medias'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we must force GSM 7 alphabet
|
||||
if ((int) ($users_settings[$id_user]['force_gsm_alphabet'] ?? false))
|
||||
{
|
||||
$text = Tool::convert_to_gsm0338($text);
|
||||
}
|
||||
|
||||
/*
|
||||
Choose phone if no phone defined for message
|
||||
Phones are choosen using type, priority and remaining volume :
|
||||
1 - If sms is a mms, try to use mms phone if any available. If mms phone available use mms phone, else use default.
|
||||
2 - In group of phones, keep only phones with remaining volume. If no phones with remaining volume, use all phones instead.
|
||||
3 - Groupe keeped phones by priority get group with biggest priority.
|
||||
4 - Get a random phone in this group.
|
||||
5 - If their is no phone matching, keep phone at null so sender will directly mark it as failed
|
||||
*/
|
||||
$random_phone = null;
|
||||
if (null === $phone_to_use)
|
||||
{
|
||||
$phones_subset = $users_phones[$id_user];
|
||||
if ($scheduled['mms'])
|
||||
{
|
||||
$phones_subset = $users_mms_phones[$id_user] ?: $phones_subset;
|
||||
}
|
||||
|
||||
$remaining_volume_phones = array_filter($phones_subset, function ($phone) {
|
||||
return $phone['remaining_volume'] > 0;
|
||||
});
|
||||
$phones_subset = $remaining_volume_phones ?: $phones_subset;
|
||||
|
||||
$max_priority_phones = [];
|
||||
$max_priority = PHP_INT_MIN;
|
||||
foreach ($phones_subset as $phone)
|
||||
{
|
||||
if ($phone['priority'] < $max_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elseif ($phone['priority'] == $max_priority)
|
||||
{
|
||||
$max_priority_phones[] = $phone;
|
||||
}
|
||||
elseif ($phone['priority'] > $max_priority)
|
||||
{
|
||||
$max_priority_phones = [$phone];
|
||||
$max_priority = $phone['priority'];
|
||||
}
|
||||
}
|
||||
|
||||
$phones_subset = $max_priority_phones;
|
||||
if ($phones_subset)
|
||||
{
|
||||
$random_phone = $phones_subset[array_rand($phones_subset)];
|
||||
}
|
||||
}
|
||||
|
||||
// This should only happen if the user try to send a message without any phone in his account, then we simply ignore.
|
||||
if (!$random_phone && !$phone_to_use)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$id_phone = $phone_to_use['id'] ?? $random_phone['id'];
|
||||
$sms_per_scheduled[$id_scheduled][] = [
|
||||
'id_user' => $id_user,
|
||||
'id_scheduled' => $id_scheduled,
|
||||
'id_phone' => $id_phone,
|
||||
'destination' => $target['number'],
|
||||
'flash' => $scheduled['flash'],
|
||||
'mms' => $scheduled['mms'],
|
||||
'medias' => $scheduled['medias'],
|
||||
'text' => $text,
|
||||
];
|
||||
|
||||
// Consume one sms from remaining volume of phone, dont forget to do the same for the entry in mms phones
|
||||
$users_phones[$id_user][$id_phone]['remaining_volume'] --;
|
||||
if ($users_mms_phones[$id_user][$id_phone] ?? false)
|
||||
{
|
||||
$users_mms_phones[$id_user][$id_phone] --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sms_per_scheduled;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,6 +179,20 @@ namespace controllers\internals;
|
|||
return $this->get_model()->get_by_uid_and_adapter_for_user($id_user, $uid, $adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of sended SMS since a date for a phone
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param int $id_phone : Phone id we want the number of sended message for
|
||||
* @param \DateTime $since : Date since which we want sended number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, \DateTime $since): int
|
||||
{
|
||||
return $this->get_model()->count_since_for_phone_and_user($id_user, $id_phone, $since);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of sended SMS for every date since a date for a specific user.
|
||||
*
|
||||
|
@ -239,17 +253,6 @@ namespace controllers\internals;
|
|||
'error_message' => null,
|
||||
];
|
||||
|
||||
//If we reached our max quota, do not send the message
|
||||
$internal_quota = new Quota($this->bdd);
|
||||
$nb_credits = $internal_quota::compute_credits_for_message($text); //Calculate how much credit the message require
|
||||
if (!$internal_quota->has_enough_credit($id_user, $nb_credits))
|
||||
{
|
||||
$return['error'] = false;
|
||||
$return['error_message'] = 'Not enough credit to send message.';
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
$at = (new \DateTime())->format('Y-m-d H:i:s');
|
||||
$media_uris = [];
|
||||
foreach ($medias as $media)
|
||||
|
@ -272,38 +275,56 @@ namespace controllers\internals;
|
|||
$text .= "\n" . join(' - ', $media_urls);
|
||||
}
|
||||
|
||||
$response = $adapter->send($destination, $text, $flash, $mms, $media_uris);
|
||||
|
||||
if ($response['error'])
|
||||
//If we reached our max quota, do not send the message
|
||||
$internal_quota = new Quota($this->bdd);
|
||||
$nb_credits = $internal_quota::compute_credits_for_message($text); //Calculate how much credit the message require
|
||||
if (!$internal_quota->has_enough_credit($id_user, $nb_credits))
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = $response['error_message'];
|
||||
$status = \models\Sended::STATUS_FAILED;
|
||||
$sended_id = $this->create($id_user, $id_phone, $at, $text, $destination, $response['uid'] ?? uniqid(), $adapter->meta_classname(), $flash, $mms, $medias, $originating_scheduled, $status);
|
||||
|
||||
$sended = [
|
||||
'id' => $sended_id,
|
||||
'at' => $at,
|
||||
'status' => $status,
|
||||
'text' => $text,
|
||||
'destination' => $destination,
|
||||
'origin' => $id_phone,
|
||||
'mms' => $mms,
|
||||
'medias' => $medias,
|
||||
'originating_scheduled' => $originating_scheduled,
|
||||
];
|
||||
|
||||
$internal_webhook = new Webhook($this->bdd);
|
||||
$internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $sended);
|
||||
|
||||
return $return;
|
||||
$return['error_message'] = 'Not enough credit to send message.';
|
||||
}
|
||||
|
||||
$internal_quota->consume_credit($id_user, $nb_credits);
|
||||
//If we reached limit for this phone, do not send the message
|
||||
$internal_phone = new Phone($this->bdd);
|
||||
$internal_sended = new Sended($this->bdd);
|
||||
$limits = $internal_phone->get_limits($id_phone);
|
||||
|
||||
$sended_id = $this->create($id_user, $id_phone, $at, $text, $destination, $response['uid'] ?? uniqid(), $adapter->meta_classname(), $flash, $mms, $medias, $originating_scheduled, $status);
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $internal_sended->count_since_for_phone_and_user($id_user, $id_phone, $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
|
||||
$sended = [
|
||||
if ($remaining_volume < 1)
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = 'Phone send limit have been reached.';
|
||||
}
|
||||
|
||||
$uid = uniqid();
|
||||
if (!$return['error'])
|
||||
{
|
||||
$response = $adapter->send($destination, $text, $flash, $mms, $media_uris);
|
||||
$uid = $response['uid'] ?? $uid;
|
||||
|
||||
if ($response['error'])
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = $response['error_message'];
|
||||
}
|
||||
else // If send with success, consume credit
|
||||
{
|
||||
$internal_quota->consume_credit($id_user, $nb_credits);
|
||||
}
|
||||
}
|
||||
|
||||
// If we fail to send or not, we will always save message as sended, only the status will change.
|
||||
$status = $return['error'] ? \models\Sended::STATUS_FAILED : \models\Sended::STATUS_UNKNOWN;
|
||||
$sended_id = $this->create($id_user, $id_phone, $at, $text, $destination, $uid, $adapter->meta_classname(), $flash, $mms, $medias, $originating_scheduled, $status);
|
||||
|
||||
$webhook_body = [
|
||||
'id' => $sended_id,
|
||||
'at' => $at,
|
||||
'status' => $status,
|
||||
|
@ -316,7 +337,7 @@ namespace controllers\internals;
|
|||
];
|
||||
|
||||
$internal_webhook = new Webhook($this->bdd);
|
||||
$internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $sended);
|
||||
$internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $webhook_body);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace controllers\internals;
|
||||
|
||||
use BenMorel\GsmCharsetConverter\Converter;
|
||||
|
||||
/**
|
||||
* Some tools frequently used.
|
||||
* Not a standard controller as it's not linked to a model in any way.
|
||||
|
@ -165,6 +167,24 @@ namespace controllers\internals;
|
|||
return $objectDate && $objectDate->format($format) === $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a relative format date (see https://www.php.net/manual/en/datetime.formats.relative.php) is valid.
|
||||
*
|
||||
* @param string $date : Relative date
|
||||
*
|
||||
* @return bool : True if valid, false else
|
||||
*/
|
||||
public static function validate_relative_date($date)
|
||||
{
|
||||
try {
|
||||
$d = new \DateTime($date);
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a sting represent a valid PHP period for creating an interval.
|
||||
*
|
||||
|
@ -394,4 +414,17 @@ namespace controllers\internals;
|
|||
|
||||
return "{$scheme}{$user}{$pass}{$host}{$port}{$path}{$query}{$fragment}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transform an UTF-8 string into a valid GSM 7 string (GSM 03.38), remplacing invalid chars with best equivalent whenever possible
|
||||
*
|
||||
* @param string $text : Input text to convert into gsm string
|
||||
* @return string : An UTF-8 string with GSM alphabet only
|
||||
*/
|
||||
public static function convert_to_gsm0338(string $text): string
|
||||
{
|
||||
$converter = new Converter();
|
||||
return $converter->cleanUpUtf8String($text, true, '?');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,10 +137,10 @@ class Webhook extends StandardController
|
|||
|
||||
$error_code = null;
|
||||
$queue = msg_get_queue(QUEUE_ID_WEBHOOK);
|
||||
$success = msg_send($queue, QUEUE_TYPE_WEBHOOK, $message, true, true, $error_code);
|
||||
|
||||
return (bool) $success;
|
||||
msg_send($queue, QUEUE_TYPE_WEBHOOK, $message, true, true, $error_code);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -506,6 +506,8 @@ namespace controllers\publics;
|
|||
* @param string $_POST['name'] : Phone name
|
||||
* @param string $_POST['adapter'] : Phone adapter
|
||||
* @param array $_POST['adapter_data'] : Phone adapter data
|
||||
* @param int $priority : Priority with which to use phone to send SMS. Default 0.
|
||||
* @param ?array $_POST['limits'] : Array of limits in number of SMS for a period to be applied to this phone.
|
||||
*
|
||||
* @return int : id phone the new phone on success
|
||||
*/
|
||||
|
@ -516,6 +518,10 @@ namespace controllers\publics;
|
|||
$name = $_POST['name'] ?? false;
|
||||
$adapter = $_POST['adapter'] ?? false;
|
||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
|
||||
$priority = $_POST['priority'] ?? 0;
|
||||
$priority = max(((int) $priority), 0);
|
||||
$limits = $_POST['limits'] ?? [];
|
||||
$limits = is_array($limits) ? $limits : [$limits];
|
||||
|
||||
if (!$name)
|
||||
{
|
||||
|
@ -535,7 +541,7 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
$name_exist = $this->internal_phone->get_by_name($name);
|
||||
$name_exist = $this->internal_phone->get_by_name_and_user($this->user['id'], $name);
|
||||
if ($name_exist)
|
||||
{
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
|
@ -545,6 +551,36 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
if ($limits)
|
||||
{
|
||||
foreach ($limits as $key => $limit)
|
||||
{
|
||||
if (!is_array($limit))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$startpoint = $limit['startpoint'] ?? false;
|
||||
$volume = $limit['volume'] ?? false;
|
||||
|
||||
if (!$startpoint || !$volume)
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$volume = (int) $volume;
|
||||
$limits[$key]['volume'] = max($volume, 1);
|
||||
|
||||
if (!\controllers\internals\Tool::validate_relative_date($startpoint))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$adapters = $this->internal_adapter->list_adapters();
|
||||
$find_adapter = false;
|
||||
foreach ($adapters as $metas)
|
||||
|
@ -627,7 +663,7 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
$phone_id = $this->internal_phone->create($this->user['id'], $name, $adapter, $adapter_data);
|
||||
$phone_id = $this->internal_phone->create($this->user['id'], $name, $adapter, $adapter_data, $priority, $limits);
|
||||
if (false === $phone_id)
|
||||
{
|
||||
$return['error'] = self::ERROR_CODES['CANNOT_CREATE'];
|
||||
|
@ -650,6 +686,7 @@ namespace controllers\publics;
|
|||
* @param string (optionnal) $_POST['name'] : New phone name
|
||||
* @param string (optionnal) $_POST['adapter'] : New phone adapter
|
||||
* @param array (optionnal) $_POST['adapter_data'] : New phone adapter data
|
||||
* @param int $priority : Priority with which to use phone to send SMS. Default 0.
|
||||
*
|
||||
* @return int : id phone the new phone on success
|
||||
*/
|
||||
|
@ -667,10 +704,16 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
$limits = $this->internal_phone->get_limits(($phone['id']));
|
||||
|
||||
$name = $_POST['name'] ?? $phone['name'];
|
||||
$priority = $_POST['priority'] ?? $phone['priority'];
|
||||
$priority = max(((int) $priority), 0);
|
||||
$adapter = $_POST['adapter'] ?? $phone['adapter'];
|
||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : json_decode($phone['adapter_data']);
|
||||
$adapter_data = is_array($adapter_data) ? $adapter_data : [$adapter_data];
|
||||
$limits = $_POST['limits'] ?? $limits;
|
||||
$limits = is_array($limits) ? $limits : [$limits];
|
||||
|
||||
|
||||
if (!$name && !$adapter && !$adapter_data)
|
||||
|
@ -683,7 +726,7 @@ namespace controllers\publics;
|
|||
}
|
||||
|
||||
|
||||
$phone_with_same_name = $this->internal_phone->get_by_name($name);
|
||||
$phone_with_same_name = $this->internal_phone->get_by_name_and_user($this->user['id'], $name);
|
||||
if ($phone_with_same_name && $phone_with_same_name['id'] != $phone['id'])
|
||||
{
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
|
@ -693,6 +736,36 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
if ($limits)
|
||||
{
|
||||
foreach ($limits as $key => $limit)
|
||||
{
|
||||
if (!is_array($limit))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$startpoint = $limit['startpoint'] ?? false;
|
||||
$volume = $limit['volume'] ?? false;
|
||||
|
||||
if (!$startpoint || !$volume)
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$volume = (int) $volume;
|
||||
$limits[$key]['volume'] = max($volume, 1);
|
||||
|
||||
if (!\controllers\internals\Tool::validate_relative_date($startpoint))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$adapters = $this->internal_adapter->list_adapters();
|
||||
$find_adapter = false;
|
||||
foreach ($adapters as $metas)
|
||||
|
@ -775,7 +848,7 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
$success = $this->internal_phone->update_for_user($this->user['id'], $phone['id'], $name, $adapter, $adapter_data);
|
||||
$success = $this->internal_phone->update_for_user($this->user['id'], $phone['id'], $name, $adapter, $adapter_data_json, $priority, $limits);
|
||||
if (!$success)
|
||||
{
|
||||
$return['error'] = self::ERROR_CODES['CANNOT_UPDATE'];
|
||||
|
|
|
@ -185,6 +185,45 @@ namespace controllers\publics;
|
|||
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return contacts of a group as json array
|
||||
* @param int $id_group = Group id
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function preview (int $id_group)
|
||||
{
|
||||
$return = [
|
||||
'success' => false,
|
||||
'result' => 'Une erreur inconnue est survenue.',
|
||||
];
|
||||
|
||||
$group = $this->internal_conditional_group->get_for_user($_SESSION['user']['id'], $id_group);
|
||||
|
||||
if (!$group)
|
||||
{
|
||||
$return['result'] = 'Ce groupe n\'existe pas.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$contacts = $this->internal_conditional_group->get_contacts_for_condition_and_user($_SESSION['user']['id'], $group['condition']);
|
||||
if (!$contacts)
|
||||
{
|
||||
$return['result'] = 'Aucun contact dans le groupe.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$return['success'] = true;
|
||||
$return['result'] = $contacts;
|
||||
echo json_encode($return);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get the preview of contacts for a conditionnal group.
|
||||
*
|
||||
|
|
|
@ -372,6 +372,7 @@ namespace controllers\publics;
|
|||
else
|
||||
{
|
||||
$invalid_type = true;
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,45 @@ namespace controllers\publics;
|
|||
return $this->redirect(\descartes\Router::url('Group', 'list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return contacts of a group as json array
|
||||
* @param int $id_group = Group id
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function preview (int $id_group)
|
||||
{
|
||||
$return = [
|
||||
'success' => false,
|
||||
'result' => 'Une erreur inconnue est survenue.',
|
||||
];
|
||||
|
||||
$group = $this->internal_group->get_for_user($_SESSION['user']['id'], $id_group);
|
||||
|
||||
if (!$group)
|
||||
{
|
||||
$return['result'] = 'Ce groupe n\'existe pas.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$contacts = $this->internal_group->get_contacts($id_group);
|
||||
if (!$contacts)
|
||||
{
|
||||
$return['result'] = 'Aucun contact dans le groupe.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$return['success'] = true;
|
||||
$return['result'] = $contacts;
|
||||
echo json_encode($return);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cette fonction retourne la liste des groups sous forme JSON.
|
||||
*/
|
||||
|
|
|
@ -55,6 +55,9 @@ class Phone extends \descartes\Controller
|
|||
|
||||
foreach ($phones as &$phone)
|
||||
{
|
||||
$limits = $this->internal_phone->get_limits($phone['id']);
|
||||
$phone['limits'] = $limits;
|
||||
|
||||
$adapter = $adapters[$phone['adapter']] ?? false;
|
||||
|
||||
if (!$adapter)
|
||||
|
@ -131,9 +134,11 @@ class Phone extends \descartes\Controller
|
|||
* Create a new phone.
|
||||
*
|
||||
* @param $csrf : CSRF token
|
||||
* @param string $_POST['name'] : Phone name
|
||||
* @param string $_POST['adapter'] : Phone adapter
|
||||
* @param array $_POST['adapter_data'] : Phone adapter data
|
||||
* @param string $_POST['name'] : Phone name
|
||||
* @param string $_POST['adapter'] : Phone adapter
|
||||
* @param ?array $_POST['adapter_data'] : Phone adapter data
|
||||
* @param ?array $_POST['limits'] : Array of limits in number of SMS for a period to be applied to this phone.
|
||||
* @param int $_POST['priority'] : Priority with which to use phone to send SMS. Default 0.
|
||||
*/
|
||||
public function create($csrf)
|
||||
{
|
||||
|
@ -146,8 +151,12 @@ class Phone extends \descartes\Controller
|
|||
|
||||
$id_user = $_SESSION['user']['id'];
|
||||
$name = $_POST['name'] ?? false;
|
||||
$priority = $_POST['priority'] ?? 0;
|
||||
$priority = max(((int) $priority), 0);
|
||||
$adapter = $_POST['adapter'] ?? false;
|
||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
|
||||
$limits = $_POST['limits'] ?? [];
|
||||
$limits = is_array($limits) ? $limits : [$limits];
|
||||
|
||||
if (!$name || !$adapter)
|
||||
{
|
||||
|
@ -156,7 +165,7 @@ class Phone extends \descartes\Controller
|
|||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
||||
}
|
||||
|
||||
$name_exist = $this->internal_phone->get_by_name($name);
|
||||
$name_exist = $this->internal_phone->get_by_name_and_user($id_user, $name);
|
||||
if ($name_exist)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Ce nom est déjà utilisé pour un autre téléphone.');
|
||||
|
@ -164,6 +173,36 @@ class Phone extends \descartes\Controller
|
|||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
||||
}
|
||||
|
||||
if ($limits)
|
||||
{
|
||||
foreach ($limits as $key => $limit)
|
||||
{
|
||||
if (!is_array($limit))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$startpoint = $limit['startpoint'] ?? false;
|
||||
$volume = $limit['volume'] ?? false;
|
||||
|
||||
if (!$startpoint || !$volume)
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$volume = (int) $volume;
|
||||
$limits[$key]['volume'] = max($volume, 1);
|
||||
|
||||
if (!\controllers\internals\Tool::validate_relative_date($startpoint))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$adapters = $this->internal_adapter->list_adapters();
|
||||
$find_adapter = false;
|
||||
foreach ($adapters as $metas)
|
||||
|
@ -245,7 +284,7 @@ class Phone extends \descartes\Controller
|
|||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
||||
}
|
||||
|
||||
$success = $this->internal_phone->create($id_user, $name, $adapter, $adapter_data);
|
||||
$success = $this->internal_phone->create($id_user, $name, $adapter, $adapter_data, $priority, $limits);
|
||||
if (!$success)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce téléphone.');
|
||||
|
@ -257,4 +296,207 @@ class Phone extends \descartes\Controller
|
|||
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'list'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the edit page for phones
|
||||
*
|
||||
* @param int... $ids : Phones ids
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$ids = $_GET['ids'] ?? [];
|
||||
$id_user = $_SESSION['user']['id'];
|
||||
|
||||
$phones = $this->internal_phone->gets_in_for_user($id_user, $ids);
|
||||
|
||||
if (!$phones)
|
||||
{
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'list'));
|
||||
}
|
||||
|
||||
$adapters = $this->internal_adapter->list_adapters();
|
||||
|
||||
foreach ($phones as &$phone)
|
||||
{
|
||||
$limits = $this->internal_phone->get_limits($phone['id']);
|
||||
$phone['limits'] = $limits;
|
||||
}
|
||||
|
||||
$this->render('phone/edit', [
|
||||
'phones' => $phones,
|
||||
'adapters' => $adapters,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update multiple phones.
|
||||
*
|
||||
* @param $csrf : CSRF token
|
||||
* @param string $_POST['phones']['id']['name'] : Phone name
|
||||
* @param string $_POST['phones']['id']['adapter'] : Phone adapter
|
||||
* @param ?array $_POST['phones']['id']['adapter_data'] : Phone adapter data
|
||||
* @param ?array $_POST['phones']['id']['limits'] : Array of limits in number of SMS for a period to be applied to this phone.
|
||||
* @param int $_POST['phones']['id']['priority'] : Priority with which to use phone to send SMS. Default 0.
|
||||
*/
|
||||
public function update($csrf)
|
||||
{
|
||||
if (!$this->verify_csrf($csrf))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
||||
}
|
||||
|
||||
if (!$_POST['phones'])
|
||||
{
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'list'));
|
||||
}
|
||||
|
||||
$id_user = $_SESSION['user']['id'];
|
||||
|
||||
$nb_update = 0;
|
||||
foreach ($_POST['phones'] as $id_phone => $phone)
|
||||
{
|
||||
$name = $phone['name'] ?? false;
|
||||
$priority = $phone['priority'] ?? 0;
|
||||
$priority = max(((int) $priority), 0);
|
||||
$adapter = $phone['adapter'] ?? false;
|
||||
$adapter_data = !empty($phone['adapter_data']) ? $phone['adapter_data'] : [];
|
||||
$limits = $phone['limits'] ?? [];
|
||||
$limits = is_array($limits) ? $limits : [$limits];
|
||||
|
||||
if (!$name || !$adapter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$phone_with_same_name = $this->internal_phone->get_by_name_and_user($id_user, $name);
|
||||
if ($phone_with_same_name && $phone_with_same_name['id'] != $id_phone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($limits)
|
||||
{
|
||||
foreach ($limits as $key => $limit)
|
||||
{
|
||||
if (!is_array($limit))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$startpoint = $limit['startpoint'] ?? false;
|
||||
$volume = $limit['volume'] ?? false;
|
||||
|
||||
if (!$startpoint || !$volume)
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$volume = (int) $volume;
|
||||
$limits[$key]['volume'] = max($volume, 1);
|
||||
|
||||
if (!\controllers\internals\Tool::validate_relative_date($startpoint))
|
||||
{
|
||||
unset($limits[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$adapters = $this->internal_adapter->list_adapters();
|
||||
$find_adapter = false;
|
||||
foreach ($adapters as $metas)
|
||||
{
|
||||
if ($metas['meta_classname'] === $adapter)
|
||||
{
|
||||
$find_adapter = $metas;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$find_adapter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($find_adapter['meta_hidden'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//If missing required data fields, error
|
||||
foreach ($find_adapter['meta_data_fields'] as $field)
|
||||
{
|
||||
if (false === $field['required'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($adapter_data[$field['name']]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
//If field phone number is invalid
|
||||
foreach ($find_adapter['meta_data_fields'] as $field)
|
||||
{
|
||||
if ('phone_number' !== ($field['type'] ?? false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($adapter_data[$field['name']]))
|
||||
{
|
||||
$adapter_data[$field['name']] = \controllers\internals\Tool::parse_phone($adapter_data[$field['name']]);
|
||||
|
||||
if ($adapter_data[$field['name']])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
$adapter_data = json_encode($adapter_data);
|
||||
|
||||
//Check adapter is working correctly with thoses names and data
|
||||
$adapter_classname = $find_adapter['meta_classname'];
|
||||
$adapter_instance = new $adapter_classname($adapter_data);
|
||||
$adapter_working = $adapter_instance->test();
|
||||
|
||||
if (!$adapter_working)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$success = $this->internal_phone->update_for_user($id_user, $id_phone, $name, $adapter, $adapter_data, $priority, $limits);
|
||||
if (!$success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$nb_update ++;
|
||||
}
|
||||
|
||||
if ($nb_update !== \count($_POST['phones']))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Certains téléphones n\'ont pas pu êtres mis à jour.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'list'));
|
||||
}
|
||||
|
||||
\FlashMessage\FlashMessage::push('success', 'Tous les téléphones ont été modifiés avec succès.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('Phone', 'list'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,12 @@ namespace controllers\publics;
|
|||
$result = $this->internal_templating->render($template, $data);
|
||||
$return = $result;
|
||||
|
||||
// If we must force GSM 7 alphabet
|
||||
if ((int) ($_SESSION['user']['settings']['force_gsm_alphabet'] ?? false))
|
||||
{
|
||||
$return['result'] = \controllers\internals\Tool::convert_to_gsm0338($return['result']);
|
||||
}
|
||||
|
||||
if (!trim($result['result']))
|
||||
{
|
||||
$return['result'] = 'Message vide, il ne sera pas envoyé.';
|
||||
|
|
|
@ -22,6 +22,7 @@ class Sender extends AbstractDaemon
|
|||
private $internal_phone;
|
||||
private $internal_scheduled;
|
||||
private $internal_received;
|
||||
private $internal_sended;
|
||||
private $bdd;
|
||||
private $msg_queue;
|
||||
|
||||
|
@ -45,6 +46,7 @@ class Sender extends AbstractDaemon
|
|||
{
|
||||
//Create the internal controllers
|
||||
$this->internal_scheduled = new \controllers\internals\Scheduled($this->bdd);
|
||||
$this->internal_sended = new \controllers\internals\Sended($this->bdd);
|
||||
|
||||
//Get smss and transmit order to send to appropriate phone daemon
|
||||
$smss_per_scheduled = $this->internal_scheduled->get_smss_to_send();
|
||||
|
@ -62,8 +64,8 @@ class Sender extends AbstractDaemon
|
|||
{
|
||||
foreach ($smss_per_scheduled as $id_scheduled => $smss)
|
||||
{
|
||||
//If queue not already exists
|
||||
if (!msg_queue_exists(QUEUE_ID_PHONE) || !isset($this->queue))
|
||||
//If queue not already exists
|
||||
if (!msg_queue_exists(QUEUE_ID_PHONE) || !isset($this->msg_queue))
|
||||
{
|
||||
$this->msg_queue = msg_get_queue(QUEUE_ID_PHONE);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class AddPhoneLimits extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* addCustomColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Any other destructive changes will result in an error when trying to
|
||||
* rollback the migration.
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('phone_limit');
|
||||
$table->addColumn('id_phone', 'integer', ['null' => false])
|
||||
->addColumn('volume', 'integer', ['null' => false])
|
||||
->addColumn('startpoint', 'string', ['null' => false, 'limit' => 254]) # A relative time to use as startpoint for counting volume. See https://www.php.net/manual/en/datetime.formats.relative.php
|
||||
->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
|
||||
->addColumn('updated_at', 'timestamp', ['null' => true, 'update' => 'CURRENT_TIMESTAMP'])
|
||||
->addForeignKey('id_phone', 'phone', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->create();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class AddPhonePriority extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* addCustomColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Any other destructive changes will result in an error when trying to
|
||||
* rollback the migration.
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$table = $this->table('phone');
|
||||
$table->addColumn('priority', 'integer', [
|
||||
'null' => false,
|
||||
'default' => 0,
|
||||
'comment' => 'Priority with which the phone will be used. The higher the more prioritary.',
|
||||
'after' => 'name'
|
||||
])
|
||||
->update();
|
||||
}
|
||||
}
|
|
@ -82,6 +82,7 @@
|
|||
'alert_quota_limit_reached' => 1,
|
||||
'alert_quota_limit_close' => 0.9,
|
||||
'hide_menus' => '',
|
||||
'force_gsm_alphabet' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -84,32 +84,6 @@ namespace models;
|
|||
return $this->_select('event', ['id_user' => $id_user], 'at', true, $nb_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets events for a type, since a date and eventually until a date (both included).
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param string $type : Event type we want
|
||||
* @param \DateTime $since : Date to get events since
|
||||
* @param ?\DateTime $until (optional) : Date until wich we want events, if not specified no limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_events_by_type_and_date_for_user(int $id_user, string $type, \DateTime $since, ?\DateTime $until = null)
|
||||
{
|
||||
$where = [
|
||||
'id_user' => $id_user,
|
||||
'type' => $type,
|
||||
'>=at' => $since->format('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
if (null !== $until)
|
||||
{
|
||||
$where['<=at'] = $until->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
return $this->_select('event', $where, 'at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return table name.
|
||||
*/
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace models;
|
|||
{
|
||||
|
||||
/**
|
||||
* Return all hones that belongs to active users
|
||||
* Return all phones that belongs to active users
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -63,6 +63,48 @@ namespace models;
|
|||
return $this->_select_one('phone', ['name' => $name]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of phone limits
|
||||
*
|
||||
* @param int $id_phone : Phone id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_limits(int $id_phone)
|
||||
{
|
||||
return $this->_select('phone_limit', ['id_phone' => $id_phone]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a limit for a phone.
|
||||
*
|
||||
* @param int $id_phone : Phone id
|
||||
* @param int $volume : Limit in volume of SMS
|
||||
* @param string $startpoint : A relative time to use as startpoint for counting volume. See https://www.php.net/manual/en/datetime.formats.relative.php
|
||||
*
|
||||
* @return mixed (bool|int) : False on error, new row id else
|
||||
*/
|
||||
public function insert_phone_limit(int $id_phone, int $volume, string $startpoint)
|
||||
{
|
||||
$success = $this->_insert('phone_limit', ['id_phone' => $id_phone, 'volume' => $volume, 'startpoint' => $startpoint]);
|
||||
|
||||
return $success ? $this->_last_id() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete limits for a phone
|
||||
*
|
||||
* @param array $id_phone : Phone id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function delete_phone_limits(int $id_phone)
|
||||
{
|
||||
return $this->_delete('phone_limit', ['id_phone' => $id_phone]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return table name.
|
||||
*/
|
||||
|
|
|
@ -178,6 +178,20 @@ namespace models;
|
|||
return $this->_select_one('sended', ['id_user' => $id_user, 'uid' => $uid, 'adapter' => $adapter]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of sended SMS since a date for a phone
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param int $id_phone : Phone id we want the number of sended message for
|
||||
* @param \DateTime $since : Date since which we want sended number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, \DateTime $since) : int
|
||||
{
|
||||
return $this->_count('sended', ['id_user' => $id_user, 'id_phone' => $id_phone, '>=at' => $since->format('c')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of sended SMS for every date since a date for a specific user.
|
||||
*
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
'delete' => '/group/delete/{csrf}/',
|
||||
'edit' => '/group/edit/',
|
||||
'update' => '/group/update/{csrf}/',
|
||||
'preview' => '/group/preview/{id_group}/',
|
||||
'json_list' => '/groups.json/',
|
||||
],
|
||||
|
||||
|
@ -88,6 +89,7 @@
|
|||
'edit' => '/conditional_group/edit/',
|
||||
'update' => '/conditional_group/update/{csrf}/',
|
||||
'contacts_preview' => '/conditional_group/preview/',
|
||||
'preview' => '/conditional_group/preview/{id_group}/',
|
||||
'json_list' => '/conditional_groups.json/',
|
||||
],
|
||||
|
||||
|
@ -160,6 +162,8 @@
|
|||
'add' => '/phone/add/',
|
||||
'create' => '/phone/create/{csrf}/',
|
||||
'delete' => '/phone/delete/{csrf}/',
|
||||
'edit' => '/phone/edit/',
|
||||
'update' => '/phone/update/{csrf}/',
|
||||
],
|
||||
|
||||
'Call' => [
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<th>Condition</th>
|
||||
<th>Date de création</th>
|
||||
<th>Dernière modification</th>
|
||||
<th>Preview</th>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -69,9 +70,56 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" tabindex="-1" id="preview-text-modal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Prévisualisation des contacts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function ()
|
||||
{
|
||||
jQuery('body').on('click', '.preview-button', function (e)
|
||||
{
|
||||
e.preventDefault();
|
||||
var group_id = jQuery(this).attr('data-id-group');
|
||||
|
||||
jQuery.ajax({
|
||||
type: "GET",
|
||||
url: HTTP_PWD + '/conditional_group/preview/' + group_id + '/',
|
||||
success: function (data) {
|
||||
if (!data.success) {
|
||||
jQuery('#preview-text-modal').find('.modal-body').text(data.result);
|
||||
} else {
|
||||
html = '';
|
||||
|
||||
for (contact of data.result)
|
||||
{
|
||||
html += '<div class="preview-contact well">';
|
||||
html += ' <div class="preview-contact-name">' + jQuery.fn.dataTable.render.text().display(contact.name) + '</div>'
|
||||
html += ' <div class="preview-contact-number">' + jQuery.fn.dataTable.render.text().display(contact.number) + '</div>'
|
||||
html += ' <code class="preview-contact-data">' + jQuery.fn.dataTable.render.text().display(contact.data) + '</code>'
|
||||
html += '</div>';
|
||||
console.log(contact);
|
||||
}
|
||||
|
||||
jQuery('#preview-text-modal').find('.modal-body').html(html);
|
||||
}
|
||||
jQuery('#preview-text-modal').modal({'keyboard': true});
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
});
|
||||
|
||||
jQuery('.datatable').DataTable({
|
||||
"pageLength": 25,
|
||||
"lengthMenu": [[25, 50, 100, 1000, 10000, -1], [25, 50, 100, 1000, 10000, "All"]],
|
||||
|
@ -97,6 +145,12 @@ jQuery(document).ready(function ()
|
|||
},
|
||||
{data: 'created_at'},
|
||||
{data: 'updated_at'},
|
||||
{
|
||||
data: '_',
|
||||
render: function (data, type, row, meta) {
|
||||
return '<a class="btn btn-info preview-button" href="#" data-id-group="' + jQuery.fn.dataTable.render.text().display(row.id) + '"><span class="fa fa-eye"></span></a>';
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'id',
|
||||
render: function (data, type, row, meta) {
|
||||
|
@ -106,7 +160,6 @@ jQuery(document).ready(function ()
|
|||
],
|
||||
"deferRender": true
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<th>Nombre de contacts</th>
|
||||
<th>Date de création</th>
|
||||
<th>Dernière modification</th>
|
||||
<th>Preview</th>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -69,6 +70,21 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" tabindex="-1" id="preview-text-modal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Prévisualisation des contacts</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function ()
|
||||
{
|
||||
|
@ -92,6 +108,12 @@ jQuery(document).ready(function ()
|
|||
{data: 'nb_contact', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'created_at'},
|
||||
{data: 'updated_at'},
|
||||
{
|
||||
data: '_',
|
||||
render: function (data, type, row, meta) {
|
||||
return '<a class="btn btn-info preview-button" href="#" data-id-group="' + jQuery.fn.dataTable.render.text().display(row.id) + '"><span class="fa fa-eye"></span></a>';
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'id',
|
||||
render: function (data, type, row, meta) {
|
||||
|
@ -102,6 +124,38 @@ jQuery(document).ready(function ()
|
|||
"deferRender": true
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.preview-button', function (e)
|
||||
{
|
||||
e.preventDefault();
|
||||
var group_id = jQuery(this).attr('data-id-group');
|
||||
|
||||
jQuery.ajax({
|
||||
type: "GET",
|
||||
url: HTTP_PWD + '/group/preview/' + group_id + '/',
|
||||
success: function (data) {
|
||||
if (!data.success) {
|
||||
jQuery('#preview-text-modal').find('.modal-body').text(data.result);
|
||||
} else {
|
||||
html = '';
|
||||
|
||||
for (contact of data.result)
|
||||
{
|
||||
html += '<div class="preview-contact well">';
|
||||
html += ' <div class="preview-contact-name">' + jQuery.fn.dataTable.render.text().display(contact.name) + '</div>'
|
||||
html += ' <div class="preview-contact-number">' + jQuery.fn.dataTable.render.text().display(contact.number) + '</div>'
|
||||
html += ' <code class="preview-contact-data">' + jQuery.fn.dataTable.render.text().display(contact.data) + '</code>'
|
||||
html += '</div>';
|
||||
console.log(contact);
|
||||
}
|
||||
|
||||
jQuery('#preview-text-modal').find('.modal-body').html(html);
|
||||
}
|
||||
jQuery('#preview-text-modal').modal({'keyboard': true});
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -48,7 +48,16 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Type de téléphone : </label>
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="priority" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($_SESSION['previous_http_post']['priority'] ?? 0) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Type de téléphone</label>
|
||||
<p class="italic small help" id="description-adapter-general">
|
||||
Le type de téléphone utilisé par RaspiSMS pour envoyer ou recevoir les SMS. Pour plus d'information, consultez <a href="https://documentation.raspisms.fr/users/adapters/overview.html" target="_blank">la documentation de RaspiSMS</a> concernant les différents types de téléphones.
|
||||
</p>
|
||||
|
@ -67,7 +76,7 @@
|
|||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
<div id="adapter-data-container" class="form-group">
|
||||
<div id="adapter-data-container" class="form-group well">
|
||||
<div id="adapter-data-description-container">
|
||||
<h4>Description du téléphone</h4>
|
||||
<div id="adapter-data-description"></div>
|
||||
|
@ -77,6 +86,15 @@
|
|||
<h4>Réglages du téléphone</h4>
|
||||
<div id="adapter-data-fields"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
|
||||
<input type="submit" class="btn btn-success" value="Enregistrer le téléphone" />
|
||||
|
@ -174,6 +192,47 @@
|
|||
{
|
||||
change_adapter();
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.phone-limits-group-remove', function (e)
|
||||
{
|
||||
e.preventDefault();
|
||||
jQuery(this).parent('.phone-limits-group').remove();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.add-phone-limit-button', function(e)
|
||||
{
|
||||
var random_id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||
var newLimit = '' +
|
||||
'<div class="row phone-limits-group">'+
|
||||
'<div class="col-xs-4">'+
|
||||
'<label>Période</label><br/>'+
|
||||
'<select name="limits[' + random_id + '][startpoint]" class="form-control" required>'+
|
||||
'<option value="" disabled selected>Période sur laquelle appliquer la limite</option>'+
|
||||
'<option value="today">Par jour</option>'+
|
||||
'<option value="-24 hours">24 heures glissantes</option>'+
|
||||
'<option value="this week midnight">Cette semaine</option>'+
|
||||
'<option value="-7 days">7 jours glissants</option>'+
|
||||
'<option value="this week midnight -1 week">Ces deux dernières semaines</option>'+
|
||||
'<option value="-14 days">14 jours glissants</option>'+
|
||||
'<option value="this month midnight">Ce mois</option>'+
|
||||
'<option value="-1 month">1 mois glissant</option>'+
|
||||
'<option value="-28 days">28 jours glissants</option>'+
|
||||
'<option value="-30 days">30 jours glissants</option>'+
|
||||
'<option value="-31 days">31 jours glissants</option>'+
|
||||
'</select>'+
|
||||
'</div>'+
|
||||
'<div class="scheduleds-number-data-container col-xs-8">'+
|
||||
'<label>Volume</label>'+
|
||||
'<div class="form-group">'+
|
||||
'<input name="limits[' + random_id + '][volume]" class="form-control" type="number" min="1" placeholder="Nombre de SMS maximum sur la période.">'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>'+
|
||||
'</div>';
|
||||
|
||||
jQuery(this).parent('div').before(newLimit);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
<?php
|
||||
//Template dashboard
|
||||
|
||||
$this->render('incs/head', ['title' => 'Phones - Edit'])
|
||||
?>
|
||||
<div id="wrapper">
|
||||
<?php
|
||||
$this->render('incs/nav', ['page' => 'phones'])
|
||||
?>
|
||||
<div id="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">
|
||||
Modification téléphones
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li>
|
||||
<i class="fa fa-dashboard"></i> <a href="<?php echo \descartes\Router::url('Dashboard', 'show'); ?>">Dashboard</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-phone"></i> <a href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Téléphones</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<i class="fa fa-edit"></i> Modifier
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><i class="fa fa-phone fa-fw"></i> Modification de téléphones</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Phone', 'update', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<div class="entry-container" data-entry-id="<?php $this->s($phone['id']); ?>">
|
||||
<div class="form-group">
|
||||
<label>Nom du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Le nom du téléphone qui enverra et recevra les messages.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="phones[<?php $this->s($phone['id']); ?>][name]" class="form-control" placeholder="Nom du téléphone" value="<?php $this->s($phone['name']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="phones[<?php $this->s($phone['id']); ?>][priority]" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($phone['priority']) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Type de téléphone</label>
|
||||
<p class="italic small help description-adapter-general">
|
||||
Le type de téléphone utilisé par RaspiSMS pour envoyer ou recevoir les SMS. Pour plus d'information, consultez <a href="https://documentation.raspisms.fr/users/adapters/overview.html" target="_blank">la documentation de RaspiSMS</a> concernant les différents types de téléphones.
|
||||
</p>
|
||||
<select name="phones[<?php $this->s($phone['id']); ?>][adapter]" class="form-control adapter-select">
|
||||
<?php foreach ($adapters as $adapter) { ?>
|
||||
<?php if ($adapter['meta_hidden'] === false) { ?>
|
||||
<option
|
||||
value="<?= $adapter['meta_classname'] ?>"
|
||||
data-description="<?php $this->s($adapter['meta_description']); ?>"
|
||||
data-data-fields="<?php $this->s(json_encode($adapter['meta_data_fields'])); ?>"
|
||||
<?php if ($phone['adapter'] == $adapter['meta_classname']) { ?>
|
||||
data-phone-adapter-data="<?php $this->s($phone['adapter_data']); ?>"
|
||||
selected
|
||||
<?php } ?>
|
||||
>
|
||||
<?php $this->s($adapter['meta_name']); ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group well adapter-data-container">
|
||||
<div class="adapter-data-description-container">
|
||||
<h4>Description du téléphone</h4>
|
||||
<div class="adapter-data-description"></div>
|
||||
</div>
|
||||
|
||||
<div class="adapter-data-fields-container">
|
||||
<h4>Réglages du téléphone</h4>
|
||||
<div class="adapter-data-fields"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<?php foreach ($phone['limits'] as $limit) { ?>
|
||||
<div class="row phone-limits-group">
|
||||
<div class="col-xs-4">
|
||||
<label>Période</label><br/>
|
||||
<?php $random_id = uniqid(); ?>
|
||||
<select name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][startpoint]" class="form-control" required>
|
||||
<option value="" disabled selected>Période sur laquelle appliquer la limite</option>
|
||||
<option <?= $limit['startpoint'] == 'today' ? 'selected' : ''; ?> value="today">Par jour</option>
|
||||
<option <?= $limit['startpoint'] == '-24 hours' ? 'selected' : ''; ?> value="-24 hours">24 heures glissantes</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight' ? 'selected' : ''; ?> value="this week midnight">Cette semaine</option>
|
||||
<option <?= $limit['startpoint'] == '-7 days' ? 'selected' : ''; ?> value="-7 days">7 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight -1 week' ? 'selected' : ''; ?> value="this week midnight -1 week">Ces deux dernières semaines</option>
|
||||
<option <?= $limit['startpoint'] == '-14 days' ? 'selected' : ''; ?> value="-14 days">14 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this month midnight' ? 'selected' : ''; ?> value="this month midnight">Ce mois</option>
|
||||
<option <?= $limit['startpoint'] == '-1 month' ? 'selected' : ''; ?> value="-1 month">1 mois glissant</option>
|
||||
<option <?= $limit['startpoint'] == '-28 days' ? 'selected' : ''; ?> value="-28 days">28 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-30 days' ? 'selected' : ''; ?> value="-30 days">30 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-31 days' ? 'selected' : ''; ?> value="-31 days">31 jours glissants</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="scheduleds-number-data-container col-xs-8">
|
||||
<label>Volume</label>
|
||||
<div class="form-group">
|
||||
<input name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][volume]" class="form-control" type="number" min="1" value="<?php $this->s($limit['volume']); ?>" placeholder="Nombre de SMS maximum sur la période.">
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<?php } ?>
|
||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
|
||||
<input type="submit" class="btn btn-success" value="Enregistrer le téléphone" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function change_adapter (target)
|
||||
{
|
||||
var phone_id = target.parents('.entry-container').attr('data-entry-id');
|
||||
|
||||
var option = target.find('option:selected');
|
||||
target.parents('.entry-container').find('.adapter-data-description').html(option.attr('data-description'));
|
||||
target.parents('.entry-container').find('.description-adapter-data').text(option.attr('data-data-help'));
|
||||
|
||||
var data_fields = option.attr('data-data-fields');
|
||||
data_fields = JSON.parse(data_fields);
|
||||
|
||||
if (option.attr('data-phone-adapter-data'))
|
||||
{
|
||||
var phone_adapter_data = option.attr('data-phone-adapter-data');
|
||||
phone_adapter_data = JSON.parse(phone_adapter_data);
|
||||
}
|
||||
|
||||
var numbers = [];
|
||||
|
||||
var html = '';
|
||||
jQuery.each(data_fields, function (index, field)
|
||||
{
|
||||
if (phone_adapter_data)
|
||||
{
|
||||
if (field.name in phone_adapter_data)
|
||||
{
|
||||
value = phone_adapter_data[field.name];
|
||||
}
|
||||
else
|
||||
{
|
||||
value = field.default_value ? field.default_value : null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = field.default_value ? field.default_value : null;
|
||||
}
|
||||
|
||||
|
||||
if (field.type == 'phone_number')
|
||||
{
|
||||
var random_id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||
html += '' +
|
||||
'<div class="form-group">' +
|
||||
'<label>' + field.title + '</label>' +
|
||||
'<p class="italic small help">' + field.description + '</p>' +
|
||||
'<div class="form-group">' +
|
||||
'<input name="" class="form-control phone-international-input" type="tel" id="' + random_id + '" ' + (field.required ? 'required' : '') + ' ' + (value ? 'value="' + value + '"' : '') + '>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
var number = {
|
||||
'id': random_id,
|
||||
'name': field.name,
|
||||
};
|
||||
|
||||
numbers.push(number);
|
||||
}
|
||||
else if (field.type == 'boolean')
|
||||
{
|
||||
html += '' +
|
||||
'<div class="form-group">' +
|
||||
'<label>' + field.title + '</label>' +
|
||||
'<p class="italic small help">' + field.description + '</p>' +
|
||||
'<div class="form-group">' +
|
||||
'<input type="checkbox" name="phones[' + phone_id + '][adapter_data][' + field.name + ']" class="form-control" ' + (field.required ? 'required' : '') + ' ' + (value ? 'value="' + value + '" checked' : 'value="1"') + '><label class="switch" for="adapter_data[' + field.name + ']"></label>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
else
|
||||
{
|
||||
html += '' +
|
||||
'<div class="form-group">' +
|
||||
'<label>' + field.title + '</label>' +
|
||||
'<p class="italic small help">' + field.description + '</p>' +
|
||||
'<div class="form-group">' +
|
||||
'<input name="phones[' + phone_id + '][adapter_data][' + field.name + ']" class="form-control" ' + (field.required ? 'required' : '') + ' ' + (value ? 'value="' + value + '"' : '') + '>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
if (html == '')
|
||||
{
|
||||
html = 'Pas de réglages.';
|
||||
}
|
||||
|
||||
target.parents('.entry-container').find('.adapter-data-fields').html(html);
|
||||
|
||||
for (i = 0; i < numbers.length; i++)
|
||||
{
|
||||
var iti_number_input = window.intlTelInput(document.getElementById(numbers[i].id), {
|
||||
hiddenInput: 'phones[' + phone_id + '][adapter_data][' + numbers[i].name + ']',
|
||||
defaultCountry: '<?php $this->s($_SESSION['user']['settings']['default_phone_country']); ?>',
|
||||
preferredCountries: <?php $this->s(json_encode(explode(',', $_SESSION['user']['settings']['preferred_phone_country'])), false, false); ?>,
|
||||
nationalMode: true,
|
||||
utilsScript: '<?php echo HTTP_PWD_JS; ?>/intlTelInput/utils.js',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
jQuery('document').ready(function($)
|
||||
{
|
||||
jQuery('.adapter-select').each(function () {
|
||||
change_adapter(jQuery(this));
|
||||
});
|
||||
|
||||
jQuery('.adapter-select').on('change', function (e)
|
||||
{
|
||||
change_adapter(jQuery(this));
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.phone-limits-group-remove', function (e)
|
||||
{
|
||||
e.preventDefault();
|
||||
jQuery(this).parent('.phone-limits-group').remove();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.add-phone-limit-button', function(e)
|
||||
{
|
||||
var phone_id = jQuery(this).parents('.entry-container').attr('data-entry-id');
|
||||
var random_id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||
var newLimit = '' +
|
||||
'<div class="row phone-limits-group">'+
|
||||
'<div class="col-xs-4">'+
|
||||
'<label>Période</label><br/>'+
|
||||
'<select name="phones[' + phone_id + '][limits][' + random_id + '][startpoint]" class="form-control adapter-select" required>'+
|
||||
'<option value="" disabled selected>Période sur laquelle appliquer la limite</option>'+
|
||||
'<option value="today">Par jour</option>'+
|
||||
'<option value="-24 hours">24 heures glissantes</option>'+
|
||||
'<option value="this week midnight">Cette semaine</option>'+
|
||||
'<option value="-7 days">7 jours glissants</option>'+
|
||||
'<option value="this week midnight -1 week">Ces deux dernières semaines</option>'+
|
||||
'<option value="-14 days">14 jours glissants</option>'+
|
||||
'<option value="this month midnight">Ce mois</option>'+
|
||||
'<option value="-1 month">1 mois glissant</option>'+
|
||||
'<option value="-28 days">28 jours glissants</option>'+
|
||||
'<option value="-30 days">30 jours glissants</option>'+
|
||||
'<option value="-31 days">31 jours glissants</option>'+
|
||||
'</select>'+
|
||||
'</div>'+
|
||||
'<div class="scheduleds-number-data-container col-xs-8">'+
|
||||
'<label>Volume</label>'+
|
||||
'<div class="form-group">'+
|
||||
'<input name="phones[' + phone_id + '][limits][' + random_id + '][volume]" class="form-control" type="number" min="1" placeholder="Nombre de SMS maximum sur la période.">'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>'+
|
||||
'</div>';
|
||||
|
||||
jQuery(this).parent('div').before(newLimit);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
$this->render('incs/footer');
|
|
@ -41,8 +41,10 @@
|
|||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Priorité</th>
|
||||
<th>Type de téléphone</th>
|
||||
<th>Callbacks</th>
|
||||
<th>Limites</th>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -56,6 +58,7 @@
|
|||
</div>
|
||||
<div class="text-right col-xs-6 no-padding">
|
||||
<strong>Action pour la séléction :</strong>
|
||||
<button class="btn btn-default" type="submit" formaction="<?php echo \descartes\Router::url('Phone', 'edit'); ?>"><span class="fa fa-edit"></span> Modifier</button>
|
||||
<button class="btn btn-default btn-confirm" type="submit" formaction="<?php echo \descartes\Router::url('Phone', 'delete', ['csrf' => $_SESSION['csrf']]); ?>"><span class="fa fa-trash-o"></span> Supprimer</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,6 +91,7 @@ jQuery(document).ready(function ()
|
|||
"columns" : [
|
||||
{data: 'id', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'name', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'priority', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'adapter', render: jQuery.fn.dataTable.render.text()},
|
||||
{
|
||||
data: '_',
|
||||
|
@ -123,6 +127,61 @@ jQuery(document).ready(function ()
|
|||
return html;
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'limits',
|
||||
render: function (limits) {
|
||||
if (!limits.length)
|
||||
{
|
||||
return 'Pas de limites.';
|
||||
}
|
||||
|
||||
var html = '';
|
||||
for (limit of limits)
|
||||
{
|
||||
switch (limit.startpoint)
|
||||
{
|
||||
case "today" :
|
||||
var startpoint = 'Par jour';
|
||||
break;
|
||||
case "-24 hours" :
|
||||
var startpoint = '24 heures glissantes';
|
||||
break;
|
||||
case "this week midnight" :
|
||||
var startpoint = 'Cette semaine';
|
||||
break;
|
||||
case "-7 days" :
|
||||
var startpoint = '7 jours glissants';
|
||||
break;
|
||||
case "this week midnight -1 week" :
|
||||
var startpoint = 'Ces deux dernières semaines';
|
||||
break;
|
||||
case "-14 days" :
|
||||
var startpoint = '14 jours glissants';
|
||||
break;
|
||||
case "this month midnight" :
|
||||
var startpoint = 'Ce mois';
|
||||
break;
|
||||
case "-1 month" :
|
||||
var startpoint = '1 mois glissant';
|
||||
break;
|
||||
case "-28 days" :
|
||||
var startpoint = '28 jours glissants';
|
||||
break;
|
||||
case "-30 days" :
|
||||
var startpoint = '30 jours glissants';
|
||||
break;
|
||||
case "-31 days" :
|
||||
var startpoint = '31 jours glissants';
|
||||
break;
|
||||
default :
|
||||
var startpoint = 'Inconnu'
|
||||
}
|
||||
html += '<div><span class="bold">' + jQuery.fn.dataTable.render.text().display(startpoint) + ' : </span>' + jQuery.fn.dataTable.render.text().display(limit.volume) + '</div>';
|
||||
}
|
||||
|
||||
return html;
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'id',
|
||||
render: function (data, type, row, meta) {
|
||||
|
|
|
@ -54,6 +54,25 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-font fa-fw"></i> Alphabet SMS optimisé</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'force_gsm_alphabet', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Optimiser la taille des SMS en remplaçant les caractères spéciaux par leur équivalent GSM 7-bit : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['force_gsm_alphabet'] ? 'selected' : ''; ?>>Oui</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-picture-o fa-fw"></i> Support des MMS</h4>
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue