Merge pull request #3 from Yasder5/yass

merge de ce que j'ai fait dans main (hehehe no merge conflict)
This commit is contained in:
Yass 2026-01-16 08:58:49 +01:00 committed by GitHub
commit 68ab50dac5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1248 additions and 0 deletions

View file

@ -0,0 +1,63 @@
<?php
require("../app/models/project_model.php");
require("../app/entities/project_entity.php");
/**
* Le controler des Project
* @author Yasser
*/
class ProjectCtrl{
/**
* Fonction d'affichage de la page d'acceuil
*/
public function home(){
$objProjectModel = new ProjectModel;
$arrProject = $objProjectModel->findAll(4);
$arrProjectToDiplay = array();
foreach($arrProject as $arrDetProject){
$objProject = new Project;
$objProject->hydrate($arrDetProject);
$arrProjectToDiplay[] = $objProject;
}
include('../app/views/partials/header.php');
include('../app/views/home.php');
include('../app/views/partials/footer.php');
}
public function search(){
// inclusion du header
include('../app/views/partials/header.php');
//Récupérer les informations du Formulaire
// Récupération des Projects
$objProjectModel = new ProjectModel;
//$arrProject = findAll(0, $strKeywords, $intAuthor, $intPeriod, $strDate, $strStartDate, $strEndDate);
// Depuis PHP 8 - accès direct aux paramètres
$arrProject = $objProjectModel->findAll();
// Initialisation d'un tableau => objets
$arrProjectToDisplay = array();
// Boucle de transformation du tableau de tableau en tableau d'objets
foreach($arrProject as $arrDetProject){
$objProject = new Project;
$objProject->hydrate($arrDetProject);
$arrProjectToDisplay[] = $objProject;
}
// Récupération des utilisateurs
require("../app/models/user_model.php");
$objUserModel = new UserModel;
$arrUser = $objUserModel->findAllUsers();
include('../app/views/search.php');
include('../app/views/partials/footer.php');
}
}

View file

@ -0,0 +1,70 @@
<?php
require("../app/models/user_model.php");
require("../app/entities/user_entity.php");
class UserCtrl{
public function login(){
include("../app/views/partials/header.php");
$strMail = $_POST['mail']??"";
$strPwd = $_POST['pwd']??"";
// Tester le formulaire
$arrError = [];
if (count($_POST) > 0) {
// Vérifier le formulaire
if ($strMail == ""){
$arrError['mail'] = "Le mail est obligatoire";
}
if ($strPwd == ""){
$arrError['pwd'] = "Le mot de passe est obligatoire";
}
// Si le formulaire est rempli correctement
if (count($arrError) == 0){
// Vérifier l'utilisateur en BDD
$objUserModel = new UserModel;
$arrResult = $objUserModel->verifUser($strMail, $strPwd);
//var_dump($arrResult);
if ($arrResult === false){ // Si la base de données ne renvoie rien
$arrError[] = "Mail ou mot de passe invalide";
}else{
// Ajoute l'utilisateur en session
/*$_SESSION['firstname'] = $arrResult['user_firstname'];
$_SESSION['name'] = $arrResult['user_name'];
$_SESSION['id'] = $arrResult['user_id'];*/
// j'enlève le mot de passe avant la session
//unset($arrResult['user_pwd']);
$_SESSION['user'] = $arrResult;
$_SESSION['success'] = "Bienvenue, vous êtes bien connecté";
header("Location:index.php");
exit;
//var_dump($_SESSION);
//var_dump("Connecté");
}
}
}
include("../app/views/login.php");
include("../app/views/partials/footer.php");
}
public function logout(){
session_start();
/*session_destroy();
session_start();*/
// on supprime l'utilisateur en session
unset($_SESSION['user']);
$_SESSION['success'] = "Vous êtes bien déconnecté";
header("Location:index.php");
exit;
}
}

View file

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

View file

