diff --git a/drone.yml b/drone.yml new file mode 100644 index 0000000..903d8ca --- /dev/null +++ b/drone.yml @@ -0,0 +1,62 @@ +kind: pipeline +type: docker +name: CI-pipeline + +trigger: + branch: + - master + event: + - push + +steps: + + + - name: code-inspection + image: hub.codefirst.iut.uca.fr/marc.chevaldonne/codefirst-dronesonarplugin-dotnet8 + secrets: [ SECRET_SONAR_LOGIN ] + settings: + sonar_host: https://codefirst.iut.uca.fr/sonar/ + sonar_token: + from_secret: SECRET_SONAR_LOGIN + commands: + - dotnet sonarscanner begin /k:WF-Website /d:sonar.host.url=$${PLUGIN_SONAR_HOST} /d:sonar.coverageReportPaths="coveragereport/SonarQube.xml" /d:sonar.coverage.exclusions="" /d:sonar.login=$${PLUGIN_SONAR_TOKEN} + + - reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport" + - dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN} + + # database container deployment + - name: deploy-container-mysql-WIKI_FANTASY + image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest + environment: + IMAGENAME: mysql:latest + CONTAINERNAME: mysql + COMMAND: create + OVERWRITE: false + PRIVATE: true + + CODEFIRST_CLIENTDRONE_ENV_MYSQL_ROOT_PASSWORD: + from_secret: db_root_password + CODEFIRST_CLIENTDRONE_ENV_MYSQL_DATABASE: + from_secret: db_database + CODEFIRST_CLIENTDRONE_ENV_MYSQL_USER: + from_secret: db_user + CODEFIRST_CLIENTDRONE_ENV_MYSQL_PASSWORD: + from_secret: db_password + ADMINS: kentinbrongniart , kevinmondejar , lenibeaulaton , louisguichard-montguers , maximerocher , tommynguyen , matthieurestituito + + + - name: generate-and-deploy-docs + image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-docdeployer + failure: ignore + volumes: + - name: + path: + commands: + - /entrypoint.sh + when: + branch: + - master + event: + - push + - pull_request + depends_on: [] diff --git a/public/pages/profil.php b/public/pages/profil.php index fb65e25..582a271 100644 --- a/public/pages/profil.php +++ b/public/pages/profil.php @@ -36,21 +36,21 @@ // Nom d'utilisateur echo "

{$u->username} - +

"; // Email echo "

{$u->email} - +

"; // Mot de passe echo "

{$u->hidenPasswd} - +

"; ?> diff --git a/public/script/changeData.js b/public/script/changeData.js index 8cc43b3..4250c12 100644 --- a/public/script/changeData.js +++ b/public/script/changeData.js @@ -1,10 +1,7 @@ -function editField(id) { - // Récupérer l'élément

via son identifiant - var pElement = document.getElementById(id); - - // Obtenir le texte actuel du

