Finish tag et commencer à ajouter les template.s
This commit is contained in:
@@ -157,6 +157,7 @@ nav {
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
|
max-width: calc(128px*0.95);
|
||||||
box-shadow: 1px 1px 1px black;
|
box-shadow: 1px 1px 1px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,25 +307,51 @@ ul {
|
|||||||
.recette-div-info {
|
.recette-div-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recette-div-liste-info{
|
.recette-div-liste-info{
|
||||||
padding: 50px;
|
padding: 30px;
|
||||||
margin: 10px;
|
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 {
|
.recette-liste-info-elem {
|
||||||
text-align: left;
|
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 {
|
.recette-liste-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recette-liste-tag {
|
.recette-liste-tag {
|
||||||
display: flex;
|
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 {
|
.formcont form .form-group input {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size:3vmin;
|
font-size:3vmin;
|
||||||
padding:1vmin;
|
padding:1vmin;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +413,7 @@ ul {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: #ffa04d;
|
background: #ffa04d;
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 5vmin;
|
font-size: 4vmin;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
box-shadow: 2px 2px 0px #000000;
|
box-shadow: 2px 2px 0px #000000;
|
||||||
}
|
}
|
||||||
@@ -400,6 +427,30 @@ ul {
|
|||||||
box-shadow: 3px 4px 5px #8c8c8c;
|
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 et son contenue*/
|
||||||
footer{
|
footer{
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ namespace App\Domain;
|
|||||||
|
|
||||||
use App\Http\Route;
|
use App\Http\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe abstraite des controllers qui vont pouvoir permettre de gérer les routes et leur retour.
|
||||||
|
*/
|
||||||
abstract class Controller {
|
abstract class Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,15 +4,30 @@ namespace App\Domain\Ingredients;
|
|||||||
|
|
||||||
use App\Domain\Model;
|
use App\Domain\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe qui va gérer les ingrédients.
|
||||||
|
*/
|
||||||
class Ingredient extends Model {
|
class Ingredient extends Model {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le numéro de l'ingrédient.
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
public int $num_ingredient;
|
public int $num_ingredient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le nom de l'ingrédient
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public string $nom_ingredient;
|
public string $nom_ingredient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le numéro de l'ingrédient.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getID(): int
|
public function getID(): int
|
||||||
{
|
{
|
||||||
return $this->num_ingredient;
|
return $this->num_ingredient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,30 @@ use App\Domain\LinkableInterface;
|
|||||||
use App\Domain\Recettes\Recette;
|
use App\Domain\Recettes\Recette;
|
||||||
use App\Domain\Repository;
|
use App\Domain\Repository;
|
||||||
use App\Domain\Model;
|
use App\Domain\Model;
|
||||||
|
use App\Domain\Tags\Tag;
|
||||||
use App\Kernel;
|
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 {
|
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
|
public static function getEntity(): string
|
||||||
{
|
{
|
||||||
return Ingredient::class;
|
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
|
public static function getStructure(): array
|
||||||
{
|
{
|
||||||
return [
|
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.
|
* 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 string $linkingField Le champ qui permet de faire la liaison des ingrédients avec une autre entité.
|
||||||
* @param Model $linkedEntity L'autre entité.
|
* @param Model $linkedEntity L'autre entité.
|
||||||
*
|
*
|
||||||
|
* @see LinkableInterface
|
||||||
* @return array|null
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array {
|
public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array {
|
||||||
@@ -64,6 +93,17 @@ class IngredientRepository extends Repository implements LinkableInterface {
|
|||||||
return $results;
|
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 {
|
public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool {
|
||||||
|
|
||||||
$linkName = 'link_' . $linkedTo;
|
$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
|
public function removeLinkBetween(string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool
|
||||||
{
|
{
|
||||||
$linkName = 'link_' . $linkedTo;
|
$linkName = 'link_' . $linkedTo;
|
||||||
@@ -88,14 +139,35 @@ class IngredientRepository extends Repository implements LinkableInterface {
|
|||||||
return $statement->execute();
|
return $statement->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajouter un ingrédient dans la BDD.
|
||||||
|
*
|
||||||
|
* @param Model $ingredient
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function add( Model $ingredient ): bool {
|
public function add( Model $ingredient ): bool {
|
||||||
return $this->addEntity( $ingredient );
|
return $this->addEntity( $ingredient );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met à jour un ingrédient dans la BDD.
|
||||||
|
*
|
||||||
|
* @param Model $ingredient
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function update( Model $ingredient ): bool {
|
public function update( Model $ingredient ): bool {
|
||||||
return $this->updateEntity( $ingredient, 'num_ingredient' );
|
return $this->updateEntity( $ingredient, 'num_ingredient' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supprime un ingrédient de la BDD.
|
||||||
|
*
|
||||||
|
* @param Model $ingredient
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function delete( Model $ingredient ): bool {
|
public function delete( Model $ingredient ): bool {
|
||||||
return $this->deleteEntity( $ingredient, 'num_ingredient' );
|
return $this->deleteEntity( $ingredient, 'num_ingredient' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ namespace App\Domain\Ingredients;
|
|||||||
|
|
||||||
use App\Domain\Model;
|
use App\Domain\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface utilisée par tous les repository qui sont en lien avec les ingrédients.
|
||||||
|
*/
|
||||||
interface UseIngredientsInterface {
|
interface UseIngredientsInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,8 +15,24 @@ interface UseIngredientsInterface {
|
|||||||
*/
|
*/
|
||||||
public function getAllLinkedIngredients( Model $entity ): ?array;
|
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;
|
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;
|
public function removeAnIngredient( Ingredient $ingredient, Model $entity ): bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,50 @@
|
|||||||
|
|
||||||
namespace App\Domain;
|
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 {
|
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;
|
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;
|
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;
|
public function removeLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $entity ): bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Domain;
|
namespace App\Domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe abstraite pour gérer l'implémentation des entités de données.
|
||||||
|
*/
|
||||||
abstract class Model {
|
abstract class Model {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,11 +11,14 @@ use App\Infrastructure\View;
|
|||||||
*/
|
*/
|
||||||
class PagesController extends Controller {
|
class PagesController extends Controller {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit les routes globales d'acceuil.
|
||||||
|
* @return array|\App\Http\Route[]
|
||||||
|
*/
|
||||||
public static function defineRoutes(): array
|
public static function defineRoutes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
self::Route( routeUrl: '/', routeName: 'home', routeAction: 'index', pageHeadTitle: "Home Page" ),
|
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' ] );
|
return new View( 'home', [ 'ok' => 'bla' ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test( string $id ): void {
|
|
||||||
echo "Coucou" . $id;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Domain\Recettes;
|
namespace App\Domain\Recettes;
|
||||||
|
|
||||||
|
use App\Domain\Ingredients\Ingredient;
|
||||||
use App\Domain\Ingredients\IngredientRepository;
|
use App\Domain\Ingredients\IngredientRepository;
|
||||||
use App\Domain\Ingredients\UseIngredientsInterface;
|
use App\Domain\Ingredients\UseIngredientsInterface;
|
||||||
use App\Domain\Model;
|
use App\Domain\Model;
|
||||||
use App\Helpers\Markdown;
|
use App\Helpers\Markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe qui va permettre de gérer tous les objets recette.
|
||||||
|
*/
|
||||||
class Recette extends Model {
|
class Recette extends Model {
|
||||||
|
|
||||||
public int $num_recette;
|
public int $num_recette;
|
||||||
@@ -22,13 +26,27 @@ class Recette extends Model {
|
|||||||
return $this->num_recette;
|
return $this->num_recette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convertit la description de Markdown à HTML.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getHTMLDescription(): string {
|
public function getHTMLDescription(): string {
|
||||||
return Markdown::convertToHTML( $this->description_recette );
|
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
|
public function getAllLinkedIngredients(): ?array
|
||||||
{
|
{
|
||||||
return new RecetteRepository()->getAllLinkedIngredients( $this );
|
return new RecetteRepository()->getAllLinkedIngredients( $this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNumberOfIngredients(): int {
|
||||||
|
|
||||||
|
$response = $this->getAllLinkedIngredients();
|
||||||
|
return $response !== null ? count( $response ) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,15 @@ use App\Domain\Ingredients\IngredientRepository;
|
|||||||
use App\Domain\Ingredients\UseIngredientsInterface;
|
use App\Domain\Ingredients\UseIngredientsInterface;
|
||||||
use App\Domain\Model;
|
use App\Domain\Model;
|
||||||
use App\Domain\Repository;
|
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
|
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.
|
* Permet d'avoir une recette par un ID.
|
||||||
*
|
*
|
||||||
@@ -72,6 +115,8 @@ class RecetteRepository extends Repository implements UseIngredientsInterface {
|
|||||||
{
|
{
|
||||||
$ingredientRepo = new IngredientRepository();
|
$ingredientRepo = new IngredientRepository();
|
||||||
$response = $ingredientRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity );
|
$response = $ingredientRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity );
|
||||||
|
if( $response === null )
|
||||||
|
return null;
|
||||||
|
|
||||||
return array_map( function($arr) use($ingredientRepo) {
|
return array_map( function($arr) use($ingredientRepo) {
|
||||||
return $ingredientRepo->getByID( $arr['num_ingredient'] );
|
return $ingredientRepo->getByID( $arr['num_ingredient'] );
|
||||||
@@ -81,13 +126,37 @@ class RecetteRepository extends Repository implements UseIngredientsInterface {
|
|||||||
public function addAnIngredient(Ingredient $ingredient, Model $entity): bool
|
public function addAnIngredient(Ingredient $ingredient, Model $entity): bool
|
||||||
{
|
{
|
||||||
$ingredientRepo = new IngredientRepository();
|
$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
|
public function removeAnIngredient(Ingredient $ingredient, Model $entity): bool
|
||||||
{
|
{
|
||||||
$ingredientRepo = new IngredientRepository();
|
$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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,10 @@
|
|||||||
namespace App\Domain\Recettes;
|
namespace App\Domain\Recettes;
|
||||||
|
|
||||||
use App\Domain\Controller;
|
use App\Domain\Controller;
|
||||||
|
use App\Domain\Ingredients\IngredientRepository;
|
||||||
|
use App\Domain\Tags\TagRepository;
|
||||||
use App\Http\JSONResponse;
|
use App\Http\JSONResponse;
|
||||||
|
use App\Http\Request;
|
||||||
use App\Infrastructure\View;
|
use App\Infrastructure\View;
|
||||||
|
|
||||||
class RecettesController extends Controller {
|
class RecettesController extends Controller {
|
||||||
@@ -18,7 +21,16 @@ class RecettesController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index(): View {
|
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 ),
|
||||||
|
] );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,9 @@ use App\Domain\Recettes\Recette;
|
|||||||
use App\Kernel;
|
use App\Kernel;
|
||||||
use PDO;
|
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 {
|
abstract class Repository {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
33
src/Domain/Tags/Tag.php
Normal file
33
src/Domain/Tags/Tag.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Tags;
|
||||||
|
|
||||||
|
use App\Domain\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe qui va gérer les tags.
|
||||||
|
*/
|
||||||
|
class Tag extends Model {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le numéro du tag.
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public int $num_tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Le nom du tag
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $nom_tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le numéro du tag.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getID(): int
|
||||||
|
{
|
||||||
|
return $this->num_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
174
src/Domain/Tags/TagRepository.php
Normal file
174
src/Domain/Tags/TagRepository.php
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Tags;
|
||||||
|
|
||||||
|
use App\Domain\LinkableInterface;
|
||||||
|
use App\Domain\Recettes\Recette;
|
||||||
|
use App\Domain\Repository;
|
||||||
|
use App\Domain\Model;
|
||||||
|
use App\Kernel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe qui va permettre de gérer les requêtes BDD en lien avec les tags.
|
||||||
|
* Les tags sont liables à d'autres entités comme les Recettes.
|
||||||
|
*/
|
||||||
|
class TagRepository 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 Tag::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 [
|
||||||
|
'table' => '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' );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
38
src/Domain/Tags/UseTagsInterface.php
Normal file
38
src/Domain/Tags/UseTagsInterface.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Tags;
|
||||||
|
|
||||||
|
use App\Domain\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface utilisée par tous les repository qui sont en lien avec les tags.
|
||||||
|
*/
|
||||||
|
interface UseTagsInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de récupérer tous les tags liés à ce Modèle.
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getAllLinkedTags( Model $entity ): ?array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet d'ajouter un tag en lien avec notre autre entité.
|
||||||
|
*
|
||||||
|
* @param Tag $tag
|
||||||
|
* @param Model $entity
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function addATag( Tag $tag, Model $entity ): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de retirer un lien entre un tag et une autre entité.
|
||||||
|
*
|
||||||
|
* @param Tag $tag
|
||||||
|
* @param Model $entity
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function removeATag( Tag $tag, Model $entity ): bool;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ final class Router {
|
|||||||
*/
|
*/
|
||||||
public static function routeTo(): void {
|
public static function routeTo(): void {
|
||||||
|
|
||||||
self::$clientRouteString = $_SERVER['REQUEST_URI'];
|
self::$clientRouteString = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||||
|
|
||||||
self::$controllers = self::fetchControllers();
|
self::$controllers = self::fetchControllers();
|
||||||
self::$routes = self::fetchRoutes();
|
self::$routes = self::fetchRoutes();
|
||||||
@@ -185,7 +185,7 @@ final class Router {
|
|||||||
return $args[$i++] ?? "";
|
return $args[$i++] ?? "";
|
||||||
}, $route->routeUrl);
|
}, $route->routeUrl);
|
||||||
|
|
||||||
return rtrim( Kernel::$configs['general']['website_url'] . $routeUrl, '/' );
|
return rtrim( rtrim( Kernel::$configs['general']['website_url'], '/' ) . $routeUrl, '/' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="nav-list">
|
<ul class="nav-list">
|
||||||
<li><a id="google" class="nav-element" href="google.com">Google</a></li>
|
<li><a id="google" class="nav-element" href="<?php V::routeUrl( 'home'); ?>">Acceuil</a></li>
|
||||||
<li><a id="unTest" class="nav-element" href="bing.com">Bing</a></li>
|
<li><a id="unTest" class="nav-element" href="<?php V::routeUrl( 'recettes->index'); ?>">Liste des recettes</a></li>
|
||||||
<?php if( \App\Helpers\Authentification::isLoggedIn() ): ?>
|
<?php if( \App\Helpers\Authentification::isLoggedIn() ): ?>
|
||||||
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'logout'); ?>">Logout</a></li>
|
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'logout'); ?>">Logout</a></li>
|
||||||
|
<li><a id="addBouton" class="nav-element" href="<?php V::routeUrl( 'recettes->create'); ?>">Ajouter une Recette</a></li>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'login'); ?>">Login</a></li>
|
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'login'); ?>">Login</a></li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
39
views/partials/tag-sidebar.php
Normal file
39
views/partials/tag-sidebar.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php use App\Infrastructure\View as V; ?>
|
||||||
|
|
||||||
|
<div class="sidebar">
|
||||||
|
<div class="tag-cont">
|
||||||
|
<h4>Tag</h4>
|
||||||
|
<div class="tag-selected-div">
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<form class="sidebar-search" action="none">
|
||||||
|
<input type="text" class="search-form search-form-tag" name="search-tag" placeholder="Rechercher..." >
|
||||||
|
</form>
|
||||||
|
<div class="tag-unselected-div">
|
||||||
|
<ul>
|
||||||
|
<?php foreach( V::arg( 'tagsList') as $tag ): ?>
|
||||||
|
<li class="tag tag-unselected" onclick="test()"><?php echo $tag->nom_tag; ?></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr id="hr">
|
||||||
|
<div class="ingr-cont">
|
||||||
|
<h4>Ingrédient</h4>
|
||||||
|
<div class="tag-selected-div">
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<form class="sidebar-search" action="none">
|
||||||
|
<input type="text" class="search-form search-form-tag" name="search-ingr" placeholder="Rechercher..." >
|
||||||
|
</form>
|
||||||
|
<div class="tag-unselected-div">
|
||||||
|
<ul>
|
||||||
|
<?php foreach( V::arg( 'ingredientsList') as $tag ): ?>
|
||||||
|
<li class="tag tag-unselected" onclick="test()"><?php echo $tag->nom_ingredient; ?></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
<?php use App\Infrastructure\View as V; ?>
|
<?php use App\Infrastructure\View as V; ?>
|
||||||
|
|
||||||
<div class="sidebar"> une sidebar</div>
|
<?php V::partial( 'tag-sidebar' ); ?>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="recettes">
|
<div class="recettes">
|
||||||
<a href="recette-en-dur.php">
|
<?php if( V::arg( 'recettesList' ) != null ) foreach( V::arg( 'recettesList' ) as $recette ): ?>
|
||||||
<div class="recette-icone">
|
<a class="recette-icone" href="<?php V::routeUrl( 'recettes->show', $recette->slug ); ?>">
|
||||||
<img class="recette-preview-image" src="random-recette.jpg">
|
<img class="recette-preview-image" src="random-recette.jpg">
|
||||||
</div>
|
<div class="recette-icone-content">
|
||||||
</a>
|
<h3><?php echo $recette->titre_recette; ?></h3>
|
||||||
<div class="recette-icone"> 2 </div>
|
<ul>
|
||||||
<div class="recette-icone"> 3 </div>
|
<li>Temps de préparation : <?php echo $recette->temps_de_preparation; ?></li>
|
||||||
<div class="recette-icone"> 4 </div>
|
<li>Nombre d'ingrédients : <?php echo $recette->getNumberOfIngredients(); ?></li>
|
||||||
<div class="recette-icone"> 5 </div>
|
</ul>
|
||||||
<div class="recette-icone"> 6 </div>
|
</div>
|
||||||
<div class="recette-icone"> 7 </div>
|
</a>
|
||||||
<div class="recette-icone"> 8 </div>
|
<?php endforeach; ?>
|
||||||
<div class="recette-icone"> 9 </div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user