@ -0,0 +1,220 @@
<?php
require_once("mother_entity.php");
/**
* Classe d'un objet Projet
* @author Yass
*/
class Project extends Entity{
private int $_id;
private string $_title;
private string $_description;
private string $_thumbnail;
private string $_content;
private string $_creation_date;
private string $_status;
private int $_user;
private int $_category;
private string $_creatorname;
private string $_user_image;
/**
* Constructeur (logique mdrr)
*/
public function __construct(){
$this->_prefix = 'project_';
}
// Méthode Getter et Setter
/**
* Récuperation de l'id du Projet
* @return int l'id du projet
*/
public function getId():int{
return $this->_id;
}
/**
* Mise à jour de l'id du projet
* @param int le nouvelle id
*/
public function setId($id){
$this->_id = $id;
}
/**
* Récuperation du titre
* @return string tite du projet
*/
public function getTitle(){
return $this->_title;
}
/**
* Mise à jour du titre
* @param string le nouveau titre
*/
public function setTitle($title){
$this->_title = $title;
}
/**
* Récuperation de la description
* @return string description du projet
*/
public function getDescription(){
return $this->_description;
}
/**
* Mise à jour de la description
* @param string la nouvelle description
*/
public function setDescription($description){
$this->_description = $description;
}
/**
* Récuperation de l'image
* @return string chemin vers l'image
*/
public function getThumbnail(){
return $this->_thumbnail;
}
/**
* Mise à jour de l'image
* @param string chemin vers nouvelle image
*/
public function setThumbnail($thumbnail){
$this->_thumbnail = $thumbnail;
}
/**
* Récuperation du contenue
* @return string contenue du projet
*/
public function getContent(){
return $this->_content;
}
/**
* Mise à jour du contenue
* @param string le nouveau contenue
*/
public function setContent($content){
$this->_content = $content;
}
/**
* Récupération de la date de création
* @param string lang de formatage de la date (par défaut = "fr_FR")
* @return string date de création formatter
*/
public function getCreation_date(string $strFormat = "fr_FR"){
$objDate = new DateTime($this->_creation_date);
$objDateFormatter = new IntlDateFormatter(
$strFormat,
IntlDateFormatter::LONG,
IntlDateFormatter::NONE,
);
$strFormat = $objDateFormatter->format($objDate);
return $strFormat;
}
/**
* Mise à jour de la date de création
* @param string la nouvelle date de création
*/
public function setCreation_date($creation_date){
$this->_creation_date = $creation_date;
}
/**
* Récupération du statut
* @return string statut
*/
public function getStatus(){
return $this->_status;
}
/**
* Mise à jour du statut
* @param string le nouveau statut
*/
public function setStatus($status){
$this->_status = $status;
}
/**
* Récupération de l'utilisateur
* @return int id de l'utilisateur
*/
public function getUser(){
return $this->_user;
}
/**
* Mise à jour de l'utilisateur
* @param int id de l'utilisateur
*/
public function setUser($user){
$this->_user = $user;
}
/**
* Récupération de la catégorie
* @return int id de la catégorie
*/
public function getCategory(){
return $this->_category;
}
/**
* Mise à jour de la catégorie
* @param int id de la catégorie
*/
public function setCategory($category){
$this->_category = $category;
}
/**
* Récupération du nom du créateur
* @return string nom du créateur
*/
public function getCreatorName(){
return $this->_creatorname;
}
/**
* Mise à jour du nom du créateur
* @param string le nom du créateur
*/
public function setCreatorName($creatorname){
$this->_creatorname = $creatorname;
}
/**
* Récupération du chemin photo profil
* @return string nom du chemin photo profil
*/
public function getUser_image(){
return $this->_user_image;
}
/**
* Mise à jour du chemin photo profil
* @param string chemin photo profil
*/
public function setUser_image($user_image){
$this->_user_image = $user_image;
}
}

View file

