Merge branch 'main' into guillaume

This commit is contained in:
Yass 2026-01-23 18:24:01 +01:00 committed by GitHub
commit 8aed1e526b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 810 additions and 40 deletions

View file

@ -3,6 +3,8 @@
require("../app/entities/project_entity.php");
require("../app/models/category_model.php");
require("../app/entities/category_entity.php");
require("../app/models/image_model.php");
require("../app/entities/image_entity.php");
/**
* Le controler des Project
@ -37,23 +39,24 @@
public function search(){
//variable pour faire fonctionner le script en footer
$strPage = "search";
// inclusion du header
include('../app/views/partials/header.php');
//Récupérer les informations du Formulaire
$strKeywords = $_GET['keywords']??'';
$intAuthor = $_GET['author']??0;
$intPeriod = $_GET['period']??0;
$strDate = $_GET['date']??'';
$strStartDate = $_GET['startdate']??'';
$strEndDate = $_GET['enddate']??'';
$intCategory = $_GET['category']??0;
// Récupération des Projects
$strKeywords = $_POST['keywords']??'';
$intAuthor = $_POST['author']??0;
$intPeriod = $_POST['period']??0;
$strDate = $_POST['date']??'';
$strStartDate = $_POST['startdate']??'';
$strEndDate = $_POST['enddate']??'';
$intCategory = $_POST['category']??0;
// Récupération des projetc
$objProjectModel = new ProjectModel;
// Depuis PHP 8 - accès direct aux paramètres
$arrProject = $objProjectModel->findAll();
$arrProject = $objProjectModel->findAll(intAuthor:$intAuthor, intPeriod:$intPeriod, strDate:$strDate,
strKeywords:$strKeywords, strStartDate:$strStartDate, strEndDate:$strEndDate, intCategory:$intCategory);
// Initialisation d'un tableau => objets
$arrProjectToDisplay = array();
@ -84,9 +87,30 @@
* Fonction d'affichage de la page projet
*/
public function project (){
$objProjectModel = new ProjectModel;
$arrProject = $objProjectModel->findAll(4);
$arrProjectToDiplay = array();
foreach($arrProject as $arrDetProject){
$objProject = new Project;
$objProject->hydrate($arrDetProject);
$arrProjectToDiplay[] = $objProject;
}
$objImageModel = new ImageModel;
$arrImage = $objImageModel->findAllImage(4);
$arrImageToDiplay = array();
foreach($arrImage as $arrDetImage){
$objImage = new Image;
$objImage->hydrate($arrDetImage);
$arrImageToDiplay[] = $objImage;
}
include("../app/views/partials/header.php");
include('../app/views/project.php');
include('../app/views/partials/footer.php');
}
}

View file

