diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..75e3d6e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +#On force les retours UNIX +text eol=lf diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/controllers/commands.php b/controllers/commands.php index a88c388..5b21da8 100755 --- a/controllers/commands.php +++ b/controllers/commands.php @@ -15,26 +15,17 @@ } /** - * Cette fonction est alias de showAll() + * Cette fonction retourne toutes les commandes, sous forme d'un tableau permettant l'administration de ces commandess */ public function byDefault() - { - $this->showAll(); - } - - /** - * Cette fonction retourne toutes les commandes, sous forme d'un tableau permettant l'administration de ces commandess - * @return void; - */ - public function showAll() { //Creation de l'object de base de données global $db; //Recupération des commandes - $commands = $db->getAll('commands'); + $commands = $db->getFromTableWhere('commands'); - $this->render('commands', array( + $this->render('commands/default', array( 'commands' => $commands, )); @@ -42,24 +33,24 @@ /** * Cette fonction va supprimer une liste de commands - * @return void; + * @param int... $ids : Les id des commandes à supprimer + * @return boolean; */ - public function delete() + public function delete($csrf, ...$ids) { - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('commands', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('commands')); + return false; } //Create de l'object de base de données global $db; - $commands_ids = $_GET; - $db->deleteCommandsIn($commands_ids); + $db->deleteCommandsIn($ids); header('Location: ' . $this->generateUrl('commands')); + return true; } /** @@ -67,91 +58,87 @@ */ public function add() { - $this->render('addCommand'); + $this->render('commands/add'); } /** - * Cette fonction retourne la page d'édition des contacts + * Cette fonction retourne la page d'édition des commandes + * @param int... $ids : Les id des commandes à editer */ - public function edit() + public function edit(...$ids) { global $db; - - $commands = $db->getCommandsIn($_GET); - $this->render('editCommands', array( + $commands = $db->getCommandsIn($ids); + $this->render('commands/edit', array( 'commands' => $commands, )); } /** * Cette fonction insert une nouvelle commande + * @param $csrf : Le jeton CSRF + * @param string $_POST['name'] : Le nom de la commande + * @param string $_POST['script'] : Le script a appeler + * @param boolean $_POST['admin'] : Si la commande necessite les droits d'admin (par défaut non) + * @return boolean; */ - public function create() + public function create($csrf) { - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('commands', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('commands')); return true; } global $db; - $nom = $_POST['name']; $script = $_POST['script']; $admin = (isset($_POST['admin']) ? $_POST['admin'] : false); - if ($db->createCommand($nom, $script, $admin)) - { - $db->createEvent('COMMAND_ADD', 'Ajout commande : ' . $nom . ' => ' . $script); - header('Location: ' . $this->generateUrl('commands', 'showAll', array( - 'successmessage' => 'La commande a bien été créée.' - ))); - return true; + if (!$db->insertIntoTable('commands', ['name' => $nom, 'script' => $script, 'admin' => $admin])) + { + $_SESSION['errormessage'] = 'Impossible créer cette commande.'; + header('Location: ' . $this->generateUrl('commands', 'add')); + return false; } - header('Location: ' . $this->generateUrl('commands', 'add', array( - 'errormessage' => 'Impossible créer cette commande.' - ))); - return false; + $db->insertIntoTable('events', ['type' => 'COMMAND_ADD', 'text' => 'Ajout commande : ' . $nom . ' => ' . $script]); + + $_SESSION['successmessage'] = 'La commande a bien été créée.'; + header('Location: ' . $this->generateUrl('commands')); + return true; + } /** * Cette fonction met à jour une commande + * @param $csrf : Le jeton CSRF + * @param array $_POST['commands'] : Un tableau des commandes avec leur nouvelle valeurs + * @return boolean; */ - public function update() + public function update($csrf) { - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('commands', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('commands')); + return false; } global $db; - $errors = array(); //On initialise le tableau qui contiendra les erreurs rencontrés + //Pour chaque commande reçu, on boucle en récupérant son id (la clef), et la commande elle-même (la value) - - foreach ($_POST['commands'] as $id => $command) { - $db->updateCommand($id, $command['name'], $command['script'], $command['admin']); + $db->updateTableWhere('commands', $command, ['id' => $id]); } - $message = 'Toutes les commandes ont été modifiées avec succès.'; - header('Location: ' . $this->generateUrl('commands', 'showAll', array( - 'successmessage' => $message, - ))); - } - - public function flagMeThat() - { - var_dump(internalTools::parseForFlag('[COMMAND:chauffer 35][PASSWORD:mon password qui rox][LOGin:monlogin]')); + $_SESSION['successmessage'] = 'Toutes les commandes ont été modifiées avec succès.'; + header('Location: ' . $this->generateUrl('commands')); } } diff --git a/controllers/connect.php b/controllers/connect.php index d00dff1..2ce7f2b 100755 --- a/controllers/connect.php +++ b/controllers/connect.php @@ -5,22 +5,11 @@ class connect extends Controller { /** - * Cette fonction est alias de login() + * Cette fonction retourne la fenetre de connexion */ public function byDefault() { - $this->login(); - } - - /** - * Cette fonction retourne la fenetre de connexion - * @return void; - */ - public function login() - { - //Creation de l'object de base de données - global $db; - $this->render('login'); + $this->render('connect/login'); } /** @@ -29,10 +18,6 @@ */ public function forgetPassword() { - //Creation de l'object de base de données - global $db; - - $this->render('forgetPassword'); } @@ -48,32 +33,32 @@ //Creation de l'object de base de données global $db; - $email = $_POST['mail']; $password = $_POST['password']; - if ($user = $db->getUserFromEmail($email)) + if (!$users = $db->getFromTableWhere('users', ['email' => $email])) { - if (sha1($password) == $user['password']) - { - $_SESSION['connect'] = true; - $_SESSION['admin'] = $user['admin']; - $_SESSION['email'] = $user['email']; - $_SESSION['csrf'] = str_shuffle(uniqid().uniqid()); - header('Location: ' . $this->generateUrl('')); - return true; - } - - header('Location: ' . $this->generateUrl('connect', 'login', array( - 'errormessage' => 'Identifiants incorrects.' - ))); + $_SESSION['errormessage'] = 'Identifiants incorrects.'; + header('Location: ' . $this->generateUrl('connect', 'login')); return false; } - header('Location: ' . $this->generateUrl('connect', 'login', array( - 'errormessage' => 'Cet e-mail n\'existe pas.' - ))); - return false; + $user = $users[0]; + + if (sha1($password) != $user['password']) + { + $_SESSION['errormessage'] = 'Cet e-mail n\'existe pas.'; + header('Location: ' . $this->generateUrl('connect', 'login')); + return false; + } + + $_SESSION['connect'] = true; + $_SESSION['admin'] = $user['admin']; + $_SESSION['email'] = $user['email']; + $_SESSION['transfer'] = $user['transfer']; + $_SESSION['csrf'] = str_shuffle(uniqid().uniqid()); + header('Location: ' . $this->generateUrl('')); + return true; } /** @@ -86,38 +71,40 @@ //Creation de l'object de base de données global $db; - $email = $_POST['mail']; - if ($user = $db->getUserFromEmail($email)) + if (!$users = $db->getFromTableWhere('users', ['email' => $email])) { - $password = internalTools::generatePassword(rand(8,12)); - $message = "Vous avez demandé un nouveau mot de passe pour le site " . HTTP_PWD . ".\n"; - $message = "Votre nouveau mot de passe a été généré aléatoirement, et n'est connu que de vous. Le voici : \n"; - $message .= "Nouveau mot de passe : " . $password . "\n\n"; - $message .= "-------------------------------------\n"; - $message .= "Pour plus d'informations sur le système RaspiSMS, rendez-vous sur le site http://raspbian-france.fr\n"; - if (mail($email, 'RaspiSMS - Recuperation de mot de passe', $message)) - { - $new_password = sha1($password); - if ($db->updateUser($user['id'], $user['email'], $new_password, $user['admin'])) - { - header('Location: ' . $this->generateUrl('connect', 'login', array( - 'successmessage' => 'Un nouveau mot de passe vous a été envoyé par mail.' - ))); - return true; - } - } - - header('Location: ' . $this->generateUrl('connect', 'forgetPassword', array( - 'errormessage' => 'Impossible d\'envoyer les nouveaux identifiants.' - ))); + $_SESSION['errormessage'] = 'Cet e-mail n\'existe pas.'; + header('Location: ' . $this->generateUrl('connect', 'forgetPassword')); return false; } - header('Location: ' . $this->generateUrl('connect', 'forgetPassword', array( - 'errormessage' => 'Cet e-mail n\'existe pas.' - ))); - return false; + + $password = internalTools::generatePassword(rand(8,12)); + $message = "Vous avez demandé un nouveau mot de passe pour le site " . HTTP_PWD . ".\n"; + $message = "Votre nouveau mot de passe a été généré aléatoirement, et n'est connu que de vous. Le voici : \n"; + $message .= "Nouveau mot de passe : " . $password . "\n\n"; + $message .= "-------------------------------------\n"; + $message .= "Pour plus d'informations sur le système RaspiSMS, rendez-vous sur le site http://raspbian-france.fr\n"; + if (!mail($email, 'RaspiSMS - Recuperation de mot de passe', $message)) + { + $_SESSION['errormessage'] = 'Impossible d\'envoyer les nouveaux identifiants.'; + header('Location: ' . $this->generateUrl('connect', 'forgetPassword')); + return false; + } + + $new_password = sha1($password); + if (!$db->updateTableWhere('users', ['email' => $user['email'], 'password' => $new_password, 'admin' => $user['admin']], ['id' => $user['id']])) + { + $_SESSION['errormessage'] = 'Impossible de mettre à jour le mot de passe.'; + header('Location: ' . $this->generateUrl('connect', 'login')); + return false; + } + + $_SESSION['successmessage'] = 'Un nouveau mot de passe vous a été envoyé par mail.'; + header('Location: ' . $this->generateUrl('connect', 'login')); + return true; + } /** diff --git a/controllers/contacts.php b/controllers/contacts.php index 7d7e21b..5800a7e 100755 --- a/controllers/contacts.php +++ b/controllers/contacts.php @@ -15,51 +15,43 @@ } /** - * Cette fonction est alias de showAll() + * Cette fonction retourne tous les contacts, sous forme d'un tableau permettant l'administration de ces contacts */ public function byDefault() - { - $this->showAll(); - } - - /** - * Cette fonction retourne tous les contacts, sous forme d'un tableau permettant l'administration de ces contacts - * @return void; - */ - public function showAll() { //Creation de l'object de base de données global $db; //Recupération des nombres des 4 panneaux d'accueil - $contacts = $db->getAll('contacts'); + $contacts = $db->getFromTableWhere('contacts'); - $this->render('contacts', array( + $this->render('contacts/default', array( 'contacts' => $contacts, )); - } /** * Cette fonction supprimer une liste de contacts - * @return void; + * @param $csrf : Le jeton CSRF + * @param int... $ids : Les id des commandes à supprimer + * @return Boolean; */ - public function delete() + public function delete($csrf, ...$ids) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('contacts')); + return false; } //Create de l'object de base de données global $db; - $contacts_ids = $_GET; - $db->deleteContactsIn($contacts_ids); - header('Location: ' . $this->generateUrl('contacts')); + $db->deleteContactsIn($ids); + header('Location: ' . $this->generateUrl('contacts')); + return true; } /** @@ -67,110 +59,112 @@ */ public function add() { - $this->render('addContact'); + $this->render('contacts/add'); } /** * Cette fonction retourne la page d'édition des contacts + * @param int... $ids : Les id des commandes à supprimer */ - public function edit() + public function edit(...$ids) { global $db; - - $contacts = $db->getContactsIn($_GET); - $this->render('editContacts', array( + $contacts = $db->getContactsIn($ids); + $this->render('contacts/edit', array( 'contacts' => $contacts, )); } /** * Cette fonction insert un nouveau contact + * @param $csrf : Le jeton CSRF + * @param string $_POST['name'] : Le nom du contact + * @param string $_POST['phone'] : Le numero de téléphone du contact */ - public function create() + public function create($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('contacts')); + return false; } global $db; - + + if (empty($_POST['name']) || empty($_POST['phone'])) + { + $_SESSION['errormessage'] = 'Des champs sont manquants.'; + header('Location: ' . $this->generateUrl('contacts', 'add')); + return false; + } $nom = $_POST['name']; $phone = $_POST['phone']; - if ($phone = internalTools::parsePhone($phone)) + + if (!$phone = internalTools::parsePhone($phone)) { - if ($db->createContact($nom, $phone)) - { - $db->createEvent('CONTACT_ADD', 'Ajout contact : ' . $nom . ' (' . internalTools::phoneAddSpace($phone) . ')'); - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'successmessage' => 'Le contact a bien été créé.' - ))); - - return true; - } - - header('Location: ' . $this->generateUrl('contacts', 'add', array( - 'errormessage' => 'Impossible créer ce contact.' - ))); - return true; + $_SESSION['errormessage'] = 'Numéro de téléphone incorrect.'; + header('Location: ' . $this->generateUrl('contacts', 'add')); + return false; } - header('Location: ' . $this->generateUrl('contacts', 'add', array( - 'errormessage' => 'Numéro de téléphone incorrect.' - ))); + if (!$db->insertIntoTable('contacts', ['name' => $nom, 'number' => $phone])) + { + $_SESSION['errormessage'] = 'Impossible créer ce contact.'; + header('Location: ' . $this->generateUrl('contacts', 'add')); + return false; + } + + $db->insertIntoTable('events', ['type' => 'CONTACT_ADD', 'text' => 'Ajout contact : ' . $nom . ' (' . internalTools::phoneAddSpace($phone) . ')']); + + $_SESSION['successmessage'] = 'Le contact a bien été créé.'; + header('Location: ' . $this->generateUrl('contacts')); + return true; } /** * Cette fonction met à jour une liste de contacts + * @param $csrf : Le jeton CSRF + * @param array $_POST['contacts'] : Un tableau des contacts avec leur nouvelle valeurs + * @return boolean; */ - public function update() + public function update($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('contacts')); } global $db; - $errors = array(); //On initialise le tableau qui contiendra les erreurs rencontrés //Pour chaque contact reçu, on boucle en récupérant son id (la clef), et le contact lui-même (la value) foreach ($_POST['contacts'] as $id => $contact) { - if ($number = internalTools::parsePhone($contact['phone'])) - { - $db->updateContact($id, $contact['name'], $number); - } - else + if (!$number = internalTools::parsePhone($contact['phone'])) { $errors[] = $contact['id']; + continue; } + + $db->updateTableWhere('contacts', ['name' => $contact['name'], 'number' => $number], ['id' => $id]); } //Si on a eu des erreurs if (count($errors)) { - $message = 'Certains contacts n\'ont pas pu êtres mis à jour. Voici leurs identifiants : ' . implode(', ', $errors); - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'errormessage' => $message, - ))); - } - else - { - $message = 'Tous les contacts ont été modifiés avec succès.'; - header('Location: ' . $this->generateUrl('contacts', 'showAll', array( - 'successmessage' => $message, - ))); + $_SESSION['errormessage'] = 'Certains contacts n\'ont pas pu êtres mis à jour. Voici leurs identifiants : ' . implode(', ', $errors); + return header('Location: ' . $this->generateUrl('contacts')); } + + $_SESSION['successmessage'] = 'Tous les contacts ont été modifiés avec succès.'; + return header('Location: ' . $this->generateUrl('contacts')); } /** @@ -180,6 +174,6 @@ { global $db; - echo json_encode($db->getAll('contacts')); + echo json_encode($db->getFromTableWhere('contacts')); } } diff --git a/controllers/dashboard.php b/controllers/dashboard.php index cfef016..475d6c0 100755 --- a/controllers/dashboard.php +++ b/controllers/dashboard.php @@ -15,25 +15,19 @@ } /** - * Cette fonction retourne l'index temporaire du site + * Cette fonction est un alias de show * @return void; */ public function byDefault() - { - $this->show(); - } - - public function show() { //Creation de l'object de base de données global $db; - //Recupération des nombres des 4 panneaux d'accueil - $nb_contacts = $db->countContacts(); - $nb_groups = $db->countGroups(); - $nb_scheduleds = $db->countScheduleds(); - $nb_commands = $db->countCommands(); + $nb_contacts = $db->countTable('contacts');; + $nb_groups = $db->countTable('groups'); + $nb_scheduleds = $db->countTable('scheduleds'); + $nb_commands = $db->countTable('commands'); //Création de la date d'il y a une semaine $now = new DateTime(); @@ -42,9 +36,9 @@ $formated_date = $date->format('Y-m-d'); //Récupération des 10 derniers SMS envoyés, SMS reçus et evenements enregistrés. Par date. - $sendeds = $db->getAll('sendeds', 'at', true, 10); - $receiveds = $db->getAll('receiveds', 'at', true, 10); - $events = $db->getAll('events', 'at', true, 10); + $sendeds = $db->getFromTableWhere('sendeds', [], 'at', true, 10); + $receiveds = $db->getFromTableWhere('receiveds', [], 'at', true, 10); + $events = $db->getFromTableWhere('events', [], 'at', true, 10); //Récupération du nombre de SMS envoyés et reçus depuis les 7 derniers jours $nb_sendeds = $db->getNbSendedsSinceGroupDay($formated_date); @@ -98,7 +92,7 @@ $array_area_chart = array_values($array_area_chart); - $this->render('dashboard', array( + $this->render('dashboard/default', array( 'nb_contacts' => $nb_contacts, 'nb_groups' => $nb_groups, 'nb_scheduleds' => $nb_scheduleds, diff --git a/controllers/discussions.php b/controllers/discussions.php new file mode 100755 index 0000000..d1be75c --- /dev/null +++ b/controllers/discussions.php @@ -0,0 +1,235 @@ +getDiscussions(); + + foreach ($discussions as $key => $discussion) + { + if (!$contacts = $db->getFromTableWhere('contacts', ['number' => $discussion['number']])) + { + continue; + } + + $discussions[$key]['contact'] = $contacts[0]['name']; + } + + $this->render('discussions/default', array( + 'discussions' => $discussions, + )); + } + + /** + * Cette fonction permet d'afficher la discussion avec un numero + * @param string $number : La numéro de téléphone avec lequel on discute + */ + public function show ($number) + { + global $db; + + $contact = ''; + + if ($contacts = $db->getFromTableWhere('contacts', ['number' => $number])) + { + $contact = $contacts[0]['name']; + } + + $this->render('discussions/show', array( + 'number' => $number, + 'contact' => $contact, + )); + } + + /** + * Cette fonction récupère l'ensemble des messages pour un numéro, recçus, envoyés, en cours + * @param string $number : Le numéro cible + * @param string $transactionId : Le numéro unique de la transaction ajax (sert à vérifier si la requete doit être prise en compte) + */ + function getmessages($number, $transactionId) + { + global $db; + + $now = new DateTime(); + $now = $now->format('Y-m-d H:i:s'); + + $sendeds = $db->getFromTableWhere('sendeds', ['target' => $number], 'at'); + $receiveds = $db->getFromTableWhere('receiveds', ['send_by' => $number], 'at'); + $scheduleds = $db->getScheduledsBeforeDateForNumber($now, $number); + + $messages = []; + + foreach ($sendeds as $sended) + { + $messages[] = array( + 'date' => htmlspecialchars($sended['at']), + 'text' => htmlspecialchars($sended['content']), + 'type' => 'sended', + ); + } + + foreach ($receiveds as $received) + { + $messages[] = array( + 'date' => htmlspecialchars($received['at']), + 'text' => htmlspecialchars($received['content']), + 'type' => 'received', + ); + } + + foreach ($scheduleds as $scheduled) + { + $messages[] = array( + 'date' => htmlspecialchars($scheduled['at']), + 'text' => htmlspecialchars($scheduled['content']), + 'type' => 'inprogress', + ); + } + + //On va trier le tableau des messages + usort($messages, function($a, $b) { + return strtotime($a["date"]) - strtotime($b["date"]); + }); + + //On récupère uniquement les 25 derniers messages sur l'ensemble + $messages = array_slice($messages, -25); + + echo json_encode(['transactionId' => $transactionId, 'messages' => $messages]); + return true; + } + + /** + * Cette fonction permet d'envoyer facilement un sms à un numéro donné + * @param string $csrf : Le jeton csrf + * @param string $_POST['content'] : Le contenu du SMS + * @param string $_POST['numbers'] : Un tableau avec le numero des gens auxquel envoyer le sms + * @return json : Le statut de l'envoi + */ + function send ($csrf) + { + global $db; + $return = ['success' => true, 'message' => '']; + + //On vérifie que le jeton csrf est bon + if (!internalTools::verifyCSRF($csrf)) + { + $return['success'] = false; + $return['message'] = 'Jeton CSRF invalide'; + echo json_encode($return); + return false; + } + + $now = new DateTime(); + $now = $now->format('Y-m-d H:i:s'); + + $_POST['date'] = $now; + + $scheduleds = new scheduleds(); + if (!$scheduleds->create('', true, true)) + { + $return['success'] = false; + $return['message'] = 'Impossible de créer le SMS'; + echo json_encode($return); + return false; + } + + $return['id'] = $_SESSION['discussion_wait_progress'][count($_SESSION['discussion_wait_progress']) - 1]; + + echo json_encode($return); + return true; + } + + /** + * Cette fonction retourne les id des sms qui sont envoyés + * @return json : Tableau des ids des sms qui sont envoyés + */ + function checksendeds () + { + global $db; + + $_SESSION['discussion_wait_progress'] = isset($_SESSION['discussion_wait_progress']) ? $_SESSION['discussion_wait_progress'] : []; + + $scheduleds = $db->getScheduledsIn($_SESSION['discussion_wait_progress']); + + //On va chercher à chaque fois si on a trouvé le sms. Si ce n'est pas le cas c'est qu'il a été envoyé + $sendeds = []; + foreach ($_SESSION['discussion_wait_progress'] as $key => $id) + { + $found = false; + foreach ($scheduleds as $scheduled) + { + if ($id == $scheduled['id']) + { + $found = true; + } + } + + if (!$found) + { + unset($_SESSION['discussion_wait_progress'][$key]); + $sendeds[] = $id; + } + } + + echo json_encode($sendeds); + return true; + } + + /** + * Cette fonction retourne les messages reçus pour un numéro après la date $_SESSION['discussion_last_checkreceiveds'] + * @param string $number : Le numéro de téléphone pour lequel on veux les messages + * @return json : Un tableau avec les messages + */ + function checkreceiveds ($number) + { + global $db; + + $now = new DateTime(); + $now = $now->format('Y-m-d H:i'); + + $_SESSION['discussion_last_checkreceiveds'] = isset($_SESSION['discussion_last_checkreceiveds']) ? $_SESSION['discussion_last_checkreceiveds'] : $now; + + $receiveds = $db->getReceivedsSinceForNumberOrderByDate($_SESSION['discussion_last_checkreceiveds'], $number); + + //On va gérer le cas des messages en double en stockant ceux déjà reçus et en eliminant les autres + $_SESSION['discussion_already_receiveds'] = isset($_SESSION['discussion_already_receiveds']) ? $_SESSION['discussion_already_receiveds'] : []; + + foreach ($receiveds as $key => $received) + { + //Sms jamais recu + if (array_search($received['id'], $_SESSION['discussion_already_receiveds']) === false) + { + $_SESSION['discussion_already_receiveds'][] = $received['id']; + continue; + } + + //Sms déjà reçu => on le supprime des resultats + unset($receiveds[$key]); + } + + //On met à jour la date de dernière verif + $_SESSION['discussion_last_checkreceiveds'] = $now; + + echo json_encode($receiveds); + } + } diff --git a/controllers/events.php b/controllers/events.php index a8e0c87..8b4f431 100755 --- a/controllers/events.php +++ b/controllers/events.php @@ -24,23 +24,22 @@ /** * Cette fonction retourne tous les événements, sous forme d'un tableau permettant l'administration de ces événements + * @param int $page : La page à consulter. Par défaut 0 * @return void; */ - public function showAll() + public function showAll($page = 0) { //Creation de l'object de base de données global $db; - - - $page = (int)(isset($_GET['page']) ? $_GET['page'] : 0); + + $page = (int)($page < 0 ? $page = 0 : $page); $limit = 25; $offset = $limit * $page; - //Récupération des évènements triés par date, du plus récent au plus ancien, par paquets de $limit, en ignorant les $offset premiers - $events = $db->getAll('events', 'at', true, $limit, $offset); + $events = $db->getFromTableWhere('events', [], 'at', true, $limit, $offset); - $this->render('events', array( + $this->render('events/default', array( 'events' => $events, 'page' => $page, 'limit' => $limit, diff --git a/controllers/groups.php b/controllers/groups.php index 59d9406..cfa24f5 100755 --- a/controllers/groups.php +++ b/controllers/groups.php @@ -15,51 +15,41 @@ } /** - * Cette fonction est alias de showAll() + * Cette fonction retourne tous les groupes, sous forme d'un tableau permettant l'administration de ces groupes */ public function byDefault() - { - $this->showAll(); - } - - /** - * Cette fonction retourne tous les groupes, sous forme d'un tableau permettant l'administration de ces groupes - * @return void; - */ - public function showAll() { //Creation de l'object de base de données global $db; - $groups = $db->getGroupsWithContactsNb(); - $this->render('groups', array( + $this->render('groups/default', array( 'groups' => $groups, )); - } /** * Cette fonction supprime une liste de groupes + * @param $csrf : Le jeton CSRF + * @param int... $ids : Les id des groups à supprimer * @return void; */ - public function delete() + public function delete($csrf, ...$ids) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('groups')); + return false; } //Create de l'object de base de données global $db; - $groups_ids = $_GET; - $db->deleteGroupsIn($groups_ids); - header('Location: ' . $this->generateUrl('groups')); + $db->deleteGroupsIn($ids); + header('Location: ' . $this->generateUrl('groups')); + return true; } /** @@ -67,17 +57,18 @@ */ public function add() { - $this->render('addGroup'); + $this->render('groups/add'); } /** * Cette fonction retourne la page d'édition des groupes + * @param int... $ids : Les id des groups à modifier */ - public function edit() + public function edit(...$ids) { global $db; - $groups = $db->getGroupsIn($_GET); + $groups = $db->getGroupsIn($ids); $blocks = array(); //On défini la variable qui correspondra à un bloc groupe et contacts //Pour chaque groupe, on récupère les contacts liés @@ -86,82 +77,81 @@ $groups[$key]['contacts'] = $db->getContactsForGroup($group['id']); } - $this->render('editGroups', array( + $this->render('groups/edit', array( 'groups' => $groups, )); } /** * Cette fonction insert un nouveau contact + * @param $csrf : Le jeton CSRF + * @param string $_POST['name'] : Le nom du groupe + * @param array $_POST['contacts'] : Les id des contacts à mettre dans le du groupe */ - public function create() + public function create($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('groups')); + return false; } global $db; - $nom = $_POST['name']; - if ($db->createGroup($nom)) + if (!$db->insertIntoTable('groups', ['name' => $nom])) { - $id_group = $db->lastId(); - $db->createEvent('GROUP_ADD', 'Ajout du groupe : ' . $nom); - foreach ($_POST['contacts'] as $id_contact) - { - $db->createGroups_contacts($id_group, $id_contact); - } - - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'successmessage' => 'Le groupe a bien été créé.' - ))); - - return true; + $_SESSION['errormessage'] = 'Impossible de créer ce groupe.'; + header('Location: ' . $this->generateUrl('groups')); + return false; } - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'errormessage' => 'Impossible de créer ce groupe.' - ))); + $id_group = $db->lastId(); + $db->insertIntoTable('events', ['type' => 'GROUP_ADD', 'text' => 'Ajout du groupe : ' . $nom]); + + foreach ($_POST['contacts'] as $id_contact) + { + $db->insertIntoTable('groups_contacts', ['id_group' => $id_group, 'id_contact' => $id_contact]); + } + + $_SESSION['successmessage'] = 'Le groupe a bien été créé.'; + header('Location: ' . $this->generateUrl('groups')); + return true; } /** * Cette fonction met à jour une liste de groupes + * @param $csrf : Le jeton CSRF + * @param array $_POST['groups'] : Un tableau des groups avec leur nouvelle valeurs + * @return boolean; */ - public function update() + public function update($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('groups')); + return false; } global $db; - //Pour chaque groupe reçu, on boucle en récupérant son id (la clef), et le contact le tableau du groupe (nom et liste des contacts) foreach ($_POST['groups'] as $id_group => $group) { - $db->updateGroup($id_group, $group['name']); //On met à jour le nom du groupe - $db->deleteGroups_contactsForGroup($id_group); //On supprime tous les contacts de ce groupe + $db->updateTableWhere('groups', $group, ['id' => $id_group]); //On met à jour le nom du groupe + $db->deleteFromTableWhere('groups_contacts', ['id_group' => $id_group]); //On supprime tous les contacts de ce groupe foreach ($group['contacts'] as $id_contact) //Pour chaque contact on l'ajoute au groupe { - $db->createGroups_contacts($id_group, $id_contact); + $db->insertIntoTable('groups_contacts', ['id_group' => $id_group, 'id_contact' => $id_contact]); } } - $message = 'Tous les groupes ont été modifiés avec succès.'; - header('Location: ' . $this->generateUrl('groups', 'showAll', array( - 'successmessage' => $message, - ))); + $_SESSION['successmessage'] = 'Tous les groupes ont été modifiés avec succès.'; + header('Location: ' . $this->generateUrl('groups')); } /** @@ -171,6 +161,6 @@ { global $db; - echo json_encode($db->getAll('groups')); + echo json_encode($db->getFromTableWhere('groups')); } } diff --git a/controllers/internalConsole.php b/controllers/internalConsole.php index 5755367..57d7934 100755 --- a/controllers/internalConsole.php +++ b/controllers/internalConsole.php @@ -20,6 +20,11 @@ ), 'optionals' => array(), ), + 'sendTransfers' => array( + 'description' => 'Cette commande permet d\'envoyer par mails les sms à transférés.', + 'requireds' => [], + 'optionals' => [], + ), ); $message = "Vous êtes ici dans l'aide de la console.\n"; @@ -71,86 +76,93 @@ //On créé l'objet de base de données global $db; + for ($i = 0; $i < 30; $i++) + { + $now = new DateTime(); + $now = $now->format('Y-m-d H:i:s'); - $now = new DateTime(); - $now = $now->format('Y-m-d H:i:s'); + echo "Début de l'envoi des SMS programmés\n"; - echo "Début de l'envoi des SMS programmés\n"; + $scheduleds = $db->getScheduledsNotInProgressBefore($now); - $scheduleds = $db->getScheduledsNotInProgressBefore($now); + $ids_scheduleds = array(); - $ids_scheduleds = array(); - - //On passe en cours de progression tous les SMS - foreach ($scheduleds as $scheduled) - { - $ids_scheduleds[] = $scheduled['id']; - } - - echo count($ids_scheduleds) . " SMS à envoyer ont été trouvés et ajoutés à la liste des SMS en cours d'envoi.\n"; - - $db->updateProgressScheduledsIn($ids_scheduleds, true); - - //Pour chaque SMS à envoyer - foreach ($scheduleds as $scheduled) - { - $id_scheduled = $scheduled['id']; - $text_sms = escapeshellarg($scheduled['content']); - - //On initialise les numéros auxquelles envoyer le SMS - $numbers = array(); - - //On récupère les numéros pour le SMS et on les ajoute - $target_numbers = $db->getNumbersForScheduled($id_scheduled); - foreach ($target_numbers as $target_number) + //On passe en cours de progression tous les SMS + foreach ($scheduleds as $scheduled) { - $numbers[] = $target_number['number']; + $ids_scheduleds[] = $scheduled['id']; } - //On récupère les contacts, et on ajoute les numéros - $contacts = $db->getContactsForScheduled($id_scheduled); - foreach ($contacts as $contact) - { - $numbers[] = $contact['number']; - } + echo count($ids_scheduleds) . " SMS à envoyer ont été trouvés et ajoutés à la liste des SMS en cours d'envoi.\n"; - //On récupère les groupes - $groups = $db->getGroupsForScheduled($id_scheduled); - foreach ($groups as $group) + $db->updateProgressScheduledsIn($ids_scheduleds, true); + + //Pour chaque SMS à envoyer + foreach ($scheduleds as $scheduled) { - //On récupère les contacts du groupe et on les ajoute aux numéros - $contacts = $db->getContactsForGroup($group['id']); + $id_scheduled = $scheduled['id']; + $text_sms = escapeshellarg($scheduled['content']); + + //On initialise les numéros auxquelles envoyer le SMS + $numbers = array(); + + //On récupère les numéros pour le SMS et on les ajoute + $target_numbers = $db->getNumbersForScheduled($id_scheduled); + foreach ($target_numbers as $target_number) + { + $numbers[] = $target_number['number']; + } + + //On récupère les contacts, et on ajoute les numéros + $contacts = $db->getContactsForScheduled($id_scheduled); foreach ($contacts as $contact) { $numbers[] = $contact['number']; } - } - - foreach ($numbers as $number) - { - echo " Envoi d'un SMS au " . $number . "\n"; - //On ajoute le SMS aux SMS envoyés - //Pour plus de précision, on remet la date à jour en réinstanciant l'objet DateTime (et on reformatte la date, bien entendu) - $now = new DateTime(); - $now = $now->format('Y-m-d H:i:s'); - //On peut maintenant ajouter le SMS - $db->createSended($now, $number, $scheduled['content']); - $id_sended = $db->lastId(); + + //On récupère les groupes + $groups = $db->getGroupsForScheduled($id_scheduled); + foreach ($groups as $group) + { + //On récupère les contacts du groupe et on les ajoute aux numéros + $contacts = $db->getContactsForGroup($group['id']); + foreach ($contacts as $contact) + { + $numbers[] = $contact['number']; + } + } - //Commande qui envoie le SMS - $commande_send_sms = 'gammu-smsd-inject TEXT ' . escapeshellarg($number) . ' -len ' . mb_strlen($text_sms) . ' -text ' . $text_sms; - //Commande qui s'assure de passer le SMS dans ceux envoyés, et de lui donner le bon statut + foreach ($numbers as $number) + { + echo " Envoi d'un SMS au " . $number . "\n"; + //On ajoute le SMS aux SMS envoyés + //Pour plus de précision, on remet la date à jour en réinstanciant l'objet DateTime (et on reformatte la date, bien entendu) + $now = new DateTime(); + $now = $now->format('Y-m-d H:i:s'); + //On peut maintenant ajouter le SMS + if (!$db->insertIntoTable('sendeds', ['at' => $now, 'target' => $number, 'content' => $scheduled['content']])) + { + echo 'Impossible d\'inserer le sms pour le numero ' . $number . "\n"; + } + $id_sended = $db->lastId(); + + //Commande qui envoie le SMS + $commande_send_sms = 'gammu-smsd-inject TEXT ' . escapeshellarg($number) . ' -len ' . mb_strlen($text_sms) . ' -text ' . $text_sms; + //Commande qui s'assure de passer le SMS dans ceux envoyés, et de lui donner le bon statut - //On va lier les deux commandes pour envoyer le SMS puis le passer en echec - $commande = '(' . $commande_send_sms . ') >/dev/null 2>/dev/null &'; - - exec($commande); //On execute la commande d'envoi d'un SMS + //On va liée les deux commandes pour envoyer le SMS puis le passer en echec + $commande = '(' . $commande_send_sms . ') >/dev/null 2>/dev/null &'; + exec($commande); //On execute la commande d'envoie d'un SMS + } } - } - echo "Tous les SMS sont en cours d'envoi.\n"; - //Tous les SMS ont été envoyés. - $db->deleteScheduledsIn($ids_scheduleds); + echo "Tous les SMS sont en cours d'envoi.\n"; + //Tous les SMS ont été envoyés. + $db->deleteScheduledsIn($ids_scheduleds); + + //On dors 2 secondes + sleep(2); + } } /** @@ -161,112 +173,165 @@ //On créer l'objet de base de données global $db; - foreach (scandir(PWD_RECEIVEDS) as $dir) - { - //Si le fichier est un fichier système, on passe à l'itération suivante - if ($dir == '.' || $dir == '..') + for ($i = 0; $i < 30; $i++) + { + foreach (scandir(PWD_RECEIVEDS) as $dir) { - continue; - } - - //On récupère la date du SMS à la seconde près grâce au nom du fichier (Cf. parseSMS.sh) - //Il faut mettre la date au format Y-m-d H:i:s - $date = substr($dir, 0, 4) . '-' . substr($dir, 4, 2) . '-' . substr($dir, 6, 2) . ' ' . substr($dir, 8, 2) . ':' . substr($dir, 10, 2) . ':' . substr($dir, 12, 2); - - //On récupère le fichier, et on récupère la chaine jusqu'au premier ':' pour le numéro de téléphone source, et la fin pour le message - $content_file = file_get_contents(PWD_RECEIVEDS . $dir); - //Si on ne peut pas ouvrir le fichier, alors on quitte en logant une erreur - if (!$content_file) - { - $this->wlog('Unable to read file "' . $dir); - die(4); - } - - //On supprime le fichier. Si on n'y arrive pas, alors on log - if (!unlink(PWD_RECEIVEDS . $dir)) - { - $this->wlog('Unable to delete file "' . $dir); - die(8); - } - - $content_file = explode(':', $content_file, 2); - - //Si on a pas passé de numéro ou de message, alors on lève une erreur - if (!isset($content_file[0], $content_file[1])) - { - $this->wlog('Missing params in file "' . $dir); - die(5); - } - - $number = $content_file[0]; - $number = internalTools::parsePhone($number); - $text = $content_file[1]; - - - if (!$number) - { - $this->wlog('Invalid phone number in file "' . $dir); - die(6); - } - - //On va vérifier si on a reçu une commande, et des identifiants - $flags = internalTools::parseForFlag($text); - - //On créer le tableau qui permettra de stocker les commandes trouvées - - $found_commands = array(); - - //Si on reçu des identifiants - if (array_key_exists('LOGIN', $flags) && array_key_exists('PASSWORD', $flags)) - { - //Si on a bien un utilisateur avec les identifiants reçus - $user = $db->getUserFromEmail($flags['LOGIN']); - $this->wlog('We found ' . count($user) . ' users'); - if ($user && $user['password'] == sha1($flags['PASSWORD'])) + //Si le fichier est un fichier système, on passe à l'itération suivante + if ($dir == '.' || $dir == '..') { - $this->wlog('Password is valid'); - //On va passer en revue toutes les commandes, pour voir si on en trouve dans ce message - $commands = $db->getAll('commands'); + continue; + } - $this->wlog('We found ' . count($commands) . ' commands'); - foreach ($commands as $command) + //On récupère la date du SMS à la seconde près grâce au nom du fichier (Cf. parseSMS.sh) + //Il faut mettre la date au format Y-m-d H:i:s + $date = substr($dir, 0, 4) . '-' . substr($dir, 4, 2) . '-' . substr($dir, 6, 2) . ' ' . substr($dir, 8, 2) . ':' . substr($dir, 10, 2) . ':' . substr($dir, 12, 2); + + //On récupère le fichier, et on récupère la chaine jusqu'au premier ':' pour le numéro de téléphone source, et la fin pour le message + $content_file = file_get_contents(PWD_RECEIVEDS . $dir); + + //Si on peux pas ouvrir le fichier, on quitte en logant une erreur + if ($content_file == false) + { + $this->wlog('Unable to read file "' . $dir); + die(4); + } + + //On supprime le fichier. Si on n'y arrive pas, alors on log + if (!unlink(PWD_RECEIVEDS . $dir)) + { + $this->wlog('Unable to delete file "' . $dir); + die(8); + } + + $content_file = explode(':', $content_file, 2); + + //Si on a pas passé de numéro ou de message, alors on lève une erreur + if (!isset($content_file[0], $content_file[1])) + { + $this->wlog('Missing params in file "' . $dir); + die(5); + } + + $number = $content_file[0]; + $number = internalTools::parsePhone($number); + $text = $content_file[1]; + + + if (!$number) + { + $this->wlog('Invalid phone number in file "' . $dir); + die(6); + } + + //On va vérifier si on a reçu une commande, et des identifiants + $flags = internalTools::parseForFlag($text); + + //On créer le tableau qui permettra de stocker les commandes trouvées + + $found_commands = array(); + + //Si on reçu des identifiants + if (array_key_exists('LOGIN', $flags) && array_key_exists('PASSWORD', $flags)) + { + //Si on a bien un utilisateur avec les identifiants reçus + $user = $db->getUserFromEmail($flags['LOGIN']); + $this->wlog('We found ' . count($user) . ' users'); + if ($user && $user['password'] == sha1($flags['PASSWORD'])) { - $command_name = mb_strtoupper($command['name']); - if (array_key_exists($command_name, $flags)) + $this->wlog('Password is valid'); + //On va passer en revue toutes les commandes, pour voir si on en trouve dans ce message + $commands = $db->getAll('commands'); + + $this->wlog('We found ' . count($commands) . ' commands'); + foreach ($commands as $command) { - $this->wlog('We found command ' . $command_name); - - //Si la commande ne nécessite pas d'être admin, ou si on est admin - if (!$command['admin'] || $user['admin']) + $command_name = mb_strtoupper($command['name']); + if (array_key_exists($command_name, $flags)) { - $this->wlog('And the count is ok'); - $found_commands[$command_name] = PWD_SCRIPTS . $command['script'] . escapeshellcmd($flags[$command_name]); + $this->wlog('We found command ' . $command_name); + + //Si la commande ne nécessite pas d'être admin, ou si on est admin + if (!$command['admin'] || $user['admin']) + { + $this->wlog('And the count is ok'); + $found_commands[$command_name] = PWD_SCRIPTS . $command['script'] . escapeshellcmd($flags[$command_name]); + } } } } } + + //On va supprimer le mot de passe du SMS pour pouvoir l'enregistrer sans danger + if (isset($flags['PASSWORD'])) + { + $text = str_replace($flags['PASSWORD'], '*****', $text); + } + + //On map les données et on créer le SMS reçu + $send_by = $number; + $content = $text; + $is_command = count($found_commands); + if (!$db->insertIntoTable('receiveds', ['at' => $date, 'send_by' => $send_by, 'content' => $content, 'is_command' => $is_command])) + { + echo "Erreur lors de l'enregistrement du SMS\n"; + $this->wlog('Unable to process the SMS in file "' . $dir); + die(7); + } + + //On insert le SMS dans le tableau des sms à envoyer par mail + $db->insertIntoTable('transfers', ['id_received' => $db->lastId(), 'progress' => false]); + + //Chaque commande sera executée. + foreach ($found_commands as $command_name => $command) + { + echo 'Execution de la commande : ' . $command_name . ' :: ' . $command . "\n"; + exec($command); + } } - //On va supprimer le mot de passe du SMS pour pouvoir l'enregistrer sans danger - $text = str_replace($flags['PASSWORD'], '*****', $text); - - //On map les données et on créer le SMS reçu - $send_by = $number; - $content = $text; - $is_command = count($found_commands); - if (!$db->createReceived($date, $send_by, $content, $is_command)) - { - echo "Erreur lors de l'enregistrement du SMS\n"; - $this->wlog('Unable to process the SMS in file "' . $dir); - die(7); - } - - //Chaque commande sera executée. - foreach ($found_commands as $command_name => $command) - { - echo 'Execution de la commande : ' . $command_name . ' :: ' . $command . "\n"; - exec($command); - } + //On attend 2 secondes + sleep(2); } } + + /** + * Cette fonction permet d'envoyer par mail les sms à transférer + */ + public function sendTransfers () + { + global $db; + $transfers = $db->getFromTableWhere('transfers', ['progress' => false]); + + $ids_transfers = []; + $ids_receiveds = []; + foreach ($transfers as $transfer) + { + $ids_transfers[] = $transfer['id']; + $ids_receiveds[] = $transfer['id_received']; + } + + $db->updateProgressTransfersIn($ids_transfers, true); + + $receiveds = $db->getReceivedsIn($ids_receiveds); + + $users = $db->getFromTableWhere('users', ['transfer' => true]); + + foreach ($users as $user) + { + foreach ($receiveds as $received) + { + echo "Transfer d'un SMS du " . $received['send_by'] . " à l'email " . $user['email']; + $to = $user['email']; + $subject = '[RaspiSMS] - Transfert d\'un SMS du ' . $received['send_by']; + $message = "Le numéro " . $received['send_by'] . " vous a envoyé un SMS : \n" . $received['content']; + + $ok = mail($to, $subject, $message); + + echo " ... " . ($ok ? 'OK' : 'KO') . "\n"; + } + } + + $db->deleteTransfersIn($ids_transfers); + } } diff --git a/controllers/internalIncs.php b/controllers/internalIncs.php index 6ab5a7f..ea1ecdf 100755 --- a/controllers/internalIncs.php +++ b/controllers/internalIncs.php @@ -8,13 +8,24 @@ */ public function head($title = '') { - $title = (!empty($title)) ? $title . ' - RaspiSMS' : 'RaspiSMS'; - $author = 'Ajani'; + $title = (!empty($title)) ? $title . ' - ' . WEBSITE_TITLE : WEBSITE_TITLE; + $author = WEBSITE_AUTHOR; - $error_message = (isset($_GET['errormessage'])) ? $_GET['errormessage'] : ''; - $success_message = (isset($_GET['successmessage'])) ? $_GET['successmessage'] : ''; + $error_message = false; + $success_message = false; + if (isset($_SESSION['errormessage'])) + { + $error_message = $_SESSION['errormessage']; + unset($_SESSION['errormessage']); + } - $this->render('head', array( + if (isset($_SESSION['successmessage'])) + { + $success_message = $_SESSION['successmessage']; + unset($_SESSION['successmessage']); + } + + $this->render('internalIncs/head', array( 'title' => $title, 'author' => $author, 'error_message' => $error_message, @@ -30,7 +41,7 @@ public function nav($page = '') { $email = isset($_SESSION['email']) ? $_SESSION['email'] : 'Mon compte'; - $this->render('nav', array( + $this->render('internalIncs/nav', array( 'email' => $email, 'page' => $page, )); @@ -38,6 +49,14 @@ public function footer() { - $this->render('footer'); + $this->render('internalIncs/footer'); + } + + /** + * Cette fonction retourne une page js avec des constantes php sous forme js + */ + public function phptojs() + { + $this->render('internalIncs/phptojs'); } } diff --git a/controllers/internalTools.php b/controllers/internalTools.php index 5942a68..4d33043 100755 --- a/controllers/internalTools.php +++ b/controllers/internalTools.php @@ -8,8 +8,8 @@ */ public static function parsePhone($number) { - $number = preg_replace('#[^0-9+]#', '', $number); - if (preg_match('#^(0|\+33)[1-9][0-9]{8}$#', $number)) + $number = preg_replace('#[^-0-9+]#', '', $number); + if (preg_match('#^(0|\+[1-9]{1,3}|\+1\-[0-9]{3})[1-9][0-9]{8}$#', $number)) { return $number; } diff --git a/controllers/profile.php b/controllers/profile.php index 63fd678..a81ac72 100755 --- a/controllers/profile.php +++ b/controllers/profile.php @@ -15,83 +15,110 @@ } /** - * Cette fonction est alias de show() + * Cette fonction retourne la fenetre du profile */ public function byDefault() { - $this->show(); - } - - /** - * Cette fonction retourne la fenetre du profile - * @return void; - */ - public function show() - { - //Creation de l'object de base de données - global $db; - - - $this->render('profile'); + $this->render('profile/default'); } /** * Cette fonction change le mot de passe de l'utilisateur + * @param $csrf : Le jeton CSRF * @param string $_POST['password'] : Le nouveau mot de passe de l'utilisateur * @param string $_POST['verif_password'] : La vérification du nouveau mot de passe de l'utilisateur * @return void; */ - public function changePassword() + public function changePassword($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('profile', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; } //Creation de l'object de base de données global $db; - if (empty($_POST['password']) || empty($_POST['verif_password']) || $_POST['password'] != $_POST['verif_password']) { - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'errormessage' => 'Les mots de passe ne correspondent pas.' - ))); + $_SESSION['errormessage'] = 'Les mots de passe ne correspondent pas.'; + header('Location: ' . $this->generateUrl('profile')); return false; } - $user = $db->getUserFromEmail($_SESSION['email']); - + $user = $db->getFromTableWhere('users', ['email' => $_SESSION['email']]); $password = sha1($_POST['password']); - if ($db->updateUser($user['id'], $user['email'], $password, $user['admin'])) + if (!$db->updateTableWhere('users', ['password' => $password], ['id' => $user[0]['id']])) { - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'successmessage' => 'Les données ont été mises à jour.' - ))); + $_SESSION['errormessage'] = 'Impossible de mettre à jour le mot de passe.'; + header('Location: ' . $this->generateUrl('profile')); return false; } + + $_SESSION['successmessage'] = 'Les données ont été mises à jour.'; + header('Location: ' . $this->generateUrl('profile')); + return true; + } + + /** + * Cette fonction change la valeur du champ "transfer" de l'utilisateur + * @param $csrf : Le jeton CSRF + * @param string $_POST['transfer'] : Le nouveau transfer de l'utilisateur + * @return void; + */ + public function changeTransfer($csrf) + { + //On vérifie que le jeton csrf est bon + if (!internalTools::verifyCSRF($csrf)) + { + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; + } + + //Creation de l'object de base de données + global $db; + + if (!isset($_POST['transfer'])) + { + $_SESSION['errormessage'] = 'Vous devez renseigner un valeur'; + header('Location: ' . $this->generateUrl('profile')); + return false; + } + + $transfer = (boolean)$_POST['transfer']; + if (!$db->updateTableWhere('users', ['transfer' => $transfer], ['email' => $_SESSION['email']])) + { + $_SESSION['errormessage'] = 'Impossible de mettre les données à jour.'; + header('Location: ' . $this->generateUrl('profile')); + return false; + } + + $_SESSION['transfer'] = $transfer; + $_SESSION['successmessage'] = 'Les données ont été mises à jour.'; + header('Location: ' . $this->generateUrl('profile')); + return true; } /** * Cette fonction change l'email de l'utilisateur + * @param $csrf : Le jeton CSRF * @param string $_POST['email'] : Le nouvel email de l'utilisateur * @param string $_POST['verif_email'] : La vérification du nouvel email de l'utilisateur * @return void; */ - public function changeEmail() + public function changeEmail($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('profile', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; } //Creation de l'object de base de données @@ -100,7 +127,8 @@ if (empty($_POST['mail']) || empty($_POST['verif_mail']) || $_POST['mail'] != $_POST['verif_mail']) { - header('Location: ' . $this->generateUrl('profile', 'show', array( + $_SESSION['errormessage'] = 'Les e-mails ne correspondent pas.'; + header('Location: ' . $this->generateUrl('profile', array( 'errormessage' => 'Les e-mails ne correspondent pas.' ))); return false; @@ -110,62 +138,63 @@ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'errormessage' => 'L\'adresse e-mail est invalide.' - ))); + $_SESSION['errormessage'] = 'L\'adresse e-mail est invalide.'; + header('Location: ' . $this->generateUrl('profile')); return false; } - $user = $db->getUserFromEmail($_SESSION['email']); + $user = $db->getFromTableWhere('users', ['email' => $_SESSION['email']]); - if ($db->updateUser($user['id'], $email, $user['password'], $user['admin'])) + if (!$db->updateTableWhere('users', ['email' => $email], ['id' => $user[0]['id']])) { - $_SESSION['email'] = $email; - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'successmessage' => 'Les données ont été mises à jour.' - ))); + $_SESSION['errormessage'] = 'Cette adresse e-mail est déjà utilisée.'; + header('Location: ' . $this->generateUrl('profile')); return false; } - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'errormessage' => 'Cette adresse e-mail est déjà utilisée.' - ))); - return false; + $_SESSION['email'] = $email; + $_SESSION['successmessage'] = 'Les données ont été mises à jour.'; + header('Location: ' . $this->generateUrl('profile')); + return true; } /** * Cette fonction supprime l'utilisateur + * @param $csrf : Le jeton CSRF * @param string $_POST['delete_account'] : La vérification que l'on veux bien supprimer l'utilisateur * @return void; */ - public function delete() + public function delete($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('profile', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; } //Creation de l'object de base de données global $db; - //Si l'utilisateur veux vraiment supprimer son compte - if (!empty($_POST['delete_account'])) + if (empty($_POST['delete_account'])) { - $user = $db->getUserFromEmail($_SESSION['email']); //On récupère l'utilisateur en base - $db->deleteUsersIn(array($user['id'])); //On supprime l'utilisateur - $this->logout(); - return true; + $_SESSION['errormessage'] = 'Le compte n\'a pas été supprimé'; + header('Location: ' . $this->generateUrl('profile')); + return false; } - header('Location: ' . $this->generateUrl('profile', 'show', array( - 'errormessage' => 'Le compte n\'a pas été supprimé' - ))); - return false; + if (!$db->deleteFromTableWhere('users', ['email' => $_SESSION['email']])) + { + $_SESSION['errormessage'] = 'Impossible de supprime le compte'; + header('Location: ' . $this->generateUrl('profile')); + return false; + } + + $this->logout(); + return true; + } /** diff --git a/controllers/receiveds.php b/controllers/receiveds.php index 90dd04f..517ba50 100755 --- a/controllers/receiveds.php +++ b/controllers/receiveds.php @@ -24,27 +24,51 @@ /** * Cette fonction retourne tous les SMS envoyés, sous forme d'un tableau + * @param int $page : La page à consulter. Par défaut 0 * @return void; */ - public function showAll() + public function showAll($page = 0) { //Creation de l'object de base de données global $db; - - $page = (int)(isset($_GET['page']) ? $_GET['page'] : 0); + $page = (int)($page < 0 ? $page = 0 : $page); $limit = 25; $offset = $limit * $page; //Récupération des SMS envoyés triés par date, du plus récent au plus ancien, par paquets de $limit, en ignorant les $offset premiers - $receiveds = $db->getAll('receiveds', 'at', true, $limit, $offset); + $receiveds = $db->getFromTableWhere('receiveds', [], 'at', true, $limit, $offset); - $this->render('receiveds', array( + return $this->render('receiveds/showAll', array( 'receiveds' => $receiveds, 'page' => $page, 'limit' => $limit, 'nbResults' => count($receiveds), )); } + + /** + * Cette fonction retourne tous les SMS reçus aujourd'hui pour la popup + * @return json : Un tableau des sms + */ + public function popup () + { + global $db; + $now = new DateTime(); + $receiveds = $db->getReceivedsSince($now->format('Y-m-d')); + + $nbReceiveds = count($receiveds); + + if (!isset($_SESSION['popup_nb_receiveds']) || ($_SESSION['popup_nb_receiveds'] > $nbReceiveds)) + { + $_SESSION['popup_nb_receiveds'] = $nbReceiveds; + } + + $newlyReceiveds = array_slice($receiveds, $_SESSION['popup_nb_receiveds']); + + echo json_encode($newlyReceiveds); + $_SESSION['popup_nb_receiveds'] = $nbReceiveds; + return true; + } } diff --git a/controllers/scheduleds.php b/controllers/scheduleds.php index bfc2302..03517b0 100755 --- a/controllers/scheduleds.php +++ b/controllers/scheduleds.php @@ -15,50 +15,41 @@ } /** - * Cette fonction est alias de showAll() + * Cette fonction retourne tous les sms programmés, sous forme d'un tableau permettant l'administration de ces sms */ public function byDefault() - { - $this->showAll(); - } - - /** - * Cette fonction retourne tous les sms programmés, sous forme d'un tableau permettant l'administration de ces sms - * @return void; - */ - public function showAll() { //Creation de l'object de base de données global $db; - - $scheduleds = $db->getAll('scheduleds'); - $this->render('scheduleds', array( + $scheduleds = $db->getFromTableWhere('scheduleds'); + $this->render('scheduleds/default', array( 'scheduleds' => $scheduleds, )); } /** * Cette fonction supprime une liste de groupes - * @return void; + * @param $csrf : Le jeton CSRF + * @param int... $ids : Les id des commandes à supprimer + * @return boolean; */ - public function delete() + public function delete($csrf, ...$ids) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; } //Create de l'object de base de données global $db; - $scheduleds_ids = $_GET; - $db->deleteScheduledsIn($scheduleds_ids); - header('Location: ' . $this->generateUrl('scheduleds')); + $db->deleteScheduledsIn($ids); + header('Location: ' . $this->generateUrl('scheduleds')); + return true; } /** @@ -68,21 +59,22 @@ { $now = new DateTime(); $babyonemoretime = new DateInterval('PT1M'); //Haha, i'm so a funny guy - $now->add($babyonemoretime); + $now->sub($babyonemoretime); $now = $now->format('Y-m-d H:i'); - $this->render('addScheduled', array( + return $this->render('scheduleds/add', array( 'now' => $now )); } /** * Cette fonction retourne la page d'édition des sms programmés + * @param int... $ids : Les id des commandes à supprimer */ - public function edit() + public function edit(...$ids) { global $db; - $scheduleds = $db->getScheduledsIn($_GET); + $scheduleds = $db->getScheduledsIn($ids); //Pour chaque groupe, on récupère les contacts liés foreach ($scheduleds as $key => $scheduled) { @@ -94,31 +86,36 @@ $scheduleds[$key]['groups'] = $db->getGroupsForScheduled($scheduled['id']); } - $this->render('editScheduleds', array( + $this->render('scheduleds/edit', array( 'scheduleds' => $scheduleds, )); } /** * Cette fonction insert un nouveau SMS programmé + * @param $csrf : Le jeton CSRF * @param optionnal boolean $api : Si vrai (faux par défaut), on retourne des réponses au lieu de rediriger + * @param string $_POST['date'] : La date a la quelle de sms devra être envoyé + * @param string $_POST['content'] : Le contenu du SMS + * @param string $_POST['numbers'] : Un tableau avec le numero des gens auxquel envoyer le sms + * @param string $_POST['contacts'] : Un tableau avec les ids des contacts auxquels envoyer le sms + * @param string $_POST['groups'] : Un tableau avec les ids des groupes auxquels envoyer le sms + * @return boolean; */ - public function create($api = false) + public function create($csrf = '', $api = false, $discussion = false) { if (!$api) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('profile')); + return false; } } global $db; - $date = $_POST['date']; $content = $_POST['content']; @@ -131,9 +128,8 @@ { if (!$api) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Pas de texte pour ce SMS !' - ))); + $_SESSION['errormessage'] = 'Pas de texte pour ce SMS !'; + header('Location: ' . $this->generateUrl('scheduleds')); } return false; } @@ -143,102 +139,105 @@ { if (!$api) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Pas numéro, de contacts, ni de groupes définis pour envoyer ce SMS !' - ))); + $_SESSION['errormessage'] = 'Pas numéro, de contacts, ni de groupes définis pour envoyer ce SMS !'; + header('Location: ' . $this->generateUrl('scheduleds')); } return false; } - if (!internalTools::validateDate($date, 'Y-m-d H:i')) + if (!internalTools::validateDate($date, 'Y-m-d H:i:s') && !internalTools::validateDate($date, 'Y-m-d H:i')) { if (!$api) { - header('Location: ' . $this->generateUrl('scheduleds', 'add', array( - 'errormessage' => 'La date renseignée est invalide.' - ))); + $_SESSION['errormessage'] = 'La date renseignée est invalide.'; + header('Location: ' . $this->generateUrl('scheduleds')); } return false; } - if ($db->createScheduleds($date, $content)) + if (!$db->insertIntoTable('scheduleds', ['at' => $date, 'content' => $content, 'progress' => false])) { - $id_scheduled = $db->lastId(); - $db->createEvent('SCHEDULED_ADD', 'Ajout d\'un SMS pour le ' . $date); - $errors = false; - - foreach ($numbers as $number) + if (!$api) { - if ($number = internalTools::parsePhone($number)) - { - $db->createScheduleds_numbers($id_scheduled, $number); - } - else - { - $errors = true; - } + $_SESSION['errormessage'] = 'Impossible de créer ce SMS.'; + header('Location: ' . $this->generateUrl('scheduleds')); + } + return false; + } + + $id_scheduled = $db->lastId(); + + if ($discussion) + { + $_SESSION['discussion_wait_progress'] = isset($_SESSION['discussion_wait_progress']) ? $_SESSION['discussion_wait_progress'] : []; + $_SESSION['discussion_wait_progress'][] = $id_scheduled; + } + + $db->insertIntoTable('events', ['type' => 'SCHEDULED_ADD', 'text' => 'Ajout d\'un SMS pour le ' . $date]); + $errors = false; + + foreach ($numbers as $number) + { + if (!$number = internalTools::parsePhone($number)) + { + $errors = true; + continue; } - foreach ($contacts as $id_contact) + if (!$db->insertIntoTable('scheduleds_numbers', ['id_scheduled' => $id_scheduled, 'number' => $number])) { - if (!$db->createScheduleds_contacts($id_scheduled, $id_contact)) - { - $errors = true; - } + $errors = true; } + } - foreach ($groups as $id_group) + foreach ($contacts as $id_contact) + { + if (!$db->insertIntoTable('scheduleds_contacts', ['id_scheduled' => $id_scheduled, 'id_contact' => $id_contact])) { - if (!$db->createScheduleds_groups($id_scheduled, $id_group)) - { - $errors = true; - } + $errors = true; } + } - if ($errors) + foreach ($groups as $id_group) + { + if (!$db->insertIntoTable('scheduleds_groups', ['id_scheduled' => $id_scheduled, 'id_group' => $id_group])) { - if (!$api) - { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Le SMS a bien été créé, mais certains numéro ne sont pas valides.' - ))); - } - return true; + $errors = true; } - else + } + + if ($errors) + { + if (!$api) { - if (!$api) - { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'successmessage' => 'Le SMS a bien été créé.' - ))); - } - return true; + $_SESSION['errormessage'] = 'Le SMS a bien été créé, mais certains numéro ne sont pas valides.'; + header('Location: ' . $this->generateUrl('scheduleds')); } + return true; } if (!$api) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Impossible de créer ce SMS.' - ))); + $_SESSION['successmessage'] = 'Le SMS a bien été créé.'; + header('Location: ' . $this->generateUrl('scheduleds')); } - return false; + return true; } /** * Cette fonction met à jour une liste de sms + * @param $csrf : Le jeton CSRF + * @param array $_POST['scheduleds'] : Un tableau contenant les sms avec leurs nouvelles valeurs */ - public function update() + public function update($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['successmessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('scheduleds')); + return false; } global $db; @@ -248,68 +247,64 @@ foreach ($_POST['scheduleds'] as $id_scheduled => $scheduled) { $date = $scheduled['date']; - if (!internalTools::validateDate($date, 'Y-m-d H:i')) + if (!internalTools::validateDate($date, 'Y-m-d H:i:s') && !internalTools::validateDate($date, 'Y-m-d H:i')) { - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => 'La date renseignée pour le SMS numéro ' . $scheduled['id'] . ' est invalide.' - ))); - return true; + $_SESSION['errormessage'] = 'La date renseignée pour le SMS numéro ' . $scheduled['id'] . ' est invalide.'; + header('Location: ' . $this->generateUrl('scheduleds')); + return false; } //Si la date fournie est passée, on la change pour dans 2 minutes $objectDate = DateTime::createFromFormat('Y-m-d H:i', $date); - $db->updateScheduled($id_scheduled, $date, $scheduled['content'], false); //On met à jour le sms + $db->updateTableWhere('scheduleds', ['content' => $scheduled['content'], 'at' => $date], ['id' => $id_scheduled]); $db->deleteScheduleds_numbersForScheduled($id_scheduled); //On supprime tous les numéros pour ce SMS $db->deleteScheduleds_contactsForScheduled($id_scheduled); //On supprime tous les contacts pour ce SMS $db->deleteScheduleds_GroupsForScheduled($id_scheduled); //On supprime tous les groupes pour ce SMS - //Pour chaque numéro, on va le vérifier et l'ajouter au sms foreach ($scheduled['numbers'] as $number) { - if (internalTools::parsePhone($number)) + if (!$number = internalTools::parsePhone($number)) { - $db->createScheduleds_numbers($id_scheduled, $number); + $errors = true; + continue; } - else + + if (!$db->insertIntoTable('scheduleds_numbers', ['id_scheduled' => $id_scheduled, 'number' => $number])) { $errors = true; } } - //Pour chaque contact, on va l'ajouter au sms foreach ($scheduled['contacts'] as $id_contact) { - if (!$db->createScheduleds_contacts($id_scheduled, $id_contact)) + if (!$db->insertIntoTable('scheduleds_contacts', ['id_scheduled' => $id_scheduled, 'id_contact' => $id_contact])) { $errors = true; } } - //Pour chaque groupe, on va l'ajouter au sms foreach ($scheduled['groups'] as $id_group) { - if (!$db->createScheduleds_groups($id_scheduled, $id_group)) + if (!$db->insertIntoTable('scheduleds_groups', ['id_scheduled' => $id_scheduled, 'id_group' => $id_group])) { $errors = true; } } } - if (!$errors) + if ($errors) { - $message = 'Tous les SMS ont été modifiés avec succès.'; - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'successmessage' => $message, - ))); + $_SESSION['errormessage'] = 'Tous les SMS ont été modifiés mais certaines données incorrects ont été ignorées.'; + header('Location: ' . $this->generateUrl('scheduleds')); + return false; } else { - $message = 'Tous les SMS ont été modifiés mais certaines données incorrects ont été ignorées.'; - header('Location: ' . $this->generateUrl('scheduleds', 'showAll', array( - 'errormessage' => $message, - ))); + $_SESSION['successmessage'] = 'Tous les SMS ont été modifiés avec succès.'; + header('Location: ' . $this->generateUrl('scheduleds')); + return true; } } } diff --git a/controllers/sendeds.php b/controllers/sendeds.php index 9f67128..68402eb 100755 --- a/controllers/sendeds.php +++ b/controllers/sendeds.php @@ -24,23 +24,24 @@ /** * Cette fonction retourne tous les SMS envoyés, sous forme d'un tableau + * @param int $page : La page à consulter. Par défaut 0 * @return void; */ - public function showAll() + public function showAll($page = 0) { //Creation de l'object de base de données global $db; - $page = (int)(isset($_GET['page']) ? $_GET['page'] : 0); + $page = (int)($page < 0 ? $page = 0 : $page); $limit = 25; $offset = $limit * $page; //Récupération des SMS envoyés triés par date, du plus récent au plus ancien, par paquets de $limit, en ignorant les $offset premiers - $sendeds = $db->getAll('sendeds', 'at', true, $limit, $offset); + $sendeds = $db->getFromTableWhere('sendeds', [], 'at', true, $limit, $offset); - $this->render('sendeds', array( + $this->render('sendeds/showAll', array( 'sendeds' => $sendeds, 'page' => $page, 'limit' => $limit, diff --git a/controllers/smsAPI.php b/controllers/smsAPI.php index a89dc9b..1c3b05d 100755 --- a/controllers/smsAPI.php +++ b/controllers/smsAPI.php @@ -11,14 +11,6 @@ const API_ERROR_MISSING_FIELD = 3; - /** - * Cette fonction est alias de showAll() - */ - public function byDefault() - { - $this->send(); - } - /** * Cette fonction permet d'envoyer un SMS, en passant simplement des arguments à l'URL (ou pas $_GET) * @param string text = Le contenu du SMS @@ -27,7 +19,7 @@ * @param mixed groups = Les noms des groupes auxquels envoyer les SMS. Soit un seul et il s'agit d'un string. Soit plusieurs, et il s'agit d'un tableau * @param optionnal string date = La date à laquelle doit être envoyé le SMS. Au format 'Y-m-d H:i'. Si non fourni, le SMS sera envoyé dans 2 minutes */ - public function send() + public function byDefault() { global $db; @@ -82,27 +74,25 @@ //Pour chaque contact, on récupère l'id du contact foreach ($contacts as $key => $name) { - if ($contact = $db->getContactFromName($name)) - { - $contacts[$key] = $contact['id']; - } - else + if (!$contact = $db->getFromTableWhere('contacts', ['name' => $name])) { unset($contacts[$key]); + continue; } + + $contacts[$key] = $contact['id']; } //Pour chaque groupe, on récupère l'id du groupe foreach ($groups as $key => $name) { - if ($group = $db->getGroupFromName($name)) - { - $groups[$key] = $group['id']; - } - else + if ($group = $db->getFromTableWhere('groups', ['name' => $name])) { unset($groups[$key]); + continue; } + + $groups[$key] = $group['id']; } //Si la date n'est pas définie, on la met à la date du jour @@ -118,8 +108,9 @@ echo json_encode(array( 'error' => self::API_ERROR_MISSING_FIELD, )); - return true; - } + return false; + } + //On assigne les variable POST (après avoir vidé $_POST) en prévision de la création du SMS $_POST = array(); $_POST['content'] = $text; @@ -129,19 +120,20 @@ $_POST['groups'] = $groups; $scheduleds = new scheduleds(); - $success = $scheduleds->create(true); + $success = $scheduleds->create('', true); - if ($success) - { - echo json_encode(array( - 'error' => self::API_ERROR_NO, - )); - } - else + if (!$success) { echo json_encode(array( 'error' => self::API_ERROR_CREATION_FAILED, )); + + return false; } + + echo json_encode(array( + 'error' => self::API_ERROR_NO, + )); + return true; } } diff --git a/controllers/users.php b/controllers/users.php index 293b617..ac414f6 100755 --- a/controllers/users.php +++ b/controllers/users.php @@ -15,27 +15,18 @@ } /** - * Cette fonction est alias de showAll() + * Cette fonction retourne tous les utilisateurs, sous forme d'un tableau permettant l'administration de ces utilisateurs */ public function byDefault() - { - $this->showAll(); - } - - /** - * Cette fonction retourne tous les utilisateurs, sous forme d'un tableau permettant l'administration de ces utilisateurs - * @return void; - */ - public function showAll() { //Creation de l'object de base de données global $db; //Récupération des utilisateurs - $users = $db->getAll('users'); + $users = $db->getFromTableWhere('users'); - $this->render('users', array( + $this->render('users/default', array( 'users' => $users, )); } @@ -45,31 +36,32 @@ */ public function add() { - $this->render('addUser'); + $this->render('users/add'); } /** * Cette fonction insert un nouvel utilisateur + * @param $csrf : Le jeton CSRF + * @param string $_POST['email'] : L'email de l'utilisateur + * @param string $_POST['email_confirm'] : Confirmation de l'email de l'utilisateur + * @param boolean $_POST['admin'] : Optionnel : Si l'utilisateur est admin. Par défaut non */ - public function create() + public function create($csrf) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('users', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('users', 'add')); + return false; } global $db; - - if (!isset($_POST['email']) || !isset($_POST['email_confirm']) || $_POST['email'] != $_POST['email_confirm']) + if (!isset($_POST['email']) || !isset($_POST['email_confirm']) || ($_POST['email'] != $_POST['email_confirm'])) { - header('Location: ' . $this->generateUrl('users', 'add', array( - 'errormessage' => 'Les e-mails fournis ne correspondent pas.' - ))); + $_SESSION['errormessage'] = 'Les e-mails fournis ne correspondent pas.'; + header('Location: ' . $this->generateUrl('users', 'add')); return false; } @@ -79,9 +71,8 @@ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - header('Location: ' . $this->generateUrl('users', 'add', array( - 'errormessage' => 'L\'e-mail fourni présente un format incorrect.' - ))); + $_SESSION['errormessage'] = 'L\'e-mail fourni présente un format incorrect.'; + header('Location: ' . $this->generateUrl('users', 'add')); return false; } @@ -101,44 +92,40 @@ $message .= "-------------------------------------\n"; $message .= "Pour plus d'informations sur le système RaspiSMS, rendez-vous sur le site http://raspbian-france.fr\n"; - if (mail($email, 'Identifiants RaspiSMS', $message)) + if (!mail($email, 'Identifiants RaspiSMS', $message)) { - if ($db->createUser($email, $password, $admin)) - { - $db->createEvent('USER_ADD', 'Ajout de l\'utilisateur : ' . $email); - header('Location: ' . $this->generateUrl('users', 'showAll', array( - 'successmessage' => 'L\'utilisateur a bien été créé.' - ))); - return true; - } + $_SESSION['errormessage'] = 'Impossible d\'envoyer le mail d\'inscription à l\'utilisateur. Le compte n\'a donc pas été créé.'; + header('Location: ' . $this->generateUrl('users', 'add')); + return false; + } - header('Location: ' . $this->generateUrl('users', 'add', array( - 'errormessage' => 'Impossible de créer cet utilisateur.' - ))); - return false; - } - else + if (!$db->insertIntoTable('users', ['email' => $email, 'password' => $password, 'admin' => $admin])) { - header('Location: ' . $this->generateUrl('users', 'showAll', array( - 'errormessage' => 'Impossible d\'envoyer le mail d\'inscription à l\'utilisateur. Le compte n\'a donc pas été créé.' - ))); + $_SESSION['errormessage'] = 'Impossible de créer cet utilisateur.'; + header('Location: ' . $this->generateUrl('users', 'add')); return false; } + + $db->insertIntoTable('events', ['type' => 'USER_ADD', 'text' => 'Ajout de l\'utilisateur : ' . $email]); + $_SESSION['successmessage'] = 'L\'utilisateur a bien été créé.'; + header('Location: ' . $this->generateUrl('users')); + return true; } /** * Cette fonction supprimer une liste d'utilisateur - * @return void; + * @param $csrf : Le jeton CSRF + * @param int... $ids : Les id des commandes à supprimer + * @return boolean; */ - public function delete() + public function delete($csrf, ...$ids) { //On vérifie que le jeton csrf est bon - if (!internalTools::verifyCSRF()) + if (!internalTools::verifyCSRF($csrf)) { - header('Location: ' . $this->generateUrl('users', 'showAll', array( - 'errormessage' => 'Jeton CSRF invalide !' - ))); - return true; + $_SESSION['errormessage'] = 'Jeton CSRF invalide !'; + header('Location: ' . $this->generateUrl('users')); + return false; } //Create de l'object de base de données @@ -147,14 +134,13 @@ //Si on est pas admin if (!$_SESSION['admin']) { - header('Location: ' . $this->generateUrl('users', 'showAll', array( - 'errormessage' => 'Vous devez être administrateur pour effectuer cette action.' - ))); + $_SESSION['errormessage'] = 'Vous devez être administrateur pour effectuer cette action.'; + header('Location: ' . $this->generateUrl('users')); return false; } - $users_ids = $_GET; - $db->deleteUsersIn($users_ids); - header('Location: ' . $this->generateUrl('users')); + $db->deleteUsersIn($ids); + header('Location: ' . $this->generateUrl('users')); + return true; } } diff --git a/createDatabase.sql b/createDatabase.sql index 1763ae1..4310c08 100755 --- a/createDatabase.sql +++ b/createDatabase.sql @@ -3,7 +3,7 @@ CREATE DATABASE IF NOT EXISTS raspisms; USE raspisms; -CREATE TABLE receiveds +CREATE TABLE IF NOT EXISTS receiveds ( id INT NOT NULL AUTO_INCREMENT, at DATETIME NOT NULL, @@ -13,7 +13,7 @@ CREATE TABLE receiveds PRIMARY KEY (id) ); -CREATE TABLE sendeds +CREATE TABLE IF NOT EXISTS sendeds ( id INT NOT NULL AUTO_INCREMENT, at DATETIME NOT NULL, @@ -22,32 +22,34 @@ CREATE TABLE sendeds PRIMARY KEY (id) ); -CREATE TABLE scheduleds +CREATE TABLE IF NOT EXISTS scheduleds ( id INT NOT NULL AUTO_INCREMENT, at DATETIME NOT NULL, content VARCHAR(1000) NOT NULL, - progress BOOLEAN NOT NULL, + progress BOOLEAN NOT NULL DEFAULT 0, PRIMARY KEY (id) ); -CREATE TABLE contacts +CREATE TABLE IF NOT EXISTS contacts ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, number VARCHAR(12) NOT NULL, - PRIMARY KEY (id) + PRIMARY KEY (id), + UNIQUE (name) ); -CREATE TABLE groups +CREATE TABLE IF NOT EXISTS groups ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, - PRIMARY KEY (id) + PRIMARY KEY (id), + UNIQUE (name) ); -CREATE TABLE groups_contacts +CREATE TABLE IF NOT EXISTS groups_contacts ( id INT NOT NULL AUTO_INCREMENT, id_group INT NOT NULL, @@ -57,7 +59,7 @@ CREATE TABLE groups_contacts FOREIGN KEY (id_contact) REFERENCES contacts (id) ON DELETE CASCADE ON UPDATE CASCADE ); -CREATE TABLE scheduleds_contacts +CREATE TABLE IF NOT EXISTS scheduleds_contacts ( id INT NOT NULL AUTO_INCREMENT, id_scheduled INT NOT NULL, @@ -67,7 +69,7 @@ CREATE TABLE scheduleds_contacts FOREIGN KEY (id_contact) REFERENCES contacts (id) ON DELETE CASCADE ON UPDATE CASCADE ); -CREATE TABLE scheduleds_groups +CREATE TABLE IF NOT EXISTS scheduleds_groups ( id INT NOT NULL AUTO_INCREMENT, id_scheduled INT NOT NULL, @@ -77,7 +79,7 @@ CREATE TABLE scheduleds_groups FOREIGN KEY (id_group) REFERENCES groups (id) ON DELETE CASCADE ON UPDATE CASCADE ); -CREATE TABLE scheduleds_numbers +CREATE TABLE IF NOT EXISTS scheduleds_numbers ( id INT NOT NULL AUTO_INCREMENT, id_scheduled INT NOT NULL, @@ -86,7 +88,7 @@ CREATE TABLE scheduleds_numbers FOREIGN KEY (id_scheduled) REFERENCES scheduleds (id) ON DELETE CASCADE ON UPDATE CASCADE ); -CREATE TABLE commands +CREATE TABLE IF NOT EXISTS commands ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(25) NOT NULL, @@ -96,22 +98,31 @@ CREATE TABLE commands UNIQUE (name) ); -CREATE TABLE events +CREATE TABLE IF NOT EXISTS events ( id INT NOT NULL AUTO_INCREMENT, type VARCHAR(25) NOT NULL, - at DATETIME NOT NULL, + at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, text VARCHAR(255) NOT NULL, PRIMARY KEY (id) ); -CREATE TABLE users +CREATE TABLE IF NOT EXISTS users ( id INT NOT NULL AUTO_INCREMENT, email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, - admin BOOLEAN NOT NULL, + admin BOOLEAN NOT NULL DEFAULT FALSE, + transfer BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (id), UNIQUE (email) ); +CREATE TABLE IF NOT EXISTS transfers +( + id INT NOT NULL AUTO_INCREMENT, + id_received INT NOT NULL, + progress BOOLEAN NOT NULL DEFAULT 0, + PRIMARY KEY (id), + FOREIGN KEY (id_received) REFERENCES receiveds (id) ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/css/style.css b/css/style.css index dea9794..a7df0e9 100755 --- a/css/style.css +++ b/css/style.css @@ -9,12 +9,19 @@ } /** POPUPS ALERT **/ -.popup-alert +.popup-alerts-container { position: fixed; left: 0; top: 0; - z-index: 9999; + z-index: 9998; + width: 100%; +} + +.popup-alert +{ + width: 50%; + position: relative; } /** FOOTER **/ @@ -81,3 +88,103 @@ footer color: #fff; background-color: #000; } + +.goto:hover +{ + cursor: pointer; +} + +/** DISCUSSION **/ +.table-discussions tbody tr:hover +{ + cursor: pointer; + background-color: #999; +} + +.discussion-container +{ + overflow: auto; +} + +.discussion-message +{ + border-radius: 5px; + display: inline-block; + max-width: 90%; + padding: 10px; + position: relative; +} + +.discussion-message-text +{ + font-size: 1.3em; +} + +.discussion-message-date +{ + font-size: 0.9em; +} + +.message-container +{ + margin-bottom: 10px; +} + +.message-received +{ + background-color: #1abc9c; + float: left; + color: #fff; +} + +.message-sended +{ + background-color: #ddd; + float: right; +} + +.message-received .discussion-message-date +{ + color: #f0f0f0; +} + +.message-sended .discussion-message-date +{ + text-align: right; + color: #888; +} + +.message-input +{ + width: 100%; + max-width: 100%; + background-color: #ddd; +} + +.message-input textarea +{ + width: 100%; + resize: none; + height: 6em; +} + +.message-input button +{ + float: right; + margin-top: 8px; +} + +.message-in-progress-hover +{ + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 900; + opacity: 0.7; + background-color: #fff; + font-size: 20px; + text-align: center; + padding-top: 10px; +} diff --git a/fonts/glyphicons-halflings-regular.woff2 b/fonts/glyphicons-halflings-regular.woff2 old mode 100644 new mode 100755 diff --git a/js/custom.js b/js/custom.js index 45e9ebf..802ee30 100755 --- a/js/custom.js +++ b/js/custom.js @@ -17,5 +17,86 @@ function showMessage(message, type) } var alerthtml = ''; - jQuery('body').prepend(alerthtml); + jQuery('body .popup-alerts-container').prepend(alerthtml); } + +/** + * Cette fonction vérifie si un message a été reçu + */ +function verifReceived() +{ + jQuery('.popup-alert').fadeOut('slow'); + jQuery.getJSON(HTTP_PWD + "/receiveds/popup", function( data ) { + $.each(data, function(key, val) { + showMessage('SMS reçu du ' + val.send_by.replace(//g, ">") + ' : ' + val.content.replace(//g, ">"), 1); + }); + }); +} + +/** + * Cette fonction permet de scroller au dernier message + */ +function scrollDownDiscussion() +{ + var discussion_height = jQuery('.discussion-container').innerHeight(); + var discussion_scroll_height = jQuery('.discussion-container')[0].scrollHeight; + var discussion_scroll_top = jQuery('.discussion-container').scrollTop(); + var scroll_before_end = discussion_scroll_height - (discussion_scroll_top + discussion_height); + + //On scroll uniquement si on a pas remonté plus haut que la moitié de la fenetre de discussion + if (scroll_before_end <= discussion_height / 2) + { + jQuery('.discussion-container').animate({scrollTop: 1000000}); + } +} + +jQuery(document).ready(function() +{ + var verifReceivedInterval = setInterval(verifReceived, 10000); + + jQuery('body').on('click', '.goto', function (e) { + e.preventDefault(); + if (jQuery(this).attr('url')) + { + if (jQuery(this).attr('target')) + { + window.open(jQuery(this).attr('url'), jQuery(this).attr('target')); + } + else + { + window.location = jQuery(this).attr('url'); + } + } + }); + + jQuery('body').on('submit', '.send-message-discussion', function (e) + { + e.preventDefault(); + + var form = jQuery(this); + var message = form.find('textarea').val(); + var formData = new FormData(form[0]); + jQuery('.discussion-container').find('#send-message-spiner').remove(); + jQuery('.discussion-container').append('
'); + scrollDownDiscussion(); + jQuery.ajax({ + url: form.attr('action'), + type: form.attr('method'), + data: formData, + contentType: false, + processData: false, + dataType: "json", + success: function (data) + { + if (!data.success) + { + showMessage(data.message.replace(//g, ">"), 0); + jQuery('.discussion-container').find('#send-message-spiner').remove(); + } + } + }).done(function() + { + form.trigger("reset"); + }); + }); +}); diff --git a/js/locales/bootstrap-datetimepicker.lt.js b/js/locales/bootstrap-datetimepicker.lt.js index 8018a70..a639f6e 100755 --- a/js/locales/bootstrap-datetimepicker.lt.js +++ b/js/locales/bootstrap-datetimepicker.lt.js @@ -1,4 +1,4 @@ -/** +/** * Lithuanian translation for bootstrap-datetimepicker * Šarūnas Gliebus */ diff --git a/model/DataBase.php b/model/DataBase.php index 0bcd005..efe7ab7 100755 --- a/model/DataBase.php +++ b/model/DataBase.php @@ -45,58 +45,6 @@ return $this->runQuery($query, $params); } - /** - * Insert un nouveau SMS envoyé - * @param string $date : La date d'envoie du message - * @param string $target : Numéro auquel a été envoyé le message - * @param string $content : Texte du message - * @return int : le nombre de SMS créés - */ - public function createSended($date, $target, $content) - { - $query = ' - INSERT INTO sendeds(at, target, content) - VALUES (:date, :target, :content) - '; - - $params = array( - 'date' => $date, - 'target' => $target, - 'content' => $content, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); //On retourne le nombre de lignes ajoutés - } - - /** - * update un sended - * @param int $id : L'id du sended à modifier - * @param string $date : La nouvelle date du SMS - * @param string $target : La nouvelle cible du SMS - * @param string $content : Le nouveau contenu du SMS - * @param string $success : Le nouveau statut du SMS - * @return void - */ - public function updateSended($id, $date, $target, $content) - { - $query = ' - UPDATE sendeds - SET at = :date, - target = :target, - content = :content, - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'date' => $date, - 'target' => $target, - 'content' => $content, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /*********************************/ /* PARTIE DES REQUETES RECEIVEDS */ /*********************************/ @@ -147,21 +95,17 @@ return $this->runQuery($query, $params); } - /******************************/ - /* PARTIE DES REQUETES EVENTS */ - /******************************/ - /** - * Récupère les evenements enregistrés depuis une date - * @param $date : La date depuis laquelle on veux les evenements (au format 2014-10-25) - * @return array : Tableau avec tous les evenements depuis la date + * Récupère les SMS reçus depuis une date + * @param $date : La date depuis laquelle on veux les SMS (au format 2014-10-25 20:10:05) + * @return array : Tableau avec tous les SMS depuis la date */ - public function getEventsSince($date) + public function getReceivedsSince($date) { $query = " SELECT * - FROM events - WHERE at > STR_TO_DATE(:date, '%Y-%m-%d') + FROM receiveds + WHERE at > STR_TO_DATE(:date, '%Y-%m-%d %h:%i:%s') "; $params = array( @@ -172,24 +116,67 @@ } /** - * Enregistre un nouvel évenement - * @param string $type = Type d'evenement enregistré - * @param string $text = Texte de l'évenement (max 255chars) - * @return int = Nombre de lignes insérées + * Récupère les SMS reçus depuis une date pour un numero + * @param $date : La date depuis laquelle on veux les SMS (au format 2014-10-25 20:10:05) + * @param $number : Le numéro + * @return array : Tableau avec tous les SMS depuis la date */ - public function createEvent($type = '', $text = '') + public function getReceivedsSinceForNumberOrderByDate($date, $number) { - $query = ' - INSERT INTO events(type, at, text) - VALUES (:type, NOW(), :text) - '; + $query = " + SELECT * + FROM receiveds + WHERE at > STR_TO_DATE(:date, '%Y-%m-%d %h:%i:%s') + AND send_by = :number + ORDER BY at ASC + "; $params = array( - 'type' => $type, - 'text' => $text + 'date' => $date, + 'number' => $number ); - return $this->runQuery($query, $params, self::ROWCOUNT); + return $this->runQuery($query, $params); + } + + /** + * Récupère les receiveds dont l'id fait partie de la liste fournie + * @param array $receiveds_ids = Tableau des id des receiveds voulus + * @return array : Retourne un tableau avec les receiveds adaptés + */ + public function getReceivedsIn($receiveds_ids) + { + $query = " + SELECT * + FROM receiveds + WHERE id "; + + //On génère la clause IN et les paramètres adaptés depuis le tableau des id + $generted_in = $this->generateInFromArray($receiveds_ids); + $query .= $generted_in['QUERY']; + $params = $generted_in['PARAMS']; + + return $this->runQuery($query, $params); + } + + /***********************************/ + /* PARTIE DES REQUETES DISCUSSIONS */ + /***********************************/ + + /** + * Récupère les SMS reçus groupé par numéro et trié par date + * @return array : Le tablea avec les sms et la date + */ + public function getDiscussions() + { + $query = " + SELECT MAX(at) as at, number + FROM (SELECT at, target as number FROM sendeds UNION (SELECT at, send_by as number FROM receiveds)) as discussions + GROUP BY number + ORDER BY at DESC + "; + + return $this->runQuery($query); } /********************************/ @@ -215,63 +202,6 @@ return $this->runQuery($query, $params, self::ROWCOUNT); } - /** - * Compte le nombre de contacts - * @return int : le nombre de contacts - */ - public function countContacts() - { - $query = ' - SELECT COUNT(id) as nb - FROM contacts - '; - - $params = array(); - - $donnees = $this->runQuery($query, $params, self::FETCH); - return $donnees['nb']; - } - - /** - * Insert un contact - * @param string $nom : Le nom du nouveau contact - * @param string $number : Le numéro du nouveau contact - * @return int : le nombre de contacts - */ - public function createContact($name, $number) - { - $query = ' - INSERT INTO contacts(name, number) - VALUES (:name, :number) - '; - - $params = array( - 'name' => $name, - 'number' => $number, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - - /** - * Récupère un contact à partir de son nom - * @param string $name = Le nom du contact - * @return array : Retourne le contact - */ - public function getContactFromName($name) - { - $query = " - SELECT * - FROM contacts - WHERE name = :name"; - - $params = array( - 'name' => $name - ); - - return $this->runQuery($query, $params, self::FETCH); - } - /** * Récupère les contacts dont l'id fait partie de la liste fournie * @param array $contacts_ids = Tableau des id des contacts voulus @@ -292,54 +222,10 @@ return $this->runQuery($query, $params); } - /** - * update un contact - * @param int $id : L'id du contact à modifier - * @param string $name : Le nouveau nom du contact - * @param string $number : Le nouveau numéro du contact - * @return void - */ - public function updateContact($id, $name, $number) - { - $query = ' - UPDATE contacts - SET name = :name, - number = :number - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'name' => $name, - 'number' => $number, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /******************************/ /* PARTIE DES REQUETES GROUPS */ /******************************/ - /** - * Récupère un group à partir de son nom - * @param string $name = Le nom du group - * @return array : Retourne le group - */ - public function getGroupFromName($name) - { - $query = " - SELECT * - FROM groups - WHERE name = :name"; - - $params = array( - 'name' => $name - ); - - return $this->runQuery($query, $params, self::FETCH); - } - /** * Insert un group * @param string $nom : Le nom du nouveau group @@ -359,45 +245,6 @@ return $this->runQuery($query, $params, self::ROWCOUNT); } - /** - * update un groupe - * @param int $id : L'id du groupe à modifier - * @param string $name : Le nouveau nom du groupe - * @return int : Le nombre de lignes modifiés - */ - public function updateGroup($id, $name) - { - $query = ' - UPDATE groups - SET name = :name - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'name' => $name, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - - /** - * Compte le nombre de groups - * @return int : le nombre de groups - */ - public function countGroups() - { - $query = ' - SELECT COUNT(id) as nb - FROM groups - '; - - $params = array(); - - $donnees = $this->runQuery($query, $params, self::FETCH); - return $donnees['nb']; - } - /** * Récupère les groupes dont l'id fait partie de la liste fournie * @param array $groups_ids = Tableau des id des groupes voulus @@ -463,26 +310,6 @@ return $this->runQuery($query, $params); } - /* Insert un groups_contacts - * @param string $id_group : L'id du group - * @param string $id_contact : L'id du contact - * @return int : le nombre de lignes crées - */ - public function createGroups_contacts($id_group, $id_contact) - { - $query = ' - INSERT INTO groups_contacts(id_group, id_contact) - VALUES (:id_group, :id_contact) - '; - - $params = array( - 'id_group' => $id_group, - 'id_contact' => $id_contact, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Récupère tout les groupes, avec le nombre de contact dans chacun * @return array : Tableau avec tous les groupes et le nombre de contacts liés @@ -533,48 +360,10 @@ return $req->fetchAll(); } - /** - * Supprime tous les groups_contacts pour un groupe donné - * @param int $id : L'id du groupe pour lequel on doit supprimer les groups_contacts - * @return int Le nombre de lignes supprimées - */ - public function deleteGroups_contactsForGroup($id_group) - { - $query = ' - DELETE FROM groups_contacts - WHERE id_group = :id_group - '; - - $params = array( - 'id_group' => $id_group - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /**********************************/ /* PARTIE DES REQUETES SCHEDULEDS */ /**********************************/ - /** - * Récupère SMS programmé à partir de son id - * @param int $id = L'id du SMS programmé - * @return array : Retourne le contact - */ - public function getScheduledFromId($id) - { - $query = " - SELECT * - FROM scheduleds - WHERE id = :id"; - - $params = array( - 'id' => $id - ); - - return $this->runQuery($query, $params, self::FETCH); - } - /** * Récupère les sms programmés dont l'id fait partie de la liste fournie * @param array $scheduleds_ids = Tableau des id des sms voulus @@ -638,34 +427,6 @@ return $this->runQuery($query, $params, self::ROWCOUNT); } - /** - * update un sms programmé - * @param int $id : L'id du sms à modifier - * @param string $date : La nouvelle date du sms - * @param string $content : Le nouveau contenu du sms - * @param boolean $progress : Le nouveau statut de la progression du sms - * @return int : Le nombre de lignes modifiées - */ - public function updateScheduled($id, $date, $content, $progress) - { - $query = ' - UPDATE scheduleds - SET at = :date, - content = :content, - progress = :progress - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'date' => $date, - 'content' => $content, - 'progress' => $progress, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Supprime tous les sms programmés dont l'id fait partie du tableau fourni * @param $contacts_ids : Tableau des id des sms à supprimer @@ -686,20 +447,54 @@ } /** - * Compte le nombre de sms programmés - * @return int : le nombre de sms programmés + * Cette fonction retourne les sms programmés pour un numéro donné et avant une date + * @param string $date : La date avant laquel on veux les numéros (format yyyy-mm-dd hh:mm:ss) + * @param string $number : Le numéro cible + * @return array : Les scheduleds correspondants */ - public function countScheduleds() + public function getScheduledsBeforeDateForNumber($date, $number) { - $query = ' - SELECT COUNT(id) as nb + $query = " + SELECT * FROM scheduleds - '; + WHERE at <= :date + AND ( + id IN ( + SELECT id_scheduled + FROM scheduleds_numbers + WHERE number = :number + ) + OR id IN ( + SELECT id_scheduled + FROM scheduleds_contacts + WHERE id_contact IN ( + SELECT id + FROM contacts + WHERE number = :number + ) + ) + OR id IN ( + SELECT id_scheduled + FROM scheduleds_groups + WHERE id_group IN ( + SELECT id_group + FROM groups_contacts + WHERE id_contact IN ( + SELECT id + FROM contacts + WHERE number = :number + ) + ) + ) + ) + "; + + $params = array( + 'date' => $date, + 'number' => $number, + ); - $params = array(); - - $donnees = $this->runQuery($query, $params, self::FETCH); - return $donnees['nb']; + return $this->runQuery($query, $params); } /********************************/ @@ -726,57 +521,6 @@ return $this->runQuery($query, $params); } - /** - * Insert un commande - * @param string $name : Le nom de la command - * @param string $script : Le chemin du script à appeler - * @param string $admin : Défini si il est nécessaire d'être admin - * @return int : le nombre de commandes ajoutées - */ - public function createCommand($name, $script, $admin) - { - $query = ' - INSERT INTO commands(name, script, admin) - VALUES (:name, :script, :admin) - '; - - $params = array( - 'name' => $name, - 'script' => $script, - 'admin' => $admin, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - - /** - * update une commande - * @param int $id : L'id de la commande à modifier - * @param string $name : Le nouveau nom de la commande - * @param string $script : Le nouveau script de la commande - * @param string $name : Nouvel état de la necessité des droits administrateur - * @return int : Le nombre de lignes modifiée - */ - public function updateCommand($id, $name, $script, $admin) - { - $query = ' - UPDATE commands - SET name = :name, - script = :script, - admin = :admin - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'name' => $name, - 'script' => $script, - 'admin' => $admin, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Supprime tous les commands dont l'id fait partie du tableau fourni * @param $commands_ids : Tableau des id des commands à supprimer @@ -796,48 +540,10 @@ return $this->runQuery($query, $params, self::ROWCOUNT); } - /** - * Compte le nombre de commands - * @return int : le nombre de commands - */ - public function countCommands() - { - $query = ' - SELECT COUNT(id) as nb - FROM commands - '; - - $params = array(); - - $donnees = $this->runQuery($query, $params, self::FETCH); - return $donnees['nb']; - } - /*******************************************/ /* PARTIE DES REQUETES SCHEDULEDS_CONTACTS */ /*******************************************/ - /** - * Créer un nouveau scheduleds_contacts - * @param int $id_scheduled : L'id du SMS programmé lié - * @param int $id_contact : L'id du contact lié - * @return int : Le nombre de lignes insérées - */ - public function createScheduleds_contacts($id_scheduled, $id_contact) - { - $query = ' - INSERT INTO scheduleds_contacts(id_scheduled, id_contact) - VALUES (:id_scheduled, :id_contact) - '; - - $params = array( - 'id_scheduled' => $id_scheduled, - 'id_contact' => $id_contact, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Retourne tous les contacts pour un sms programmé donnée * @param int $id_sms : L'id du sms @@ -904,27 +610,6 @@ /* PARTIE DES REQUETES SCHEDULEDS_NUMBERS */ /******************************************/ - /** - * Créer un nouveau scheduleds_numbers - * @param int $id_scheduled : L'id du SMS programmé lié - * @param string $number : Le numéro de téléphone lié - * @return int : Le nombre de lignes insérées - */ - public function createScheduleds_numbers($id_scheduled, $number) - { - $query = ' - INSERT INTO scheduleds_numbers(id_scheduled, number) - VALUES (:id_scheduled, :number) - '; - - $params = array( - 'id_scheduled' => $id_scheduled, - 'number' => $number, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Supprime tous les scheduleds_numbers pour un sms donné * @param int $id_scheduled : L'id du sms pour lequel on doit supprimer les scheduleds_numbers @@ -968,27 +653,6 @@ /* PARTIE DES REQUETES SCHEDULEDS_GROUPS */ /*****************************************/ - /** - * Créer un nouveau scheduleds_groups - * @param int $id_scheduled : L'id du SMS programmé lié - * @param int $id_group : L'id du group lié - * @return int : Le nombre de lignes insérées - */ - public function createScheduleds_groups($id_scheduled, $id_group) - { - $query = ' - INSERT INTO scheduleds_groups(id_scheduled, id_group) - VALUES (:id_scheduled, :id_group) - '; - - $params = array( - 'id_scheduled' => $id_scheduled, - 'id_group' => $id_group, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Supprime tous les scheduleds_groups pour un sms donné * @param int $id_scheduled : L'id du sms pour lequel on doit supprimer les scheduleds_groups @@ -1053,57 +717,6 @@ return $this->runQuery($query, $params, self::FETCH); } - /** - * update un user - * @param int $id : L'id du user à modifier - * @param string $email : Le nouveau email du user - * @param string $password : Le nouveau password du user - * @param string $admin : Le nouveau statut admin du user - * @return void - */ - public function updateUser($id, $email, $password, $admin) - { - $query = ' - UPDATE users - SET email = :email, - password = :password, - admin = :admin - WHERE id = :id - '; - - $params = array( - 'id' => $id, - 'email' => $email, - 'password' => $password, - 'admin' => $admin, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - - /** - * Insert un utilisateur - * @param string $email : L'adresse email du nouvel utilisateur - * @param string $password : Le mot de passe de l'utilisateur - * @param boolean $admin : Le statut de l'utilisateur - * @return int : le nombre d'utilisateurs ajoutés - */ - public function createUser($email, $password, $admin) - { - $query = ' - INSERT INTO users(email, password, admin) - VALUES (:email, :password, :admin) - '; - - $params = array( - 'email' => $email, - 'password' => $password, - 'admin' => $admin, - ); - - return $this->runQuery($query, $params, self::ROWCOUNT); - } - /** * Supprime tous les users dont l'id fait partie du tableau fourni * @param $users_ids : Tableau des id des users à supprimer @@ -1123,4 +736,47 @@ return $this->runQuery($query, $params, self::ROWCOUNT); } + /*********************************/ + /* PARTIE DES REQUETES TRANSFERS */ + /*********************************/ + + /** + * Change le statut des tranfers dont l'id est fourni dans $transfers_id + * @param array $transfers_ids = Tableau des id des transfers voulus + * @return int : Retourne le nombre de lignes mises à jour + */ + public function updateProgressTransfersIn($transfers_ids, $progress) + { + $query = " + UPDATE transfers + SET progress = :progress + WHERE id "; + + //On génère la clause IN et les paramètres adaptés depuis le tableau des id + $generted_in = $this->generateInFromArray($transfers_ids); + $query .= $generted_in['QUERY']; + $params = $generted_in['PARAMS']; + $params['progress'] = (boolean)$progress; + + return $this->runQuery($query, $params, self::ROWCOUNT); + } + + /** + * Supprime tous les transfers dont l'id fait partie du tableau fourni + * @param $transfers_ids : Tableau des id des transfers à supprimer + * @return int : Nombre de lignes supprimées + */ + public function deleteTransfersIn($transfers_ids) + { + $query = " + DELETE FROM transfers + WHERE id "; + + //On génère la clause IN et les paramètres adaptés depuis le tableau des id + $generted_in = $this->generateInFromArray($transfers_ids); + $query .= $generted_in['QUERY']; + $params = $generted_in['PARAMS']; + + return $this->runQuery($query, $params, self::ROWCOUNT); + } } diff --git a/mvc/404.php b/mvc/404.php new file mode 100644 index 0000000..e45a7d3 --- /dev/null +++ b/mvc/404.php @@ -0,0 +1 @@ +