@ -0,0 +1,51 @@
<?php
require_once("mother_entity.php");
class User extends Entity{
// Attributs
private string $_name = '';
private string $_firstname = '';
private string $_mail = '';
private string $_pwd;
/**
* Constructeur
*/
public function __construct(){
// Préfixe de la table pour hydratation
$this->_prefixe = 'user_';
}
// Méthodes - getters et setters
public function getName():string{
return $this->_name;
}
public function setName(string $strNewName){
$this->_name = $this->nettoyer($strNewName);
}
public function getFirstname():string{
return $this->_firstname;
}
public function setFirstname(string $strFirstname){
$this->_firstname = $this->nettoyer($strFirstname);
}
public function getMail():string{
return $this->_mail;
}
public function setMail(string $strMail){
$this->_mail = strtolower($this->nettoyer($strMail));
}
public function getPwd():string{
return $this->_pwd;
}
public function getPwdHash():string{
return password_hash($this->_pwd, PASSWORD_DEFAULT);
}
public function setPwd(string $strPwd){
$this->_pwd = $strPwd;
}
}

View file

@ -0,0 +1,23 @@
<?php
require_once('../config/database.php');
class ProjectModel extends Connect{
public function findAll(int $intLimit=0):array{
// Ecrire la requête
$strRq = "SELECT project.*,
CONCAT(user_firstname, ' ', user_name) AS 'project_creatorname',
user_image
FROM project
INNER JOIN users ON user_id = project_user";
if ($intLimit > 0){
$strRq .= " LIMIT ".$intLimit;
}
// Lancer la requête et récupérer les résultats
return $this->_db->query($strRq)->fetchAll();
}
}

81
app/models/user_model.php Normal file
View file