@ -48,6 +48,8 @@ class UserCtrl{
public function logout(){
session_start();
/*session_destroy();
session_start();*/
// on supprime l'utilisateur en session
unset($_SESSION['user']);
@ -58,4 +60,88 @@ class UserCtrl{
exit;
}
public function signin(){
// Inclusion du header
include("../app/views/partials/header.php");
// Entité pour réafficher les valeurs dans le formulaire
$objUser = new User();
// Récupération des champs
$strPwdConfirm = $_POST['pwd_confirm'] ?? "";
// Tableau d'erreurs
$arrError = [];
// Traitement du formulaire uniquement si POST
if (!empty($_POST)) {
// Hydratation
$objUser->setName($_POST['user_name'] ?? "");
$objUser->setFirstname($_POST['user_firstname'] ?? "");
$objUser->setMail($_POST['user_mail'] ?? "");
$objUser->setPseudo($_POST['user_pseudo'] ?? "");
$objUser->setPwd($_POST['user_password'] ?? "");
// Champs optionnels : on les stocke aussi même si ils sont vides
$objUser->setPhone($_POST['user_phone'] ?? "");
$objUser->setWork($_POST['user_work'] ?? "");
$objUser->setLocation($_POST['user_location'] ?? "");
$objUser->setDescription($_POST['user_description'] ?? "");
// --- VALIDATIONS (obligatoires) ---
if (trim($objUser->getName()) === "") {
$arrError['user_name'] = "Le nom est obligatoire";
}
if (trim($objUser->getFirstname()) === "") {
$arrError['user_firstname'] = "Le prénom est obligatoire";
}
if (trim($objUser->getMail()) === "") {
$arrError['user_mail'] = "Le mail est obligatoire";
} elseif (!filter_var($objUser->getMail(), FILTER_VALIDATE_EMAIL)) {
$arrError['user_mail'] = "Le format du mail n'est pas correct";
}
if (trim($objUser->getPseudo()) === "") {
$arrError['user_pseudo'] = "Le pseudo est obligatoire";
}
$strRegex = "/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{16,}$/";
if ($objUser->getPwd() == ""){
$arrError['user_password'] = "Le mot de passe est obligatoire";
}else if (!preg_match($strRegex, $objUser->getPwd())){
$arrError['user_password'] = "Le mot de passe ne correspond pas aux règles";
}else if($objUser->getPwd() != $strPwdConfirm){
$arrError['pwd_confirm'] = "Le mot de passe et sa confirmation ne sont pas identiques";
}
// Si pas d'erreurs => insertion
if (count($arrError) === 0) {
$objUserModel = new UserModel();
$boolInsert = $objUserModel->insert($objUser);
if ($boolInsert === true) {
$_SESSION['success'] = "Compte créé avec succès";
header("Location:index.php?ctrl=user&action=login");
exit;
} else {
// Erreur globale (pas liée à un champ)
$arrError['global'] = "Erreur lors de l'ajout";
}
}
}
// Affichage de la vue inscription
include("../app/views/inscription.php");
include("../app/views/partials/footer.php");
}
}

View file

@ -1,5 +1,7 @@
<?php
require_once("mother_entity.php");
/**
* Classe d'un objet Projet
* @author Laura
@ -20,7 +22,7 @@ class Category extends Entity{
// Méthode Getter et Setter
/**
* Récuperation de l'id du Projet
* Récuperation de l'id de la catégorie
* @return int l'id de la catégorie
*/
public function getId():int{

View file

@ -0,0 +1,91 @@
<?php
require_once("mother_entity.php");
/**
* Classe d'un objet Projet
* @author Laura
*/
class Image extends Entity{
private int $_id;
private string $_name = '';
private string $_alt = '';
private string $_status ='';
private int $_project = 0;
//le construc habituel
public function __construct(){
$this->_prefix = 'image_';
}
// Méthode Getter et Setter
/**
* Récuperation de l'id de l'image
* @return int l'id de l'image
*/
public function getId():int{
return $this->_id;
}
/**
* Mise à jour de l'id de l'image
* @param int le nouvelle id
*/
public function setId($id){
$this->_id = $id;
}
/**
* Récuperation du nom de l'image
* @return string nom de l'image
*/
public function getName(){
return $this->_name;
}
/**
* Mise à jour du nom de l'image
* @param string le nouveau nom de l'image
*/
public function setName($name){
$this->_name = $name;
}
/**
* Récuperation de l'alt
* @return string contenu de l'alt
*/
public function getAlt(){
return $this->_alt;
}
/**
* Mise à jour de l'alt
* @param string le nouveau contenu de l'alt
*/
public function setAlt($alt){
$this->_alt = $alt;
}
/**
* Récuperation du statut de la photo
* @return string du statut
*/
public function getStatus(){
return $this->_status;
}
/**
* Mise à jour du statut de la photo
* @param string le nouveau statut de la photo
*/
public function setStatus($status){
$this->_status = $status;
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Classe d'une Mere de tout objet
* @author Yass
* Classe d'un Mere de tout objet
* @author Yass & Laura
*/
class Entity{
@ -13,7 +13,6 @@
public function hydrate(array $arrData){
foreach($arrData as $key=>$value){
$strMethodName = "set".ucfirst(str_replace($this->_prefix,'',$key));
var_dump($strMethodName);
if (method_exists($this,$strMethodName)){
$this->$strMethodName($value);
}

View file

@ -1,6 +1,5 @@
<?php
require_once("mother_entity.php");
/**
* Classe d'un objet Projet
* @author Yass

124
app/entity/user_entity.php Normal file
View file

@ -0,0 +1,124 @@
<?php
require_once("mother_entity.php");
class User extends Entity{
private int $_id;
private string $_name = '';
private string $_firstname = '';
private string $_pseudo = '';
private string $_image = '';
private string $_mail = '';
private string $_pwd;
private string $_phone = '';
private string $_work = '';
private string $_birth = '';
private string $_location = '';
private string $_description = '';
private string $_account_creation = '';
private int $_status;
public function __construct(){
$this->_prefix = 'user_';
}
public function getId():int{
return $this->_id;
}
public function setId(int $id){
$this->_id = $id;
}
public function getName():string{
return $this->_name;
}
public function setName(string $name){
$this->_name = $name;
}
public function getFirstname():string{
return $this->_firstname;
}
public function setFirstname(string $firstname){
$this->_firstname = $firstname;
}
public function getPseudo():string{
return $this->_pseudo;
}
public function setPseudo(string $pseudo){
$this->_pseudo = $pseudo;
}
public function getImage():string{
return $this->_image;
}
public function setImage(string $image){
$this->_image = $image;
}
public function getMail():string{
return $this->_mail;
}
public function setMail(string $mail){
$this->_mail = strtolower($mail);
}
public function getPwd():string{
return $this->_pwd;
}
public function getPwdHash():string{
return password_hash($this->_pwd, PASSWORD_DEFAULT);
}
public function setPwd(string $pwd){
$this->_pwd = $pwd;
}
public function getPhone():string{
return $this->_phone;
}
public function setPhone(string $phone){
$this->_phone = $phone;
}
public function getWork():string{
return $this->_work;
}
public function setWork(string $work){
$this->_work = $work;
}
public function getBirth():string{
return $this->_birth;
}
public function setBirth(string $birth){
$this->_birth = $birth;
}
public function getLocation():string{
return $this->_location;
}
public function setLocation(string $location){
$this->_location = $location;
}
public function getDescription():string{
return $this->_description;
}
public function setDescription(string $description){
$this->_description = $description;
}
public function getAccountCreation():string{
return $this->_account_creation;
}
public function setAccountCreation(string $account_creation){
$this->_account_creation = $account_creation;
}
public function getStatus():int{
return $this->_status;
}
public function setStatus(int $status){
$this->_status = $status;
}
}

View file

@ -1,9 +1,9 @@
<?php
require_once('../config/database.php');
/**
* Classe d'un objet Projet
* @author Laura
/**
* Traitement des requêtes pour les catégories
* @author : Laura
*/
class CategoryModel extends Connect{

View file

@ -0,0 +1,25 @@
<?php
require_once('../config/database.php');
/**
* Traitement de la requête pour les images
* @author Laura
*/
class ImageModel extends Connect{
public function findAllImage(int $intLimit=0):array{
// Ecrire la requête
$strRq = "SELECT image.*
FROM image";
if ($intLimit > 0){
$strRq .= " LIMIT ".$intLimit;
}
// Lancer la requête et récupérer les résultats
return $this->_db->query($strRq)->fetchAll();
}
}

View file

@ -1,9 +1,16 @@
<?php
require_once('../config/database.php');
/**
* Traitement des requêtes pour les projets
* @author : Laura
*/
class ProjectModel extends Connect{
public function findAll(int $intLimit=0):array{
public function findAll(int $intLimit=0, string $strKeywords='', int $intAuthor=0,
int $intPeriod=0, string $strDate='', string $strStartDate='',
string $strEndDate='', int $intCategory=0):array{
// Ecrire la requête
$strRq = "SELECT project.*,
@ -12,6 +19,51 @@
FROM project
INNER JOIN users ON user_id = project_user";
$strWhere = " WHERE ";
// Recherche par mot clé
if ($strKeywords != '') {
$strRq .= " WHERE (project_title LIKE '%".$strKeywords."%'
OR project_content LIKE '%".$strKeywords."%') ";
//$boolWhere = true;
$strWhere = " AND ";
}
// Recherche par auteur
if ($intAuthor > 0){
$strRq .= $strWhere." user_id = ".$intAuthor;
$strWhere = " AND ";
}
// Recherche par catégorie
if ($intCategory > 0){
$strRq .= $strWhere." project_category = ".$intCategory;
$strWhere = " AND ";
}
// Recherche par dates
if ($intPeriod == 0){
// Par date exacte
if ($strDate != ''){
$strRq .= $strWhere." project_creation_date = '".$strDate."'";
}
}else{
// Par période de dates
if ($strStartDate != '' && $strEndDate != ''){
$strRq .= $strWhere." project_creation_date BETWEEN '".$strStartDate."' AND '".$strEndDate."'";
}else{
if ($strStartDate != ''){
// A partir de
$strRq .= $strWhere." project_creation_date >= '".$strStartDate."'";
}else if ($strEndDate != ''){
// Avant le
$strRq .= $strWhere." project_creation_date <= '".$strEndDate."'";
}
}
}
$strRq .= " ORDER BY project_creation_date DESC";
if ($intLimit > 0){
$strRq .= " LIMIT ".$intLimit;

View file

@ -3,7 +3,7 @@
/**
* Traitement des requêtes pour les utilisateurs
* @author : Christel
* @author : meilleurGroup
* @version : V0.5
*/
class UserModel extends Connect{
@ -58,17 +58,31 @@
public function insert(object $objUser):bool{
// 2. Construire la requête
$strRq = "INSERT INTO users (user_name, user_firstname, user_mail, user_pwd)
VALUES (:name, :firstname, :mail, :pwd)";
/*$strRq = "INSERT INTO users (user_name, user_firstname, user_mail, user_pwd)
VALUES ('".$objUser->getName()."',
'".$objUser->getFirstname()."',
'".$objUser->getMail()."',
'".$objUser->getPwdHash()."')";*/
$strRq = "INSERT INTO users (user_name, user_firstname, user_pseudo, user_mail, user_password, user_phone, user_work, user_location, user_description)
VALUES (:name, :firstname, :pseudo,:mail, :pwd, :phone, :work, :location,:description)";
// Préparer la requête
$rqPrep = $this->_db->prepare($strRq);
// Donne les informations
$rqPrep->bindValue(":name", $objUser->getName(), PDO::PARAM_STR);
$rqPrep->bindValue(":firstname", $objUser->getFirstname(), PDO::PARAM_STR);
$rqPrep->bindValue(":pseudo", $objUser->getPseudo(), PDO::PARAM_STR);
$rqPrep->bindValue(":mail", $objUser->getMail(), PDO::PARAM_STR);
$rqPrep->bindValue(":pwd", $objUser->getPwdHash(), PDO::PARAM_STR);
$rqPrep->bindValue(':phone', $objUser->getPhone() ?? "", PDO::PARAM_STR);
$rqPrep->bindValue(':work', $objUser->getWork() ?? "", PDO::PARAM_STR);
$rqPrep->bindValue(':location', $objUser->getLocation() ?? "", PDO::PARAM_STR);
$rqPrep->bindValue(':description', $objUser->getDescription() ?? "", PDO::PARAM_STR);
// 3. Executer la requête
//var_dump($strRq);die;
//return $db->exec($strRq);
return $rqPrep->execute();
}
}

View file

@ -1,4 +1,9 @@
<!-- Contenu principal de la page -->
<main class="container py-5">
<!-- Centrage horizontal du formulaire -->
<div class="row justify-content-center">
<!-- Contenu principal de la page -->
<main class="container py-5">
@ -95,3 +100,92 @@
</div>
</div>
</main>
<h1 class="h3 fw-bold mb-1">Connexion</h1>
<p class="text-secondary mb-4">
Connectez-vous à votre compte.
</p>
<?php
// Affichage des erreurs (validation côté serveur)
if (!empty($arrError)) { ?>
<div class="alert alert-danger" role="alert">
<?php foreach ($arrError as $strError) { ?>
<p class="mb-0"><?php echo htmlspecialchars($strError); ?></p>
<?php } ?>
</div>
<?php } ?>
<!-- Formulaire de connexion -->
<form method="POST" action="index.php?ctrl=user&action=login">
<div class="row g-3">
<!-- Champ : adresse e-mail -->
<div class="col-12">
<label for="mail" class="form-label">
Adresse e-mail
</label>
<input
type="email"
class="form-control <?php if (isset($arrError['mail'])) { echo 'is-invalid'; } ?>"
id="mail"
name="mail"
value="<?php echo htmlspecialchars($strMail ?? ''); ?>"
>
</div>
<!-- Champ : mot de passe -->
<div class="col-12">
<label for="pwd" class="form-label">
Mot de passe
</label>
<input
type="password"
class="form-control <?php if (isset($arrError['pwd'])) { echo 'is-invalid'; } ?>"
id="pwd"
name="pwd"
>
</div>
<!-- Option "Se souvenir de moi" -->
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="remember_me" name="remember_me">
<label class="form-check-label" for="remember_me">
Se souvenir de moi
</label>
</div>
</div>
<!-- Bouton -->
<div class="col-12 d-grid mt-2">
<button type="submit" class="btn btn-primary btn-lg rounded-3">
Se connecter
</button>
</div>
<!-- Liens -->
<div class="col-12 text-center">
<small class="text-secondary">
Pas encore de compte ?
<a href="index.php?ctrl=user&action=signin" class="link-primary">Créer un compte</a>
</small>
</div>
<div class="col-12 text-center">
<small>
<a href="#" class="link-primary">
Mot de passe oublié ?
</a>
</small>
</div>
</div>
</form>
</div>
</div>
</div>
</main>

View file

@ -1,4 +1,9 @@
<!-- Page : Inscription -->
<main class="container py-5">
<!-- Centrage du formulaire -->
<div class="row justify-content-center">
<!-- Contenu principal de la page -->
<main class="container py-5">
@ -66,6 +71,193 @@
required
>
</div>
<!-- Carte Bootstrap contenant le formulaire -->
<div class="card shadow-sm border-0 rounded-4 p-4 p-lg-5">
<!-- Titre et description -->
<h1 class="h3 fw-bold mb-1">Inscription</h1>
<p class="text-secondary mb-4">
Créez votre compte utilisateur.
</p>
<?php
// Affichage des messages d'erreur du formulaire, l'affichage en Bootstrap (validation côté serveur)
if (!empty($arrError)) { ?>
<div class="alert alert-danger" role="alert">
<?php foreach ($arrError as $strError) { ?>
<p class="mb-0">
<?php echo htmlspecialchars($strError); ?>
</p>
<?php } ?>
</div>
<?php } ?>
<!-- Formulaire d'inscription -->
<!-- Les données sont envoyées en POST vers la méthode signin du user_controller.php -->
<form method="POST" action="index.php?ctrl=user&action=signin">
<div class="row g-3">
<!-- Champ : Nom -->
<div class="col-md-6">
<label class="form-label" for="user_name">
Nom *
</label>
<input
class="form-control <?php if (isset($arrError['user_name'])) echo 'is-invalid'; ?>"
type="text"
id="user_name"
name="user_name"
value="<?php echo htmlspecialchars($objUser->getName()); ?>"
required
>
</div>
<!-- Champ : Prénom -->
<div class="col-md-6">
<label class="form-label" for="user_firstname">
Prénom *
</label>
<input
class="form-control <?php if (isset($arrError['user_firstname'])) echo 'is-invalid'; ?>"
type="text"
id="user_firstname"
name="user_firstname"
value="<?php echo htmlspecialchars($objUser->getFirstname()); ?>"
required
>
</div>
<!-- Champ : Pseudo -->
<div class="col-12">
<label class="form-label" for="user_pseudo">
Pseudo *
</label>
<div class="input-group">
<span class="input-group-text">@</span>
<input
class="form-control <?php if (isset($arrError['user_pseudo'])) echo 'is-invalid'; ?>"
type="text"
id="user_pseudo"
name="user_pseudo"
value="<?php echo htmlspecialchars($objUser->getPseudo()); ?>"
required
>
</div>
</div>
<!-- Champ : Adresse e-mail -->
<div class="col-12">
<label class="form-label" for="user_mail">
Adresse e-mail *
</label>
<input
class="form-control <?php if (isset($arrError['user_mail'])) echo 'is-invalid'; ?>"
type="email"
id="user_mail"
name="user_mail"
value="<?php echo htmlspecialchars($objUser->getMail()); ?>"
required
>
</div>
<!-- Champ : Mot de passe -->
<div class="col-12">
<label class="form-label" for="user_password">
Mot de passe *
</label>
<input
class="form-control <?php if (isset($arrError['user_password'])) echo 'is-invalid'; ?>"
type="password"
id="user_password"
name="user_password"
required
>
</div>
<!-- Champ : Confirmation du mot de passe -->
<div class="col-12">
<label class="form-label" for="pwd_confirm">
Confirmation du mot de passe *
</label>
<input
class="form-control <?php if (isset($arrError['pwd_confirm'])) echo 'is-invalid'; ?>"
type="password"
id="pwd_confirm"
name="pwd_confirm"
required
>
</div>
<!-- Champ optionnel : numéro de téléphone -->
<div class="col-12">
<label class="form-label" for="user_phone">
Téléphone
</label>
<input
class="form-control"
type="text"
id="user_phone"
name="user_phone"
>
</div>
<!-- Champ optionnel : profession de l'utilisateur -->
<div class="col-12">
<label class="form-label" for="user_work">
Profession
</label>
<input
class="form-control"
type="text"
id="user_work"
name="user_work"
>
</div>
<!-- Champ optionnel : localisation de l'utilisateur -->
<div class="col-12">
<label class="form-label" for="user_location">
Localisation
</label>
<input
class="form-control"
type="text"
id="user_location"
name="user_location"
>
</div>
<!-- Champ optionnel : phrase d'accroche / description courte -->
<div class="col-12">
<label class="form-label" for="user_description">
Phrase d'accroche
</label>
<textarea
class="form-control"
id="user_description"
name="user_description"
rows="3"
></textarea>
</div>
<!-- Lien vers la page de connexion -->
<div class="col-12 text-center">
<small class="text-secondary">
Déjà un compte ?
<a href="index.php?ctrl=user&action=login">Se connecter</a>
</small>
</div>
<!-- Bouton de soumission -->
<div class="col-12 d-grid mt-2">
<button type="submit" class="btn btn-primary btn-lg rounded-3">
Créer mon compte
</button>
</div>
</div>
</form>
</div>
<!-- Champ : adresse e-mail -->
@ -186,3 +378,5 @@
</div>
</div>
</main>

View file

@ -1,5 +1,32 @@
<h2>coucou c'est le footer</h2>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
<footer class="footer container-fluid d-flex justify-content-around">
<div class="col-3">
<ul>
<li><a href="#">Découvrir</a>
<li><a href="#">Customisation</a>
<li><a href="#">Emploi</a>
<li><a href="#">A propos</a>
</ul>
</div>
<div class="col-3">
<ul>
<li><a href="#">Recruter</a>
<li><a href="#">Partenariat</a>
<li><a href="#">Blog</a>
<li><a href="#">Aide et support</a>
</ul>
</div>
<div class="col-3">
<ul>
<li><a href="#">Politique de confidentialité</a>
<li><a href="#">Politique sur les données</a>
<li><a href="#">CGU</a>
<li><a href="#">CGV</a>
</ul>
</div>
<div class="col-3">
<p>Suivez-nous</p>
</div>
</footer>
</body>
</html>

View file

@ -168,3 +168,28 @@
</section>
</div>
</section>
<script>
// Gestion de l'affichage des champs de date
const periodRadios = document.querySelectorAll('input[name="period"]');
const dateExact = document.getElementById('date-exact');
const dateRange = document.getElementById('date-range');
function toggleDateFields() {
const selectedPeriod = document.querySelector('input[name="period"]:checked').value;
if (selectedPeriod === '0') {
dateExact.style.display = 'block';
dateRange.style.display = 'none';
} else {
dateExact.style.display = 'none';
dateRange.style.display = 'block';
}
}
periodRadios.forEach(radio => {
radio.addEventListener('change', toggleDateFields);
});
// Initialisation au chargement
toggleDateFields();
</script>

View file

@ -96,3 +96,17 @@ body {
height: 20%;
padding: 0.75rem;
}
.footer{
color: white;
background-color: #0000ff;
}
.footer ul{
list-style: none;
}
.footer a{
text-decoration: none;
color: white;
}