404 Not Found

diff --git a/mvc/Controller.php b/mvc/Controller.php index 0bdc641..8dd6ef5 100755 --- a/mvc/Controller.php +++ b/mvc/Controller.php @@ -53,7 +53,7 @@ $chemin_template = PWD_TEMPLATES . $template . '.php'; if(file_exists($chemin_template)) { - require_once($chemin_template); + require($chemin_template); unset($chemin_template); return true; } @@ -65,19 +65,31 @@ * Cette fonction permet de générer une adresse URL interne au site * @param string $controller : Nom du controleur à employer (par défaut vide) * @param string $method : Nom de la méthode à employer (par défaut vide) - * @param string $params : Tableau des paramètres $_GET à employer au format 'nom' => valeur (par défaut array()) + * @param string $params : Tableau des paramètres à passer à la fonction, sous forme de tableau, sans clefs + * @param string $getParams : Tableau des paramètres $_GET à employer au format 'nom' => valeur (par défaut array()) * @return string, Url générée */ - protected function generateUrl($controller = '', $method = '', $params = array()) + protected function generateUrl($controller = '', $method = '', $params = array(), $getParams = array()) { $url = HTTP_PWD; $url .= ($controller ? $controller . '/' : ''); $url .= ($method ? $method . '/' : ''); - foreach ($params as $clef => $valeur) + + //On ajoute les paramètres framework + foreach ($params as $valeur) { - $url .= $clef . '_' . rawurlencode($valeur) . '/'; + $url .= rawurlencode($valeur) . '/'; } + //On calcul puis ajoute les paramètres get + $paramsToJoins = array(); + foreach ($getParams as $clef => $valeur) + { + $paramsToJoins[] = $clef . '=' . rawurlencode($valeur); + } + + $url .= count($getParams) ? '?' . implode('&', $paramsToJoins) : ''; + return $url; } diff --git a/mvc/Model.php b/mvc/Model.php index 1de6cea..428f203 100755 --- a/mvc/Model.php +++ b/mvc/Model.php @@ -29,20 +29,164 @@ $this->bdd = $bdd; } + /* + Fonctions relatives aux informations de la base + */ + + /** + * Cette fonction vérifie si une table existe + * @param string $table : Nom de la table + * @return mixed : Vrai si la table existe, faux sinon + */ + public function tableExist($table) + { + $tables = $this->getAllTables(); + return in_array($table, $tables); + } + + /** + * Cette fonction vérifie si un champs existe dans une table + * @param string $field : Nom du champ + * @param string $table : Nom de la table + * @return mixed : Vrai si le champs existe, faux, si le champs ou la table n'existe pas + */ + public function fieldExist($field, $table) + { + $fields = $this->getColumnsForTable($table); + $fields = $fields ? explode(', ', $fields) : array(); + return in_array($field, $fields); + } + + /** + * Cette requete retourne le dernier id inséré + * return int : le dernier id inséré + */ + public function lastId() + { + return $this->bdd->lastInsertId(); + } + + /** + * Cette fonction permet de retourner toutes les tables de la base + * @return array : La liste des tables + */ + public function getAllTables() + { + $query = 'SHOW TABLES'; + $tables = $this->runQuery($query); + $tablesNames = array(); + + foreach ($tables as $table) + { + $tablesNames[] = array_values($table)[0]; + } + + return $tablesNames; + } + + /** + * Cette fonction permet de récupérer la liste de toutes les colonnes d'une table de façon propre, appelable via MySQL. Cela permet de faire des requetes plus optimisée qu'avec "*" + * @param string $table : Nom de la table pour laquelle on veux les colonnes + * @param string $prefix : Le prefix que l'on veux devant les champs, utile pour les requetes avec jointures. Par défaut null => pas de prefix. A noter, en cas d'utilisation de prefix, les champs aurons un alias de la forme $prefix_$nom_champ + * @return boolean string : Tous les noms des colonnes liées par des ", ". Ex : 'id, nom, prenom". Si la table n'existe pas, on retourne false. + */ + public function getColumnsForTable($table, $prefix = null) + { + if ($this->tableExist($table)) + { + $query = 'SHOW COLUMNS FROM ' . $table; + + $datas = array(); + + $fields = $this->runQuery($query, $datas, self::FETCHALL); + $fieldsName = array(); + foreach ($fields as $field) + { + $fieldsName[] = $prefix ? $prefix . '.' . $field['Field'] . ' AS ' . $prefix . '_' . $field['Field'] : $field['Field']; + } + + return implode(', ', $fieldsName); + } + + return false; + } + + /** + * Cette fonction décrit une table et retourne un tableau sur cette description + * @param string $table : Le nom de la table a analyser + * @return mixed : Si la table existe un tableau la décrivant, sinon false + */ + public function describeTable($table) + { + if (!$this->tableExist($table)) + { + return false; + } + + //On recupere tous les champs pour pouvoir apres les analyser + $query = 'DESCRIBE ' . $table; + $fields = $this->runQuery($query); + + $return = array(); + foreach ($fields as $field) + { + $fieldInfo = array(); + $fieldInfo['NULL'] = $field['Null'] == 'NO' ? false : true; + $fieldInfo['AUTO_INCREMENT'] = $field['Extra'] == 'auto_increment' ? true : false; + $fieldInfo['PRIMARY'] = $field['Key'] == 'PRI' ? true : false; + $fieldInfo['UNIQUE'] = $field['Key'] == 'UNI' ? true : false; + $fieldInfo['TYPE'] = mb_convert_case(preg_replace('#[^a-z]#ui', '', $field['Type']), MB_CASE_UPPER); + $fieldInfo['SIZE'] = filter_var($field['Type'], FILTER_SANITIZE_NUMBER_INT); + $fieldInfo['HAS_DEFAULT'] = $field['Default'] !== NULL ? true : false; + $fieldInfo['DEFAULT'] = $field['Default']; + $return[$field['Field']] = $fieldInfo; + } + + return $return; + } + + /** + * Cette fonction permet de compter le nombre de ligne d'une table + * @param string $table : Le nom de la table à compter + * @return mixed : Le nombre de ligne dans la table ou false si la table n'existe pas + */ + public function countTable ($table) + { + if (!$this->tableExist($table)) + { + return false; + } + + $query = "SELECT COUNT(*) as nb_lignes FROM " . $table; + + $return = $this->runQuery($query, array(), self::FETCH); + return $return['nb_lignes']; + } + + /* + Fonctions d'execution des requetes ou de génération + */ + /** * Cette fonction joue une requete depuis une requete et un tableau d'argument * @param string $query : Requete à jouer * @param array $datas : Les données pour la requete. Si non fourni, vide par défaut. * @param const $return_type : Type de retour à utiliser. (Voir les constantes de la classe Model ici présente). Par défaut FETCHALL * @param const $fetch_mode : Le type de récupération a effectuer. Par défaut FETCH_ASSOC + * @param boolean $debug : Par défaut à faux, si vrai retourne les infos de débug de la requete * @return mixed : Dépend du type spécifié dans $return_type */ - public function runQuery($query, $datas = array(), $return_type = self::FETCHALL, $fetch_mode = PDO::FETCH_ASSOC) + public function runQuery($query, $datas = array(), $return_type = self::FETCHALL, $fetch_mode = PDO::FETCH_ASSOC, $debug = false) { $req = $this->bdd->prepare($query); $req->setFetchMode($return_type); $req->execute($datas); + if ($debug) + { + return $req->errorInfo(); + } + switch ($return_type) { case self::NO : @@ -68,62 +212,6 @@ return $return; } - /** - * Cette fonction vérifie si une table existe - * @param string $table : Nom de la table - * @return mixed : Vrai si la table existe, faux sinon - */ - public function tableExist($table) - { - $query = ' - SHOW TABLES LIKE :table - '; - - $query_datas = array( - 'table' => $table - ); - - $req = $this->bdd->prepare($query); - $req->execute($query_datas); - $result = $req->fetch(); - if(count($result)) - { - return true; - } - - return false; - } - - /** - * Cette fonction vérifie si un champs existe dans une table - * @param string $field : Nom du champ - * @param string $table : Nom de la table - * @return mixed : Vrai si le champs existe, faux, si le champs ou la table n'existe pas - */ - public function fieldExist($field, $table) - { - if($this->tableExist($table)) - { - $query = ' - SHOW COLUMNS FROM ' . $table . ' LIKE :field - '; - - $query_datas = array( - 'field' => $field - ); - - $req = $this->bdd->prepare($query); - $req->execute($query_datas); - $result = $req->fetch(); - if(count($result)) - { - return true; - } - } - - return false; - } - /** * Cette fonction permet de récupérer les éléments necessaires à une requete 'IN' depuis un tableau php * @param string $values : Tableau PHP des valeurs @@ -150,91 +238,242 @@ return $return; } - /** - * Cette requete retourne le dernier id inséré - * return int : le dernier id inséré - */ - public function lastId() - { - return $this->bdd->lastInsertId(); - } + + /* + Fonctions de manipulations basiques des données + */ /** - * Cette fonction permet de récupérer la liste de toutes les colonnes d'une table de façon propre, appelable via MySQL. Cela permet de faire des requetes plus optimisée qu'avec "*" - * @param string $table : Nom de la table pour laquelle on veux les colonnes - * @return boolean string : Tous les noms des colonnes liées par des ", ". Ex : 'id, nom, prenom". Si la table n'existe pas, on retourne false. - */ - public function getColumnsForTable($table) - { - if ($this->tableExist($table)) - { - $query = 'SHOW COLUMNS FROM ' . $table; - - $datas = array(); - - $fields = $this->runQuery($query, $datas, self::FETCHALL); - $fieldsName = array(); - foreach ($fields as $field) - { - $fieldsName[] = $field['Field']; - } - - return implode(', ', $fieldsName); - } - - return false; - } - - /** - * Cette fonction permet de récupérer une table complète, éventuellement en la triant par une colonne, éventuellement en limitant le nombre de résultat, ou en sautant certains (notamment pour de la pagination) - * @param string $table : Le nom de la table a récupérer + * Cette fonction permet de récupérer des lignes en fonction de restrictions + * @param string $table : Le nom de la table dans laquelle on veux recuperer la ligne + * @param array $restrictions : Les restrictions que l'on veux appliquer * @param string $order_by : Le nom de la colonne par laquelle on veux trier les résultats. Si non fourni, tri automatique * @param string $desc : L'ordre de tri (asc ou desc). Si non défini, ordre par défaut (ASC) * @param string $limit : Le nombre maximum de résultats à récupérer (par défaut pas le limite) * @param string $offset : Le nombre de résultats à ignorer (par défaut pas de résultats ignorés) - * @return array : Tableau avec dans chaque case une ligne de la base + * @return mixed : False en cas d'erreur, sinon les lignes retournées */ - public function getAll($table, $order_by = '', $desc = false, $limit = false, $offset = false) + public function getFromTableWhere($table, $restrictions = array(), $order_by = '', $desc = false, $limit = false, $offset = false) { - if ($this->tableExist($table)) + $restrictions = !is_array($restrictions) ? array() : $restrictions; + + $fields = $this->describeTable($table); + if (!$fields) { - $query = "SELECT " . $this->getColumnsForTable($table) . " FROM " . $table; - - if ($order_by) - { - if ($this->fieldExist($order_by, $table)) - { - $query .= ' ORDER BY '. $order_by; - if ($desc) - { - $query .= ' DESC'; - } - } - } - - if ($limit !== false) - { - $query .= ' LIMIT :limit'; - if ($offset !== false) - { - $query .= ' OFFSET :offset'; - } - } - - $req = $this->bdd->prepare($query); - - if ($limit !== false) - { - $req->bindParam(':limit', $limit, PDO::PARAM_INT); - if ($offset !== false) - { - $req->bindParam(':offset', $offset, PDO::PARAM_INT); - } - } - - $req->setFetchMode(PDO::FETCH_ASSOC); - $req->execute(); - return $req->fetchAll(); + return false; } + + //On gère les restrictions + $wheres = array(); + $params = array(); + + foreach ($restrictions as $label => $value) + { + //Si le champs pour la restriction n'existe pas on retourne false + if (!array_key_exists($label, $fields)) + { + return false; + } + + //On ajoute la restriction au WHERE + $params['where_' . $label] = $value; + $wheres[] = $label . ' = :where_' . $label . ' '; + } + + $query = "SELECT " . $this->getColumnsForTable($table) . " FROM " . $table . " WHERE 1 " . (count($wheres) ? 'AND ' : '') . implode('AND ', $wheres); + + if ($order_by) + { + if ($this->fieldExist($order_by, $table)) + { + $query .= ' ORDER BY '. $order_by; + if ($desc) + { + $query .= ' DESC'; + } + } + } + + if ($limit !== false) + { + $query .= ' LIMIT :limit'; + if ($offset !== false) + { + $query .= ' OFFSET :offset'; + } + } + + $req = $this->bdd->prepare($query); + + if ($limit !== false) + { + $req->bindParam(':limit', $limit, PDO::PARAM_INT); + if ($offset !== false) + { + $req->bindParam(':offset', $offset, PDO::PARAM_INT); + } + } + + //On associe les paramètres + foreach ($params as $label => &$param) + { + $req->bindParam(':' . $label, $param); + } + + $req->setFetchMode(PDO::FETCH_ASSOC); + $req->execute(); + return $req->fetchAll(); } + + /** + * Cette fonction permet de modifier les données d'une table pour un la clef primaire + * @param string $table : Le nom de la table dans laquelle on veux insérer des données + * @param string $primary : La clef primaire qui sert à identifier la ligne a modifier + * @param array $datas : Les données à insérer au format "champ" => "valeur" + * @param array $restrictions : Un tableau des restrictions à appliquer sous forme "champ" => "valeur". Par défaut un tableau vide + * @return mixed : False en cas d'erreur, sinon le nombre de lignes modifiées + */ + public function updateTableWhere ($table, $datas, $restrictions = array()) + { + $fields = $this->describeTable($table); + if (!$fields) + { + return false; + } + + $params = array(); + $sets = array(); + + //On gère les set + foreach ($datas as $label => $value) + { + //Si le champs pour la nouvelle valeur n'existe pas on retourne false + if (!array_key_exists($label, $fields)) + { + return false; + } + + //Si le champs est Nullable est qu'on à reçu une chaine vide, on passe à null plutot qu'à chaine vide + if ($fields[$label]['NULL'] && $value === '') + { + $value = null; + } + + $params['set_' . $label] = $value; + $sets[] = $label . ' = :set_' . $label . ' '; + } + + //On gère les restrictions + $wheres = array(); + foreach ($restrictions as $label => $value) + { + //Si le champs pour la restriction n'existe pas on retourne false + if (!array_key_exists($label, $fields)) + { + return false; + } + + //On ajoute la restriction au WHERE + $params['where_' . $label] = $value; + $wheres[] = $label . ' = :where_' . $label . ' '; + } + + //On fabrique la requete + $query = "UPDATE " . $table . " SET " . implode(', ', $sets) . " WHERE 1 AND " . implode('AND ', $wheres); + + //On retourne le nombre de lignes insérées + return $this->runQuery($query, $params, self::ROWCOUNT); + } + + /** + * Cette fonction permet de supprimer des lignes d'une table en fonctions de restrictions + * @param string $table : Le nom de la table dans laquelle on veux supprimer la ligne + * @param array $restrictions : Les restrictions pour la suppression sous la forme "label" => "valeur" + * @return mixed : False en cas d'erreur, sinon le nombre de lignes supprimées + */ + public function deleteFromTableWhere($table, $restrictions = array()) + { + + $fields = $this->describeTable($table); + if (!$fields) + { + return false; + } + + //On gère les restrictions + $wheres = array(); + $params = array(); + + foreach ($restrictions as $label => $value) + { + //Si le champs pour la restriction n'existe pas on retourne false + if (!array_key_exists($label, $fields)) + { + return false; + } + + //On ajoute la restriction au WHERE + $params['where_' . $label] = $value; + $wheres[] = $label . ' = :where_' . $label . ' '; + } + + $query = "DELETE FROM " . $table . " WHERE 1 AND " . implode('AND ', $wheres); + + return $this->runQuery($query, $params, self::ROWCOUNT); + } + + /** + * Cette fonction permet d'insérer des données dans une table + * @param string $table : Le nom de la table dans laquelle on veux insérer des données + * @param array $datas : Les données à insérer + * @return mixed : False en cas d'erreur, et le nombre de lignes insérées sinon + */ + public function insertIntoTable($table, $datas) + { + $fields = $this->describeTable($table); + if (!$fields) + { + return false; + } + + $params = array(); + $fieldNames = array(); + + //On s'assure davoir toutes les données, on evite les auto increment, on casse en cas de donnée absente + foreach ($fields as $nom => $field) + { + if ($field['AUTO_INCREMENT']) + { + continue; + } + + //Si il manque un champs qui peux être NULL ou qu'il est rempli avec une chaine vide ou null, on passe au suivant + if ((!isset($datas[$nom]) || $datas[$nom] === NULL || $datas[$nom] === '') && $field['NULL']) + { + continue; + } + + //Si il manque un champs qui a une valeur par défaut + if (!isset($datas[$nom]) && $field['HAS_DEFAULT']) + { + continue; + } + + //Si il nous manque un champs + if (!isset($datas[$nom])) + { + return false; + } + + $params[$nom] = $datas[$nom]; + $fieldNames[] = $nom; + } + + //On fabrique la requete + $query = "INSERT INTO " . $table . "(" . implode(', ', $fieldNames) . ") VALUES(:" . implode(', :', $fieldNames) . ")"; + + //On retourne le nombre de lignes insérées + return $this->runQuery($query, $params, self::ROWCOUNT); + } + } diff --git a/mvc/Router.php b/mvc/Router.php index a9d960e..9016e88 100755 --- a/mvc/Router.php +++ b/mvc/Router.php @@ -68,6 +68,16 @@ $this->params = $value; } + /** + * Cette méthode retourne la page 404 par défaut + */ + public function return404 () + { + http_response_code(404); + include(PWD . 'mvc/404.php'); + die(); + } + /** * Retourne une route avec seulement l'url parsée comme il faut * @param string $route : La route à analyser @@ -77,12 +87,12 @@ { $directory_to_remove = strstr(preg_replace('#http(s)?://#', '', HTTP_PWD), '/'); //On retire la partie protocole, et l'adresse du serveur de la partie de la route à ignorer $route = mb_strcut($route, mb_strlen($directory_to_remove)); //On retire la partie à ignorer de la route - - $route = preg_split('#[/?]#', $route); //On explose la route + $route = explode('?', $route)[0]; //on ne garde que ce qui précède les arguments + $route = preg_split('#[/]#', $route); //On explose la route foreach($route as $key => $val) //On garde seulement les repertoires non vides { - if(empty($val)) + if(empty($val) && $val !== 0 && $val !== '0') { unset($route[$key]); } @@ -100,17 +110,21 @@ public function parseController($route) { $route = $this->parseRoute($route); //On récupère la route parsé - //On lie le bon controlleur - if (empty($route[0]) || !file_exists(PWD_CONTROLLER . $route[0] . '.php') || mb_strpos($route[0], 'internal') !== false) //Si on a pas de premier parametre, ou qu'il ne correspond à aucun controlleur + + //Si pas de controlleur, on prend celui par défaut + if (empty($route[0])) { - $controllerName = DEFAULT_CONTROLLER; //On défini le nom du controlleur par défaut + return DEFAULT_CONTROLLER; } - else //Sinon, si tout est bon + + //Sinon, si le controlleur n'existe pas ou est internal, on retourne une 404 + if (!file_exists(PWD_CONTROLLER . $route[0] . '.php') || mb_strpos($route[0], 'internal') !== false) { - $controllerName = $route[0]; //On défini le nom du controlleur + return $this->return404(); } - - return $controllerName; + + //On retourne le controlleur adapté + return $route[0]; } /** @@ -120,20 +134,71 @@ */ public function parseMethod($route) { + //On instancie le controlleur $controllerName = $this->parseController($route); - require_once(PWD_CONTROLLER . $controllerName . '.php'); //On inclus le controlleur $controller = new $controllerName(); - $route = $this->parseRoute($route); //On récupère la route parsé - //On lie la bonne méthode - if (empty($route[1]) || !method_exists($controller, $route[1])) //Si on a pas de second parametre, ou qu'il ne correspond à aucune méthode du controlleur + $prefixMethod = ''; + + //On recupère les paramètres dans l'url pour les utiliser un peu plus tard + $params = $this->parseParams($route); + + + //On vérifie si le controlleur est un controlleur API, si c'est le cas on le refais avec cette fois la bonne methode + if ($controller instanceof ApiController) { - $method = DEFAULT_METHOD; //On prend la méthode par défaut - } - else //Sinon, si tout est bon - { - $method = $route[1]; //On défini la méthode appelée + //On va choisir le type à employer + $method = $_SERVER['REQUEST_METHOD']; + switch (mb_convert_case($method, MB_CASE_LOWER)) + { + case 'delete' : + $prefixMethod = 'delete'; + break; + case 'patch' : + $prefixMethod = 'patch'; + break; + case 'post' : + $prefixMethod = 'post'; + break; + case 'put' : + $prefixMethod = 'put'; + break; + default : + $prefixMethod = 'get'; + } } + $route = $this->parseRoute($route); //On récupère la route parsé + + //On regarde quelle route il nous faut et on evite les routes qui commencent par '_', qui sont maintenant considérées comme privées + if (empty($route[1])) + { + $method = DEFAULT_METHOD; + } + else + { + $method = $route[1]; + } + + if ($prefixMethod) + { + $method = $prefixMethod . mb_convert_case($method, MB_CASE_TITLE); + } + + //Si la méthode à appeler n'existe pas ou si la route commencent par '_', signe qu'elle est un outils non accessibles + if (!method_exists($controller, $method) || mb_substr($method, 0, 1) == '_') + { + return $this->return404(); + } + + //On instancie la classe reflection de PHP sur la méthode que l'on veux analyser pour l'objet controller + $methodAnalyser = new ReflectionMethod($controller, $method); + + //Si la méthode à appeler demande plus de paramètres que fournis on retourne une 404 + if ($methodAnalyser->getNumberOfRequiredParameters() > count($params)) + { + return $this->return404(); + } + return $method; } @@ -146,48 +211,83 @@ { $route = $this->parseRoute($route); //On récupère la route parsé $params = array(); - $already_use_params = array(); - //On transforme les paramètres $_GET passés par l'url au format clef_value. Ex : prenom_pierre-lin = $_GET['prenom'] => 'pierre-lin' + + //On transforme les paramètres $_GET passés par l'url au format clef-value. Ex : prenom-pierre-lin = $_GET['prenom'] => 'pierre-lin' if (count($route) > 2) //Si on a plus de deux paramètres qui ont été passé { unset($route[0], $route[1]); //On supprime le controlleur, et la route, des paramètres, il ne reste que les parametres a passer en GET - foreach($route as $param) //On passe sur chaque paramètre a transformer en GET + foreach ($route as $param) { - $param = explode('_', $param, 2); //On récupère le paramètre, via la délimiteur '_', en s'arretant au premier - - //Si on a déjà utilisé cette variable GET - if (in_array($param[0], $already_use_params)) - { - if (isset($params[$param[0]])) - { - $tmp_value = $params[$param[0]]; - $params[$param[0]] = array($tmp_value); - unset($tmp_value); - } - - $params[$param[0]][] = (isset($param[1])) ? rawurldecode($param[1]) : NULL; - } - else - { - $params[$param[0]] = (isset($param[1])) ? rawurldecode($param[1]) : NULL; //On définit la propriétée GET correspondante - $already_use_params[] = $param[0]; - } + $params[] = rawurldecode($param); } } - return $params; } + /** + * Cette fonction permet de vérifier si le cache est activé pour une route, et si oui quel fichier utiliser + * @param string $route : Route à analyser + * @return mixed : Si pas de cache, faux. Sinon un tableau avec deux clefs, "state" => statut du nom de fichier retourné (true, le fichier doit être utilisé, false, le fichier doit être créé), "file" => Le nom du fcihier de cache + */ + public function verifyCache($route) + { + //On récupère le nom du controller et de la méthode + $controllerName = $this->parseController($route); + $methodName = $this->parseMethod($route); + $params = $this->parseParams($route); + + $controller = new $controllerName(); + + //Si on ne doit pas activer le cache ou si on na pas de cache pour ce fichier + if (!ACTIVATING_CACHE || !property_exists($controller, 'cache_' . $methodName)) + { + return false; + } + + //Si on a du cache, on va déterminer le nom approprié + //Format de nom = + $hashName = md5($controllerName . $methodName); + $hashDatas = md5(json_encode($_GET) . json_encode($_POST) . json_encode($params)); + $fileName = $hashName . $hashDatas; + + //Si il n'existe pas de fichier de cache pour ce fichier + if (!file_exists(PWD_CACHE . $fileName)) + { + return array('state' => false, 'file' => $fileName); + } + + //Sinon, si le fichier de cache existe + $fileLastChange = filemtime(PWD_CACHE . $fileName); + + //On calcul la date de mise à jour valide la plus ancienne possible + $now = new DateTime(); + $propertyName = 'cache_' . $methodName; + $propertyValue = $controller->$propertyName; + $now->sub(new DateInterval('PT' . $propertyValue . 'M')); + $maxDate = $now->format('U'); + + //Si le fichier de cache est trop vieux + if ($fileLastChange < $maxDate) + { + return array('state' => false, 'file' => $fileName); + } + + //Sinon, on retourne le fichier de cache en disant de l'utiliser + return array('state' => true, 'file' => $fileName); + } + /** * Cette fonction permet de charger la page adaptée a partir d'une url + * Elle gère également le cache * @param string $route : Route à analyser pour charger une page * @return void */ public function loadRoute($route) { - $_GET = array_merge($_GET, $this->parseParams($route)); //On fusionne les paramètres GET et ceux passés dans la route du controller + $params = $this->parseParams($route); //On récupère les paramètres à passer à la fonction $controllerName = $this->parseController($route); //On récupère le nom du controleur à appeler $controller = new $controllerName(); //On créer le controleur + $beforeMethodName = DEFAULT_BEFORE; //On défini le nom de la fonction before if (method_exists($controller, $beforeMethodName)) //Si une fonction before existe pour ce controller, on l'appel { @@ -195,7 +295,27 @@ } $methodName = $this->parseMethod($route); //On récupère le nom de la méthode - $controller->$methodName(); //On appel la méthode - } + $verifyCache = $this->verifyCache($route); + //Si on ne doit pas utiliser de cache + if ($verifyCache === false) + { + call_user_func_array(array($controller, $methodName), $params); //On appel la methode, en lui passant les arguments necessaires + return null; + } + + //Si on doit utiliser un cache avec un nouveau fichier + if ($verifyCache['state'] == false) + { + //On créer le fichier avec le contenu adapté + ob_start(); + call_user_func_array(array($controller, $methodName), $params); //On appel la methode, en lui passant les arguments necessaires + $content = ob_get_contents(); + file_put_contents(PWD_CACHE . $verifyCache['file'], $content); + ob_end_clean(); + } + + //On utilise le fichier de cache + readfile(PWD_CACHE . $verifyCache['file']); + } } diff --git a/mvc/autoload.php b/mvc/autoload.php index c9d4938..b90fd5d 100755 --- a/mvc/autoload.php +++ b/mvc/autoload.php @@ -9,6 +9,8 @@ */ function autoloader($class) { + $class = str_replace('\\', '/', $class); #Gestion des namespaces + if (file_exists(PWD_CONTROLLER . $class . '.php')) { require_once(PWD_CONTROLLER . $class . '.php'); @@ -17,6 +19,10 @@ { require_once(PWD_MODEL . $class . '.php'); } + else if (file_exists(PWD . 'mvc/modules/' . $class . '.php')) + { + require_once(PWD . 'mvc/modules/' . $class . '.php'); + } } spl_autoload_register('autoloader'); diff --git a/mvc/conn_bdd.php b/mvc/conn_bdd.php index 6b2d06a..0bd8b1b 100755 --- a/mvc/conn_bdd.php +++ b/mvc/conn_bdd.php @@ -1,19 +1,19 @@ - TRUE)); - $bdd->exec("SET CHARACTER SET utf8"); - } - catch(Exception $e) - { - // En cas d'erreur, on affiche un message et on arrête tout - die('Erreur : '.$e->getMessage()); - } -?> + TRUE)); + $bdd->exec("SET CHARACTER SET utf8"); + } + catch(Exception $e) + { + // En cas d'erreur, on affiche un message et on arrête tout + die('Erreur : '.$e->getMessage()); + } +?> diff --git a/mvc/constants.php b/mvc/constants.php index 040a134..576455d 100755 --- a/mvc/constants.php +++ b/mvc/constants.php @@ -31,3 +31,18 @@ //Réglages des logs define('LOG_ACTIVATED', 1); //On active les logs + + //Réglages du cache + define('ACTIVATING_CACHE', false); //On desactive le cache + + //Réglages divers + define('WEBSITE_TITLE', 'RaspiSMS'); //Le titre du site + define('WEBSITE_DESCRIPTION', ''); //Description du site + define('WEBSITE_KEYWORDS', ''); //Mots clefs du site + define('WEBSITE_AUTHOR', 'Raspbian-France'); //Auteur du site + + //Réglages des identifiants de base de données + define('DATABASE_HOST', 'localhost'); //Hote de la bdd + define('DATABASE_NAME', 'raspisms'); //Nom de la bdd + define('DATABASE_USER', 'root'); //Utilisateur de la bdd + define('DATABASE_PASSWORD', ''); //Password de l'utilisateur diff --git a/mvc/secho.php b/mvc/secho.php index 5a007a6..62cbb6d 100755 --- a/mvc/secho.php +++ b/mvc/secho.php @@ -8,7 +8,7 @@ ARGUMENTS : Obligatoires : - - string &$text_source : Une variable passé par référence qui sera utilisé comme texte source + - string $text_source : Une variable qui sera utilisé comme texte source Optionnels : - boolean $no_nl2br : Par défaut à faux -> les retours à la lignes sont transformé en
. A vrai -> ils sont conservés tels quels - boolean $escape_quotes : Par défaut à faux -> les guillemets ne sont pas échappés. A vrai -> ils sont transformés en entitées HTML @@ -17,7 +17,7 @@ RETOUR : Cette fonction retourne le texte transformé en cas de success, false sinon */ - function secho(&$text_source, $no_nl2br = false, $escape_quotes = false, $authorize_null = true) //On utilise une reference, si la variable n'existe pas, ça ne lévera pas d'erreur + function secho($text_source, $no_nl2br = false, $escape_quotes = false, $authorize_null = true) //On utilise une reference, si la variable n'existe pas, ça ne lévera pas d'erreur { if ($authorize_null) //Si on les variables null, false ou '' doivent être prises comme définies { diff --git a/templates/addCommand.php b/templates/commands/add.php similarity index 97% rename from templates/addCommand.php rename to templates/commands/add.php index 3fb78e3..bd60c19 100755 --- a/templates/addCommand.php +++ b/templates/commands/add.php @@ -37,7 +37,7 @@

Ajout d'une nouvelle commande

-
+
diff --git a/templates/commands.php b/templates/commands/default.php similarity index 91% rename from templates/commands.php rename to templates/commands/default.php index e535445..96d1a05 100755 --- a/templates/commands.php +++ b/templates/commands/default.php @@ -72,8 +72,8 @@
@@ -96,7 +96,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/command' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; }); diff --git a/templates/editCommands.php b/templates/commands/edit.php similarity index 97% rename from templates/editCommands.php rename to templates/commands/edit.php index 91bf0a1..0e04e74 100755 --- a/templates/editCommands.php +++ b/templates/commands/edit.php @@ -37,7 +37,7 @@

Modification de commandes

- +
footer(); diff --git a/templates/addContact.php b/templates/contacts/add.php similarity index 90% rename from templates/addContact.php rename to templates/contacts/add.php index b6ca384..517c3a0 100755 --- a/templates/addContact.php +++ b/templates/contacts/add.php @@ -37,7 +37,7 @@

Ajout d'un contact

- +
@@ -49,7 +49,7 @@
- +
Annuler diff --git a/templates/contacts.php b/templates/contacts/default.php similarity index 91% rename from templates/contacts.php rename to templates/contacts/default.php index 53aa494..5739d19 100755 --- a/templates/contacts.php +++ b/templates/contacts/default.php @@ -70,8 +70,8 @@
@@ -94,7 +94,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/contacts' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; }); diff --git a/templates/editContacts.php b/templates/contacts/edit.php similarity index 93% rename from templates/editContacts.php rename to templates/contacts/edit.php index 0fc2153..90b151d 100755 --- a/templates/editContacts.php +++ b/templates/contacts/edit.php @@ -37,7 +37,7 @@

Modification de contacts

- + Numéro de téléphone du contact
- +

diff --git a/templates/dashboard.php b/templates/dashboard/default.php similarity index 100% rename from templates/dashboard.php rename to templates/dashboard/default.php diff --git a/templates/discussions/default.php b/templates/discussions/default.php new file mode 100755 index 0000000..52a17fe --- /dev/null +++ b/templates/discussions/default.php @@ -0,0 +1,68 @@ +head('Discussions - Show All'); +?> +
+nav('discussions'); +?> +
+
+ +
+
+

+ Dashboard Discussions +

+ +
+
+ + +
+
+
+
+

Liste des discussions

+
+
+
+ + + + + + + + + + + + + + + +
Date du dernier messageNuméro
+
+
+
+
+
+
+
+
+footer(); diff --git a/templates/discussions/show.php b/templates/discussions/show.php new file mode 100755 index 0000000..519bf12 --- /dev/null +++ b/templates/discussions/show.php @@ -0,0 +1,134 @@ +head('Discussions - Show All'); +?> +
+nav('discussions'); +?> +
+
+ +
+
+

+ Discussion +

+ +
+
+ + +
+
+
+
+
+
+ + + + + +
+
+
+
+
+
+ +footer(); diff --git a/templates/events.php b/templates/events/default.php similarity index 100% rename from templates/events.php rename to templates/events/default.php diff --git a/templates/addGroup.php b/templates/groups/add.php similarity index 97% rename from templates/addGroup.php rename to templates/groups/add.php index a406e25..421b796 100755 --- a/templates/addGroup.php +++ b/templates/groups/add.php @@ -37,7 +37,7 @@

Ajout d'un groupe

-
+
diff --git a/templates/groups.php b/templates/groups/default.php similarity index 94% rename from templates/groups.php rename to templates/groups/default.php index 6d86ded..1f277d5 100755 --- a/templates/groups.php +++ b/templates/groups/default.php @@ -71,7 +71,7 @@
@@ -94,7 +94,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/groups' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; }); diff --git a/templates/editGroups.php b/templates/groups/edit.php similarity index 97% rename from templates/editGroups.php rename to templates/groups/edit.php index 278d2c6..a6e18b9 100755 --- a/templates/editGroups.php +++ b/templates/groups/edit.php @@ -37,7 +37,7 @@

Modification de groupes

- + font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"> + phptojs(); + ?> @@ -58,3 +62,4 @@ + diff --git a/templates/nav.php b/templates/internalIncs/nav.php similarity index 95% rename from templates/nav.php rename to templates/internalIncs/nav.php index 84e78de..49ba288 100755 --- a/templates/nav.php +++ b/templates/internalIncs/nav.php @@ -34,6 +34,9 @@
  • > SMS
  • +
  • > + Discussions +
  • > Commandes
  • diff --git a/templates/internalIncs/phptojs.php b/templates/internalIncs/phptojs.php new file mode 100644 index 0000000..0c49bc5 --- /dev/null +++ b/templates/internalIncs/phptojs.php @@ -0,0 +1,3 @@ + diff --git a/templates/profile.php b/templates/profile/default.php similarity index 80% rename from templates/profile.php rename to templates/profile/default.php index 06b1e24..6e6018d 100755 --- a/templates/profile.php +++ b/templates/profile/default.php @@ -49,7 +49,7 @@

    Modifier mot de passe

    - +
    @@ -64,6 +64,23 @@
    +
    +
    +

    Supprimer ce compte

    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    @@ -71,7 +88,7 @@

    Modifier e-mail

    -
    +
    @@ -88,17 +105,19 @@
    -

    Supprimer ce compte

    +

    Transfert des SMS par e-mail

    - -
    - + +
    + +
    - +
    @@ -121,7 +140,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/users' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; }); diff --git a/templates/receiveds.php b/templates/receiveds/showAll.php similarity index 100% rename from templates/receiveds.php rename to templates/receiveds/showAll.php diff --git a/templates/addScheduled.php b/templates/scheduleds/add.php similarity index 96% rename from templates/addScheduled.php rename to templates/scheduleds/add.php index 71c94b1..8eb838a 100755 --- a/templates/addScheduled.php +++ b/templates/scheduleds/add.php @@ -37,7 +37,7 @@

    Ajout d'un SMS programmé

    -
    +
    @@ -73,7 +73,7 @@ { jQuery('.form-datetime').datetimepicker( { - format: 'yyyy-mm-dd hh:ii', + format: 'yyyy-mm-dd hh:ii:ss', autoclose: true, minuteStep: 1, language: 'fr' diff --git a/templates/scheduleds.php b/templates/scheduleds/default.php similarity index 92% rename from templates/scheduleds.php rename to templates/scheduleds/default.php index 3e07c2b..a92515d 100755 --- a/templates/scheduleds.php +++ b/templates/scheduleds/default.php @@ -52,7 +52,7 @@ - ... + Action pour la sélection
    @@ -94,7 +94,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/scheduleds' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; }); diff --git a/templates/editScheduleds.php b/templates/scheduleds/edit.php similarity index 97% rename from templates/editScheduleds.php rename to templates/scheduleds/edit.php index 1a3e632..5a0cc8a 100755 --- a/templates/editScheduleds.php +++ b/templates/scheduleds/edit.php @@ -37,7 +37,7 @@

    Modification des SMS programmés

    - + Ajout d'un utilisateur
    - +
    diff --git a/templates/users.php b/templates/users/default.php similarity index 94% rename from templates/users.php rename to templates/users/default.php index 1758484..e4312d2 100755 --- a/templates/users.php +++ b/templates/users/default.php @@ -70,7 +70,7 @@
    @@ -93,7 +93,7 @@ var url = jQuery(this).attr('href'); jQuery(target).find('input:checked').each(function () { - url += '/users' + jQuery(this).val() + '_' + jQuery(this).val(); + url += '/' + jQuery(this).val(); }); window.location = url; });