Merge branch 'main' into yass
9
.github/workflows/deploy.yml
vendored
|
|
@ -15,22 +15,23 @@ jobs:
|
|||
with:
|
||||
host: boulayoune.com
|
||||
username: yass
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
key: |
|
||||
${{ secrets.SSH_KEY }}
|
||||
port: 22
|
||||
debug: true
|
||||
script: |
|
||||
set -e
|
||||
echo "➡️ Connexion réussie !"
|
||||
cd /var/www/projet_php
|
||||
|
||||
echo "➡️ Mise à jour du code..."
|
||||
# On enlève le SUDO ici pour que Git utilise la clé de l'utilisateur yass
|
||||
git fetch origin main
|
||||
git reset --hard origin/main
|
||||
|
||||
echo "➡️ Correction des permissions et nettoyage..."
|
||||
# On garde le SUDO ici car ces commandes touchent au système
|
||||
sudo chown -R yass:www-data /var/www/projet_php
|
||||
sudo chmod -R 775 /var/www/projet_php/templates_c
|
||||
sudo rm -rf /var/www/projet_php/templates_c/*
|
||||
sudo chmod -R 775 /var/www/projet_php/uploads/projects
|
||||
sudo chmod -R 775 /var/www/projet_php/uploads/profiles
|
||||
|
||||
echo "✅ Déploiement terminé ! (Shin-en no Egotisu)"
|
||||
|
|
@ -116,20 +116,21 @@
|
|||
* Fonction d'affichage de la page projet
|
||||
* @author Christel adapter par Guillaume
|
||||
*/
|
||||
public function addedit_project() {
|
||||
public function addedit_project(){
|
||||
if (!isset($_SESSION['user'])){ // Pas d'utilisateur connecté
|
||||
header("Location:index.php?ctrl=error&action=error_403");
|
||||
exit;
|
||||
}
|
||||
|
||||
$objProject = new Project;
|
||||
$objProjectModel = new ProjectModel;
|
||||
$objCategoryModel = new CategoryModel;
|
||||
$objProject = new Project;
|
||||
$objProjectModel = new ProjectModel;
|
||||
$objCategoryModel = new CategoryModel;
|
||||
|
||||
// dans la cas de modif
|
||||
// Dans la cas de modif
|
||||
if (isset($_GET['id'])){
|
||||
$arrProject = $objProjectModel->findOne($_GET['id']);
|
||||
$arrProject = $objProjectModel->findOne($_GET['id']);
|
||||
$objProject->hydrate($arrProject); // BDD
|
||||
$this->_arrData['arrImages'] = $objProjectModel->getImagesByProjectId($objProject->getId());
|
||||
}
|
||||
|
||||
// Tester le formulaire
|
||||
|
|
@ -149,24 +150,21 @@
|
|||
$arrError['content'] = "Le contenu est obligatoire";
|
||||
}
|
||||
|
||||
// Vérification de l'image
|
||||
$arrTypeAllowed = array('image/jpeg', 'image/png', 'image/webp');
|
||||
// Vérification de l'image (Thumbnail)
|
||||
$arrTypeAllowed = array('image/jpeg', 'image/png', 'image/webp');
|
||||
if ($_FILES['thumbnail']['error'] != 4){
|
||||
if (!in_array($_FILES['thumbnail']['type'], $arrTypeAllowed)){
|
||||
$arrError['thumbnail'] = "Le type de fichier n'est pas autorisé";
|
||||
}else{
|
||||
// Vérification des codes d'erreur
|
||||
switch ($_FILES['thumbnail']['error']){
|
||||
case 0 :
|
||||
// Renommage de l'image
|
||||
$strImageName = uniqid().".webp";
|
||||
|
||||
// Récupère le nom de l'image avant changement
|
||||
$strOldImg = $objProject->getThumbnail();
|
||||
// Mise à jour du nom de l'image dans l'objet
|
||||
$strImageName = uniqid().".webp";
|
||||
$strOldImg = $objProject->getThumbnail();
|
||||
$objProject->setThumbnail($strImageName);
|
||||
break;
|
||||
case 1 :
|
||||
$arrError['thumbnail'] = "Le fichier est trop volumineux";
|
||||
break;
|
||||
case 2 :
|
||||
$arrError['thumbnail'] = "Le fichier est trop volumineux";
|
||||
break;
|
||||
|
|
@ -181,99 +179,194 @@
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
// Est-ce que le fichier existe ?
|
||||
if (is_null($objProject->getThumbnail())){
|
||||
$arrError['thumbnail'] = "L'image est obligatoire";
|
||||
}
|
||||
}
|
||||
|
||||
// SI pas d'erreur : on traite l'image depuis la bdd
|
||||
if (count($arrError) == 0){
|
||||
// SI pas d'erreur : on traite l'image principale
|
||||
if (count($arrError) == 0){
|
||||
|
||||
$boolImageOk = true;
|
||||
$boolImageOk = true;
|
||||
|
||||
// Redimensionnement de l'image
|
||||
if (isset($strImageName)){
|
||||
$strDest = $_ENV['IMG_PATH'].$strImageName;
|
||||
$strSource = $_FILES['thumbnail']['tmp_name'];
|
||||
list($intWidth, $intHeight) = getimagesize($strSource);
|
||||
// On peux changer ces dimensions si on veux que la miniature soit plus grande/petite
|
||||
if (isset($strImageName)){
|
||||
$strDest = $_ENV['IMG_PROJECT_PATH'].$strImageName;
|
||||
$strSource = $_FILES['thumbnail']['tmp_name'];
|
||||
list($intWidth, $intHeight) = getimagesize($strSource);
|
||||
|
||||
$intDestWidth = 200; $intDestHeight = 250;
|
||||
$fltDestRatio = $intDestWidth / $intDestHeight;
|
||||
$fltSourceRatio = $intWidth / $intHeight;
|
||||
// Redimensionnement de la Thumbnail
|
||||
$intDestWidth = 200; $intDestHeight = 250;
|
||||
$fltDestRatio = $intDestWidth / $intDestHeight;
|
||||
$fltSourceRatio = $intWidth / $intHeight;
|
||||
|
||||
if ($fltSourceRatio > $fltDestRatio) {
|
||||
$intCropHeight = $intHeight;
|
||||
$intCropWidth = (int)round($intHeight * $fltDestRatio);
|
||||
$intCropX = (int)(($intWidth - $intCropWidth) / 2);
|
||||
$intCropY = 0;
|
||||
} else {
|
||||
$intCropWidth = $intWidth;
|
||||
$intCropHeight = (int)round($intWidth / $fltDestRatio);
|
||||
$intCropX = 0;
|
||||
$intCropY = (int)(($intHeight - $intCropHeight) / 2);
|
||||
}
|
||||
if ($fltSourceRatio > $fltDestRatio) {
|
||||
$intCropHeight = $intHeight;
|
||||
$intCropWidth = (int)round($intHeight * $fltDestRatio);
|
||||
$intCropX = (int)(($intWidth - $intCropWidth) / 2);
|
||||
$intCropY = 0;
|
||||
} else {
|
||||
$intCropWidth = $intWidth;
|
||||
$intCropHeight = (int)round($intWidth / $fltDestRatio);
|
||||
$intCropX = 0;
|
||||
$intCropY = (int)(($intHeight - $intCropHeight) / 2);
|
||||
}
|
||||
|
||||
// Condition en fonction de l'extension de l'image
|
||||
$objDest = imagecreatetruecolor($intDestWidth, $intDestHeight);
|
||||
switch ($_FILES['thumbnail']['type']) {
|
||||
case 'image/jpeg' :
|
||||
$objDest = imagecreatetruecolor($intDestWidth, $intDestHeight);
|
||||
switch ($_FILES['thumbnail']['type']) {
|
||||
case 'image/jpeg' :
|
||||
$objSource = imagecreatefromjpeg($strSource);
|
||||
break;
|
||||
case 'image/png' :
|
||||
break;
|
||||
case 'image/png' :
|
||||
$objSource = imagecreatefrompng($strSource);
|
||||
break;
|
||||
case 'image/webp' :
|
||||
break;
|
||||
case 'image/webp' :
|
||||
$objSource = imagecreatefromwebp($strSource);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
imagecopyresampled($objDest, $objSource, 0, 0, $intCropX, $intCropY, $intDestWidth, $intDestHeight, $intCropWidth, $intCropHeight);
|
||||
imagecopyresampled($objDest, $objSource, 0, 0, $intCropX, $intCropY, $intDestWidth, $intDestHeight, $intCropWidth, $intCropHeight);
|
||||
$boolImageOk = imagewebp($objDest, $strDest);
|
||||
|
||||
// Sauvegarde du fichier
|
||||
$boolImageOk = imagewebp($objDest, $strDest);
|
||||
imagedestroy($objDest);
|
||||
imagedestroy($objSource);
|
||||
}
|
||||
//Suppression des doublons pour la mémoire vive
|
||||
imagedestroy($objDest);
|
||||
imagedestroy($objSource);
|
||||
}
|
||||
|
||||
// SI image ok, on balance tout dans la bdd
|
||||
if ($boolImageOk){
|
||||
if (!isset($_GET['id'])){
|
||||
$objProject->setUser_id($_SESSION['user']['user_id']);
|
||||
$boolOk = $objProjectModel->insert($objProject);
|
||||
} else {
|
||||
$boolOk = $objProjectModel->updateProject($objProject);
|
||||
}
|
||||
// SI image ok, on balance tout dans la bdd
|
||||
if ($boolImageOk){
|
||||
if (!isset($_GET['id'])){
|
||||
$objProject->setUser_id($_SESSION['user']['user_id']);
|
||||
$boolOk = $objProjectModel->insert($objProject);
|
||||
} else {
|
||||
$boolOk = $objProjectModel->updateProject($objProject);
|
||||
}
|
||||
|
||||
if ($boolOk){
|
||||
// Suppression de l'ancienne image
|
||||
if(isset($strOldImg) && !empty($strOldImg) && isset($strImageName)){
|
||||
$strOldFile = $_ENV['IMG_PATH'].$strOldImg;
|
||||
if (file_exists($strOldFile)) unlink($strOldFile);
|
||||
}
|
||||
// Gestion des 20 Images après l'envoie de la Thumbnail en BDD
|
||||
if ($boolOk){
|
||||
//Si pas d'erreur
|
||||
if (isset($_FILES['imageProject']) && $_FILES['imageProject']['error'][0] != 4) {
|
||||
$files = $_FILES['imageProject'];
|
||||
$maxPhotos = 20;
|
||||
|
||||
$_SESSION['success'] = (!isset($_GET['id'])) ? "Le projet a bien été créé" : "Le projet a bien été modifié";
|
||||
header("Location:index.php");
|
||||
exit;
|
||||
} else {
|
||||
$arrError[] = "Erreur lors de l'enregistrement en base de données";
|
||||
}
|
||||
} else {
|
||||
$arrError['thumbnail'] = "Erreur dans le traitement de l'image";
|
||||
}
|
||||
}
|
||||
// 1. On compte combien d'images le projet possède déjà en BDD
|
||||
$currentImages = $objProjectModel->getImagesByProjectId($objProject->getId());
|
||||
$totalExisting = count($currentImages);
|
||||
|
||||
// 2. On calcule combien de photos on peut encore ajouter
|
||||
$remainingSlots = $maxPhotos - $totalExisting;
|
||||
|
||||
// Si on a déjà atteint ou dépassé la limite, on ne traite même pas les fichiers
|
||||
if ($remainingSlots <= 0) {
|
||||
$_SESSION['error'] = "Limite de $maxPhotos photos atteinte. Supprimez-en pour en ajouter de nouvelles.";
|
||||
} else {
|
||||
$uploadedCount = 0;
|
||||
|
||||
foreach ($files['name'] as $key => $name) {
|
||||
// 3. On utilise le quota restant comme condition d'arrêt
|
||||
if ($uploadedCount >= $remainingSlots) break;
|
||||
|
||||
if ($files['error'][$key] === 0 && in_array($files['type'][$key], $arrTypeAllowed)) {
|
||||
|
||||
$galleryName = uniqid() . "_gallery.webp";
|
||||
$strDestGallery = $_ENV['IMG_PROJECT_PATH'].$galleryName;
|
||||
$strSourceGallery = $files['tmp_name'][$key];
|
||||
|
||||
// Reprise de la logique de redimensionnement
|
||||
list($intW, $intH) = getimagesize($strSourceGallery);
|
||||
|
||||
// On peux changer ces dimensions si on veux que la galerie soit plus grande/petite
|
||||
$intDestW = 150; $intDestH = 150;
|
||||
$fltDestR = $intDestW / $intDestH;
|
||||
$fltSourceR = $intW / $intH;
|
||||
|
||||
if ($fltSourceR > $fltDestR) {
|
||||
$intCropH = $intH;
|
||||
$intCropW = (int)round($intH * $fltDestR);
|
||||
$intCropX = (int)(($intW - $intCropW) / 2);
|
||||
$intCropY = 0;
|
||||
} else {
|
||||
$intCropW = $intW;
|
||||
$intCropH = (int)round($intW / $fltDestR);
|
||||
$intCropX = 0;
|
||||
$intCropY = (int)(($intH - $intCropH) / 2);
|
||||
}
|
||||
|
||||
$objDestGallery = imagecreatetruecolor($intDestW, $intDestH);
|
||||
|
||||
// Création de la source selon le type de chaque image de la boucle
|
||||
switch ($files['type'][$key]) {
|
||||
case 'image/jpeg' :
|
||||
$objSourceGallery = imagecreatefromjpeg($strSourceGallery);
|
||||
break;
|
||||
case 'image/png' :
|
||||
$objSourceGallery = imagecreatefrompng($strSourceGallery);
|
||||
break;
|
||||
case 'image/webp' :
|
||||
$objSourceGallery = imagecreatefromwebp($strSourceGallery);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($objSourceGallery) {
|
||||
imagecopyresampled($objDestGallery, $objSourceGallery, 0, 0, $intCropX, $intCropY, $intDestW, $intDestH, $intCropW, $intCropH);
|
||||
|
||||
if (imagewebp($objDestGallery, $strDestGallery)) {
|
||||
// Insertion en BDD
|
||||
$objProjectModel->addImageInProject($galleryName, $objProject->getId());
|
||||
$uploadedCount++;
|
||||
}
|
||||
|
||||
imagedestroy($objDestGallery);
|
||||
imagedestroy($objSourceGallery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($uploadedCount > 0) {
|
||||
$_SESSION['success'] = "$uploadedCount image(s) ajoutée(s) à la galerie !";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suppression de l'ancienne miniature
|
||||
if(isset($strOldImg) && !empty($strOldImg) && isset($strImageName)){
|
||||
$strOldFile = $_ENV['IMG_PROJECT_PATH'].$strOldImg;
|
||||
if (file_exists($strOldFile)) unlink($strOldFile);
|
||||
}
|
||||
|
||||
$_SESSION['success'] = (!isset($_GET['id'])) ? "Le projet a bien été créé" : "Le projet a bien été modifié";
|
||||
header("Location:index.php");
|
||||
exit;
|
||||
} else {
|
||||
$arrError[] = "Erreur lors de l'enregistrement en base de données";
|
||||
}
|
||||
} else {
|
||||
$arrError['thumbnail'] = "Erreur dans le traitement de l'image";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Données pour la vue
|
||||
$this->_arrData['arrCategory'] = $objCategoryModel->findAllCategory();
|
||||
$this->_arrData['objProject'] = $objProject;
|
||||
$this->_arrData['arrError'] = $arrError;
|
||||
$this->_arrData['objProject'] = $objProject;
|
||||
$this->_arrData['arrError'] = $arrError;
|
||||
|
||||
// Si on est en modifications de projet, on récupère les images pour les afficher dans le formulaire
|
||||
if ($objProject->getId()) {
|
||||
// On récupère les images via le modèle et on les stocke dans le tableau de données
|
||||
$this->_arrData['arrImages'] = $objProjectModel->getImagesByProjectId($objProject->getId());
|
||||
} else {
|
||||
// Sinon on initialise un tableau vide pour éviter que Smarty ne râle
|
||||
$this->_arrData['arrImages'] = [];
|
||||
}
|
||||
|
||||
$this->_display('addedit_project');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction d'affichage de projet
|
||||
*/
|
||||
public function display() {
|
||||
$intId = $_GET['id'] ?? null;
|
||||
|
||||
|
|
@ -281,13 +374,18 @@
|
|||
$objProjectModel = new ProjectModel();
|
||||
$arrProject = $objProjectModel->findOne((int)$intId);
|
||||
|
||||
// CORRECTION ICI : on utilise $intId (pas $id)
|
||||
$arrImages = $objProjectModel->getImagesByProjectId((int)$intId);
|
||||
|
||||
if ($arrProject) {
|
||||
$objProject = new Project();
|
||||
$objProject->hydrate($arrProject);
|
||||
|
||||
$this->_arrData["objProject"] = $objProject;
|
||||
$this->_arrData["arrProject"] = $arrProject;
|
||||
$this->_arrData["objProject"] = $objProject;
|
||||
$this->_arrData["arrImages"] = $arrImages;
|
||||
|
||||
$this->_display("project_display");
|
||||
|
||||
} else {
|
||||
header("Location: index.php?ctrl=project&action=home");
|
||||
exit;
|
||||
|
|
@ -298,6 +396,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de partage de projet
|
||||
*/
|
||||
public function shareProject(){
|
||||
if (count($_POST) > 0)
|
||||
{
|
||||
|
|
@ -364,6 +465,10 @@
|
|||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de modération de projet = accepté
|
||||
* @author Guillaume
|
||||
*/
|
||||
public function accept(){
|
||||
|
||||
//Récupéré l'id dans l'url
|
||||
|
|
@ -378,6 +483,10 @@
|
|||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de modération de projet = refusé
|
||||
* @author Guillaume
|
||||
*/
|
||||
public function refuse(){
|
||||
|
||||
//Récupéré l'id dans l'url
|
||||
|
|
@ -392,6 +501,10 @@
|
|||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de suppression de projet
|
||||
* @author Guillaume
|
||||
*/
|
||||
public function delete(){
|
||||
|
||||
//Récupéré l'id dans l'url
|
||||
|
|
@ -406,6 +519,99 @@
|
|||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de changement de statut (Approuvé, Refusé, En attente)
|
||||
* @author Guillaume
|
||||
*/
|
||||
public function change_image_status() {
|
||||
if (isset($_GET['id_img']) && isset($_GET['status'])) {
|
||||
$idImg = (int)$_GET['id_img'];
|
||||
$status = $_GET['status']; // "en_attente" passage à "approuvé"
|
||||
|
||||
$objProjectModel = new ProjectModel();
|
||||
|
||||
// On passe le statut texte directement à ta méthode de modèle
|
||||
if ($objProjectModel->updateImageStatus($idImg, $status)) {
|
||||
$_SESSION['success'] = "Le statut de l'image est désormais : " . ucfirst($status);
|
||||
}
|
||||
}
|
||||
|
||||
// La redirection : Si on sait d'où on vient, on y retourne, sinon index
|
||||
$urlRedirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "index.php";
|
||||
header("Location: " . $urlRedirect);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fonction de validation de l'image de projet
|
||||
* @author Guillaume
|
||||
*/
|
||||
public function delete_image() {
|
||||
// Vérifier l'id de l'image
|
||||
$idImg = $_GET['id_img'];
|
||||
$objProjectModel = new ProjectModel();
|
||||
|
||||
// Récupérer le nom du fichier pour le supprimer physiquement
|
||||
$image = $objProjectModel->findImage($idImg);
|
||||
if ($image) {
|
||||
$filePath = $_ENV['IMG_PROJECT_PATH'] . $image['image_name'];
|
||||
if (file_exists($filePath)) unlink($filePath);
|
||||
|
||||
$objProjectModel->deleteImage($idImg);
|
||||
$_SESSION['success'] = "Image supprimée !";
|
||||
}
|
||||
|
||||
// La redirection : Si on sait d'où on vient, on y retourne, sinon index
|
||||
$url = (isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : "index.php";
|
||||
header("Location: " . $url);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fonction d'ajout des 20 images max du projet
|
||||
* @author Guillaume
|
||||
* @param string $fileName = le nom de l'image, int $projectId = L'Id du projet que l'on veut afficher, string $alt = qui affichera pars défaut "Image de projet"
|
||||
* @return bool Est-ce que la requête s'est bien passée
|
||||
*/
|
||||
public function addImageInProject(string $fileName, int $projectId, string $alt = "Image de projet"): bool {
|
||||
$strRq = "INSERT INTO image (
|
||||
image_name,
|
||||
image_alt,
|
||||
image_status,
|
||||
image_project
|
||||
)
|
||||
VALUES (:name, :alt, :status, :project)";
|
||||
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
|
||||
$rqPrep->bindValue(":name", $fileName, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":alt", $alt, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":status", "en_attente", PDO::PARAM_STR); // Valeur string en brute
|
||||
$rqPrep->bindValue(":project", $projectId, PDO::PARAM_INT);
|
||||
|
||||
return $rqPrep->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction d'affichage des 20 images max du projet
|
||||
* @author Guillaume
|
||||
* @param array $ProjectId L'Id du projet que l'on veut afficher
|
||||
* @return bool Est-ce que la requête s'est bien passée
|
||||
*/
|
||||
public function getImagesByProjectId(int $projectId): array {
|
||||
$strRq = "SELECT image_id, image_name, image_alt, image_status
|
||||
FROM image
|
||||
WHERE image_project = :id";
|
||||
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
$rqPrep->bindValue(":id", $projectId, PDO::PARAM_INT);
|
||||
$rqPrep->execute();
|
||||
|
||||
return $rqPrep->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page mentions légales
|
||||
*/
|
||||
|
|
@ -414,7 +620,6 @@
|
|||
$this->_display("mentions");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Page à propos
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/* Smarty version 5.7.0, created on 2026-02-06 08:21:14
|
||||
from 'file:views/home.tpl' */
|
||||
|
||||
/* @var \Smarty\Template $_smarty_tpl */
|
||||
if ($_smarty_tpl->getCompiled()->isFresh($_smarty_tpl, array (
|
||||
'version' => '5.7.0',
|
||||
'unifunc' => 'content_6985a47abcda40_19846426',
|
||||
'has_nocache_code' => false,
|
||||
'file_dependency' =>
|
||||
array (
|
||||
'299f75d7692a19207f23bf5795a2721f507c3fc6' =>
|
||||
array (
|
||||
0 => 'views/home.tpl',
|
||||
1 => 1770365364,
|
||||
2 => 'file',
|
||||
),
|
||||
),
|
||||
'includes' =>
|
||||
array (
|
||||
'file:views/_partial/preview.tpl' => 1,
|
||||
),
|
||||
))) {
|
||||
function content_6985a47abcda40_19846426 (\Smarty\Template $_smarty_tpl) {
|
||||
$_smarty_current_dir = 'C:\\wamp64\\www\\projetphp\\views';
|
||||
$_smarty_tpl->getInheritance()->init($_smarty_tpl, false);
|
||||
?>
|
||||
|
||||
<?php
|
||||
$_smarty_tpl->getInheritance()->instanceBlock($_smarty_tpl, 'Block_3150142016985a47abb6c29_00747518', "content");
|
||||
?>
|
||||
|
||||
<?php }
|
||||
/* {block "content"} */
|
||||
class Block_3150142016985a47abb6c29_00747518 extends \Smarty\Runtime\Block
|
||||
{
|
||||
public function callBlock(\Smarty\Template $_smarty_tpl) {
|
||||
$_smarty_current_dir = 'C:\\wamp64\\www\\projetphp\\views';
|
||||
?>
|
||||
|
||||
<section class="container mt-5 p-5 d-flex flex-column align-items-center text-center">
|
||||
<h1 class="logo">Folliow</h1>
|
||||
<h2>Là où 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 class="container" aria-label="Articles récents">
|
||||
<h2 class="visually-hidden">Les 4 derniers articles</h2>
|
||||
<div class="row mb-2">
|
||||
|
||||
<?php
|
||||
$_from = $_smarty_tpl->getSmarty()->getRuntime('Foreach')->init($_smarty_tpl, $_smarty_tpl->getValue('arrProjectToDisplay'), 'objProject');
|
||||
$foreach0DoElse = true;
|
||||
foreach ($_from ?? [] as $_smarty_tpl->getVariable('objProject')->value) {
|
||||
$foreach0DoElse = false;
|
||||
?>
|
||||
<?php $_smarty_tpl->renderSubTemplate("file:views/_partial/preview.tpl", $_smarty_tpl->cache_id, $_smarty_tpl->compile_id, 0, $_smarty_tpl->cache_lifetime, array(), (int) 0, $_smarty_current_dir);
|
||||
?>
|
||||
<?php
|
||||
}
|
||||
$_smarty_tpl->getSmarty()->getRuntime('Foreach')->restore($_smarty_tpl, 1);?>
|
||||
</section>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
/* {/block "content"} */
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/* Smarty version 5.7.0, created on 2026-02-06 08:21:14
|
||||
from 'file:views/_partial/preview.tpl' */
|
||||
|
||||
/* @var \Smarty\Template $_smarty_tpl */
|
||||
if ($_smarty_tpl->getCompiled()->isFresh($_smarty_tpl, array (
|
||||
'version' => '5.7.0',
|
||||
'unifunc' => 'content_6985a47ad585d5_25749521',
|
||||
'has_nocache_code' => false,
|
||||
'file_dependency' =>
|
||||
array (
|
||||
'c724044e55872f26030b02de6dcd14dc34a20b16' =>
|
||||
array (
|
||||
0 => 'views/_partial/preview.tpl',
|
||||
1 => 1770365554,
|
||||
2 => 'file',
|
||||
),
|
||||
),
|
||||
'includes' =>
|
||||
array (
|
||||
),
|
||||
))) {
|
||||
function content_6985a47ad585d5_25749521 (\Smarty\Template $_smarty_tpl) {
|
||||
$_smarty_current_dir = 'C:\\wamp64\\www\\projetphp\\views\\_partial';
|
||||
?><article class="col-md-3 mb-4">
|
||||
<div class="card h-100 shadow-sm article-card">
|
||||
|
||||
<div class="ratio ratio-16x9">
|
||||
<img src=".<?php echo $_smarty_tpl->getValue('objProject')->getThumbnail();?>
|
||||
"
|
||||
class="w-100 h-100 object-fit-cover"
|
||||
alt=""
|
||||
loading="lazy">
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
|
||||
<img src=".<?php echo $_smarty_tpl->getValue('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">
|
||||
|
||||
<div class="flex-grow-1 card-body p-3">
|
||||
<h3 class="h6 mb-1"><?php echo $_smarty_tpl->getValue('objProject')->getTitle();?>
|
||||
</h3>
|
||||
|
||||
<small class="text-body-secondary d-block mb-1">
|
||||
<time><?php echo $_smarty_tpl->getValue('objProject')->getCreation_date();?>
|
||||
</time>
|
||||
– <?php echo $_smarty_tpl->getValue('objProject')->getCreatorname();?>
|
||||
|
||||
</small>
|
||||
|
||||
<a href="?id=<?php echo $_smarty_tpl->getValue('objProject')->getId();?>
|
||||
"
|
||||
class="stretched-link small">
|
||||
Lire la suite →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</article><?php }
|
||||
}
|
||||
|
|
@ -74,7 +74,13 @@ class UserCtrl extends MotherCtrl {
|
|||
exit;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction d'inscription d'un utilisateur
|
||||
* Effectue les validations du formulaire,
|
||||
* vérifie l'unicité du mail et du pseudo,
|
||||
* puis insère l'utilisateur en base de données
|
||||
* @return void
|
||||
*/
|
||||
public function signin(){
|
||||
|
||||
// Entité pour réafficher les valeurs dans le formulaire
|
||||
|
|
@ -113,33 +119,40 @@ class UserCtrl extends MotherCtrl {
|
|||
}
|
||||
|
||||
if (trim($objUser->getMail()) === "") {
|
||||
$arrError['user_mail'] = "Le mail est obligatoire";
|
||||
$arrError['user_mail'] = "L'adresse e-mail est obligatoire";
|
||||
} elseif (!filter_var($objUser->getMail(), FILTER_VALIDATE_EMAIL)) {
|
||||
$arrError['user_mail'] = "Le format du mail n'est pas correct";
|
||||
$arrError['user_mail'] = "Le format de l'adresse e-mail est invalide";
|
||||
}
|
||||
|
||||
if (trim($objUser->getPseudo()) === "") {
|
||||
$arrError['user_pseudo'] = "Le pseudo est obligatoire";
|
||||
}
|
||||
|
||||
$strRegex = "/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{16,}$/";
|
||||
$strRegex = "/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{15,}$/";
|
||||
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";
|
||||
$arrError['user_password'] = "Le mot de passe ne respecte pas les critères";
|
||||
}else if($objUser->getPwd() != $strPwdConfirm){
|
||||
$arrError['pwd_confirm'] = "Le mot de passe et sa confirmation ne sont pas identiques";
|
||||
$arrError['pwd_confirm'] = "La confirmation du mot de passe ne correspond pas";
|
||||
}
|
||||
|
||||
|
||||
// Si pas d'erreurs => insertion
|
||||
if (count($arrError) === 0) {
|
||||
$objUserModel = new UserModel();
|
||||
|
||||
// Vérif mail
|
||||
if ($objUserModel->mailExists($objUser->getMail())) {
|
||||
$arrError['user_mail'] = "Impossible de créer le compte avec ces informations";
|
||||
}
|
||||
|
||||
$arrError['user_mail'] = "Ce mail existe déjà";
|
||||
} else {
|
||||
// Vérif pseudo
|
||||
if ($objUserModel->pseudoExists($objUser->getPseudo())) {
|
||||
$arrError['user_pseudo'] = "Ce pseudo existe déjà";
|
||||
}
|
||||
|
||||
// Si aucune erreur => insert
|
||||
if (count($arrError) === 0) {
|
||||
$boolInsert = $objUserModel->insert($objUser);
|
||||
|
||||
if ($boolInsert === true) {
|
||||
|
|
@ -154,172 +167,236 @@ class UserCtrl extends MotherCtrl {
|
|||
}
|
||||
|
||||
// Affichage de la vue inscription
|
||||
$this->_arrData["arrError"] = $arrError;
|
||||
$this->_display("inscription");
|
||||
$this->_arrData['objUser'] = $objUser;
|
||||
$this->_arrData['arrError'] = $arrError;
|
||||
$this->_display("signup");
|
||||
}
|
||||
|
||||
/**
|
||||
* le controlleur affichage de la page user
|
||||
*/
|
||||
public function user(){
|
||||
/**
|
||||
* Fonction de connexion d'un utilisateur
|
||||
* Vérifie les informations envoyées par le formulaire
|
||||
* et crée la session si les identifiants sont valides
|
||||
* @return void
|
||||
*/
|
||||
public function login(){
|
||||
|
||||
/**$intId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$strMail = $_POST['user_mail']??"";
|
||||
$strPwd = $_POST['user_password']??"";
|
||||
|
||||
if ($intId <= 0) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
// Tester le formulaire
|
||||
$arrError = [];
|
||||
if (count($_POST) > 0) {
|
||||
// Vérifier le formulaire
|
||||
if ($strMail == ""){
|
||||
$arrError['mail'] = "L'adresse e-mail est obligatoire";
|
||||
}
|
||||
if ($strPwd == ""){
|
||||
$arrError['pwd'] = "Le mot de passe est obligatoire";
|
||||
}
|
||||
|
||||
//affichage info utilisateur
|
||||
$objUserModel = new UserModel;
|
||||
$arrUserData = $objUserModel->findUserById($intId);
|
||||
// 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[] = "Identifiants incorrects";
|
||||
}else{
|
||||
// Ajoute l'utilisateur en session
|
||||
$_SESSION['user'] = $arrResult;
|
||||
$_SESSION['success'] = "Bienvenue, vous êtes bien connecté";
|
||||
|
||||
if ($arrUserData === false) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}*/
|
||||
|
||||
$strPseudo = $_GET['pseudo']??'';
|
||||
|
||||
$objUserModel = new UserModel;
|
||||
$arrUserData = $objUserModel->findUserByPseudo($strPseudo);
|
||||
|
||||
if ($arrUserData === false) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$objUser = new User;
|
||||
$objUser->hydrate($arrUserData);
|
||||
|
||||
//affichage projet de l'utilisateur
|
||||
$objProjectModel = new ProjectModel;
|
||||
$arrProjects = $objProjectModel->findAll(0,'',$objUser->getId());
|
||||
|
||||
$arrProjectToDisplay = array();
|
||||
foreach($arrProjects as $projectData) {
|
||||
$objProject = new Project();
|
||||
$objProject->hydrate($projectData);
|
||||
$arrProjectToDisplay[] = $objProject;
|
||||
}
|
||||
|
||||
$this->_arrData['user'] = $objUser;
|
||||
$this->_arrData['arrProjectToDisplay'] = $arrProjectToDisplay;
|
||||
$this->_display("user");
|
||||
}
|
||||
|
||||
public function edit(){
|
||||
if(!isset($_SESSION['user'])){
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$objUserModel = new UserModel;
|
||||
$arrError = [];
|
||||
$objUser = new User;
|
||||
$arrUserData = $objUserModel->findUserById($_SESSION['user']['user_id']);
|
||||
$objUser->hydrate($arrUserData);
|
||||
if (!empty($_POST)) {
|
||||
if ($objUserModel->mailExists($_POST['user_mail']) && ($_POST['user_mail'] != $objUser->getMail())) {
|
||||
|
||||
$arrError['user_mail'] = "Ce mail est déjà associé";
|
||||
} else {
|
||||
if ($objUserModel->pseudoExists($_POST['user_pseudo']) && ($_POST['user_pseudo'] != $objUser->getPseudo())){
|
||||
$arrError['user_pseudo'] = "Ce pseudo est déjà utiliser";
|
||||
}else{
|
||||
$objUser->hydrate($_POST);
|
||||
$objUser->setId($_SESSION['user']['user_id']);
|
||||
|
||||
// Vérification de l'image
|
||||
$arrTypeAllowed = array('image/jpeg', 'image/png', 'image/webp');
|
||||
$boolImageOk = true;
|
||||
|
||||
if ($_FILES['image']['error'] != 4) {
|
||||
if (!in_array($_FILES['image']['type'], $arrTypeAllowed)) {
|
||||
$arrError['image'] = "Le type de fichier n'est pas autorisé";
|
||||
} else {
|
||||
switch ($_FILES['image']['error']) {
|
||||
case 0:
|
||||
$strImageName = uniqid() . ".webp";
|
||||
$strOldImg = $objUser->getImage();
|
||||
$objUser->setImage($strImageName);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
$arrError['image'] = "Le fichier est trop volumineux";
|
||||
break;
|
||||
case 3:
|
||||
$arrError['image'] = "Le fichier a été partiellement téléchargé";
|
||||
break;
|
||||
case 6:
|
||||
$arrError['image'] = "Le répertoire temporaire est manquant";
|
||||
break;
|
||||
default:
|
||||
$arrError['image'] = "Erreur sur l'image";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traitement de l'image si pas d'erreur
|
||||
if (count($arrError) == 0 && isset($strImageName)) {
|
||||
$strDest = $_ENV['IMG_USER_PATH'] . $strImageName;
|
||||
$strSource = $_FILES['image']['tmp_name'];
|
||||
list($intWidth, $intHeight) = getimagesize($strSource);
|
||||
|
||||
$intDestWidth = 200; $intDestHeight = 200;
|
||||
$fltDestRatio = $intDestWidth / $intDestHeight;
|
||||
$fltSourceRatio = $intWidth / $intHeight;
|
||||
|
||||
if ($fltSourceRatio > $fltDestRatio) {
|
||||
$intCropHeight = $intHeight;
|
||||
$intCropWidth = (int)round($intHeight * $fltDestRatio);
|
||||
$intCropX = (int)(($intWidth - $intCropWidth) / 2);
|
||||
$intCropY = 0;
|
||||
} else {
|
||||
$intCropWidth = $intWidth;
|
||||
$intCropHeight = (int)round($intWidth / $fltDestRatio);
|
||||
$intCropX = 0;
|
||||
$intCropY = (int)(($intHeight - $intCropHeight) / 2);
|
||||
}
|
||||
|
||||
$objDest = imagecreatetruecolor($intDestWidth, $intDestHeight);
|
||||
switch ($_FILES['image']['type']) {
|
||||
case 'image/jpeg': $objSource = imagecreatefromjpeg($strSource); break;
|
||||
case 'image/png': $objSource = imagecreatefrompng($strSource); break;
|
||||
case 'image/webp': $objSource = imagecreatefromwebp($strSource); break;
|
||||
}
|
||||
|
||||
imagecopyresampled($objDest, $objSource, 0, 0, $intCropX, $intCropY, $intDestWidth, $intDestHeight, $intCropWidth, $intCropHeight);
|
||||
$boolImageOk = imagewebp($objDest, $strDest);
|
||||
imagedestroy($objDest);
|
||||
imagedestroy($objSource);
|
||||
}
|
||||
|
||||
|
||||
$boolInsert = $objUserModel->update($objUser);
|
||||
|
||||
if ($boolInsert === true) {
|
||||
if (isset($strOldImg) && !empty($strOldImg) && isset($strImageName)) {
|
||||
$strOldFile = $_ENV['IMG_USER_PATH'] . $strOldImg;
|
||||
if (file_exists($strOldFile)) unlink($strOldFile);
|
||||
}
|
||||
$arrNewInfo = $objUserModel->findUserByPseudo($objUser->getPseudo());
|
||||
$_SESSION['user'] = $arrNewInfo;
|
||||
$_SESSION['success'] = "Compte modifier avec succès";
|
||||
header("Location:?ctrl=user&action=user&pseudo=".$objUser->getPseudo());
|
||||
exit;
|
||||
} else {
|
||||
$arrError['global'] = "Erreur lors de l'update";
|
||||
}
|
||||
}
|
||||
header("Location:index.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_arrData['arrError'] = $arrError;
|
||||
$this->_display("login");
|
||||
|
||||
}
|
||||
|
||||
$this->_arrData["arrError"] = $arrError;
|
||||
$this->_arrData['objUser'] = $objUser;
|
||||
$this->_display("useredit");
|
||||
|
||||
}
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* le controlleur affichage de la page user
|
||||
*/
|
||||
public function user(){
|
||||
|
||||
/**$intId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
if ($intId <= 0) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
//affichage info utilisateur
|
||||
$objUserModel = new UserModel;
|
||||
$arrUserData = $objUserModel->findUserById($intId);
|
||||
|
||||
if ($arrUserData === false) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}*/
|
||||
|
||||
$strPseudo = $_GET['pseudo']??'';
|
||||
|
||||
$objUserModel = new UserModel;
|
||||
$arrUserData = $objUserModel->findUserByPseudo($strPseudo);
|
||||
|
||||
if ($arrUserData === false) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$objUser = new User;
|
||||
$objUser->hydrate($arrUserData);
|
||||
|
||||
//affichage projet de l'utilisateur
|
||||
$objProjectModel = new ProjectModel;
|
||||
$arrProjects = $objProjectModel->findAll(0,'',$objUser->getId());
|
||||
|
||||
$arrProjectToDisplay = array();
|
||||
foreach($arrProjects as $projectData) {
|
||||
$objProject = new Project();
|
||||
$objProject->hydrate($projectData);
|
||||
$arrProjectToDisplay[] = $objProject;
|
||||
}
|
||||
|
||||
$this->_arrData['user'] = $objUser;
|
||||
$this->_arrData['arrProjectToDisplay'] = $arrProjectToDisplay;
|
||||
$this->_display("user");
|
||||
}
|
||||
|
||||
public function edit(){
|
||||
if(!isset($_SESSION['user'])){
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$objUserModel = new UserModel;
|
||||
$arrError = [];
|
||||
$objUser = new User;
|
||||
$arrUserData = $objUserModel->findUserById($_SESSION['user']['user_id']);
|
||||
$objUser->hydrate($arrUserData);
|
||||
if (!empty($_POST)) {
|
||||
if ($objUserModel->mailExists($_POST['user_mail']) && ($_POST['user_mail'] != $objUser->getMail())) {
|
||||
|
||||
$arrError['user_mail'] = "Ce mail est déjà associé";
|
||||
} else {
|
||||
if ($objUserModel->pseudoExists($_POST['user_pseudo']) && ($_POST['user_pseudo'] != $objUser->getPseudo())){
|
||||
$arrError['user_pseudo'] = "Ce pseudo est déjà utiliser";
|
||||
}else{
|
||||
$objUser->hydrate($_POST);
|
||||
$objUser->setId($_SESSION['user']['user_id']);
|
||||
|
||||
// Vérification de l'image
|
||||
$arrTypeAllowed = array('image/jpeg', 'image/png', 'image/webp');
|
||||
$boolImageOk = true;
|
||||
|
||||
if ($_FILES['image']['error'] != 4) {
|
||||
if (!in_array($_FILES['image']['type'], $arrTypeAllowed)) {
|
||||
$arrError['image'] = "Le type de fichier n'est pas autorisé";
|
||||
} else {
|
||||
switch ($_FILES['image']['error']) {
|
||||
case 0:
|
||||
$strImageName = uniqid() . ".webp";
|
||||
$strOldImg = $objUser->getImage();
|
||||
$objUser->setImage($strImageName);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
$arrError['image'] = "Le fichier est trop volumineux";
|
||||
break;
|
||||
case 3:
|
||||
$arrError['image'] = "Le fichier a été partiellement téléchargé";
|
||||
break;
|
||||
case 6:
|
||||
$arrError['image'] = "Le répertoire temporaire est manquant";
|
||||
break;
|
||||
default:
|
||||
$arrError['image'] = "Erreur sur l'image";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traitement de l'image si pas d'erreur
|
||||
if (count($arrError) == 0 && isset($strImageName)) {
|
||||
$strDest = $_ENV['IMG_USER_PATH'] . $strImageName;
|
||||
$strSource = $_FILES['image']['tmp_name'];
|
||||
list($intWidth, $intHeight) = getimagesize($strSource);
|
||||
|
||||
$intDestWidth = 200; $intDestHeight = 200;
|
||||
$fltDestRatio = $intDestWidth / $intDestHeight;
|
||||
$fltSourceRatio = $intWidth / $intHeight;
|
||||
|
||||
if ($fltSourceRatio > $fltDestRatio) {
|
||||
$intCropHeight = $intHeight;
|
||||
$intCropWidth = (int)round($intHeight * $fltDestRatio);
|
||||
$intCropX = (int)(($intWidth - $intCropWidth) / 2);
|
||||
$intCropY = 0;
|
||||
} else {
|
||||
$intCropWidth = $intWidth;
|
||||
$intCropHeight = (int)round($intWidth / $fltDestRatio);
|
||||
$intCropX = 0;
|
||||
$intCropY = (int)(($intHeight - $intCropHeight) / 2);
|
||||
}
|
||||
|
||||
$objDest = imagecreatetruecolor($intDestWidth, $intDestHeight);
|
||||
switch ($_FILES['image']['type']) {
|
||||
case 'image/jpeg': $objSource = imagecreatefromjpeg($strSource); break;
|
||||
case 'image/png': $objSource = imagecreatefrompng($strSource); break;
|
||||
case 'image/webp': $objSource = imagecreatefromwebp($strSource); break;
|
||||
}
|
||||
|
||||
imagecopyresampled($objDest, $objSource, 0, 0, $intCropX, $intCropY, $intDestWidth, $intDestHeight, $intCropWidth, $intCropHeight);
|
||||
$boolImageOk = imagewebp($objDest, $strDest);
|
||||
imagedestroy($objDest);
|
||||
imagedestroy($objSource);
|
||||
}
|
||||
|
||||
|
||||
$boolInsert = $objUserModel->update($objUser);
|
||||
|
||||
if ($boolInsert === true) {
|
||||
if (isset($strOldImg) && !empty($strOldImg) && isset($strImageName)) {
|
||||
$strOldFile = $_ENV['IMG_USER_PATH'] . $strOldImg;
|
||||
if (file_exists($strOldFile)) unlink($strOldFile);
|
||||
}
|
||||
$arrNewInfo = $objUserModel->findUserByPseudo($objUser->getPseudo());
|
||||
$_SESSION['user'] = $arrNewInfo;
|
||||
$_SESSION['success'] = "Compte modifier avec succès";
|
||||
header("Location:?ctrl=user&action=user&pseudo=".$objUser->getPseudo());
|
||||
exit;
|
||||
} else {
|
||||
$arrError['global'] = "Erreur lors de l'update";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_arrData["arrError"] = $arrError;
|
||||
$this->_arrData['objUser'] = $objUser;
|
||||
$this->_display("useredit");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ class Project extends Entity{
|
|||
* Mise à jour de l'id du projet
|
||||
* @param int le nouvelle id
|
||||
*/
|
||||
public function setId($id){
|
||||
public function setId(int $id){
|
||||
$this->_id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
4
env
|
|
@ -5,3 +5,7 @@ DB_HOSTNAME=boulayoune.com
|
|||
DB_DATABASE=projet_folliow
|
||||
DB_USERNAME=
|
||||
DB_PASSWORD=
|
||||
|
||||
# image path
|
||||
IMG_PROJECT_PATH = uploads/projects/
|
||||
IMG_USER_PATH = uploads/profiles/
|
||||
|
|
@ -23,14 +23,14 @@
|
|||
}
|
||||
|
||||
/**
|
||||
Pour passer sur le serveur de YASS:
|
||||
*Pour passer sur le serveur de YASS:
|
||||
*"mysql:host=boulayoune.com;dbname=projet_folliow", // Serveur et BDD
|
||||
"projet_user", //Nom d'utilisateur de la base de données
|
||||
"F0lliowRules!",// Mot de passe de la base de données
|
||||
Site pour BDD: https://phpmyadmin.boulayoune.com/index.php?route=/sql&pos=0&db=projet_folliow&table=project
|
||||
|
||||
Pour passer en local:
|
||||
"mysql:host=localhost;dbname=projet_folliow", // Serveur et BDD
|
||||
"root", //Nom d'utilisateur de la base de données
|
||||
"",// Mot de passe de la base de données
|
||||
*Pour passer en local:
|
||||
*"mysql:host=localhost;dbname=projet_folliow", // Serveur et BDD
|
||||
*"root", //Nom d'utilisateur de la base de données
|
||||
*"",// Mot de passe de la base de données
|
||||
*/
|
||||
|
|
@ -16,60 +16,45 @@
|
|||
* @return array
|
||||
*/
|
||||
public function findAll(int $intLimit=0, string $strKeywords='', int $intAuthor=0,
|
||||
int $intPeriod=0, string $strDate='', string $strStartDate='',
|
||||
string $strEndDate='', int $intCategory=0, bool $bool6Months=false):array{
|
||||
int $intPeriod=0, string $strDate='', string $strStartDate='',
|
||||
string $strEndDate='', int $intCategory=0, bool $boolOlderThan6Months=false): array {
|
||||
|
||||
|
||||
$strRq = "SELECT project.*,
|
||||
user_pseudo AS 'project_creatorname',
|
||||
user_image
|
||||
FROM project
|
||||
INNER JOIN users ON user_id = project_user_id";
|
||||
INNER JOIN users ON user_id = project_user_id
|
||||
WHERE 1=1";
|
||||
|
||||
$strWhere = " WHERE ";
|
||||
|
||||
// Recherche par mot clé avec quote pour éviter bug du '
|
||||
if ($strKeywords != '') {
|
||||
|
||||
$strSafeKeywords = $this->_db->quote("%" . $strKeywords . "%");
|
||||
|
||||
$strRq .= " WHERE (project_title LIKE ".$strSafeKeywords."
|
||||
OR project_content LIKE ".$strSafeKeywords.") ";
|
||||
|
||||
//$boolWhere = true;
|
||||
$strWhere = " AND ";
|
||||
$strRq .= " AND (project_title LIKE :keywords OR project_content LIKE :keywords)";
|
||||
}
|
||||
|
||||
// Recherche par auteur
|
||||
if ($intAuthor > 0){
|
||||
$strRq .= $strWhere." user_id = ".$intAuthor;
|
||||
$strWhere = " AND ";
|
||||
$strRq .= " AND project_user_id = :author";
|
||||
}
|
||||
|
||||
// Recherche par catégorie
|
||||
if ($intCategory > 0){
|
||||
$strRq .= $strWhere." project_category = ".$intCategory;
|
||||
$strWhere = " AND ";
|
||||
$strRq .= " AND project_category = :category";
|
||||
}
|
||||
|
||||
//recherche par ancienneté
|
||||
if ($bool6Months === true) {
|
||||
$strRq .= $strWhere . " project_creation_date <= DATE_SUB(NOW(), INTERVAL 6 MONTH) ";
|
||||
$strWhere = " AND ";
|
||||
if ($boolOlderThan6Months === true) {
|
||||
$strRq .= " AND project_creation_date <= DATE_SUB(NOW(), INTERVAL 6 MONTH)";
|
||||
}
|
||||
|
||||
// Recherche par dates
|
||||
if ($intPeriod == 0){
|
||||
if ($strDate != ''){
|
||||
$strRq .= $strWhere." project_creation_date = '".$strDate."'";
|
||||
$strRq .= " AND project_creation_date = :date_exacte";
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
if ($strStartDate != '' && $strEndDate != ''){
|
||||
$strRq .= $strWhere." project_creation_date BETWEEN '".$strStartDate."' AND '".$strEndDate."'";
|
||||
}else{
|
||||
$strRq .= " AND project_creation_date BETWEEN :date_debut AND :date_fin";
|
||||
} else {
|
||||
if ($strStartDate != ''){
|
||||
$strRq .= $strWhere." project_creation_date >= '".$strStartDate."'";
|
||||
}else if ($strEndDate != ''){
|
||||
$strRq .= $strWhere." project_creation_date <= '".$strEndDate."'";
|
||||
$strRq .= " AND project_creation_date >= :date_debut";
|
||||
} else if ($strEndDate != ''){
|
||||
$strRq .= " AND project_creation_date <= :date_fin";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,12 +62,45 @@
|
|||
$strRq .= " ORDER BY project_creation_date DESC";
|
||||
|
||||
if ($intLimit > 0){
|
||||
$strRq .= " LIMIT ".$intLimit;
|
||||
$strRq .= " LIMIT :limit";
|
||||
}
|
||||
|
||||
return $this->_db->query($strRq)->fetchAll();
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
|
||||
if ($strKeywords != '') {
|
||||
$rqPrep->bindValue(':keywords', '%' . $strKeywords . '%', PDO::PARAM_STR);
|
||||
}
|
||||
if ($intAuthor > 0){
|
||||
$rqPrep->bindValue(':author', $intAuthor, PDO::PARAM_INT);
|
||||
}
|
||||
if ($intCategory > 0){
|
||||
$rqPrep->bindValue(':category', $intCategory, PDO::PARAM_INT);
|
||||
}
|
||||
if ($intPeriod == 0){
|
||||
if ($strDate != ''){
|
||||
$rqPrep->bindValue(':date_exacte', $strDate, PDO::PARAM_STR);
|
||||
}
|
||||
} else {
|
||||
if ($strStartDate != '' && $strEndDate != ''){
|
||||
$rqPrep->bindValue(':date_debut', $strStartDate, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(':date_fin', $strEndDate, PDO::PARAM_STR);
|
||||
} else {
|
||||
if ($strStartDate != ''){
|
||||
$rqPrep->bindValue(':date_debut', $strStartDate, PDO::PARAM_STR);
|
||||
} else if ($strEndDate != ''){
|
||||
$rqPrep->bindValue(':date_fin', $strEndDate, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($intLimit > 0){
|
||||
$rqPrep->bindValue(':limit', $intLimit, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$rqPrep->execute();
|
||||
return $rqPrep->fetchAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fonction d'insertion d'un nouveau projet dans la bdd
|
||||
* @param object $objProject l'objet projet
|
||||
|
|
@ -103,7 +121,16 @@
|
|||
$rqPrep->bindValue(":project_user_id", $objProject->getUser_id(), PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":project_category", $objProject->getCategory(), PDO::PARAM_STR);
|
||||
|
||||
return $rqPrep->execute();
|
||||
// On met une variable boolOk pour récupérer l'id du projet
|
||||
$boolOk = $rqPrep->execute();
|
||||
|
||||
// Si boolOk est remplis
|
||||
if ($boolOk) {
|
||||
// On récupère l'ID auto-incrémenté et on l'injecte dans l'objet
|
||||
$objProject->setId($this->_db->lastInsertId());
|
||||
}
|
||||
|
||||
return $boolOk;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,7 +140,7 @@
|
|||
*/
|
||||
public function findOne(int $intId) :array{
|
||||
$strRq = "SELECT project.*,
|
||||
CONCAT(users.user_firstname, ' ', users.user_name) AS 'project_creatorname',
|
||||
users.user_pseudo AS 'project_creatorname',
|
||||
users.user_image,
|
||||
category.category_name
|
||||
FROM project
|
||||
|
|
@ -136,12 +163,10 @@
|
|||
*/
|
||||
public function accept(int $id){
|
||||
|
||||
//SQL pour changer le status en accept
|
||||
$strRq = "UPDATE project
|
||||
SET project_status= 'publié'
|
||||
WHERE project_id =".$id;
|
||||
|
||||
//retourne la commande
|
||||
return $this->_db->query($strRq);
|
||||
}
|
||||
|
||||
|
|
@ -200,10 +225,16 @@
|
|||
return $rqPrep->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de récupération d'image d'un projet en BDD
|
||||
* @author Guillaume
|
||||
* @param int $objProject L'Id du projet choisit
|
||||
* @return array Un tableau avec les informations de la bdd
|
||||
*/
|
||||
public function getImagesByProjectId(int $projectId): array {
|
||||
$strRq = "SELECT image_id, image_name, image_alt
|
||||
$strRq = "SELECT image_id, image_name, image_alt, image_status
|
||||
FROM image
|
||||
WHERE image_project = :id AND image_status = 1";
|
||||
WHERE image_project = :id";
|
||||
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
$rqPrep->bindValue(":id", $projectId, PDO::PARAM_INT);
|
||||
|
|
@ -212,6 +243,56 @@
|
|||
return $rqPrep->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de récupération d'image d'un projet en BDD
|
||||
* @author Guillaume
|
||||
* @param int $id L'Id de l'image choisit
|
||||
* @return array Un tableau avec les informations de la bdd
|
||||
*/
|
||||
public function deleteImage(int $id): bool {
|
||||
$strRq = "DELETE FROM image WHERE image_id = :id";
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
$rqPrep->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
return $rqPrep->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de modifications de status de l'image d'un projet en BDD
|
||||
* @author Guillaume
|
||||
* @param int $id L'Id de l'image choisit, string $status le status choisit
|
||||
* @return array Un tableau avec les informations de la bdd
|
||||
*/
|
||||
public function updateImageStatus(int $id, string $status): bool {
|
||||
$strRq = "UPDATE image SET image_status = :status WHERE image_id = :id";
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
$rqPrep->bindValue(':status', $status, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
return $rqPrep->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction de récupération d'image d'un projet en BDD
|
||||
* @author Guillaume
|
||||
* @param int $id L'Id de l'image choisit
|
||||
* @return array Un tableau avec les informations de la bdd
|
||||
*/
|
||||
public function findImage(int $id): array|bool {
|
||||
$strRq = "SELECT * FROM image WHERE image_id = :id";
|
||||
$rqPrep = $this->_db->prepare($strRq);
|
||||
$rqPrep->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
$rqPrep->execute();
|
||||
return $rqPrep->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ajoute une image liée à un projet dans la table 'image'
|
||||
* @author Guillaume
|
||||
* @param string $fileName Nom du fichier image
|
||||
* @param int $projectId ID du projet parent
|
||||
* @param string $alt Texte alternatif
|
||||
* @return bool
|
||||
*/
|
||||
public function addImageInProject(string $fileName, int $projectId, string $alt = "Image projet"): bool {
|
||||
$strRq = "INSERT INTO image (
|
||||
image_name,
|
||||
|
|
@ -225,7 +306,8 @@
|
|||
|
||||
$rqPrep->bindValue(":name", $fileName, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":alt", $alt, PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":status", "en_attente", PDO::PARAM_STR); // Valeur string brute
|
||||
// On met le statut par défaut en "en_attente" pour la modération
|
||||
$rqPrep->bindValue(":status", "en_attente", PDO::PARAM_STR);
|
||||
$rqPrep->bindValue(":project", $projectId, PDO::PARAM_INT);
|
||||
|
||||
return $rqPrep->execute();
|
||||
|
|
|
|||
BIN
uploads/profiles/699d648ba35c3.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
uploads/profiles/images.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
BIN
uploads/projects/699ca2c207e75.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
uploads/projects/699ca2cf9f010.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
uploads/projects/699ca324b5dbc.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
uploads/projects/699ca3d159d4f.webp
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
uploads/projects/699d9a6c0f3ff.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
uploads/projects/699da2d0f019d_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699da361ad88b_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699da361b8269_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daa1221be1.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
uploads/projects/699daa122cd7e_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daa1237170_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daa1240e76_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daaaa3ad2f_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daaaa465e2_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daaaa508c2_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daab323eba_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daab32e68b_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daab3382c9_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daad12bbd3_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daad137975_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daad141d4f_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daad14c4c0_gallery.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
uploads/projects/699daae1accb0_gallery.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
uploads/projects/699daae1b71a4_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699daae1c14d4_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daae1cb709_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daaee31689_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699daaee3cfe3_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699daaee4725f_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699dadac0af45_gallery.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
uploads/projects/699dadac15713_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699dadac202e2_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699db11d01cb6_gallery.webp
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
uploads/projects/699db11d0d418_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
uploads/projects/699db11d1741e_gallery.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
uploads/projects/699db11d21c20_gallery.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
|
@ -5,7 +5,7 @@
|
|||
<li><a href="#">Découvrir</a>
|
||||
<li><a href="#">Customisation</a>
|
||||
<li><a href="#">Emploi</a>
|
||||
<li><a href="#">A propos</a>
|
||||
<li><a href="?ctrl=project&action=about">A propos</a>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
<div class="col-3">
|
||||
<ul>
|
||||
<li><a href="#">Politique de confidentialité</a>
|
||||
<li><a href="#">Politique sur les données</a>
|
||||
<li><a href="?ctrl=project&action=mentions">Mentions légales</a>
|
||||
<li><a href="#">CGU</a>
|
||||
<li><a href="#">CGV</a>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<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">
|
||||
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
|
||||
<title>Folliow</title>
|
||||
<title>Folliow{block name="title"}{/block}</title>
|
||||
</head>
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
{* 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">
|
||||
<a class="nav-link" href="index.php?ctrl=user&action=signup" title="Créer un compte" aria-label="Créer un compte">
|
||||
S'inscrire
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="index.php?ctrl=user&action=user&pseudo={$smarty.session.user.user_pseudo}" title="Modifier mon compte" aria-label="Modifier mon compte">
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$smarty.session.user.user_image}"
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$smarty.session.user.user_image ?? "images.jpg"}"
|
||||
class="rounded-circle flex-shrink-0 mt-2 ml-5"
|
||||
style="width: 36px; height: 36px; object-fit: cover;"
|
||||
alt="Photo de profil">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<div class="card-body p-3 bg-light">
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
{* PHOTO DE PROFIL (cercle à gauche - plus grand) *}
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$objProject->getUser_image()}"
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$objProject->getUser_image() ?? "images.jpg"}"
|
||||
class="rounded-circle flex-shrink-0 border border-2 border-white"
|
||||
style="width: 64px; height: 64px; object-fit: cover; margin-top: 8px;"
|
||||
alt="Photo de profil">
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
{if isset($smarty.session.user)}
|
||||
{if $smarty.session.user.user_id == $objProject->getUser_id()}
|
||||
<a href="index.php?ctrl=project&action=display&id={$objProject->getId()}"
|
||||
<a href="index.php?ctrl=project&action=addedit_project&id={$objProject->getId()}"
|
||||
class="btn btn-sm btn-outline-secondary mt-2 w-100"
|
||||
style="position: relative; z-index: 2;">
|
||||
Editer
|
||||
|
|
@ -72,12 +72,12 @@
|
|||
name="toRefused">Refuser</a>
|
||||
<a class="btn btn-sm btn-danger flex-fill"
|
||||
href="?ctrl=project&action=delete&id={$objProject->getId()}"
|
||||
name="toDelete">Supprimer</a>
|
||||
name="toDelete" onclick="return confirm('Attention ! Êtes-vous sûr de vouloir supprimer ce projet ? Cette action est irréversible.');">Supprimer</a>
|
||||
</div>
|
||||
</div>
|
||||
{elseif $objProject->getStatus() == "refusé"}
|
||||
<div class="card-footer bg-white border-top-0 p-2">
|
||||
<p class="text-danger fw-bold text-center mb-0 small">Portfolio refusé</p>
|
||||
<p class="text-danger fw-bold text-center mb-0 small">Projet refusé</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
160
views/about.tpl
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
|
||||
{block name="title" append} - À propos{/block}
|
||||
|
||||
{block name="h2"}À propos de FOLLIOW{/block}
|
||||
{block name="p"}Plateforme de partage de projets – Projet pédagogique{/block}
|
||||
|
||||
{block name="content"}
|
||||
|
||||
<section aria-label="À propos de FOLLIOW">
|
||||
<div class="row g-5">
|
||||
|
||||
<!-- Présentation principale -->
|
||||
<div class="col-lg-8">
|
||||
|
||||
<section aria-labelledby="presentation">
|
||||
<h3 id="presentation" class="h4 mb-3">
|
||||
<i class="fas fa-lightbulb me-2 text-primary"></i>
|
||||
Présentation du projet
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<strong>FOLLIOW</strong> est une plateforme web développée dans le cadre d’un projet pédagogique.
|
||||
Elle permet aux utilisateurs de publier, consulter et partager des projets numériques
|
||||
à travers une interface simple et structurée.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ce projet a été conçu afin de mettre en pratique les compétences acquises en
|
||||
développement web, notamment l’architecture MVC, la gestion des bases de données
|
||||
et la sécurisation des échanges.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="fonctionnalites" class="mt-4">
|
||||
<h3 id="fonctionnalites" class="h4 mb-3">
|
||||
<i class="fas fa-cogs me-2 text-primary"></i>
|
||||
Fonctionnalités principales
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Création et gestion de projets</li>
|
||||
<li>Affichage dynamique des contenus</li>
|
||||
<li>Gestion des utilisateurs</li>
|
||||
<li>Partage d’un projet par email</li>
|
||||
<li>Interface responsive et accessible</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="objectifs" class="mt-4">
|
||||
<h3 id="objectifs" class="h4 mb-3">
|
||||
<i class="fas fa-bullseye me-2 text-primary"></i>
|
||||
Objectifs pédagogiques
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
L’objectif principal de FOLLIOW est de démontrer la capacité à concevoir
|
||||
une application web complète, structurée et sécurisée.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Structuration d’un projet en architecture MVC</li>
|
||||
<li>Manipulation de bases de données relationnelles</li>
|
||||
<li>Validation et sécurisation des données</li>
|
||||
<li>Implémentation d’un système d’envoi d’emails</li>
|
||||
<li>Respect des bonnes pratiques (RGPD, accessibilité, organisation du code)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="technologies" class="mt-4">
|
||||
<h3 id="technologies" class="h4 mb-3">
|
||||
<i class="fas fa-code me-2 text-primary"></i>
|
||||
Technologies utilisées
|
||||
</h3>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100 border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<strong>Backend</strong>
|
||||
<p class="small mb-0">
|
||||
PHP orienté objet – Architecture MVC – MySQL
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100 border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<strong>Frontend</strong>
|
||||
<p class="small mb-0">
|
||||
HTML5 – CSS3 – Bootstrap – Smarty
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100 border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<strong>Emails</strong>
|
||||
<p class="small mb-0">
|
||||
PHPMailer – SMTP – Brevo
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100 border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<strong>Sécurité</strong>
|
||||
<p class="small mb-0">
|
||||
Validation des données – Protection des formulaires – Gestion des sessions
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
<div class="card shadow-sm p-4">
|
||||
|
||||
<h4 class="h5 mb-3">
|
||||
<i class="fas fa-graduation-cap me-2 text-primary"></i>
|
||||
Projet pédagogique
|
||||
</h4>
|
||||
|
||||
<p class="small">
|
||||
FOLLIOW a été réalisé dans le cadre d’une formation en développement web.
|
||||
Il s’agit d’un projet démonstratif à visée éducative.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4 class="h5 mb-3">
|
||||
<i class="fas fa-envelope me-2 text-primary"></i>
|
||||
Contact
|
||||
</h4>
|
||||
|
||||
<p class="small mb-1">
|
||||
Pour toute question :
|
||||
</p>
|
||||
|
||||
<a href="mailto:projet.folliow@hotmail.com" class="small">
|
||||
projet.folliow@hotmail.com
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/block}
|
||||
|
|
@ -40,14 +40,56 @@
|
|||
<input name="thumbnail" class="form-control" type="file">
|
||||
{if $objProject && $objProject->getId()}
|
||||
<label class="h5">Miniature actuelle :</label>
|
||||
<img src="uploads/projects/{$objProject->getThumbnail()}" alt="Miniature">
|
||||
<img src="{$smarty.env.IMG_PROJECT_PATH}{$objProject->getThumbnail()}" alt="Miniature">
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="h5">Images de votre projet</label>
|
||||
<input name="imageProject" class="form-control" type="file" multiple>
|
||||
</div>
|
||||
<label class="form-label h5">Galerie de photos (Max 20)</label>
|
||||
{assign var="nbActuel" value=$arrImages|@count}
|
||||
{assign var="disponible" value=20 - $nbActuel}
|
||||
|
||||
{if $disponible > 0}
|
||||
<p class="small text-muted">Il vous reste <strong>{$disponible}</strong> emplacement(s) libre(s).</p>
|
||||
<input type="file" name="imageProject[]" multiple class="form-control" accept="image/*">
|
||||
{else}
|
||||
<div class="alert alert-warning p-2">
|
||||
<i class="fas fa-exclamation-triangle"></i> Quota de 20 photos atteint.
|
||||
</div>
|
||||
{* On désactive l'input si le quota est plein *}
|
||||
<input type="file" disabled class="form-control">
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{* Affichage de Images du projet (s'il y en a)*}
|
||||
<div class="row mt-4">
|
||||
<label class="h5">Galerie du projet</label>
|
||||
{foreach $arrImages as $image}
|
||||
<div class="col-md-3 mb-3 text-center">
|
||||
<div class="card shadow-sm h-100 border-{if $image.image_status == 'approuvé'}success{elseif $image.image_status == 'refusé'}danger{else}warning{/if}">
|
||||
<img src="{$smarty.env.IMG_PROJECT_PATH}{$image.image_name}"
|
||||
class="card-img-top img-thumbnail"
|
||||
alt="{$image.image_alt}"
|
||||
style="height: 150px; object-fit: cover;">
|
||||
|
||||
<div class="card-body p-2">
|
||||
<span class="badge {if $image.image_status == 'approuvé'}bg-success{elseif $image.image_status == 'refusé'}bg-danger{else}bg-warning text-dark{/if}">
|
||||
{*Permet de remplacer certains character par d'autre*}
|
||||
{$image.image_status|replace:'_':' '}
|
||||
</span>
|
||||
|
||||
<div class="mt-2 d-flex flex-column gap-1">
|
||||
<a href="index.php?ctrl=project&action=delete_image&id_img={$image.image_id}"
|
||||
class="btn btn-sm btn-danger"
|
||||
onclick="return confirm('Supprimer définitivement cette image ?')">Supprimer</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{foreachelse}
|
||||
<p class="text-muted italic">Aucune photo dans la galerie pour le moment.</p>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-md" name="sendProject">Envoyer</button>
|
||||
|
|
|
|||
|
|
@ -1,197 +0,0 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
|
||||
{block name="content"}
|
||||
<!-- Page : Inscription -->
|
||||
|
||||
|
||||
<main class="container py-5">
|
||||
|
||||
<!-- Centrage horizontal du formulaire -->
|
||||
<div class="row justify-content-center position-relative">
|
||||
<div class="col-12 col-md-10 col-lg-6">
|
||||
|
||||
<!-- Carte contenant le formulaire d'inscription -->
|
||||
<div class="card shadow-sm border-0 rounded-4 p-4 p-lg-5">
|
||||
|
||||
<!-- Titre principal de la page -->
|
||||
<h1 class="h3 fw-bold mb-1">Inscription</h1>
|
||||
|
||||
<!-- Texte descriptif -->
|
||||
<p class="text-secondary mb-4">
|
||||
Créez votre compte utilisateur.
|
||||
</p>
|
||||
{if (isset($arrError) && count($arrError) > 0) }
|
||||
<div class="alert alert-danger">
|
||||
{foreach $arrError as $strError}
|
||||
<p>{$strError}</p>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
<!-- Formulaire d'inscription -->
|
||||
<!-- Les données seront traitées côté serveur en PHP via la méthode POST -->
|
||||
<form method="POST">
|
||||
|
||||
<div class="row g-3">
|
||||
|
||||
<!-- Champ : prénom de l'utilisateur -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="user_firstname">
|
||||
Prénom *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
id="user_firstname"
|
||||
name="user_firstname"
|
||||
required >
|
||||
</div>
|
||||
|
||||
<!-- Champ : nom de l'utilisateur -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="user_name">
|
||||
Nom *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
id="user_name"
|
||||
name="user_name"
|
||||
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"
|
||||
type="text"
|
||||
id="user_pseudo"
|
||||
name="user_pseudo"
|
||||
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"
|
||||
type="email"
|
||||
id="user_mail"
|
||||
name="user_mail"
|
||||
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"
|
||||
type="password"
|
||||
id="user_password"
|
||||
name="user_password"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<!-- Champ : confirmer le mot de passe -->
|
||||
<div class="col-12">
|
||||
<label class="form-label" for="pwd_confirm">
|
||||
Confirmer le Mot de passe *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
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 -->
|
||||
<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>
|
||||
|
||||
<!-- Bouton de soumission du formulaire -->
|
||||
<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>
|
||||
|
||||
<!-- 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>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{/block}
|
||||
162
views/login.tpl
|
|
@ -1,116 +1,84 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
{block name="title" append} - Connexion{/block}
|
||||
|
||||
{block name="content"}
|
||||
<section aria-label="Se connecter">
|
||||
{* Affichage des erreurs *}
|
||||
{if $arrError|count > 0}
|
||||
<div class="alert alert-danger">
|
||||
{foreach from=$arrError item=strError}
|
||||
<p>{$strError}</p>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
<!-- 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">
|
||||
<div class="py-5">
|
||||
<!-- Centrage horizontal du formulaire -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-8 col-lg-5">
|
||||
|
||||
<!-- Centrage horizontal du formulaire -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-8 col-lg-5">
|
||||
<!-- Carte contenant le formulaire de connexion -->
|
||||
<div class="card shadow-sm border-0 rounded-4 p-4 p-lg-5">
|
||||
|
||||
<!-- Carte contenant le formulaire de connexion -->
|
||||
<div class="card shadow-sm border-0 rounded-4 p-4 p-lg-5">
|
||||
<!-- Titre principal -->
|
||||
<h1 class="h3 fw-bold mb-1">Connexion</h1>
|
||||
|
||||
<!-- Titre principal -->
|
||||
<h1 class="h3 fw-bold mb-1">Connexion</h1>
|
||||
<!-- Texte descriptif -->
|
||||
<p class="text-secondary mb-4">
|
||||
Connectez-vous à votre compte.
|
||||
</p>
|
||||
|
||||
<!-- Texte descriptif -->
|
||||
<p class="text-secondary mb-4">
|
||||
Connectez-vous à votre compte.
|
||||
</p>
|
||||
<!-- Formulaire de connexion -->
|
||||
<!-- Le traitement sera effectué en PHP via la méthode POST -->
|
||||
<form method="POST">
|
||||
<div class="row g-3">
|
||||
|
||||
<!-- Formulaire de connexion -->
|
||||
<!-- Le traitement sera effectué en PHP via la méthode POST -->
|
||||
<form method="POST">
|
||||
<!-- Champ : adresse e-mail de l'utilisateur -->
|
||||
<div class="col-12">
|
||||
<label for="user_mail" class="form-label">
|
||||
Adresse e-mail
|
||||
</label>
|
||||
<input
|
||||
value="{$strMail|default:''}"
|
||||
type="email"
|
||||
class="form-control {if isset($arrError.user_mail)}is-invalid{/if}"
|
||||
id="user_mail"
|
||||
name="user_mail"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<!-- Champ : mot de passe -->
|
||||
<div class="col-12">
|
||||
<label for="user_password" class="form-label">
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control {if isset($arrError.user_password)}is-invalid{/if}"
|
||||
id="user_password"
|
||||
name="user_password"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Champ : adresse e-mail de l'utilisateur -->
|
||||
<div class="col-12">
|
||||
<label for="user_mail" class="form-label">
|
||||
Adresse e-mail
|
||||
</label>
|
||||
<input
|
||||
value="{$strMail|default:''}"
|
||||
type="email"
|
||||
class="form-control {if isset($arrError.mail)}is-invalid{/if}"
|
||||
id="user_mail"
|
||||
name="user_mail"
|
||||
required
|
||||
<!-- Bouton de soumission du formulaire -->
|
||||
<div class="col-12 d-grid mt-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg rounded-3">
|
||||
Se connecter
|
||||
</button>
|
||||
</div>
|
||||
|
||||
>
|
||||
</div>
|
||||
<!-- Lien vers la page d'inscription -->
|
||||
<div class="col-12 text-center">
|
||||
<small class="text-secondary">
|
||||
Pas encore de compte ?
|
||||
<a href="index.php?ctrl=user&action=signup" class="link-primary">
|
||||
Créer un compte
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Champ : mot de passe -->
|
||||
<div class="col-12">
|
||||
<label for="user_password" class="form-label">
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control {if isset($arrError.pwd)}is-invalid{/if}"
|
||||
id="user_password"
|
||||
name="user_password"
|
||||
required
|
||||
</div>
|
||||
</form>
|
||||
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Option "Se souvenir de moi" (fonctionnalité optionnelle côté PHP) -->
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bouton de soumission du formulaire -->
|
||||
<div class="col-12 d-grid mt-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg rounded-3">
|
||||
Se connecter
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Lien vers la page d'inscription -->
|
||||
<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>
|
||||
|
||||
<!-- Lien pour la récupération du mot de passe -->
|
||||
<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>
|
||||
</section>
|
||||
{/block}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
|
||||
{block name="title" append}Mentions légales{/block}
|
||||
{block name="title" append} - Mentions légales{/block}
|
||||
|
||||
{block name="h2"}Mentions légales{/block}
|
||||
{block name="p"}Informations légales et politique de confidentialité{/block}
|
||||
|
||||
|
|
|
|||
75
views/project.tpl
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
|
||||
{block name="content"}
|
||||
<body>
|
||||
<section class="container mt-5 p-5 d-flex flex-column align-items-center">
|
||||
<div>
|
||||
<h2>Alimenter votre projet</h2>
|
||||
<form method="post">
|
||||
<button type="submit" class="btn btn-primary btn-lg" name="showForm">+</button>
|
||||
{if isset($smarty.post.toContinue)}
|
||||
<button type="submit" class="btn btn-warning btn-lg" name="showFormContinue">Reprendre</button>
|
||||
{/if}
|
||||
</form>
|
||||
|
||||
{* Affichage d'un formulaire en cas d'appuie sur le bouton "+" *}
|
||||
{if isset($smarty.post.showForm) || isset($smarty.post.showFormContinue)}
|
||||
{if isset($smarty.session.user)}
|
||||
<form class="m-2" method="post" enctype="multipart/form-data" onsubmit="return confirm('Voulez-vous vraiment envoyer le formulaire ?')">
|
||||
<div>
|
||||
<label>Titre</label>
|
||||
<input type="text" name="titleProject">
|
||||
</div>
|
||||
<div>
|
||||
<label>Description</label>
|
||||
<input type="text" name="descProject">
|
||||
</div>
|
||||
<div>
|
||||
<label>Texte Portfolio</label>
|
||||
<input type="text" name="textProject">
|
||||
</div>
|
||||
<div>
|
||||
<h3>Image thumbnail</h3>
|
||||
<input name="imageThumbnail" class="form-control" type="file">
|
||||
</div>
|
||||
<div>
|
||||
<h3>Image du projet</h3>
|
||||
<input name="imageProject" class="form-control" type="file">
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<button type="submit" class="btn btn-primary btn-md" name="sendMessage">Envoyer</button>
|
||||
<button type="submit" class="btn btn-warning btn-md" name="toContinue">Remettre à plus tard</button>
|
||||
</div>
|
||||
</form>
|
||||
{else}
|
||||
<div class="border rounded mt-5">
|
||||
<p class="text-danger p-2">Vous devez vous connecter pour accéder à cette fonctionnalité</p>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<h3>Description</h3>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Photos behind the scene</h3>
|
||||
<div class="row mb-2">
|
||||
<img>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Other projects</h3>
|
||||
<div class="row mb-2">
|
||||
{foreach $arrProjectToDisplay as $objProject}
|
||||
{include file="../app/views/partials/preview.tpl"}
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section>
|
||||
</body>
|
||||
{/block}
|
||||
|
|
@ -35,6 +35,46 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Images du projet -->
|
||||
<section id="galerie-projet">
|
||||
<h2>Galerie du projet</h2>
|
||||
<div class="row">
|
||||
{foreach $arrImages as $image}
|
||||
|
||||
{* On affiche l'image si elle est approuvée OU si l'utlilisateur possède le projet OU si l'utlilisateur est Modérateur*}
|
||||
{if ($image.image_status == 'approuvé') ||
|
||||
(isset($smarty.session.user) && $smarty.session.user.user_status == 2) ||
|
||||
(isset($smarty.session.user) && $smarty.session.user.user_id == $objProject->getUser_id())}
|
||||
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card {if $image.image_status != 'approuvé'}border-warning shadow-none opacity-75{/if}">
|
||||
|
||||
<img src="{$smarty.env.IMG_PROJECT_PATH}{$image.image_name}" class="card-img-top" alt="{$image.image_alt}">
|
||||
|
||||
{* Visible uniquement par le modérateur *}
|
||||
{if isset($smarty.session.user.user_status) && $smarty.session.user.user_status == 2}
|
||||
<div class="moderator-tools border-top pt-2 mt-2">
|
||||
<div class="d-flex gap-2">
|
||||
<a href="index.php?ctrl=project&action=change_image_status&id_img={$image.image_id}&status=approuvé"
|
||||
class="btn btn-sm btn-success">Valider</a>
|
||||
|
||||
<a href="index.php?ctrl=project&action=delete_image&id_img={$image.image_id}"
|
||||
class="btn btn-sm btn-outline-danger"
|
||||
onclick="return confirm('Supprimer définitivement ?')">Supprimer</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{foreachelse}
|
||||
<p>Aucune image disponible pour ce projet.</p>
|
||||
{/foreach}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Formulaire qui envoie la demande au contrôleur (shareProject) -->
|
||||
<div class="card shadow-sm p-4 mb-5">
|
||||
<form method="post" action="index.php?ctrl=project&action=shareProject">
|
||||
|
|
@ -59,7 +99,7 @@
|
|||
<div class="col-lg-4">
|
||||
<div class="card text-center shadow-sm p-4">
|
||||
<a href="index.php?ctrl=user&action=user&id={$objProject->getUser_id()}" class="text-decoration-none text-dark">
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$objProject->getUser_image()}"
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$objProject->getUser_image() ?? "images.jpg"}"
|
||||
class="rounded-circle mb-3 mx-auto"
|
||||
style="width:100px;height:100px;object-fit:cover;">
|
||||
</a>
|
||||
|
|
@ -67,7 +107,6 @@
|
|||
|
||||
<p class="text-muted small">
|
||||
Publié le {$objProject->getCreation_date()}
|
||||
|
||||
</p>
|
||||
|
||||
<button class="btn btn-primary">Contacter le talent</button>
|
||||
|
|
@ -97,7 +136,6 @@
|
|||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
{/block}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
{block name="title" append} - Rechercher{/block}
|
||||
|
||||
{block name="content"}
|
||||
<section aria-label="Blog">
|
||||
|
|
|
|||
202
views/signup.tpl
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
{extends file="views/layout.tpl"}
|
||||
{block name="title" append} - Inscription{/block}
|
||||
|
||||
{block name="content"}
|
||||
<!-- Page : Inscription -->
|
||||
|
||||
<div class="py-5">
|
||||
|
||||
<!-- Centrage horizontal du formulaire -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-10 col-lg-6">
|
||||
|
||||
<!-- Carte contenant le formulaire d'inscription -->
|
||||
<div class="card shadow-sm border-0 rounded-4 p-4 p-lg-5">
|
||||
|
||||
<!-- Titre principal de la page -->
|
||||
<h1 class="h3 fw-bold mb-1">Inscription</h1>
|
||||
|
||||
<!-- Texte descriptif -->
|
||||
<p class="text-secondary mb-4">
|
||||
Créez votre compte utilisateur.
|
||||
</p>
|
||||
|
||||
<!-- Formulaire d'inscription -->
|
||||
<!-- Les données seront traitées côté serveur en PHP via la méthode POST -->
|
||||
<form method="POST">
|
||||
<div class="row g-3">
|
||||
|
||||
<!-- Champ : prénom de l'utilisateur -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="user_firstname">
|
||||
Prénom *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
id="user_firstname"
|
||||
name="user_firstname"
|
||||
value="{$objUser->getFirstname()|default:''}"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Champ : nom de l'utilisateur -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="user_name">
|
||||
Nom *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
id="user_name"
|
||||
name="user_name"
|
||||
value="{$objUser->getName()|default:''}"
|
||||
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"
|
||||
type="text"
|
||||
id="user_pseudo"
|
||||
name="user_pseudo"
|
||||
value="{$objUser->getPseudo()|default:''}"
|
||||
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"
|
||||
type="email"
|
||||
id="user_mail"
|
||||
name="user_mail"
|
||||
value="{$objUser->getMail()|default:''}"
|
||||
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"
|
||||
type="password"
|
||||
id="user_password"
|
||||
name="user_password"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Champ : confirmer le mot de passe -->
|
||||
<div class="col-12">
|
||||
<label class="form-label" for="pwd_confirm">
|
||||
Confirmer le mot de passe *
|
||||
</label>
|
||||
<input
|
||||
class="form-control"
|
||||
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"
|
||||
value="{$objUser->getPhone()|default:''}"
|
||||
>
|
||||
</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"
|
||||
value="{$objUser->getWork()|default:''}"
|
||||
>
|
||||
</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"
|
||||
value="{$objUser->getLocation()|default:''}"
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Champ optionnel : phrase d'accroche -->
|
||||
<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"
|
||||
value="{$objUser->getDescription()|default:''}"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Bouton de soumission du formulaire -->
|
||||
<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>
|
||||
|
||||
<!-- Lien vers la page de connexion -->
|
||||
<div class="col-12 text-center">
|
||||
<small class="text-secondary">
|
||||
Déjà un compte ?
|
||||
<a class="link-primary" href="index.php?ctrl=user&action=login">
|
||||
Se connecter
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/block}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<section class="user-profile mb-5 mt-5/*vh /*">
|
||||
<div class="row">
|
||||
<div class="col-md-4 text-center">
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$user->getImage()}" alt="Avatar de {$user->getPseudo()}" class="rounded-circle flex-shrink-0 border border-2 border-white"
|
||||
<img src="{$smarty.env.IMG_USER_PATH}{$user->getImage() ?? "images.jpg"}" alt="Avatar de {$user->getPseudo()}" class="rounded-circle flex-shrink-0 border border-2 border-white"
|
||||
style="width: 256px; height: 256px; object-fit: cover; margin-top: 8px;"
|
||||
>
|
||||
</div>
|
||||
|
|
|
|||