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]]
|
* @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 : [
|
* @return array : [
|
||||||
* bool 'error' => false if no error, true else
|
* bool 'error' => false if no error, true else,
|
||||||
* ?string 'error_message' => null if no error, else error message
|
* ?string 'error_message' => null if no error, else error message,
|
||||||
* array 'uid' => Uid of the sms created on success
|
* 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;
|
public function send(string $destination, string $text, bool $flash = false, bool $mms = false, array $medias = []): array;
|
||||||
|
|
|
@ -311,7 +311,8 @@ footer img
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SCHEDULEDS */
|
/* SCHEDULEDS */
|
||||||
.add-number-button
|
.add-number-button,
|
||||||
|
.add-phone-limit-button
|
||||||
{
|
{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
color: #DADFE1;
|
color: #DADFE1;
|
||||||
|
@ -319,7 +320,8 @@ footer img
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-number-button:hover
|
.add-number-button:hover,
|
||||||
|
.add-phone-limit-button:hover
|
||||||
{
|
{
|
||||||
color: #3498DB;
|
color: #3498DB;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -373,7 +375,8 @@ footer img
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scheduleds-number-groupe
|
.scheduleds-number-groupe,
|
||||||
|
.phone-limits-group
|
||||||
{
|
{
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
|
@ -383,7 +386,8 @@ footer img
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scheduleds-number-groupe-remove
|
.scheduleds-number-groupe-remove,
|
||||||
|
.phone-limits-group-remove
|
||||||
{
|
{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
|
@ -391,7 +395,8 @@ footer img
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scheduleds-number-groupe-remove:hover
|
.scheduleds-number-groupe-remove:hover,
|
||||||
|
.phone-limits-group-remove:hover
|
||||||
{
|
{
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
|
@ -466,6 +471,16 @@ footer img
|
||||||
color: #9b2420;
|
color: #9b2420;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PREVIEW CONTACT */
|
||||||
|
.preview-contact-name
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-contact-number
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
/* PHONE */
|
/* PHONE */
|
||||||
#adapter-data-container
|
#adapter-data-container
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
"symfony/yaml": "^5.0",
|
"symfony/yaml": "^5.0",
|
||||||
"phpmailer/phpmailer": "^6.1",
|
"phpmailer/phpmailer": "^6.1",
|
||||||
"xantios/mimey": ">=2.1",
|
"xantios/mimey": ">=2.1",
|
||||||
"kreait/firebase-php": "^5.14"
|
"kreait/firebase-php": "^5.14",
|
||||||
},
|
"benmorel/gsm-charset-converter": "^0.3.0"
|
||||||
"require-dev": {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,21 +73,6 @@ namespace controllers\internals;
|
||||||
return $this->get_model()->insert($event);
|
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.
|
* 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);
|
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)
|
}, function ($arguments, DateTime $birthdate)
|
||||||
{
|
{
|
||||||
if (!($birthdate ?? false))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $birthdate->format('m-d') == (new DateTime())->format('m-d');
|
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
|
* @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 $name : The name of the phone
|
||||||
* @param string $adapter : The adapter to use 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 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
|
* @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 = [
|
$phone = [
|
||||||
'id_user' => $id_user,
|
'id_user' => $id_user,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
|
'priority' => $priority,
|
||||||
'adapter' => $adapter,
|
'adapter' => $adapter,
|
||||||
'adapter_data' => $adapter_data,
|
'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 int $id : Phone id
|
||||||
* @param string $name : The name of the phone
|
* @param string $name : The name of the phone
|
||||||
* @param string $adapter : The adapter to use 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
|
* @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 = [
|
$phone = [
|
||||||
'id_user' => $id_user,
|
'id_user' => $id_user,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'adapter' => $adapter,
|
'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);
|
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.
|
* Parse a CSV file of numbers, potentially associated with datas.
|
||||||
*
|
*
|
||||||
|
@ -627,4 +397,292 @@ use Monolog\Logger;
|
||||||
|
|
||||||
return $this->model;
|
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);
|
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.
|
* 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,
|
'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');
|
$at = (new \DateTime())->format('Y-m-d H:i:s');
|
||||||
$media_uris = [];
|
$media_uris = [];
|
||||||
foreach ($medias as $media)
|
foreach ($medias as $media)
|
||||||
|
@ -272,38 +275,56 @@ namespace controllers\internals;
|
||||||
$text .= "\n" . join(' - ', $media_urls);
|
$text .= "\n" . join(' - ', $media_urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $adapter->send($destination, $text, $flash, $mms, $media_uris);
|
//If we reached our max quota, do not send the message
|
||||||
|
$internal_quota = new Quota($this->bdd);
|
||||||
if ($response['error'])
|
$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'] = true;
|
||||||
$return['error_message'] = $response['error_message'];
|
$return['error_message'] = 'Not enough credit to send 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$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,
|
'id' => $sended_id,
|
||||||
'at' => $at,
|
'at' => $at,
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
|
@ -316,7 +337,7 @@ namespace controllers\internals;
|
||||||
];
|
];
|
||||||
|
|
||||||
$internal_webhook = new Webhook($this->bdd);
|
$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;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace controllers\internals;
|
namespace controllers\internals;
|
||||||
|
|
||||||
|
use BenMorel\GsmCharsetConverter\Converter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some tools frequently used.
|
* Some tools frequently used.
|
||||||
* Not a standard controller as it's not linked to a model in any way.
|
* 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;
|
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.
|
* 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}";
|
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;
|
$error_code = null;
|
||||||
$queue = msg_get_queue(QUEUE_ID_WEBHOOK);
|
$queue = msg_get_queue(QUEUE_ID_WEBHOOK);
|
||||||
$success = msg_send($queue, QUEUE_TYPE_WEBHOOK, $message, true, true, $error_code);
|
msg_send($queue, QUEUE_TYPE_WEBHOOK, $message, true, true, $error_code);
|
||||||
|
|
||||||
return (bool) $success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -506,6 +506,8 @@ namespace controllers\publics;
|
||||||
* @param string $_POST['name'] : Phone name
|
* @param string $_POST['name'] : Phone name
|
||||||
* @param string $_POST['adapter'] : Phone adapter
|
* @param string $_POST['adapter'] : Phone adapter
|
||||||
* @param array $_POST['adapter_data'] : Phone adapter data
|
* @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
|
* @return int : id phone the new phone on success
|
||||||
*/
|
*/
|
||||||
|
@ -516,6 +518,10 @@ namespace controllers\publics;
|
||||||
$name = $_POST['name'] ?? false;
|
$name = $_POST['name'] ?? false;
|
||||||
$adapter = $_POST['adapter'] ?? false;
|
$adapter = $_POST['adapter'] ?? false;
|
||||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
|
$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)
|
if (!$name)
|
||||||
{
|
{
|
||||||
|
@ -535,7 +541,7 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
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)
|
if ($name_exist)
|
||||||
{
|
{
|
||||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||||
|
@ -545,6 +551,36 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
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();
|
$adapters = $this->internal_adapter->list_adapters();
|
||||||
$find_adapter = false;
|
$find_adapter = false;
|
||||||
foreach ($adapters as $metas)
|
foreach ($adapters as $metas)
|
||||||
|
@ -627,7 +663,7 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
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)
|
if (false === $phone_id)
|
||||||
{
|
{
|
||||||
$return['error'] = self::ERROR_CODES['CANNOT_CREATE'];
|
$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['name'] : New phone name
|
||||||
* @param string (optionnal) $_POST['adapter'] : New phone adapter
|
* @param string (optionnal) $_POST['adapter'] : New phone adapter
|
||||||
* @param array (optionnal) $_POST['adapter_data'] : New phone adapter data
|
* @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
|
* @return int : id phone the new phone on success
|
||||||
*/
|
*/
|
||||||
|
@ -667,10 +704,16 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
return $this->json($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$limits = $this->internal_phone->get_limits(($phone['id']));
|
||||||
|
|
||||||
$name = $_POST['name'] ?? $phone['name'];
|
$name = $_POST['name'] ?? $phone['name'];
|
||||||
|
$priority = $_POST['priority'] ?? $phone['priority'];
|
||||||
|
$priority = max(((int) $priority), 0);
|
||||||
$adapter = $_POST['adapter'] ?? $phone['adapter'];
|
$adapter = $_POST['adapter'] ?? $phone['adapter'];
|
||||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : json_decode($phone['adapter_data']);
|
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : json_decode($phone['adapter_data']);
|
||||||
$adapter_data = is_array($adapter_data) ? $adapter_data : [$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)
|
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'])
|
if ($phone_with_same_name && $phone_with_same_name['id'] != $phone['id'])
|
||||||
{
|
{
|
||||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||||
|
@ -693,6 +736,36 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
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();
|
$adapters = $this->internal_adapter->list_adapters();
|
||||||
$find_adapter = false;
|
$find_adapter = false;
|
||||||
foreach ($adapters as $metas)
|
foreach ($adapters as $metas)
|
||||||
|
@ -775,7 +848,7 @@ namespace controllers\publics;
|
||||||
return $this->json($return);
|
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)
|
if (!$success)
|
||||||
{
|
{
|
||||||
$return['error'] = self::ERROR_CODES['CANNOT_UPDATE'];
|
$return['error'] = self::ERROR_CODES['CANNOT_UPDATE'];
|
||||||
|
|
|
@ -185,6 +185,45 @@ namespace controllers\publics;
|
||||||
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
|
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.
|
* Try to get the preview of contacts for a conditionnal group.
|
||||||
*
|
*
|
||||||
|
|
|
@ -372,6 +372,7 @@ namespace controllers\publics;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$invalid_type = true;
|
$invalid_type = true;
|
||||||
|
$result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,45 @@ namespace controllers\publics;
|
||||||
return $this->redirect(\descartes\Router::url('Group', 'list'));
|
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.
|
* Cette fonction retourne la liste des groups sous forme JSON.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -55,6 +55,9 @@ class Phone extends \descartes\Controller
|
||||||
|
|
||||||
foreach ($phones as &$phone)
|
foreach ($phones as &$phone)
|
||||||
{
|
{
|
||||||
|
$limits = $this->internal_phone->get_limits($phone['id']);
|
||||||
|
$phone['limits'] = $limits;
|
||||||
|
|
||||||
$adapter = $adapters[$phone['adapter']] ?? false;
|
$adapter = $adapters[$phone['adapter']] ?? false;
|
||||||
|
|
||||||
if (!$adapter)
|
if (!$adapter)
|
||||||
|
@ -131,9 +134,11 @@ class Phone extends \descartes\Controller
|
||||||
* Create a new phone.
|
* Create a new phone.
|
||||||
*
|
*
|
||||||
* @param $csrf : CSRF token
|
* @param $csrf : CSRF token
|
||||||
* @param string $_POST['name'] : Phone name
|
* @param string $_POST['name'] : Phone name
|
||||||
* @param string $_POST['adapter'] : Phone adapter
|
* @param string $_POST['adapter'] : Phone adapter
|
||||||
* @param array $_POST['adapter_data'] : Phone adapter data
|
* @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)
|
public function create($csrf)
|
||||||
{
|
{
|
||||||
|
@ -146,8 +151,12 @@ class Phone extends \descartes\Controller
|
||||||
|
|
||||||
$id_user = $_SESSION['user']['id'];
|
$id_user = $_SESSION['user']['id'];
|
||||||
$name = $_POST['name'] ?? false;
|
$name = $_POST['name'] ?? false;
|
||||||
|
$priority = $_POST['priority'] ?? 0;
|
||||||
|
$priority = max(((int) $priority), 0);
|
||||||
$adapter = $_POST['adapter'] ?? false;
|
$adapter = $_POST['adapter'] ?? false;
|
||||||
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
|
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
|
||||||
|
$limits = $_POST['limits'] ?? [];
|
||||||
|
$limits = is_array($limits) ? $limits : [$limits];
|
||||||
|
|
||||||
if (!$name || !$adapter)
|
if (!$name || !$adapter)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +165,7 @@ class Phone extends \descartes\Controller
|
||||||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
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)
|
if ($name_exist)
|
||||||
{
|
{
|
||||||
\FlashMessage\FlashMessage::push('danger', 'Ce nom est déjà utilisé pour un autre téléphone.');
|
\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'));
|
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();
|
$adapters = $this->internal_adapter->list_adapters();
|
||||||
$find_adapter = false;
|
$find_adapter = false;
|
||||||
foreach ($adapters as $metas)
|
foreach ($adapters as $metas)
|
||||||
|
@ -245,7 +284,7 @@ class Phone extends \descartes\Controller
|
||||||
return $this->redirect(\descartes\Router::url('Phone', 'add'));
|
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)
|
if (!$success)
|
||||||
{
|
{
|
||||||
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce téléphone.');
|
\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 $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);
|
$result = $this->internal_templating->render($template, $data);
|
||||||
$return = $result;
|
$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']))
|
if (!trim($result['result']))
|
||||||
{
|
{
|
||||||
$return['result'] = 'Message vide, il ne sera pas envoyé.';
|
$return['result'] = 'Message vide, il ne sera pas envoyé.';
|
||||||
|
|
|
@ -22,6 +22,7 @@ class Sender extends AbstractDaemon
|
||||||
private $internal_phone;
|
private $internal_phone;
|
||||||
private $internal_scheduled;
|
private $internal_scheduled;
|
||||||
private $internal_received;
|
private $internal_received;
|
||||||
|
private $internal_sended;
|
||||||
private $bdd;
|
private $bdd;
|
||||||
private $msg_queue;
|
private $msg_queue;
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ class Sender extends AbstractDaemon
|
||||||
{
|
{
|
||||||
//Create the internal controllers
|
//Create the internal controllers
|
||||||
$this->internal_scheduled = new \controllers\internals\Scheduled($this->bdd);
|
$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
|
//Get smss and transmit order to send to appropriate phone daemon
|
||||||
$smss_per_scheduled = $this->internal_scheduled->get_smss_to_send();
|
$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)
|
foreach ($smss_per_scheduled as $id_scheduled => $smss)
|
||||||
{
|
{
|
||||||
//If queue not already exists
|
//If queue not already exists
|
||||||
if (!msg_queue_exists(QUEUE_ID_PHONE) || !isset($this->queue))
|
if (!msg_queue_exists(QUEUE_ID_PHONE) || !isset($this->msg_queue))
|
||||||
{
|
{
|
||||||
$this->msg_queue = msg_get_queue(QUEUE_ID_PHONE);
|
$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_reached' => 1,
|
||||||
'alert_quota_limit_close' => 0.9,
|
'alert_quota_limit_close' => 0.9,
|
||||||
'hide_menus' => '',
|
'hide_menus' => '',
|
||||||
|
'force_gsm_alphabet' => 0,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -84,32 +84,6 @@ namespace models;
|
||||||
return $this->_select('event', ['id_user' => $id_user], 'at', true, $nb_entry);
|
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.
|
* 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
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -63,6 +63,48 @@ namespace models;
|
||||||
return $this->_select_one('phone', ['name' => $name]);
|
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.
|
* Return table name.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -178,6 +178,20 @@ namespace models;
|
||||||
return $this->_select_one('sended', ['id_user' => $id_user, 'uid' => $uid, 'adapter' => $adapter]);
|
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.
|
* Get number of sended SMS for every date since a date for a specific user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
'delete' => '/group/delete/{csrf}/',
|
'delete' => '/group/delete/{csrf}/',
|
||||||
'edit' => '/group/edit/',
|
'edit' => '/group/edit/',
|
||||||
'update' => '/group/update/{csrf}/',
|
'update' => '/group/update/{csrf}/',
|
||||||
|
'preview' => '/group/preview/{id_group}/',
|
||||||
'json_list' => '/groups.json/',
|
'json_list' => '/groups.json/',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@
|
||||||
'edit' => '/conditional_group/edit/',
|
'edit' => '/conditional_group/edit/',
|
||||||
'update' => '/conditional_group/update/{csrf}/',
|
'update' => '/conditional_group/update/{csrf}/',
|
||||||
'contacts_preview' => '/conditional_group/preview/',
|
'contacts_preview' => '/conditional_group/preview/',
|
||||||
|
'preview' => '/conditional_group/preview/{id_group}/',
|
||||||
'json_list' => '/conditional_groups.json/',
|
'json_list' => '/conditional_groups.json/',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -160,6 +162,8 @@
|
||||||
'add' => '/phone/add/',
|
'add' => '/phone/add/',
|
||||||
'create' => '/phone/create/{csrf}/',
|
'create' => '/phone/create/{csrf}/',
|
||||||
'delete' => '/phone/delete/{csrf}/',
|
'delete' => '/phone/delete/{csrf}/',
|
||||||
|
'edit' => '/phone/edit/',
|
||||||
|
'update' => '/phone/update/{csrf}/',
|
||||||
],
|
],
|
||||||
|
|
||||||
'Call' => [
|
'Call' => [
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<th>Condition</th>
|
<th>Condition</th>
|
||||||
<th>Date de création</th>
|
<th>Date de création</th>
|
||||||
<th>Dernière modification</th>
|
<th>Dernière modification</th>
|
||||||
|
<th>Preview</th>
|
||||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -69,9 +70,56 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
<script>
|
||||||
jQuery(document).ready(function ()
|
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({
|
jQuery('.datatable').DataTable({
|
||||||
"pageLength": 25,
|
"pageLength": 25,
|
||||||
"lengthMenu": [[25, 50, 100, 1000, 10000, -1], [25, 50, 100, 1000, 10000, "All"]],
|
"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: 'created_at'},
|
||||||
{data: 'updated_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',
|
data: 'id',
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
|
@ -106,7 +160,6 @@ jQuery(document).ready(function ()
|
||||||
],
|
],
|
||||||
"deferRender": true
|
"deferRender": true
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<th>Nombre de contacts</th>
|
<th>Nombre de contacts</th>
|
||||||
<th>Date de création</th>
|
<th>Date de création</th>
|
||||||
<th>Dernière modification</th>
|
<th>Dernière modification</th>
|
||||||
|
<th>Preview</th>
|
||||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -69,6 +70,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
<script>
|
||||||
jQuery(document).ready(function ()
|
jQuery(document).ready(function ()
|
||||||
{
|
{
|
||||||
|
@ -92,6 +108,12 @@ jQuery(document).ready(function ()
|
||||||
{data: 'nb_contact', render: jQuery.fn.dataTable.render.text()},
|
{data: 'nb_contact', render: jQuery.fn.dataTable.render.text()},
|
||||||
{data: 'created_at'},
|
{data: 'created_at'},
|
||||||
{data: 'updated_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',
|
data: 'id',
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
|
@ -102,6 +124,38 @@ jQuery(document).ready(function ()
|
||||||
"deferRender": true
|
"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>
|
</script>
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -48,7 +48,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<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">
|
<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.
|
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>
|
</p>
|
||||||
|
@ -67,7 +76,7 @@
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="adapter-data-container" class="form-group">
|
<div id="adapter-data-container" class="form-group well">
|
||||||
<div id="adapter-data-description-container">
|
<div id="adapter-data-description-container">
|
||||||
<h4>Description du téléphone</h4>
|
<h4>Description du téléphone</h4>
|
||||||
<div id="adapter-data-description"></div>
|
<div id="adapter-data-description"></div>
|
||||||
|
@ -77,6 +86,15 @@
|
||||||
<h4>Réglages du téléphone</h4>
|
<h4>Réglages du téléphone</h4>
|
||||||
<div id="adapter-data-fields"></div>
|
<div id="adapter-data-fields"></div>
|
||||||
</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>
|
</div>
|
||||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
|
<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" />
|
<input type="submit" class="btn btn-success" value="Enregistrer le téléphone" />
|
||||||
|
@ -174,6 +192,47 @@
|
||||||
{
|
{
|
||||||
change_adapter();
|
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>
|
</script>
|
||||||
<?php
|
<?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>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Nom</th>
|
<th>Nom</th>
|
||||||
|
<th>Priorité</th>
|
||||||
<th>Type de téléphone</th>
|
<th>Type de téléphone</th>
|
||||||
<th>Callbacks</th>
|
<th>Callbacks</th>
|
||||||
|
<th>Limites</th>
|
||||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -56,6 +58,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right col-xs-6 no-padding">
|
<div class="text-right col-xs-6 no-padding">
|
||||||
<strong>Action pour la séléction :</strong>
|
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,6 +91,7 @@ jQuery(document).ready(function ()
|
||||||
"columns" : [
|
"columns" : [
|
||||||
{data: 'id', render: jQuery.fn.dataTable.render.text()},
|
{data: 'id', render: jQuery.fn.dataTable.render.text()},
|
||||||
{data: 'name', 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: 'adapter', render: jQuery.fn.dataTable.render.text()},
|
||||||
{
|
{
|
||||||
data: '_',
|
data: '_',
|
||||||
|
@ -123,6 +127,61 @@ jQuery(document).ready(function ()
|
||||||
return html;
|
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',
|
data: 'id',
|
||||||
render: function (data, type, row, meta) {
|
render: function (data, type, row, meta) {
|
||||||
|
|
|
@ -54,6 +54,25 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</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 panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h4 class="panel-title"><i class="fa fa-picture-o fa-fw"></i> Support des MMS</h4>
|
<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