@ -0,0 +1,81 @@
<?php
require_once('../config/database.php');
/**
* Traitement des requêtes pour les utilisateurs
* @author : Christel
* @version : V0.5
*/
class UserModel extends Connect{
// Attributs
// Méthodes
public function __construct(){
parent::__construct();
}
/**
* @return array
*/
public function findAllUsers():array{
// Ecrire la requête
$strRq = "SELECT user_id, user_firstname, user_name, user_image
FROM users ";
// Lancer la requête et récupérer les résultats
return $this->_db->query($strRq)->fetchAll();
}
/**
* @param string $strMail
* @param string $strPwd
* @return array|bool
*/
public function verifUser(string $strMail, string $strPwd):array|bool{
// 2. Construire la requête
$strRq = "SELECT user_id, user_name, user_firstname, user_password, user_image
FROM users
WHERE user_mail = '".$strMail."'";
// Récupère mon utilisateur
// Executer la requête et récupérer les résultats
$arrUser = $this->_db->query($strRq)->fetch();
// Vérification du mot de passe haché
if (password_verify($strPwd, $arrUser['user_password'])){
// Renvoi l'utilisateur
unset($arrUser['user_password']); // on enlève le pwd
return $arrUser;
}else{
return false;
}
}
//public function insert(string $strName, string $strFirstname, string $strMail, string $strPwd):int{
/**
* Fonction d'insertion d'un utilisateur en BDD
* @param object $objUser L'objet utilisateur
* @return bool Est-ce que la requête s'est bien passée (true/false)
*/
public function insert(object $objUser):bool{
// 2. Construire la requête
/*$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_mail, user_pwd)
VALUES (:name, :firstname, :mail, :pwd)";
// 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(":mail", $objUser->getMail(), PDO::PARAM_STR);
$rqPrep->bindValue(":pwd", $objUser->getPwdHash(), PDO::PARAM_STR);
// 3. Executer la requête
//var_dump($strRq);die;
//return $db->exec($strRq);
return $rqPrep->execute();
}
}

17
app/views/home.php Normal file
View file

@ -0,0 +1,17 @@
<section class="container mt-5 p-5 d-flex flex-column align-items-center text-center">
<h1 class="logo">Folliow</h1>
<h2> les talents rencontrent leur avenir</h2>
<p class="col-6">Une plateforme de portfolio adapté à vos besoins et aux besoins des entreprises.
Créer un portfolio réellement pertinent aux exigences du marché et rentrez
directement en contact avec les entreprises.</p>
</section>
<section aria-label="Articles récents">
<h2 class="visually-hidden">Les 4 derniers articles</h2>
<div class="row mb-2">
<?php
foreach($arrProjectToDiplay as $objProject){
include("../app/views/partials/project.php");
}
?>
</section>

23
app/views/login.php Normal file
View file

@ -0,0 +1,23 @@
<section aria-label="Se connecter">
<?php if (count($arrError) > 0) {?>
<div class="alert alert-danger">
<?php foreach ($arrError as $strError){ ?>
<p><?php echo $strError; ?></p>
<?php } ?>
</div>
<?php } ?>
<form method="post">
<p>
<label>Mail:</label>
<input name="mail" value="<?php echo($strMail); ?>"
class="form-control <?php if (isset($arrError['mail'])) { echo 'is-invalid'; } ?> " type="text" >
</p>
<p>
<label>Mot de passe:</label>
<input name="pwd" class="form-control <?php if (isset($arrError['pwd'])) { echo 'is-invalid'; } ?> " type="text" >
</p>
<p>
<input class="form-control btn btn-primary" type="submit" >
</p>
</form>
</section>

View file

@ -0,0 +1,5 @@
<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>
</body>
</html>

View file

@ -0,0 +1,88 @@
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assests/css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
<title>Folliow</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<!-- Logo -->
<a class="navbar-brand d-flex align-items-center" href="#">
<img src="assests/img/logo.png" alt="Logo" class="logo-image">
</a>
<!-- Toggler pour mobile -->
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Menu de navigation -->
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="?ctrl=&action=">Découvrir</a>
</li>
<li class="nav-item">
<a class="nav-link" href="?ctrl=''&action=''">Customisation</a>
</li>
<li class="nav-item">
<a class="nav-link" href="?ctrl=''&action=''">Orientation</a>
</li>
<li class="nav-item">
<a class="nav-link" href="?ctrl=''&action=''">À propos</a>
</li>
<li class="nav-item">
<a class="nav-link" href="?ctrl=project&action=search">Rechercher</a>
</li>
</ul>
<!-- Menu secondaire -->
<nav class="col-4 d-flex justify-content-end align-items-center" aria-label="Connexion utilisateur">
<?php if (!isset($_SESSION['user'])){ ?>
<!--- Utilisateur non connecté -->
<ul class="navbar-nav ">
<li class="nav-item">
<a class="nav-link" href="index.php?ctrl=user&action=signin" title="Créer un compte" aria-label="Créer un compte">
S'inscrire
</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="index.php?ctrl=user&action=login" title="Se connecter" aria-label="Se connecter">
Se connecter
</a>
</li>
</ul>
<?php }else{ ?>
<!--- Utilisateur connecté -->
<ul class="navbar-nav ">
<li class="nav-item ">
<a class="nav-link" href="edit_account.php" title="Modifier mon compte" aria-label="Modifier mon compte">
<img src=".<?php echo $_SESSION["user"]["user_image"]; ?>"
class="rounded-circle flex-shrink-0 mt-2 ml-5"
style="width: 36px; height: 36px; object-fit: cover;"
alt="Photo de profil">
</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="index.php?ctrl=user&action=logout" title="Se déconnecter" aria-label="Se déconnecter">
Logout
</a>
</li>
</ul>
<?php } ?>
</nav>
</div>
</div>
</nav>

View file

@ -0,0 +1,38 @@
<article class="col-md-3 mb-4">
<div class="card h-100 shadow-sm article-card">
<!-- IMAGE (80%) -->
<div class="ratio ratio-16x9">
<img src=".<?php echo $objProject->getThumbnail(); ?>"
class="w-100 h-100 object-fit-cover"
alt=""
loading="lazy">
</div>
<div class="d-flex align-items-start gap-3">
<!-- PHOTO DE PROFIL -->
<img src=".<?php echo $objProject->getUser_image(); ?>"
class="rounded-circle flex-shrink-0 mt-2 ml-5"
style="width: 48px; height: 48px; object-fit: cover;"
alt="Photo de profil">
<!-- INFOS -->
<div class="flex-grow-1 card-body p-3">
<h3 class="h6 mb-1"><?php echo $objProject->getTitle(); ?></h3>
<small class="text-body-secondary d-block mb-1">
<time><?php echo $objProject->getCreation_date(); ?></time>
<?php echo $objProject->getCreatorname(); ?>
</small>
<a href="?id=<?php echo $objProject->getId()?>"
class="stretched-link small">
Lire la suite
</a>
</div>
</div>
</div>
</article>

135
app/views/search.php Normal file
View file

@ -0,0 +1,135 @@
<section aria-label="Blog">
<h2 class="visually-hidden">Rechercher parmi les articles</h2>
<div class="row mb-2">
<section class="mb-5" aria-labelledby="search-heading">
<form name="formSearch" method="post" action="?ctrl=project&action=search" class="border rounded p-4 bg-light">
<h3 id="search-heading" class="h4 mb-4">
<i class="fas fa-search me-2" aria-hidden="true"></i>
Rechercher des articles
</h3>
<div class="row g-3">
<div class="col-md-6">
<label for="keywords" class="form-label">Mots-clés</label>
<input
value=""
type="text"
class="form-control"
id="keywords"
name="keywords"
placeholder="Ex: JavaScript, CSS..."
aria-describedby="keywords-help">
<small id="keywords-help" class="form-text text-muted">
Recherchez dans les titres et contenus
</small>
</div>
<div class="col-md-6">
<label for="author" class="form-label">Auteur</label>
<select class="form-select" id="author" name="author">
<option value="0">Tous les auteurs</option>
</select>
</div>
<div class="col-12">
<fieldset>
<legend class="form-label">Type de recherche par date</legend>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="period"
id="period-exact"
value="0"
aria-controls="date-exact date-range">
<label class="form-check-label" for="period-exact">
Date exacte
</label>
</div>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="period"
id="period-range"
value="1"
aria-controls="date-exact date-range">
<label class="form-check-label" for="period-range">
Période
</label>
</div>
</fieldset>
</div>
<div class="col-md-6" id="date-exact">
<label for="date" class="form-label">Date</label>
<input
type="date"
class="form-control"
id="date"
name="date"
aria-describedby="date-help"
value="" >
<small id="date-help" class="form-text text-muted">
Format: JJ/MM/AAAA
</small>
</div>
<div id="date-range" style="display: none;">
<div class="row g-3">
<div class="col-md-6">
<label for="startdate" class="form-label">Date de début</label>
<input
type="date"
class="form-control"
id="startdate"
name="startdate"
value="" >
</div>
<div class="col-md-6">
<label for="enddate" class="form-label">Date de fin</label>
<input
type="date"
class="form-control"
id="enddate"
name="enddate"
value="" >
</div>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">
<i class="fas fa-search me-2" aria-hidden="true"></i>
Rechercher
</button>
<button type="reset" class="btn btn-secondary ms-2">
<i class="fas fa-redo me-2" aria-hidden="true"></i>
Réinitialiser
</button>
</div>
</div>
</form>
</section>
<!-- Liste des articles -->
<section aria-labelledby="articles-heading">
<h3 id="articles-heading" class="visually-hidden">Liste des projets</h3>
<div class="row mb-2">
<?php
if (count($arrProject) == 0){
?>
<div class="alert alert-warning">
<p>Pas de résultats</p>
</div>
<?php
}
foreach($arrProjectToDisplay as $objProject){
include("../app/views/partials/project.php");
} ?>
</div>
</section>
</div>
</section>