- var currentValue = pElement.textContent.trim(); +function editFieldUsername(id) { + var pElement = document.getElementById(id);// Récupérer l'élément

via son identifiant + var currentValue = pElement.textContent.trim();// Obtenir le texte actuel du

// Créer un champ de saisie avec la valeur actuelle var input = document.createElement('input'); @@ -12,19 +9,55 @@ function editField(id) { input.value = currentValue input.class = 'changeValue'; - // Sauvegarde lors de la perte de focus - input.setAttribute('onblur', 'saveField("' + id + '", this.value)'); + input.setAttribute('onblur', 'saveFieldUsername("' + id + '", this.value)'); // Sauvegarde lors de la perte de focus + + // Remplacer le

par le champ + pElement.innerHTML = ''; + pElement.appendChild(input); + + input.focus(); // Mettre le focus sur le champ de saisie +} + +//Sauvegarder les changements sur la vue pour le username +function saveFieldUsername(id, newValue) { + if (id === 'username') { + if (newValue.trim() === "") { + alert('Le nom d\'utilisateur ne peut pas être vide.'); + document.getElementById(id).querySelector('input').focus(); + return; // Ne pas sauvegarder si le nom d'utilisateur est vide + } + } + + var pElement = document.getElementById(id);// Récupérer l'élément

via son identifiant + + // Mettre à jour la valeur avec la nouvelle saisie + pElement.innerHTML = '' + newValue + ' '; +} + + + + +function editFieldEmail(id) { + var pElement = document.getElementById(id);// Récupérer l'élément

via son identifiant + var currentValue = pElement.textContent.trim();// Obtenir le texte actuel du

+ + // Créer un champ de saisie avec la valeur actuelle + var input = document.createElement('input'); + input.type = 'email'; + input.value = currentValue + input.class = 'changeValue'; + + input.setAttribute('onblur', 'saveFieldEmail("' + id + '", this.value)'); // Sauvegarde lors de la perte de focus // Remplacer le

par le champ pElement.innerHTML = ''; pElement.appendChild(input); - // Mettre le focus sur le champ de saisie - input.focus(); + input.focus(); // Mettre le focus sur le champ de saisie } -//Sauvegarder les changements sur la vue -function saveField(id, newValue) { +//Sauvegarder les changements sur la vue pour l'email +function saveFieldEmail(id, newValue) { if (id === 'email') { if (!validateEmail(newValue)) { alert('Adresse email invalide. Veuillez entrer un email valide.'); @@ -39,17 +72,98 @@ function saveField(id, newValue) { return; // Ne pas sauvegarder si le nom d'utilisateur est vide } } - - // Récupérer l'élément

via son identifiant - var pElement = document.getElementById(id); + + var pElement = document.getElementById(id); // Récupérer l'élément

via son identifiant // Mettre à jour la valeur avec la nouvelle saisie - pElement.innerHTML = '' + newValue + ' '; + pElement.innerHTML = '' + newValue + ' '; } + + + //Email valide function validateEmail(email) { - // Regex pour vérifier le format de l'email - var re = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; + var re = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;// Regex pour vérifier le format de l'email return re.test(String(email).toLowerCase()); } + + + + + + + +function editFieldPassWd(id) { + var pElement = document.getElementById(id);// Récupérer l'élément

via son identifiant + + pElement.innerHTML = '';// Effacer le contenu actuel de

pour insérer les inputs + + // Créer le champ de saisie pour le nouveau mot de passe + var inputNewPass = document.createElement('input'); + inputNewPass.type = 'password'; + inputNewPass.placeholder = 'Nouveau mot de passe'; // Un placeholder pour indiquer la fonction du champ + inputNewPass.classList.add('changeValue'); // Ajouter une classe CSS pour styliser l'input + inputNewPass.setAttribute('id', 'newPassword'); // Ajouter un ID pour la gestion + inputNewPass.classList.add('inputPasswd'); // Ajouter une classe au input + + + // Créer le champ de saisie pour la confirmation du mot de passe + var inputConfirmPass = document.createElement('input'); + inputConfirmPass.type = 'password'; + inputConfirmPass.placeholder = 'Confirmer le mot de passe'; // Un placeholder pour indiquer la fonction du champ + inputConfirmPass.classList.add('changeValue'); // Ajouter une classe CSS pour styliser l'input + inputConfirmPass.setAttribute('id', 'confirmPassword'); // Ajouter un ID pour la gestion + inputConfirmPass.classList.add('inputPasswd'); // Ajouter une classe au input + + // Ajouter un bouton de sauvegarde + var saveButton = document.createElement('button'); + saveButton.textContent = 'Sauvegarder le mot de passe'; + saveButton.classList.add('saveButtonPasswd'); // Ajouter une classe au bouton + + saveButton.onclick = function() { + savePasswordFields(id, inputNewPass.value, inputConfirmPass.value); + + }; + + // Ajouter les deux champs de saisie et le bouton dans l'élément

+ pElement.appendChild(inputNewPass); + pElement.appendChild(document.createElement('br')); // Saut de ligne pour espacer les champs + pElement.appendChild(inputConfirmPass); + pElement.appendChild(document.createElement('br')); // Saut de ligne pour espacer + pElement.appendChild(saveButton); + + inputNewPass.focus();// Mettre le focus sur le premier champ de saisie +} + + + +function savePasswordFields(id, newPassword, confirmPassword) { + // Vérification si les champs sont vides + if (newPassword.trim() === "" || confirmPassword.trim() === ""){ + alert("Les champs de mot de passe ne doivent pas être vides."); + return; + } + + // Vérification de la correspondance des deux mots de passe + if (newPassword === confirmPassword) { + + var pElement = document.getElementById(id);// Récupérer l'élément

via son identifiant + + if(newPassword.length >= 16){ + var maskedPassword = '*'.repeat(16); // Masquer le nouveau mot de passe pour l'affichage + } + else{ + var maskedPassword = "*".repeat(newPassword.length); // Masquer le nouveau mot de passe pour l'affichage + } + + // Remplacer les champs input par le texte masqué + pElement.innerHTML = '' + maskedPassword + ' '; + alert('Mot de passe mis à jour avec succès'); + + // Possibilité d'ajouter ici une fonction pour envoyer les nouveaux mots de passe au serveur + + } else { + alert('Les mots de passe ne correspondent pas.'); + } +} diff --git a/public/script/comment.php b/public/script/comment.php new file mode 100644 index 0000000..e69de29 diff --git a/public/script/quote.php b/public/script/quote.php new file mode 100644 index 0000000..d3c07ac --- /dev/null +++ b/public/script/quote.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/public/script/quoteGateway.php b/public/script/quoteGateway.php new file mode 100644 index 0000000..db85b36 --- /dev/null +++ b/public/script/quoteGateway.php @@ -0,0 +1,49 @@ +con=$con; + } + + public function searchQuote(string $quote,int $numpage,string $language):array{ + + //recherche par citation + $query="SELECT q.id_quote, q.content, c.caracter, c.img_path, s.title, s.date, q.like, q.language FROM Quote q JOIN Caracter c ON c.id_caracter = q.id_caracter JOIN Source s ON s.id_source = q.id_source WHERE content LIKE '%:quote%' AND isValid = true AND language = :language LIMIT 20 OFFSET :page*20;"; + $this->con->executeQuery($query,array(':quote' => array($quote,PDO::PARAM_STR),':page' => array($numpage,PDO::PARAM_INT),':language' => array($language,PDO::PARAM_STR))); + $result=$this->con->getResults(); + return $result; + } + + public function searchSource(string $source,int $numpage,string $language):array{ + + //recherche par source + $query="SELECT q.id_quote, q.content, c.caracter, c.img_path, s.title, s.date, q.like, q.language FROM Quote q JOIN Caracter c ON c.id_caracter = q.id_caracter JOIN Source s ON s.id_source = q.id_source WHERE s.title LIKE '%:source%' AND q.isValid = true AND language = :language LIMIT 20 OFFSET :page*20;"; + $this->con->executeQuery($query,array(':source' => array($source,PDO::PARAM_STR),':page' => array($numpage,PDO::PARAM_INT),':language' => array($language,PDO::PARAM_STR))); + $result=$this->con->getResults(); + return $result; + } + + public function searchPers(string $Carac,int $numpage,string $language):array{ + + //recherche par personnage + $query="SELECT q.id_quote, q.content, c.caracter, c.img_path, s.title, s.date, q.like, q.language FROM Quote q JOIN Caracter c ON c.id_caracter = q.id_caracter JOIN Source s ON s.id_source = q.id_source WHERE c.caracter LIKE '%:pers%' AND q.isValid = true AND language = :language LIMIT 20 OFFSET :page*20;"; + $this->con->executeQuery($query,array(':pers' => array($Pers,PDO::PARAM_STR),':page' => array($numpage,PDO::PARAM_INT),':language' => array($language,PDO::PARAM_STR))); + $result=$this->con->getResults(); + return $result; + } + + public function getComment(int $id):array{ + + //obtention des commentaire d'une citation + $query="SELECT c.id_comment u.username, u.imgPath, c.comment, c.date FROM Commentary c JOIN Quote q ON c.quote = q.id_quote JOIN User u ON u.id_user = c.user JOIN Image i ON i.id_img = u.img WHERE id_quote = :id;"; + $this->con->executeQuery($query,array(':id' => array($id,PDO::PARAM_INT))); + $result=$this->con->getResults(); + return $result; + } + +} + +?> \ No newline at end of file diff --git a/public/script/user.php b/public/script/user.php index 32aeb82..4a2b0c0 100644 --- a/public/script/user.php +++ b/public/script/user.php @@ -6,9 +6,9 @@ class User{ public string $hidenPasswd; public string $img; public string $email; - public bool $admin = false; - function __construct(string $pseudo, string $password, string $image, string $mail) { + function __construct(int $id, string $pseudo, string $password, string $image, string $mail) { + $this->id = $id; $this->username = $pseudo; $this->passwd = $password; $this->hidenPasswd = hidenPassWd($password); @@ -17,27 +17,20 @@ class User{ } public function updateUsername(string $newUsername){ - if(!empty($newUsername)){ + if(isset($newUsername)){ $this->username = $newUsername; } } public function updateEmail(string $newEmail) { - if(!empty($newEmail)){ + if(isset($newEmail)){ $this->email = $newEmail; } } - public function updatePassWd(string $newPassword1, string $newPassword2){ - if(!empty($newPassword2) && !empty($newPassword1)){ - if($newPassword1 == $newPassword2){ - $u->passwd = $newPassword1; - } - } - } public function modifyImage(string $image){ - if(!empty($image)){ + if(isset($image)){ $u->img = $image; } } diff --git a/public/script/userGateway.php b/public/script/userGateway.php index 08b8f37..6549956 100644 --- a/public/script/userGateway.php +++ b/public/script/userGateway.php @@ -1,6 +1,5 @@ con=$con; } - public function insert(User $u):int{ + public function insert(string $username,string $email,string $passwd):int{ // récupération id $query='SELECT id_user FROM Users WHERE id_user >= ALL (SELECT id_user FROM Users);'; @@ -30,12 +29,14 @@ Class UserGateway{ $query='DELETE FROM Users WHERE id_user = :id;'; $this->con->executeQuery($query,array(':id' => array($id,PDO::PARAM_INT))); } - - public function searchQuote(string $quote,int $numpage)//: - { - $query="Select * From Quote Where content LIKE '%:quote%' Limit 20 OFFSET :page*20;"; - $this->con->executeQuery($query,array(':quote' => array($quote,PDO::PARAM_STR),':page' => array($numpage,PDO::PARAM_INT))); - //return ; + + public function getFavorite(int $id):array{ + + //obtention favoris d'un user + $query='SELECT * FROM Quote WHERE id_quote IN (SELECT id_quote IN Favorite f JOIN User u ON u.id_user = f.user WHERE id_user = :id);'; + $this->con->executeQuery($query,array(':id' => array($id,PDO::PARAM_INT))); + $result=$this->con->getResults(); + return $result; } } diff --git a/public/styles/styleProfil.css b/public/styles/styleProfil.css index f58d3b6..de2ea5d 100644 --- a/public/styles/styleProfil.css +++ b/public/styles/styleProfil.css @@ -68,8 +68,30 @@ body.dark-mode .infoProfil > input { border: none; font-size: 15px; font-family: "Lemon", serif; + } + +body.dark-mode .inputPasswd{ + font-family: "Lemon", serif; + margin-top: 40%; + color: black; +} + +body.dark-mode .saveButtonPasswd { + background: linear-gradient(90deg, #6100ff 0%, #1b0048 100%); + font-family: "Lemon", serif; + border: none; + color: white; + padding: 1%; + border-radius: 25px; + width: 55%; + font-size: 15px; + margin-top: 5%; +} + + + /* ====== LIGHT MODE ====== */ body.light-mode h1{ color : black; @@ -139,6 +161,26 @@ body.light-mode .infoProfil > input { background-color: #fff1f1; font-size: 15px; font-family: "Lemon", serif; + color : black; +} + + +body.light-mode .inputPasswd{ + font-family: "Lemon", serif; + margin-top: 40%; + color: black; +} + +body.light-mode .saveButtonPasswd { + background: linear-gradient(180deg, rgba(187,211,249,1) 0%, rgba(199,246,196,1) 100%); + font-family: "Lemon", serif; + border: none; + color: black; + padding: 1%; + border-radius: 25px; + width: 55%; + font-size: 15px; + margin-top: 5%; } @@ -180,3 +222,5 @@ body.light-mode .infoProfil > input { margin-left: 25%; display:block; } + + diff --git a/src/questionEntity.php b/src/questionEntity.php new file mode 100644 index 0000000..6b3dcc9 --- /dev/null +++ b/src/questionEntity.php @@ -0,0 +1,88 @@ + id_question = $id_question; + $this -> question = $question; + $this -> answerA = $answerA; + $this -> answerB = $answerB; + $this -> answerC = $answerC; + $this -> answerD = $answerD; + $this -> cAnswer = $cAnswer; + } + + public function getIdQuestion() : int + { + return $this -> id_question; + } + + public function getQuestion() : string + { + return $this -> question; + } + + public function getAnswerA() : string + { + return $this -> answerA; + } + + public function getAnswerB() : string + { + return $this -> answerB; + } + + public function getAnswerC() : string + { + return $this -> answerC; + } + + public function getAnswerD() : string + { + return $this -> answerD; + } + + public function getCAnswer() : string + { + return $this -> cAnswer; + } + + public function setQuestion(string $newQuestion) : void + { + $this -> question = $question; + } + + public function setAnswerA(string $newAnswerA) : void + { + $this -> answerA = $newAnswerA; + } + + public function setAnswerB(string $newAnswerB) : void + { + $this -> answerB = $newAnswerB; + } + + public function setAnswerC(string $newAnswerC) : void + { + $this -> answerC = $newAnswerC; + } + + public function setAnswerD(string $newAnswerD) : void + { + $this -> answerD = $newAnswerD; + } + + public function setCAnswer(string $newCAnswer) : void + { + $this -> cAnswer = $newCAnswer; + } + } \ No newline at end of file diff --git a/src/questionGateway.php b/src/questionGateway.php new file mode 100644 index 0000000..77d964e --- /dev/null +++ b/src/questionGateway.php @@ -0,0 +1,152 @@ + co = $co; + } + + /** + * Inserts a new question into the database + * + * @param QuestionEntity $q The `Question` object to insert + * @return bool True if the question was successfully inserted, false otherwise + */ + public function create(QuestionEntity $q) : bool + { + $query = " + INSERT INTO Question + VALUES(:id_q, :question, :answerA, :answerB, :answerC, :answerD, :cAnswer) + "; + $stmt = $this -> co -> prepare($query); + + return $stmt -> execute([ + ':id_q' => $q -> getIdquestion(), + ':question' => $q -> getQuestion(), + ':answerA' => $q -> getAnswerA(), + ':answerB' => $q -> getAnswerB(), + ':answerC' => $q -> getAnswerC(), + ':answerD' => $q -> getAnswerD(), + ':cAnswer' => $q -> getCAnswer() + ]); + } + + /** + * Retrieves a question from the database by its ID + * + * @param int $id The ID of the question to retrieve + * @return QuestionEntity|null The `Question` object if found, null otherwise + */ + public function findById(int $id) : ?QuestionEntity + { + $query = "SELECT * FROM Question WHERE id_question = :id_q"; + $stmt = $this -> co -> prepare($query); + $stmt -> execute([':id' => $id]); + $res = $stmt -> fetch(PDO::FETCH_ASSOC); + + if ($res) + return new QuestionEntity( + $res['id_q'], + $res['question'], + $res['answerA'], + $res['answerB'], + $res['answerC'], + $res['answerD'], + $res['cAnswer'], + ); + return null; + } + + /** + * Updates the text of and an existing question in the database + * + * @param QuestionEntity $q The `Question` object with updated information + * @return bool True if the text of the question was successfully updated, false otherwise + */ + public function updateText(QuestionEntity $q) : bool + { + $query = " + UPDATE Question + SET question = :question + WHERE id_question = :id_q + "; + $stmt = $this -> co -> prepare($query); + + return $stmt -> execute([':question' => $q -> getQuestion()]); + } + + /** + * Updates the answers of an existing question in the database + * + * @param QuestionEntity $q The `Question` object with updated information + * @return bool True if the answers of the question was successfully updated, false otherwise + */ + public function updateAnswers(QuestionEntity $q) : bool + { + $query = " + UPDATE Question + SET answerA = :answerA, answerB = :answerB, + answerC = :answerC, answerD = :answerD, cAnswer = :cAnswer + WHERE id_question = :id_q + "; + $stmt = $this -> co -> prepare($query); + + return $stmt -> execute([ + ':id_q' => $q -> getIdQuestion(), + ':answerA' => $q -> getAnswerA(), + ':answerB' => $q -> getAnswerB(), + ':answerC' => $q -> getAnswerC(), + ':answerD' => $q -> getAnswerD(), + ':cAnswer' => $q -> getCAnswer(), + ]); + } + + /** + * Deletes a question from the database by its ID + * + * @param int $id The ID of the question + * @return bool + */ + public function delete(int $id) : bool + { + $query = "DELETE FROM Question WHERE id_question = :id_q"; + $stmt = $this -> co -> prepare($query); + + return $stmt -> execute([':id_q' => $id]); + } + + /** + * Retrieves all quizzes from the database + * + * @return QuestionEntity[] An array of `Question` objects + */ + public function findAll() : array + { + $query = "SELECT * FROM Question"; + $stmt = $this -> co -> prepare($query); + $stmt->execute(); + $res = $stmt -> fetchAll(PDO::FETCH_ASSOC); + + $questions = []; + + foreach ($res as $q) + $questions[] = new QuestionEntity( + $q['id_question'], + $q['question'], + $q['answerA'], + $q['answerB'], + $q['answerC'], + $q['answerD'], + $q['cAnswer'] + ); + + return $questions; + } + +} \ No newline at end of file diff --git a/src/questionModel.php b/src/questionModel.php new file mode 100644 index 0000000..d0dc225 --- /dev/null +++ b/src/questionModel.php @@ -0,0 +1,65 @@ + gateway = $gateway; + } + + public function createQuestion(int $id_question, string $question, string $answerA, string $answerB, string $answerC, string $answerD, string $cAnswer) : bool + { + $q = new QuestionEntity($id_question, $question, $answerA, $answerB, $answerC, $answerD, $cAnswer); + return $this -> gateway -> create($q); + } + + public function getQuestion(int $id_question) : ?QuestionEntity + { + return $this -> gateway -> findById($id_question); + } + + public function updateTextQuestion(int $id_question, string $question) : bool + { + $q = $this -> gateway -> findById($id_question); + + if ($q) + { + $q -> setQuestion($question); + return $this -> gateway -> updateText($q); + } + + return false; + } + + public function updateAnswersQuestion(int $id_question, string $answerA, string $answerB, string $answerC, string $answerD, string $cAnswer) : bool + { + $q = $this -> gateway -> findById($id_question); + + if ($q) + { + $q -> setAnswerA($answerA); + $q -> setAnswerB($answerB); + $q -> setAnswerC($answerC); + $q -> setAnswerD($answerD); + $q -> setAnswerC($cAnswer); + return $this -> gateway -> updateAnswers($q); + } + + return false; + } + + public function deleteQuestion(int $id_question) : bool + { + return $this -> gateway -> delete($id_question); + } + + public function getAllQuestions() : array + { + return $this -> gateway -> findAll(); + } +} \ No newline at end of file diff --git a/src/user.txt b/src/user.txt new file mode 100644 index 0000000..44492d5 --- /dev/null +++ b/src/user.txt @@ -0,0 +1,4 @@ +TesteurFichier +motDepasseFichier +../images/imageProfil.png +testeurFichier.compte@wikifantasy.com \ No newline at end of file