From 651c428ed709f955889fb9f30a8c06f59630d3aa Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Fri, 16 Jul 2021 22:53:33 +0200 Subject: [PATCH 1/8] move received listing to serverside processing --- controllers/internals/Received.php | 22 ++++++++- controllers/internals/Sended.php | 12 +++-- controllers/publics/Received.php | 54 ++++++++++++--------- models/Received.php | 75 ++++++++++++++++++++---------- routes.php | 6 ++- templates/received/list.php | 4 +- 6 files changed, 116 insertions(+), 57 deletions(-) diff --git a/controllers/internals/Received.php b/controllers/internals/Received.php index b9b6cfc..c921469 100644 --- a/controllers/internals/Received.php +++ b/controllers/internals/Received.php @@ -15,6 +15,26 @@ namespace controllers\internals; { protected $model; + /** + * Return the list of entries for a user. + * + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results + * @param bool $unread : Should only unread messages be returned + * + * @return array : Entrys list + */ + public function datatable_list_for_user(int $id_user, ?int $limit = null, ?int $offset = null, ?string $search = null, ?array $search_columns = [], ?string $order_column = null, bool $order_desc = false, bool $count = false, bool $unread = false) + { + return $this->get_model()->datatable_list_for_user($id_user, $limit, $offset, $search, $search_columns, $order_column, $order_desc, $count, $unread); + } + /** * Return the list of unread messages for a user. * @@ -355,7 +375,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Received { $this->model = $this->model ?? new \models\Received($this->bdd); diff --git a/controllers/internals/Sended.php b/controllers/internals/Sended.php index 455cd0a..a153873 100644 --- a/controllers/internals/Sended.php +++ b/controllers/internals/Sended.php @@ -16,15 +16,17 @@ namespace controllers\internals; protected $model; /** - * Return the list of entries for a user. - * + * * @param int $id_user : User id * @param ?int $limit : Number of entry to return * @param ?int $offset : Number of entry to avoid * @param ?string $search : String to search for - * @param ?array $orders : How to order results + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results * - * @return array : Entrys list + * @return array : Entries list */ public function datatable_list_for_user(int $id_user, ?int $limit = null, ?int $offset = null, ?string $search = null, ?array $search_columns = [], ?string $order_column = null, bool $order_desc = false, $count = false) { @@ -305,7 +307,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Sended { $this->model = $this->model ?? new \models\Sended($this->bdd); diff --git a/controllers/publics/Received.php b/controllers/publics/Received.php index d6ab5a4..09c9fd6 100644 --- a/controllers/publics/Received.php +++ b/controllers/publics/Received.php @@ -47,11 +47,31 @@ namespace controllers\publics; } /** - * Return received as json. + * Return receiveds as json. + * + * @param bool $unread : Should we only search for unread messages */ - public function list_json() + public function list_json(bool $unread = false) { - $entities = $this->internal_received->list_for_user($_SESSION['user']['id']); + $draw = (int)($_GET['draw'] ?? false); + + $columns = [ + 0 => 'searchable_origin', + 1 => 'phone_name', + 2 => 'text', + 3 => 'at', + 4 => 'status', + 5 => 'command', + ]; + + $search = $_GET['search']['value'] ?? null; + $order_column = $columns[$_GET['order'][0]['column']] ?? null; + $order_desc = ($_GET['order'][0]['dir'] ?? 'asc') == 'desc' ? true : false; + $offset = (int) ($_GET['start'] ?? 0); + $limit = (int) ($_GET['length'] ?? 25); + + $entities = $this->internal_received->datatable_list_for_user($_SESSION['user']['id'], $limit, $offset, $search, $columns, $order_column, $order_desc, false, $unread); + $count_entities = $this->internal_received->datatable_list_for_user($_SESSION['user']['id'], $limit, $offset, $search, $columns, $order_column, $order_desc, true, $unread); foreach ($entities as &$entity) { $entity['origin_formatted'] = \controllers\internals\Tool::phone_link($entity['origin']); @@ -61,8 +81,15 @@ namespace controllers\publics; } } + $records_total = $this->internal_received->count_for_user($_SESSION['user']['id']); + header('Content-Type: application/json'); - echo json_encode(['data' => $entities]); + echo json_encode([ + 'draw' => $draw, + 'recordsTotal' => $records_total, + 'recordsFiltered' => $count_entities, + 'data' => $entities, + ]); } /** @@ -73,25 +100,6 @@ namespace controllers\publics; $this->render('received/list', ['is_unread' => true]); } - /** - * Return unred received as json. - */ - public function list_unread_json() - { - $entities = $this->internal_received->list_unread_for_user($_SESSION['user']['id']); - foreach ($entities as &$entity) - { - $entity['origin_formatted'] = \controllers\internals\Tool::phone_link($entity['origin']); - if ($entity['mms']) - { - $entity['medias'] = $this->internal_media->gets_for_received($entity['id']); - } - } - - header('Content-Type: application/json'); - echo json_encode(['data' => $entities]); - } - /** * Mark messages as. * diff --git a/models/Received.php b/models/Received.php index c25289f..728720e 100644 --- a/models/Received.php +++ b/models/Received.php @@ -20,29 +20,60 @@ namespace models; const STATUS_READ = 'read'; /** - * Return a list of received messages for a user. - * Add a column contact_name and phone_name when available. + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results + * @param bool $unread : Should only unread messages be returned * - * @param int $id_user : user id - * @param ?int $limit : Number of entry to return or null - * @param ?int $offset : Number of entry to ignore or null - * - * @return array + * @return array : Entrys list */ - public function list_for_user(int $id_user, $limit, $offset) + public function datatable_list_for_user(int $id_user, ?int $limit = null, ?int $offset = null, ?string $search = null, ?array $search_columns = [], ?string $order_column = null, bool $order_desc = false, bool $count = false, bool $unread = false) { - $query = ' - SELECT received.*, contact.name as contact_name, phone.name as phone_name - FROM received - LEFT JOIN contact - ON contact.number = received.origin - AND contact.id_user = received.id_user - LEFT JOIN phone - ON phone.id = received.id_phone - WHERE received.id_user = :id_user - '; + $params = [ + 'id_user' => $id_user, + ]; - if (null !== $limit) + $query = $count ? 'SELECT COUNT(*) as nb' : 'SELECT * '; + $query .= ' + FROM ( + SELECT received.*, contact.name as contact_name, phone.name as phone_name, IF(contact.name IS NULL, received.origin, CONCAT(received.origin, " (", contact.name, ")")) as searchable_origin + FROM received + LEFT JOIN contact + ON contact.number = received.origin + AND contact.id_user = received.id_user + LEFT JOIN phone + ON phone.id = received.id_phone + WHERE received.id_user = :id_user + ' . ($unread ? ' AND received.status = \'unread\'' : '') . ' + ) as results +'; + + if ($search && $search_columns) + { + $like_search = '%' . str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $search) . '%'; + $params[':like_search'] = $like_search; + + $query .= ' WHERE (0'; + + foreach ($search_columns as $column) + { + $query .= ' OR ' . $column . ' LIKE :like_search'; + } + + $query .= ')'; + } + + if ($order_column) + { + $query .= ' ORDER BY ' . $order_column . ($order_desc ? ' DESC' : ' ASC'); + } + + if (null !== $limit && !$count) { $limit = (int) $limit; @@ -54,11 +85,7 @@ namespace models; } } - $params = [ - 'id_user' => $id_user, - ]; - - return $this->_run_query($query, $params); + return ($count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params)) ; } /** diff --git a/routes.php b/routes.php index 5ddf90b..b9f6f96 100644 --- a/routes.php +++ b/routes.php @@ -93,9 +93,11 @@ 'Received' => [ 'list' => '/received/', - 'list_json' => '/received/json/', + 'list_json' => [ + '/received/json/', + '/received/json/{unread}/', + ], 'list_unread' => '/unread/', - 'list_unread_json' => '/unread/json/', 'mark_as' => '/mark/{status}/{csrf}/', 'delete' => '/received/delete/{csrf}/', 'popup' => '/received/popup/', diff --git a/templates/received/list.php b/templates/received/list.php index f470a11..eca0c02 100644 --- a/templates/received/list.php +++ b/templates/received/list.php @@ -87,9 +87,9 @@ jQuery(document).ready(function () 'targets': 'checkcolumn', 'orderable': false, }], - + "serverSide": true, "ajax": { - 'url': '', + 'url': ' true]) : \descartes\Router::url('Received', 'list_json'); ?>', 'dataSrc': 'data', }, "columns" : [ From 8f3634b921a2ab1d6f5ef6e3fcd8ac96b085d9f1 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 15:57:18 +0200 Subject: [PATCH 2/8] fix get model --- controllers/internals/Received.php | 2 +- controllers/internals/Sended.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/internals/Received.php b/controllers/internals/Received.php index c921469..0126e42 100644 --- a/controllers/internals/Received.php +++ b/controllers/internals/Received.php @@ -375,7 +375,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \models\Received + protected function get_model(): \descartes\Model { $this->model = $this->model ?? new \models\Received($this->bdd); diff --git a/controllers/internals/Sended.php b/controllers/internals/Sended.php index a153873..3734dda 100644 --- a/controllers/internals/Sended.php +++ b/controllers/internals/Sended.php @@ -307,7 +307,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \models\Sended + protected function get_model(): \descartes\Model { $this->model = $this->model ?? new \models\Sended($this->bdd); From 231efc736bf4090c938fc5b7f42e9d239d348c02 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 17:02:37 +0200 Subject: [PATCH 3/8] Fix smsstop list on non-admin --- templates/smsstop/list.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/templates/smsstop/list.php b/templates/smsstop/list.php index 5010c5d..ff6b418 100644 --- a/templates/smsstop/list.php +++ b/templates/smsstop/list.php @@ -40,7 +40,7 @@ Numéro - + @@ -50,7 +50,7 @@
- +
Action pour la séléction : @@ -74,11 +74,11 @@ jQuery(document).ready(function () "language": { "url": HTTP_PWD + "/assets/js/datatables/french.json", }, + "orderMulti": false, "columnDefs": [{ 'targets': 'checkcolumn', 'orderable': false, }], - "ajax": { 'url': '', 'dataSrc': 'data', @@ -86,13 +86,16 @@ jQuery(document).ready(function () "columns" : [ { data: 'number_formatted', + render: jQuery.fn.dataTable.render.text() }, + { data: 'id', render: function (data, type, row, meta) { return ''; }, }, + ], "deferRender": true }); From e21b89cc7ceaf9f59c6cc812e9bde2d033c1ced1 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 17:03:31 +0200 Subject: [PATCH 4/8] Fix smsstop list on non-admin --- templates/smsstop/list.php | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/smsstop/list.php b/templates/smsstop/list.php index ff6b418..598429b 100644 --- a/templates/smsstop/list.php +++ b/templates/smsstop/list.php @@ -86,7 +86,6 @@ jQuery(document).ready(function () "columns" : [ { data: 'number_formatted', - render: jQuery.fn.dataTable.render.text() }, { From e957c9feb7115a050c241993494eab2d6e6a3a31 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 17:32:23 +0200 Subject: [PATCH 5/8] use correct model and fix style --- .gitignore | 1 + adapters/OctopushShortcodeAdapter.php | 26 ++++++++---------- adapters/OctopushVirtualNumberAdapter.php | 29 ++++++++------------ controllers/internals/Call.php | 2 +- controllers/internals/Command.php | 2 +- controllers/internals/ConditionalGroup.php | 2 +- controllers/internals/Contact.php | 2 +- controllers/internals/Event.php | 2 +- controllers/internals/Group.php | 2 +- controllers/internals/Media.php | 2 +- controllers/internals/Phone.php | 2 +- controllers/internals/Quota.php | 2 +- controllers/internals/Received.php | 20 +++++++------- controllers/internals/Scheduled.php | 2 +- controllers/internals/Sended.php | 21 +++++++------- controllers/internals/Setting.php | 2 +- controllers/internals/SmsStop.php | 25 +++++++++-------- controllers/internals/StandardController.php | 2 +- controllers/internals/Webhook.php | 2 +- controllers/publics/Account.php | 8 ++++-- controllers/publics/Connect.php | 1 - controllers/publics/Received.php | 4 +-- controllers/publics/Sended.php | 3 +- controllers/publics/User.php | 14 +++++----- models/Received.php | 24 ++++++++-------- models/Sended.php | 8 +++--- templates/received/list.php | 1 + templates/sended/list.php | 1 + templates/smsstop/list.php | 4 +-- 29 files changed, 105 insertions(+), 111 deletions(-) diff --git a/.gitignore b/.gitignore index 78ab9f5..939d0c2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .php_cs.cache .credentials .credentials* +.vscode/ vendor/ scripts/ composer.lock diff --git a/adapters/OctopushShortcodeAdapter.php b/adapters/OctopushShortcodeAdapter.php index d7ed533..afa4802 100644 --- a/adapters/OctopushShortcodeAdapter.php +++ b/adapters/OctopushShortcodeAdapter.php @@ -38,9 +38,9 @@ class OctopushShortcodeAdapter implements AdapterInterface * Sender name to use instead of shortcode. */ private $sender; - + /** - * Octopush SMS type + * Octopush SMS type. */ private $sms_type; @@ -49,7 +49,6 @@ class OctopushShortcodeAdapter implements AdapterInterface */ private $api_url = 'https://api.octopush.com/v1/public'; - /** * Adapter constructor, called when instanciated by RaspiSMS. * @@ -64,7 +63,7 @@ class OctopushShortcodeAdapter implements AdapterInterface $this->api_key = $this->data['api_key']; $this->sms_type = self::SMS_TYPE_LOWCOST; - if (($this->data['sms_type'] ?? false) && $this->data['sms_type'] === 'premium') + if (($this->data['sms_type'] ?? false) && 'premium' === $this->data['sms_type']) { $this->sms_type = self::SMS_TYPE_PREMIUM; } @@ -234,7 +233,7 @@ class OctopushShortcodeAdapter implements AdapterInterface $data = [ 'text' => $text, - 'recipients' => [['phone_number' => $destination]], + 'recipients' => [['phone_number' => $destination]], 'sms_type' => $this->sms_type, 'purpose' => 'alert', ]; @@ -245,12 +244,11 @@ class OctopushShortcodeAdapter implements AdapterInterface } else { - $data['with_replies'] = "True"; + $data['with_replies'] = 'True'; } $data = json_encode($data); - $endpoint = $this->api_url . '/sms-campaign/send'; $curl = curl_init(); @@ -260,7 +258,7 @@ class OctopushShortcodeAdapter implements AdapterInterface curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - + $curl_response = curl_exec($curl); $http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); @@ -332,7 +330,7 @@ class OctopushShortcodeAdapter implements AdapterInterface { return false; } - + $headers = [ 'api-login: ' . $this->login, 'api-key: ' . $this->api_key, @@ -350,7 +348,7 @@ class OctopushShortcodeAdapter implements AdapterInterface $http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); - if ($http_code !== 200) + if (200 !== $http_code) { return false; } @@ -369,14 +367,13 @@ class OctopushShortcodeAdapter implements AdapterInterface header('Content-Encoding: none'); header('Content-Length: 0'); - $input = file_get_contents('php://input'); $content = json_decode($input, true); if (null === $content) { return false; } - + $uid = $content['message_id'] ?? false; $status = $content['status'] ?? false; @@ -385,7 +382,6 @@ class OctopushShortcodeAdapter implements AdapterInterface return false; } - switch ($status) { case 'DELIVERED': @@ -420,14 +416,14 @@ class OctopushShortcodeAdapter implements AdapterInterface header('Connection: close'); header('Content-Encoding: none'); header('Content-Length: 0'); - + $input = file_get_contents('php://input'); $content = json_decode($input, true); if (null === $content) { $response['error'] = true; $response['error_message'] = 'Cannot read input data from callback request.'; - + return $response; } diff --git a/adapters/OctopushVirtualNumberAdapter.php b/adapters/OctopushVirtualNumberAdapter.php index 1715937..d758f8a 100644 --- a/adapters/OctopushVirtualNumberAdapter.php +++ b/adapters/OctopushVirtualNumberAdapter.php @@ -35,7 +35,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface private $api_key; /** - * Octopush SMS type + * Octopush SMS type. */ private $sms_type; @@ -45,11 +45,10 @@ class OctopushVirtualNumberAdapter implements AdapterInterface private $api_url = 'https://api.octopush.com/v1/public'; /** - * Octopush phone number + * Octopush phone number. */ private $number; - /** * Adapter constructor, called when instanciated by RaspiSMS. * @@ -65,7 +64,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface $this->number = $this->data['number']; $this->sms_type = self::SMS_TYPE_LOWCOST; - if (($this->data['sms_type'] ?? false) && $this->data['sms_type'] === 'premium') + if (($this->data['sms_type'] ?? false) && 'premium' === $this->data['sms_type']) { $this->sms_type = self::SMS_TYPE_PREMIUM; } @@ -118,7 +117,6 @@ class OctopushVirtualNumberAdapter implements AdapterInterface Envoi de SMS avec un numéro virtuel en utilisant Octopush. Pour trouver vos clés API Octopush cliquez ici.
Pour plus d\'information sur l\'utilisation de ce téléphone, reportez-vous à la documentation sur les téléphones "Octopush Numéro Virtuel". '; - } /** @@ -154,7 +152,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface 'description' => 'Type de SMS à employer coté Octopush, rentrez "low cost" ou "premium" selon le type de SMS que vous souhaitez employer. Laissez vide pour utiliser par défaut des SMS low cost.', 'required' => false, ], - ]; + ]; } /** @@ -233,16 +231,15 @@ class OctopushVirtualNumberAdapter implements AdapterInterface $data = [ 'text' => $text, - 'recipients' => [['phone_number' => $destination]], + 'recipients' => [['phone_number' => $destination]], 'sms_type' => $this->sms_type, 'purpose' => 'alert', 'sender' => $this->number, - 'with_replies' => "True", + 'with_replies' => 'True', ]; $data = json_encode($data); - $endpoint = $this->api_url . '/sms-campaign/send'; $curl = curl_init(); @@ -252,7 +249,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - + $curl_response = curl_exec($curl); $http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); @@ -325,7 +322,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface { return false; } - + $headers = [ 'api-login: ' . $this->login, 'api-key: ' . $this->api_key, @@ -343,7 +340,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface $http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); - if ($http_code !== 200) + if (200 !== $http_code) { return false; } @@ -362,14 +359,13 @@ class OctopushVirtualNumberAdapter implements AdapterInterface header('Content-Encoding: none'); header('Content-Length: 0'); - $input = file_get_contents('php://input'); $content = json_decode($input, true); if (null === $content) { return false; } - + $uid = $content['message_id'] ?? false; $status = $content['status'] ?? false; @@ -378,7 +374,6 @@ class OctopushVirtualNumberAdapter implements AdapterInterface return false; } - switch ($status) { case 'DELIVERED': @@ -413,14 +408,14 @@ class OctopushVirtualNumberAdapter implements AdapterInterface header('Connection: close'); header('Content-Encoding: none'); header('Content-Length: 0'); - + $input = file_get_contents('php://input'); $content = json_decode($input, true); if (null === $content) { $response['error'] = true; $response['error_message'] = 'Cannot read input data from callback request.'; - + return $response; } diff --git a/controllers/internals/Call.php b/controllers/internals/Call.php index 9f47aaa..79ce96c 100644 --- a/controllers/internals/Call.php +++ b/controllers/internals/Call.php @@ -136,7 +136,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Call { $this->model = $this->model ?? new \models\Call($this->bdd); diff --git a/controllers/internals/Command.php b/controllers/internals/Command.php index 10f10c5..2059746 100644 --- a/controllers/internals/Command.php +++ b/controllers/internals/Command.php @@ -150,7 +150,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Command { $this->model = $this->model ?? new \models\Command($this->bdd); diff --git a/controllers/internals/ConditionalGroup.php b/controllers/internals/ConditionalGroup.php index bed5fa2..17f66b0 100644 --- a/controllers/internals/ConditionalGroup.php +++ b/controllers/internals/ConditionalGroup.php @@ -134,7 +134,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\ConditionalGroup { $this->model = $this->model ?? new \models\ConditionalGroup($this->bdd); diff --git a/controllers/internals/Contact.php b/controllers/internals/Contact.php index 502299e..8934d2e 100644 --- a/controllers/internals/Contact.php +++ b/controllers/internals/Contact.php @@ -351,7 +351,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Contact { $this->model = $this->model ?? new \models\Contact($this->bdd); diff --git a/controllers/internals/Event.php b/controllers/internals/Event.php index d43de0e..cdf62b3 100644 --- a/controllers/internals/Event.php +++ b/controllers/internals/Event.php @@ -74,7 +74,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Event { $this->model = $this->model ?? new \models\Event($this->bdd); diff --git a/controllers/internals/Group.php b/controllers/internals/Group.php index c000d59..cf70970 100644 --- a/controllers/internals/Group.php +++ b/controllers/internals/Group.php @@ -130,7 +130,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Group { $this->model = $this->model ?? new \models\Group($this->bdd); diff --git a/controllers/internals/Media.php b/controllers/internals/Media.php index 8d230fc..25fb988 100644 --- a/controllers/internals/Media.php +++ b/controllers/internals/Media.php @@ -313,7 +313,7 @@ class Media extends StandardController /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Media { $this->model = $this->model ?? new \models\Media($this->bdd); diff --git a/controllers/internals/Phone.php b/controllers/internals/Phone.php index b473a02..8cef65e 100644 --- a/controllers/internals/Phone.php +++ b/controllers/internals/Phone.php @@ -166,7 +166,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Phone { $this->model = $this->model ?? new \models\Phone($this->bdd); diff --git a/controllers/internals/Quota.php b/controllers/internals/Quota.php index e1bcaf1..b93f8b2 100644 --- a/controllers/internals/Quota.php +++ b/controllers/internals/Quota.php @@ -288,7 +288,7 @@ class Quota extends StandardController /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Quota { $this->model = $this->model ?? new \models\Quota($this->bdd); diff --git a/controllers/internals/Received.php b/controllers/internals/Received.php index 0126e42..3e6218e 100644 --- a/controllers/internals/Received.php +++ b/controllers/internals/Received.php @@ -18,15 +18,15 @@ namespace controllers\internals; /** * Return the list of entries for a user. * - * @param int $id_user : User id - * @param ?int $limit : Number of entry to return - * @param ?int $offset : Number of entry to avoid - * @param ?string $search : String to search for - * @param ?array $search_columns : List of columns to search on - * @param ?string $order_column : Name of the column to order by - * @param bool $order_desc : Should result be ordered DESC, if false order ASC - * @param bool $count : Should the query only count results - * @param bool $unread : Should only unread messages be returned + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results + * @param bool $unread : Should only unread messages be returned * * @return array : Entrys list */ @@ -375,7 +375,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Received { $this->model = $this->model ?? new \models\Received($this->bdd); diff --git a/controllers/internals/Scheduled.php b/controllers/internals/Scheduled.php index 9282aed..09dc566 100644 --- a/controllers/internals/Scheduled.php +++ b/controllers/internals/Scheduled.php @@ -544,7 +544,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Scheduled { $this->model = $this->model ?? new \models\Scheduled($this->bdd); diff --git a/controllers/internals/Sended.php b/controllers/internals/Sended.php index 3734dda..504cece 100644 --- a/controllers/internals/Sended.php +++ b/controllers/internals/Sended.php @@ -14,17 +14,16 @@ namespace controllers\internals; class Sended extends StandardController { protected $model; - + /** - * - * @param int $id_user : User id - * @param ?int $limit : Number of entry to return - * @param ?int $offset : Number of entry to avoid - * @param ?string $search : String to search for - * @param ?array $search_columns : List of columns to search on - * @param ?string $order_column : Name of the column to order by - * @param bool $order_desc : Should result be ordered DESC, if false order ASC - * @param bool $count : Should the query only count results + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results * * @return array : Entries list */ @@ -307,7 +306,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Sended { $this->model = $this->model ?? new \models\Sended($this->bdd); diff --git a/controllers/internals/Setting.php b/controllers/internals/Setting.php index d2620e5..84f62cf 100644 --- a/controllers/internals/Setting.php +++ b/controllers/internals/Setting.php @@ -89,7 +89,7 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Setting { $this->model = $this->model ?? new \models\Setting($this->bdd); diff --git a/controllers/internals/SmsStop.php b/controllers/internals/SmsStop.php index 1cfc649..29d310a 100644 --- a/controllers/internals/SmsStop.php +++ b/controllers/internals/SmsStop.php @@ -64,24 +64,25 @@ namespace controllers\internals; return $this->get_model()->get_by_number_for_user($id_user, $number); } + /** + * Parse a string to check if its a SMS stop. + * + * @param string $str : The string to check + * + * @return bool : true if sms stop, false else + */ + public function check_for_stop(string $str) + { + return 'stop' == trim(mb_strtolower($str)); + } + /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\SmsStop { $this->model = $this->model ?? new \models\SmsStop($this->bdd); return $this->model; } - - /** - * Parse a string to check if its a SMS stop - * - * @param string $str : The string to check - * @return bool : true if sms stop, false else - */ - public function check_for_stop (string $str) - { - return trim(mb_strtolower($str)) == 'stop'; - } } diff --git a/controllers/internals/StandardController.php b/controllers/internals/StandardController.php index 6c9b52b..66b39a1 100644 --- a/controllers/internals/StandardController.php +++ b/controllers/internals/StandardController.php @@ -138,5 +138,5 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - abstract protected function get_model(): \descartes\Model; + abstract protected function get_model(): \models\StandardModel; } diff --git a/controllers/internals/Webhook.php b/controllers/internals/Webhook.php index 3cbaff0..bb2c3bd 100644 --- a/controllers/internals/Webhook.php +++ b/controllers/internals/Webhook.php @@ -146,7 +146,7 @@ class Webhook extends StandardController /** * Get the model for the Controller. */ - protected function get_model(): \descartes\Model + protected function get_model(): \models\Webhook { $this->model = $this->model ?? new \models\Webhook($this->bdd); diff --git a/controllers/publics/Account.php b/controllers/publics/Account.php index bcd4327..3daddfd 100644 --- a/controllers/publics/Account.php +++ b/controllers/publics/Account.php @@ -204,10 +204,11 @@ namespace controllers\publics; return $this->redirect(\descartes\Router::url('Connect', 'login')); } - + /** - * Allow to stop impersonating a user - * @param mixed $csrf + * Allow to stop impersonating a user. + * + * @param mixed $csrf */ public function stop_impersonate() { @@ -223,6 +224,7 @@ namespace controllers\publics; $_SESSION = $old_session; \FlashMessage\FlashMessage::push('success', 'Vous n\'incarnez plus l\'utilisateur ' . $user_email . '.'); + return $this->redirect(\descartes\Router::url('Dashboard', 'show')); } } diff --git a/controllers/publics/Connect.php b/controllers/publics/Connect.php index 8c5faf2..d254b97 100644 --- a/controllers/publics/Connect.php +++ b/controllers/publics/Connect.php @@ -164,5 +164,4 @@ namespace controllers\publics; return $this->redirect(\descartes\Router::url('Connect', 'login')); } - } diff --git a/controllers/publics/Received.php b/controllers/publics/Received.php index 09c9fd6..4d52ca7 100644 --- a/controllers/publics/Received.php +++ b/controllers/publics/Received.php @@ -48,12 +48,12 @@ namespace controllers\publics; /** * Return receiveds as json. - * + * * @param bool $unread : Should we only search for unread messages */ public function list_json(bool $unread = false) { - $draw = (int)($_GET['draw'] ?? false); + $draw = (int) ($_GET['draw'] ?? false); $columns = [ 0 => 'searchable_origin', diff --git a/controllers/publics/Sended.php b/controllers/publics/Sended.php index b96e50e..d82bed6 100644 --- a/controllers/publics/Sended.php +++ b/controllers/publics/Sended.php @@ -53,8 +53,7 @@ namespace controllers\publics; */ public function list_json() { - - $draw = (int)($_GET['draw'] ?? false); + $draw = (int) ($_GET['draw'] ?? false); $columns = [ 0 => 'phone_name', diff --git a/controllers/publics/User.php b/controllers/publics/User.php index 0581548..1b20046 100644 --- a/controllers/publics/User.php +++ b/controllers/publics/User.php @@ -410,13 +410,13 @@ class User extends \descartes\Controller return $this->redirect(\descartes\Router::url('User', 'list')); } - /** - * Allow an admin to impersonate a user + * Allow an admin to impersonate a user. + * * @param mixed $csrf * @param array int $_GET['user_ids'] : Ids of users to impersonate, the array should actually contain one id only, we keep use of array for simpler compatibility in UI */ - public function impersonate ($csrf) + public function impersonate($csrf) { if (!$this->verify_csrf($csrf)) { @@ -425,7 +425,7 @@ class User extends \descartes\Controller return $this->redirect(\descartes\Router::url('User', 'list')); } - if (count($_GET['user_ids']) != 1) + if (1 != count($_GET['user_ids'])) { \FlashMessage\FlashMessage::push('danger', 'Vous devez séléctionner un et un seul utilisateur à incarner !'); @@ -460,17 +460,17 @@ class User extends \descartes\Controller $user['settings'] = $settings; - //Save old session to get it back later + //Save old session to get it back later $old_session = $_SESSION; $_SESSION = [ - 'old_session' => $old_session, + 'old_session' => $old_session, 'impersonate' => true, 'connect' => true, 'user' => $user, ]; \FlashMessage\FlashMessage::push('success', 'Vous incarnez désormais l\'utilisateur ' . $user['email'] . '.'); + return $this->redirect(\descartes\Router::url('Dashboard', 'show')); } - } diff --git a/models/Received.php b/models/Received.php index 728720e..66fc4b4 100644 --- a/models/Received.php +++ b/models/Received.php @@ -20,15 +20,15 @@ namespace models; const STATUS_READ = 'read'; /** - * @param int $id_user : User id - * @param ?int $limit : Number of entry to return - * @param ?int $offset : Number of entry to avoid - * @param ?string $search : String to search for - * @param ?array $search_columns : List of columns to search on - * @param ?string $order_column : Name of the column to order by - * @param bool $order_desc : Should result be ordered DESC, if false order ASC - * @param bool $count : Should the query only count results - * @param bool $unread : Should only unread messages be returned + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results + * @param bool $unread : Should only unread messages be returned * * @return array : Entrys list */ @@ -57,9 +57,9 @@ namespace models; { $like_search = '%' . str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $search) . '%'; $params[':like_search'] = $like_search; - + $query .= ' WHERE (0'; - + foreach ($search_columns as $column) { $query .= ' OR ' . $column . ' LIKE :like_search'; @@ -85,7 +85,7 @@ namespace models; } } - return ($count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params)) ; + return $count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params); } /** diff --git a/models/Sended.php b/models/Sended.php index 9657619..b401ccc 100644 --- a/models/Sended.php +++ b/models/Sended.php @@ -48,15 +48,15 @@ namespace models; ON phone.id = sended.id_phone WHERE sended.id_user = :id_user ) as results -'; + '; if ($search && $search_columns) { $like_search = '%' . str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $search) . '%'; $params[':like_search'] = $like_search; - + $query .= ' WHERE (0'; - + foreach ($search_columns as $column) { $query .= ' OR ' . $column . ' LIKE :like_search'; @@ -82,7 +82,7 @@ namespace models; } } - return ($count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params)) ; + return $count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params); } /** diff --git a/templates/received/list.php b/templates/received/list.php index eca0c02..cd240b6 100644 --- a/templates/received/list.php +++ b/templates/received/list.php @@ -83,6 +83,7 @@ jQuery(document).ready(function () "language": { "url": HTTP_PWD + "/assets/js/datatables/french.json", }, + "orderMulti": false, "columnDefs": [{ 'targets': 'checkcolumn', 'orderable': false, diff --git a/templates/sended/list.php b/templates/sended/list.php index a8ee985..9cb1761 100644 --- a/templates/sended/list.php +++ b/templates/sended/list.php @@ -73,6 +73,7 @@ jQuery(document).ready(function () "language": { "url": HTTP_PWD + "/assets/js/datatables/french.json", }, + "orderMulti": false, "columnDefs": [{ 'targets': 'checkcolumn', 'orderable': false, diff --git a/templates/smsstop/list.php b/templates/smsstop/list.php index 598429b..15cbcb5 100644 --- a/templates/smsstop/list.php +++ b/templates/smsstop/list.php @@ -86,9 +86,9 @@ jQuery(document).ready(function () "columns" : [ { data: 'number_formatted', - }, + } - { + ,{ data: 'id', render: function (data, type, row, meta) { return ''; From 169cbfde2db3a1c76279b2b140ad3524453be239 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 20:55:45 +0200 Subject: [PATCH 6/8] remove return type on get model to make it more widely compatible --- controllers/internals/StandardController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/internals/StandardController.php b/controllers/internals/StandardController.php index 66b39a1..69ca128 100644 --- a/controllers/internals/StandardController.php +++ b/controllers/internals/StandardController.php @@ -138,5 +138,5 @@ namespace controllers\internals; /** * Get the model for the Controller. */ - abstract protected function get_model(): \models\StandardModel; + abstract protected function get_model(); } From 3084288e5d55a9fe8f4941499daea7b0ca4b08c8 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 20:56:44 +0200 Subject: [PATCH 7/8] remove return type on get model to make it more widely compatible --- controllers/internals/StandardController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/controllers/internals/StandardController.php b/controllers/internals/StandardController.php index 69ca128..58d693e 100644 --- a/controllers/internals/StandardController.php +++ b/controllers/internals/StandardController.php @@ -137,6 +137,8 @@ namespace controllers\internals; /** * Get the model for the Controller. + * + * @return \models\StandardModel */ abstract protected function get_model(); } From 8e43c53498c4dbeca7630b8cd15a5a6342b02288 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Mon, 19 Jul 2021 21:14:56 +0200 Subject: [PATCH 8/8] Add serverside list for contacts --- controllers/internals/Contact.php | 17 +++++++++ controllers/publics/Contact.php | 28 +++++++++++++-- models/Contact.php | 59 +++++++++++++++++++++++++++++++ templates/contact/list.php | 3 +- 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/controllers/internals/Contact.php b/controllers/internals/Contact.php index 8934d2e..b9d19f9 100644 --- a/controllers/internals/Contact.php +++ b/controllers/internals/Contact.php @@ -15,6 +15,23 @@ namespace controllers\internals; { protected $model; + /** + * @param int $id_user : User id + * @param ?int $limit : Number of entry to return + * @param ?int $offset : Number of entry to avoid + * @param ?string $search : String to search for + * @param ?array $search_columns : List of columns to search on + * @param ?string $order_column : Name of the column to order by + * @param bool $order_desc : Should result be ordered DESC, if false order ASC + * @param bool $count : Should the query only count results + * + * @return array : Entries list + */ + public function datatable_list_for_user(int $id_user, ?int $limit = null, ?int $offset = null, ?string $search = null, ?array $search_columns = [], ?string $order_column = null, bool $order_desc = false, $count = false) + { + return $this->get_model()->datatable_list_for_user($id_user, $limit, $offset, $search, $search_columns, $order_column, $order_desc, $count); + } + /** * Return a contact for a user by a number. * diff --git a/controllers/publics/Contact.php b/controllers/publics/Contact.php index 600e5e8..6fed079 100644 --- a/controllers/publics/Contact.php +++ b/controllers/publics/Contact.php @@ -45,19 +45,43 @@ namespace controllers\publics; return $this->render('contact/list'); } + /** * Return contacts as json. */ public function list_json() { - $entities = $this->internal_contact->list_for_user($_SESSION['user']['id']); + $draw = (int) ($_GET['draw'] ?? false); + + $columns = [ + 0 => 'name', + 1 => 'number', + 2 => 'created_at', + 3 => 'updated_at', + ]; + + $search = $_GET['search']['value'] ?? null; + $order_column = $columns[$_GET['order'][0]['column']] ?? null; + $order_desc = ($_GET['order'][0]['dir'] ?? 'asc') == 'desc' ? true : false; + $offset = (int) ($_GET['start'] ?? 0); + $limit = (int) ($_GET['length'] ?? 25); + + $entities = $this->internal_contact->datatable_list_for_user($_SESSION['user']['id'], $limit, $offset, $search, $columns, $order_column, $order_desc); + $count_entities = $this->internal_contact->datatable_list_for_user($_SESSION['user']['id'], $limit, $offset, $search, $columns, $order_column, $order_desc, true); foreach ($entities as &$entity) { $entity['number_formatted'] = \controllers\internals\Tool::phone_link($entity['number']); } + $records_total = $this->internal_contact->count_for_user($_SESSION['user']['id']); + header('Content-Type: application/json'); - echo json_encode(['data' => $entities]); + echo json_encode([ + 'draw' => $draw, + 'recordsTotal' => $records_total, + 'recordsFiltered' => $count_entities, + 'data' => $entities, + ]); } /** diff --git a/models/Contact.php b/models/Contact.php index 5646424..b9e682e 100644 --- a/models/Contact.php +++ b/models/Contact.php @@ -13,6 +13,65 @@ namespace models; class Contact extends StandardModel { + /** + * Return a list of sended messages for a user. + * Add a column contact_name and phone_name when available. + * + * @param int $id_user : user id + * @param ?int $limit : Number of entry to return or null + * @param ?int $offset : Number of entry to ignore or null + * + * @return array + */ + public function datatable_list_for_user(int $id_user, ?int $limit = null, ?int $offset = null, ?string $search = null, ?array $search_columns = [], ?string $order_column = null, bool $order_desc = false, ?bool $count = false) + { + $params = [ + 'id_user' => $id_user, + ]; + + $query = $count ? 'SELECT COUNT(*) as nb' : 'SELECT * '; + $query .= ' + FROM ( + SELECT * FROM contact + WHERE id_user = :id_user + ) as results + '; + + if ($search && $search_columns) + { + $like_search = '%' . str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $search) . '%'; + $params[':like_search'] = $like_search; + + $query .= ' WHERE (0'; + + foreach ($search_columns as $column) + { + $query .= ' OR ' . $column . ' LIKE :like_search'; + } + + $query .= ')'; + } + + if ($order_column) + { + $query .= ' ORDER BY ' . $order_column . ($order_desc ? ' DESC' : ' ASC'); + } + + if (null !== $limit && !$count) + { + $limit = (int) $limit; + + $query .= ' LIMIT ' . $limit; + if (null !== $offset) + { + $offset = (int) $offset; + $query .= ' OFFSET ' . $offset; + } + } + + return $count ? $this->_run_query($query, $params)[0]['nb'] ?? 0 : $this->_run_query($query, $params); + } + /** * Return a contact by his number for a user. * diff --git a/templates/contact/list.php b/templates/contact/list.php index 03de988..2284706 100644 --- a/templates/contact/list.php +++ b/templates/contact/list.php @@ -186,11 +186,12 @@ jQuery(document).ready(function() "language": { "url": HTTP_PWD + "/assets/js/datatables/french.json", }, + "orderMulti": false, "columnDefs": [{ 'targets': 'checkcolumn', 'orderable': false, }], - + "serverSide": true, "ajax": { 'url': '', 'dataSrc': 'data',