diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 898ca90..2156e6d 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -157,6 +157,7 @@ nav { border: 1px solid black; border-radius: 10px; width: 95%; + max-width: calc(128px*0.95); box-shadow: 1px 1px 1px black; } @@ -170,7 +171,7 @@ nav { .tag-unselected { background-color: white; - + } .tag-unselected:hover { background-color: #ffa04d; @@ -306,25 +307,51 @@ ul { .recette-div-info { display: flex; flex-direction: row; + padding: 20px; } .recette-div-liste-info{ - padding: 50px; + padding: 30px; margin: 10px; + width: 100%; + flex:1; +} + +.recette-list-buttons { + display: flex; + flex-direction: row-reverse; +} + +.recette-button { + border: 1px solid black; + border-radius: 10px; + padding : 10px; + box-shadow: 1px 1px 1px black; + background-color: blanchedalmond; +} + +.recette-button:hover{ + background-color: rgb(243, 215, 174); } .recette-liste-info-elem { text-align: left; + padding: 4px; + padding-top: 6px; + padding-bottom: 6px; + color: #535353bd; + border-right: 1px solid #535353bd; + border-left: 1px solid #535353bd; } .recette-liste-info { display: flex; - flex-direction: column; + flex-direction: row; } .recette-liste-tag { display: flex; - flex-direction: row; + flex-wrap: wrap; /*trouvé à l'aide de ChatGPT car je n'arrivais pas à trouver*/ } @@ -373,8 +400,8 @@ ul { .formcont form .form-group input { width: 95%; box-sizing: border-box; - font-size:3vmin; - padding:1vmin; + font-size:3vmin; + padding:1vmin; } @@ -386,7 +413,7 @@ ul { margin: 0 auto; background: #ffa04d; color: black; - font-size: 5vmin; + font-size: 4vmin; border-radius: 7px; box-shadow: 2px 2px 0px #000000; } @@ -400,6 +427,30 @@ ul { box-shadow: 3px 4px 5px #8c8c8c; } +.recette-form-div-desc { + height: 90%; +} + +.recette-form { + height: 100%; + width: 100%; + margin: 10px; + padding: 10px; +} + +.recette-form-group { + display: flex; + flex-direction: column; +} + +#recette-form-div-desc { + height: 400px; +} + +#recette-form-description { + height: 95%; +} + /*Footer et son contenue*/ footer{ padding: 25px; diff --git a/src/Domain/Controller.php b/src/Domain/Controller.php index 4311c0b..0be0ade 100644 --- a/src/Domain/Controller.php +++ b/src/Domain/Controller.php @@ -4,6 +4,9 @@ namespace App\Domain; use App\Http\Route; +/** + * Classe abstraite des controllers qui vont pouvoir permettre de gérer les routes et leur retour. + */ abstract class Controller { /** diff --git a/src/Domain/Ingredients/Ingredient.php b/src/Domain/Ingredients/Ingredient.php index 9fb655e..8a965db 100644 --- a/src/Domain/Ingredients/Ingredient.php +++ b/src/Domain/Ingredients/Ingredient.php @@ -4,15 +4,30 @@ namespace App\Domain\Ingredients; use App\Domain\Model; +/** + * Classe qui va gérer les ingrédients. + */ class Ingredient extends Model { + /** + * Le numéro de l'ingrédient. + * @var int + */ public int $num_ingredient; + + /** + * Le nom de l'ingrédient + * @var string + */ public string $nom_ingredient; + /** + * Retourne le numéro de l'ingrédient. + * @return int + */ public function getID(): int { return $this->num_ingredient; } - } \ No newline at end of file diff --git a/src/Domain/Ingredients/IngredientRepository.php b/src/Domain/Ingredients/IngredientRepository.php index b0f2376..daca14c 100644 --- a/src/Domain/Ingredients/IngredientRepository.php +++ b/src/Domain/Ingredients/IngredientRepository.php @@ -6,15 +6,30 @@ use App\Domain\LinkableInterface; use App\Domain\Recettes\Recette; use App\Domain\Repository; use App\Domain\Model; +use App\Domain\Tags\Tag; use App\Kernel; +/** + * Classe qui va permettre de gérer les requêtes BDD en lien avec les ingrédients. + * Les ingrédients sont liables à d'autres entités comme les Recettes. + */ class IngredientRepository extends Repository implements LinkableInterface { + /** + * Permet d'avoir le nom de l'entité dont dépend ce repo. + * @return string + */ public static function getEntity(): string { return Ingredient::class; } + /** + * La structure de notre table dans la BDD. + * Un champ link_recettes a été ajouté pour donner le nom de la table de lien entre nos recettes. + * + * @return array + */ public static function getStructure(): array { return [ @@ -27,6 +42,19 @@ class IngredientRepository extends Repository implements LinkableInterface { } + /** + * Permet d'obtenir une liste de tous les ingrédients objet Ingreident. + * + * @return Ingredient[]|null + */ + public function getAll(): ?array { + $sqlQuery = "SELECT * FROM {$this->tableName};"; + $results = $this->selectGetAll($sqlQuery); + if( $results === null ) + return null; + return $results; + } + /** * Permet d'obtenir un ingrédient spécifique par son ID. * @@ -49,6 +77,7 @@ class IngredientRepository extends Repository implements LinkableInterface { * @param string $linkingField Le champ qui permet de faire la liaison des ingrédients avec une autre entité. * @param Model $linkedEntity L'autre entité. * + * @see LinkableInterface * @return array|null */ public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array { @@ -64,6 +93,17 @@ class IngredientRepository extends Repository implements LinkableInterface { return $results; } + /** + * Permet d'ajouter un lien entre un ingrédient et une autre entité comme Recette. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $ingredientEntity + * + * @see LinkableInterface + * @return bool + */ public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool { $linkName = 'link_' . $linkedTo; @@ -77,6 +117,17 @@ class IngredientRepository extends Repository implements LinkableInterface { } + /** + * Retire un lien dans la BDD entre un ingrédient et une autre entité. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $ingredientEntity + * + * @see LinkableInterface + * @return bool + */ public function removeLinkBetween(string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool { $linkName = 'link_' . $linkedTo; @@ -88,14 +139,35 @@ class IngredientRepository extends Repository implements LinkableInterface { return $statement->execute(); } + /** + * Ajouter un ingrédient dans la BDD. + * + * @param Model $ingredient + * + * @return bool + */ public function add( Model $ingredient ): bool { return $this->addEntity( $ingredient ); } + /** + * Met à jour un ingrédient dans la BDD. + * + * @param Model $ingredient + * + * @return bool + */ public function update( Model $ingredient ): bool { return $this->updateEntity( $ingredient, 'num_ingredient' ); } + /** + * Supprime un ingrédient de la BDD. + * + * @param Model $ingredient + * + * @return bool + */ public function delete( Model $ingredient ): bool { return $this->deleteEntity( $ingredient, 'num_ingredient' ); } diff --git a/src/Domain/Ingredients/UseIngredientsInterface.php b/src/Domain/Ingredients/UseIngredientsInterface.php index d0163d6..9019473 100644 --- a/src/Domain/Ingredients/UseIngredientsInterface.php +++ b/src/Domain/Ingredients/UseIngredientsInterface.php @@ -4,6 +4,9 @@ namespace App\Domain\Ingredients; use App\Domain\Model; +/** + * Interface utilisée par tous les repository qui sont en lien avec les ingrédients. + */ interface UseIngredientsInterface { /** @@ -12,8 +15,24 @@ interface UseIngredientsInterface { */ public function getAllLinkedIngredients( Model $entity ): ?array; + /** + * Permet d'ajouter un ingrédient en lien avec notre autre entité. + * + * @param Ingredient $ingredient + * @param Model $entity + * + * @return bool + */ public function addAnIngredient( Ingredient $ingredient, Model $entity ): bool; + /** + * Permet de retirer un lien entre un ingrédient et une autre entité. + * + * @param Ingredient $ingredient + * @param Model $entity + * + * @return bool + */ public function removeAnIngredient( Ingredient $ingredient, Model $entity ): bool; } \ No newline at end of file diff --git a/src/Domain/LinkableInterface.php b/src/Domain/LinkableInterface.php index 79d9399..7ba5af9 100644 --- a/src/Domain/LinkableInterface.php +++ b/src/Domain/LinkableInterface.php @@ -2,12 +2,50 @@ namespace App\Domain; +/** + * Interface pour dire qu'un objet peut avoir un lien avec un autre objet par une table. + * Il s'agit d'une interface qui s'utilise sur des repositories de meta-données (Tag, Ingrédients) + * + * Les champs de toutes les méthodes se présentent de la même façon. + * $linkedTo : Champ qui va désigner le nom de la table de liens que vous avez dans getStructure(). + * $linkingField : Champ dans la BDD qui va permettre de lier l'élément courant et l'étranger. + * $linkedEntity : Une instance de l'entité étrangère que l'on veut lier. + */ interface LinkableInterface { + /** + * Permet de récupérer tous les liens entre notre entité implémentée et notre entité étrangère. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * + * @return array|null + */ public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array; + /** + * Permet d'ajouter un lien entre notre entité implémentée et notre entité étrangère. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $entity + * + * @return bool + */ public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $entity ): bool; + /** + * Permet de retirer un lien entre notre entité implémentée et notre entité étrangère. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $entity + * + * @return bool + */ public function removeLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $entity ): bool; } \ No newline at end of file diff --git a/src/Domain/Model.php b/src/Domain/Model.php index fc59f5b..e9caa90 100644 --- a/src/Domain/Model.php +++ b/src/Domain/Model.php @@ -2,6 +2,9 @@ namespace App\Domain; +/** + * Classe abstraite pour gérer l'implémentation des entités de données. + */ abstract class Model { /** diff --git a/src/Domain/Pages/PagesController.php b/src/Domain/Pages/PagesController.php index 3d8612b..9982a09 100644 --- a/src/Domain/Pages/PagesController.php +++ b/src/Domain/Pages/PagesController.php @@ -11,11 +11,14 @@ use App\Infrastructure\View; */ class PagesController extends Controller { + /** + * Définit les routes globales d'acceuil. + * @return array|\App\Http\Route[] + */ public static function defineRoutes(): array { return [ self::Route( routeUrl: '/', routeName: 'home', routeAction: 'index', pageHeadTitle: "Home Page" ), - self::Route( routeUrl: '/test/{int}/', routeName: 'test', routeAction: 'test' ), ]; } @@ -28,8 +31,4 @@ class PagesController extends Controller { return new View( 'home', [ 'ok' => 'bla' ] ); } - public function test( string $id ): void { - echo "Coucou" . $id; - } - } \ No newline at end of file diff --git a/src/Domain/Recettes/Recette.php b/src/Domain/Recettes/Recette.php index c7f44c2..6073250 100644 --- a/src/Domain/Recettes/Recette.php +++ b/src/Domain/Recettes/Recette.php @@ -2,11 +2,15 @@ namespace App\Domain\Recettes; +use App\Domain\Ingredients\Ingredient; use App\Domain\Ingredients\IngredientRepository; use App\Domain\Ingredients\UseIngredientsInterface; use App\Domain\Model; use App\Helpers\Markdown; +/** + * Classe qui va permettre de gérer tous les objets recette. + */ class Recette extends Model { public int $num_recette; @@ -22,13 +26,27 @@ class Recette extends Model { return $this->num_recette; } + /** + * Convertit la description de Markdown à HTML. + * @return string + */ public function getHTMLDescription(): string { return Markdown::convertToHTML( $this->description_recette ); } + /** + * Récupère une liste de tous les ingrédients liés à la recette. + * @return Ingredient[]|null + */ public function getAllLinkedIngredients(): ?array { return new RecetteRepository()->getAllLinkedIngredients( $this ); } + public function getNumberOfIngredients(): int { + + $response = $this->getAllLinkedIngredients(); + return $response !== null ? count( $response ) : 0; + } + } \ No newline at end of file diff --git a/src/Domain/Recettes/RecetteRepository.php b/src/Domain/Recettes/RecetteRepository.php index 10692ba..5806f8b 100644 --- a/src/Domain/Recettes/RecetteRepository.php +++ b/src/Domain/Recettes/RecetteRepository.php @@ -7,8 +7,15 @@ use App\Domain\Ingredients\IngredientRepository; use App\Domain\Ingredients\UseIngredientsInterface; use App\Domain\Model; use App\Domain\Repository; +use App\Domain\Tags\Tag; +use App\Domain\Tags\TagRepository; +use App\Domain\Tags\UseTagsInterface; -class RecetteRepository extends Repository implements UseIngredientsInterface { +/** + * Classe qui permet de faire le lien entre la BDD et le site pour les recettes. + * Les recettes sont en lien avec les ingrédients. + */ +class RecetteRepository extends Repository implements UseIngredientsInterface, UseTagsInterface { public static function getEntity(): string { @@ -26,6 +33,42 @@ class RecetteRepository extends Repository implements UseIngredientsInterface { } + /** + * Permet d'obtenir une liste de toutes les recettes objet Recette. + * + * @return Recette[]|null + */ + public function getAll(): ?array { + $sqlQuery = "SELECT * FROM {$this->tableName};"; + $results = $this->selectGetAll($sqlQuery); + if( $results === null ) + return null; + return $results; + } + + /** + * Permet d'obtenir toutes les recettes paginées. + * Mise par défaut dans l'ordre croissant du titre et avec une pagination de 15 éléments. + * + * @param int $page + * @param int $pagination + * + * @return array|null + */ + public function getAllRecettesBrowse( int $page = 1, int $pagination = 15 ){ + + if( $page <= 0 ) + $page = 1; + + $offset = ( $page - 1 ) * $pagination; + + $sqlQuery = "SELECT * FROM {$this->tableName} ORDER BY titre_recette ASC LIMIT {$pagination} OFFSET {$offset};"; + $results = $this->selectGetAll($sqlQuery); + if( $results === null ) + return null; + return $results; + } + /** * Permet d'avoir une recette par un ID. * @@ -72,6 +115,8 @@ class RecetteRepository extends Repository implements UseIngredientsInterface { { $ingredientRepo = new IngredientRepository(); $response = $ingredientRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity ); + if( $response === null ) + return null; return array_map( function($arr) use($ingredientRepo) { return $ingredientRepo->getByID( $arr['num_ingredient'] ); @@ -81,13 +126,37 @@ class RecetteRepository extends Repository implements UseIngredientsInterface { public function addAnIngredient(Ingredient $ingredient, Model $entity): bool { $ingredientRepo = new IngredientRepository(); - return $ingredientRepo->addLinkBetween( 'recettes', 'num_recette', $ingredient, $entity ); + return $ingredientRepo->addLinkBetween( 'recettes', 'num_recette', $entity, $ingredient ); } public function removeAnIngredient(Ingredient $ingredient, Model $entity): bool { $ingredientRepo = new IngredientRepository(); - return $ingredientRepo->removeLinkBetween( 'recettes', 'num_recette', $ingredient, $entity ); + return $ingredientRepo->removeLinkBetween( 'recettes', 'num_recette', $entity, $ingredient ); + } + + public function getAllLinkedTags(Model $entity): ?array + { + $tagRepo = new TagRepository(); + $response = $tagRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity ); + if( $response === null ) + return null; + + return array_map( function($arr) use($tagRepo) { + return $tagRepo->getByID( $arr['num_tag'] ); + }, $response ); + } + + public function addATag(Tag $tag, Model $entity): bool + { + $tagRepo = new TagRepository(); + return $tagRepo->addLinkBetween( 'recettes', 'num_recette', $entity, $tag ); + } + + public function removeATag(Tag $tag, Model $entity): bool + { + $tagRepo = new TagRepository(); + return $tagRepo->removeLinkBetween( 'recettes', 'num_recette', $entity, $tag ); } } \ No newline at end of file diff --git a/src/Domain/Recettes/RecettesController.php b/src/Domain/Recettes/RecettesController.php index 1ed1dc8..6264eb0 100644 --- a/src/Domain/Recettes/RecettesController.php +++ b/src/Domain/Recettes/RecettesController.php @@ -3,7 +3,10 @@ namespace App\Domain\Recettes; use App\Domain\Controller; +use App\Domain\Ingredients\IngredientRepository; +use App\Domain\Tags\TagRepository; use App\Http\JSONResponse; +use App\Http\Request; use App\Infrastructure\View; class RecettesController extends Controller { @@ -18,7 +21,16 @@ class RecettesController extends Controller { } public function index(): View { - return new View( 'recettes/index', [] ); + + $page = Request::get( 'page' ); + if( $page == null ) + $page = 1; + + return new View( 'recettes/index', [ + 'tagsList' => new TagRepository()->getAll(), + 'ingredientsList' => new IngredientRepository()->getAll(), + 'recettesList' => new RecetteRepository()->getAllRecettesBrowse( $page ), + ] ); } } \ No newline at end of file diff --git a/src/Domain/Repository.php b/src/Domain/Repository.php index 2de7a9a..c6fb738 100644 --- a/src/Domain/Repository.php +++ b/src/Domain/Repository.php @@ -6,6 +6,9 @@ use App\Domain\Recettes\Recette; use App\Kernel; use PDO; +/** + * Classe abstraite avec des méthodes pour pouvoir gérer les liens entre le site et la base de données. + */ abstract class Repository { /** diff --git a/src/Domain/Tags/Tag.php b/src/Domain/Tags/Tag.php new file mode 100644 index 0000000..56f1102 --- /dev/null +++ b/src/Domain/Tags/Tag.php @@ -0,0 +1,33 @@ +num_tag; + } + +} \ No newline at end of file diff --git a/src/Domain/Tags/TagRepository.php b/src/Domain/Tags/TagRepository.php new file mode 100644 index 0000000..e42e1f3 --- /dev/null +++ b/src/Domain/Tags/TagRepository.php @@ -0,0 +1,174 @@ + 'Tag', + 'columns' => [ + 'num_tag', 'nom_tag' + ], + 'link_recettes' => 'Referencetag' + ]; + + } + + /** + * Permet d'obtenir une liste de tous les tags objet Tag. + * + * @return Tag[]|null + */ + public function getAll(): ?array { + $sqlQuery = "SELECT * FROM {$this->tableName};"; + $results = $this->selectGetAll($sqlQuery); + if( $results === null ) + return null; + return $results; + } + + /** + * Permet d'obtenir un tag spécifique par son ID. + * + * @param int $id + * + * @return Tag|null + */ + public function getByID( int $id ): ?Tag { + $sqlQuery = "SELECT * FROM {$this->tableName} WHERE num_tag = {$id}"; + $results = $this->selectGetAll($sqlQuery); + if( $results === null || count( $results ) > 1 ) + return null; + return $results[0]; + } + + /** + * Permet d'obtenir, sous forme de liste, toutes les entrées qui lient des tags. + * + * @param string $linkedTo La table qui permet de faire la liaison des tags avec une autre entité. + * @param string $linkingField Le champ qui permet de faire la liaison des tags avec une autre entité. + * @param Model $linkedEntity L'autre entité. + * + * @see LinkableInterface + * @return array|null + */ + public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array { + + $linkName = 'link_' . $linkedTo; + if( !isset( $this->globalStructure[$linkName])) + return null; + + $sqlQuery = "SELECT * FROM {$this->globalStructure[$linkName]} WHERE {$linkingField} = {$linkedEntity->getId()};"; + $results = $this->selectGetAll($sqlQuery, true); + if( $results === null ) + return null; + return $results; + } + + /** + * Permet d'ajouter un lien entre un tag et une autre entité comme Recette. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $tagEntity + * + * @see LinkableInterface + * @return bool + */ + public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $tagEntity ): bool { + + $linkName = 'link_' . $linkedTo; + if( !isset( $this->globalStructure[$linkName])) + return false; + + $query = "INSERT INTO {$this->globalStructure[$linkName]} ({$linkingField},num_tag) VALUES ({$linkedEntity->getId()}, {$tagEntity->getID()});"; + $statement = Kernel::$DB->pdo->prepare( $query ); + + return $statement->execute(); + + } + + /** + * Retire un lien dans la BDD entre un tag et une autre entité. + * + * @param string $linkedTo + * @param string $linkingField + * @param Model $linkedEntity + * @param Model $tagEntity + * + * @see LinkableInterface + * @return bool + */ + public function removeLinkBetween(string $linkedTo, string $linkingField, Model $linkedEntity, Model $tagEntity ): bool + { + $linkName = 'link_' . $linkedTo; + if( !isset( $this->globalStructure[$linkName])) + return false; + + $query = "DELETE FROM {$this->globalStructure[$linkName]} WHERE {$linkingField} = {$linkedEntity->getId()} AND num_tag = {$tagEntity->getId()};"; + $statement = Kernel::$DB->pdo->prepare( $query ); + return $statement->execute(); + } + + /** + * Ajouter un tag dans la BDD. + * + * @param Model $ingredient + * + * @return bool + */ + public function add( Model $tag ): bool { + return $this->addEntity( $tag ); + } + + /** + * Met à jour un tag dans la BDD. + * + * @param Model $tag + * + * @return bool + */ + public function update( Model $tag ): bool { + return $this->updateEntity( $tag, 'num_tag' ); + } + + /** + * Supprime un tag de la BDD. + * + * @param Model $tag + * + * @return bool + */ + public function delete( Model $tag ): bool { + return $this->deleteEntity( $tag, 'num_tag' ); + } + +} \ No newline at end of file diff --git a/src/Domain/Tags/UseTagsInterface.php b/src/Domain/Tags/UseTagsInterface.php new file mode 100644 index 0000000..90a6fa2 --- /dev/null +++ b/src/Domain/Tags/UseTagsInterface.php @@ -0,0 +1,38 @@ +routeUrl); - return rtrim( Kernel::$configs['general']['website_url'] . $routeUrl, '/' ); + return rtrim( rtrim( Kernel::$configs['general']['website_url'], '/' ) . $routeUrl, '/' ); } } diff --git a/views/partials/header.php b/views/partials/header.php index 2848cdd..292c5c5 100644 --- a/views/partials/header.php +++ b/views/partials/header.php @@ -16,10 +16,11 @@