diff options
| author | polo <ordipolo@gmx.fr> | 2025-10-24 02:27:19 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2025-10-24 02:27:19 +0200 |
| commit | 5311271ae590460b986e3e09edcdc665b73710ca (patch) | |
| tree | f31f6b9602d1607e838a7a4bfe320db9c8d44bb4 /src/model | |
| parent | f9a9bf1ae4fac9317fd71f0bcb207544b000e6f1 (diff) | |
| download | cms-5311271ae590460b986e3e09edcdc665b73710ca.zip | |
entité pour table intermédiaire à 3 champs entre NodeData et Asset, table Asset repensée
Diffstat (limited to 'src/model')
| -rw-r--r-- | src/model/Model.php | 11 | ||||
| -rw-r--r-- | src/model/entities/Asset.php | 63 | ||||
| -rw-r--r-- | src/model/entities/Image.php | 3 | ||||
| -rw-r--r-- | src/model/entities/NodeData.php | 69 | ||||
| -rw-r--r-- | src/model/entities/NodeDataAsset.php | 55 |
5 files changed, 140 insertions, 61 deletions
diff --git a/src/model/Model.php b/src/model/Model.php index 16061e7..68c4c08 100644 --- a/src/model/Model.php +++ b/src/model/Model.php | |||
| @@ -203,6 +203,17 @@ class Model | |||
| 203 | return true; | 203 | return true; |
| 204 | } | 204 | } |
| 205 | } | 205 | } |
| 206 | public function getWhatever(string $class, string $field, string $value): array | ||
| 207 | { | ||
| 208 | // penser au entityManager "repository" | ||
| 209 | $queryBuilder = $this->entityManager->createQueryBuilder(); | ||
| 210 | $queryBuilder | ||
| 211 | ->select('n') | ||
| 212 | ->from($class, 'n') | ||
| 213 | ->where("n.$field = :value") | ||
| 214 | ->setParameter('value', $value); | ||
| 215 | return $queryBuilder->getQuery()->getResult(); | ||
| 216 | } | ||
| 206 | 217 | ||
| 207 | // récupération d'un article pour modification | 218 | // récupération d'un article pour modification |
| 208 | public function makeArticleNode(string $id = '', bool $get_section = false): bool | 219 | public function makeArticleNode(string $id = '', bool $get_section = false): bool |
diff --git a/src/model/entities/Asset.php b/src/model/entities/Asset.php index e359e21..5400db4 100644 --- a/src/model/entities/Asset.php +++ b/src/model/entities/Asset.php | |||
| @@ -6,6 +6,7 @@ declare(strict_types=1); | |||
| 6 | namespace App\Entity; | 6 | namespace App\Entity; |
| 7 | 7 | ||
| 8 | use Doctrine\ORM\Mapping as ORM; | 8 | use Doctrine\ORM\Mapping as ORM; |
| 9 | use Doctrine\Common\Collections\Collection; | ||
| 9 | 10 | ||
| 10 | #[ORM\Entity] | 11 | #[ORM\Entity] |
| 11 | #[ORM\Table(name: TABLE_PREFIX . "asset")] | 12 | #[ORM\Table(name: TABLE_PREFIX . "asset")] |
| @@ -13,71 +14,55 @@ class Asset | |||
| 13 | { | 14 | { |
| 14 | const PATH = 'assets/'; | 15 | const PATH = 'assets/'; |
| 15 | const USER_PATH = 'user_data/assets/'; | 16 | const USER_PATH = 'user_data/assets/'; |
| 17 | // choisir un répertoire du genre /var/www/html/uploads/? ou au moins hors de /src? j'en sais rien | ||
| 16 | 18 | ||
| 17 | #[ORM\Id] | 19 | #[ORM\Id] |
| 18 | #[ORM\GeneratedValue] | 20 | #[ORM\GeneratedValue] |
| 19 | #[ORM\Column(type: "integer")] | 21 | #[ORM\Column(type: "integer")] |
| 20 | private int $id_asset; | 22 | private int $id_asset; |
| 21 | 23 | ||
| 22 | #[ORM\Column(type: "string", length: 255, unique: true)] // nom d'image UNIQUE | 24 | #[ORM\Column(type: "string", length: 255)] // nom de fichier modifié avec uniqid (fichiers différents de même nom) |
| 23 | private string $file_name; | 25 | private string $file_name; |
| 24 | 26 | ||
| 25 | // choisir un répertoire du genre /var/www/html/uploads/, au moins hors de /src | ||
| 26 | #[ORM\Column(type: "string", length: 255, unique: true, nullable: true)] | ||
| 27 | private ?string $file_path; | ||
| 28 | |||
| 29 | #[ORM\Column(type: "string", length: 255, nullable: true)] | 27 | #[ORM\Column(type: "string", length: 255, nullable: true)] |
| 30 | private string $mime_type; // image/jpeg, image/png, etc | 28 | private string $mime_type; // image/jpeg, image/png, etc |
| 31 | 29 | ||
| 32 | #[ORM\Column(type: "string", length: 255, nullable: true)] | 30 | #[ORM\Column(type: "string", length: 64, unique: true)] // doctrine n'a pas d'équivalent au type CHAR des BDD (on voulait CHAR(64)), c'est pas grave! |
| 33 | private string $alt; // texte alternatif | 31 | private string $hash; // pour détecter deux fichiers identiques, même si leurs noms et les métadonnées changent |
| 34 | |||
| 35 | // autre champs optionnels: file_size, date (default current timestamp) | ||
| 36 | |||
| 37 | /* étapes au téléchargement: | ||
| 38 | => Validation du type de fichier : On vérifie que le fichier est bien une image en utilisant le type MIME. On peut aussi vérifier la taille du fichier. | ||
| 39 | => Création d'un répertoire structuré : On génère un chemin dynamique basé sur la date (uploads/2024/12/24/) pour organiser les images. | ||
| 40 | => Génération d'un nom de fichier unique : On utilise uniqid() pour générer un nom unique et éviter les conflits de nom. | ||
| 41 | => Déplacement du fichier sur le serveur : Le fichier est déplacé depuis son emplacement temporaire vers le répertoire uploads/. | ||
| 42 | => Enregistrement dans la base de données : On enregistre les informations de l'image dans la base de données. */ | ||
| 43 | 32 | ||
| 44 | #[ORM\ManyToMany(targetEntity: NodeData::class, mappedBy: "assets")] | 33 | #[ORM\OneToMany(mappedBy: 'asset', targetEntity: NodeDataAsset::class)] |
| 45 | private $node_data; | 34 | private Collection $nda_collection; |
| 46 | 35 | ||
| 47 | public function __construct(string $name, ?string $path, string $mime_type, string $alt) | 36 | public function __construct(string $name, string $mime_type, string $hash) |
| 48 | { | 37 | { |
| 49 | $this->file_name = $name; | 38 | $this->file_name = $name; |
| 50 | $this->file_path = $path; | ||
| 51 | $this->mime_type = $mime_type; | 39 | $this->mime_type = $mime_type; |
| 52 | $this->alt = $alt; | 40 | $this->hash = $hash; |
| 53 | } | 41 | } |
| 54 | 42 | ||
| 55 | public function getFileName(): string | 43 | public function getFileName(): string |
| 56 | { | 44 | { |
| 57 | return $this->file_name; | 45 | return $this->file_name; |
| 58 | } | 46 | } |
| 59 | public function getFilePath(): string | 47 | public function setFileName(string $name): void |
| 60 | { | 48 | { |
| 61 | return $this->file_path; | 49 | $this->file_name = $name; |
| 62 | } | 50 | } |
| 63 | public function getAlt(): string | 51 | public function getMimeType(): string |
| 64 | { | 52 | { |
| 65 | return $this->alt; | 53 | return $this->mime_type; |
| 66 | } | 54 | } |
| 67 | 55 | public function setMimeType(string $mime_type): void | |
| 68 | |||
| 69 | // pour ViewBuilderController? | ||
| 70 | /*public function displayImage($imageId): void | ||
| 71 | { | 56 | { |
| 72 | //$imageId = 1; // Exemple d'ID d'image | 57 | $this->mime_type = $mime_type; |
| 73 | $stmt = $pdo->prepare("SELECT file_path FROM images WHERE id = ?"); | 58 | } |
| 74 | $stmt->execute([$imageId]); | 59 | public function getHash(): string |
| 75 | $image = $stmt->fetch(); | 60 | { |
| 61 | return $this->hash; | ||
| 62 | } | ||
| 76 | 63 | ||
| 77 | if ($image) { | 64 | public function getNodeDataAssets(): Collection |
| 78 | echo "<img src='" . $image['file_path'] . "' alt='Image'>"; | 65 | { |
| 79 | } else { | 66 | return $this->nda_collection; |
| 80 | echo "Image non trouvée."; | 67 | } |
| 81 | } | ||
| 82 | }*/ | ||
| 83 | } | 68 | } |
diff --git a/src/model/entities/Image.php b/src/model/entities/Image.php index e867a5f..2ee379a 100644 --- a/src/model/entities/Image.php +++ b/src/model/entities/Image.php | |||
| @@ -5,6 +5,7 @@ declare(strict_types=1); | |||
| 5 | 5 | ||
| 6 | namespace App\Entity; | 6 | namespace App\Entity; |
| 7 | 7 | ||
| 8 | use Doctrine\Common\Collections\Collection; | ||
| 8 | use Doctrine\ORM\Mapping as ORM; | 9 | use Doctrine\ORM\Mapping as ORM; |
| 9 | 10 | ||
| 10 | #[ORM\Entity] | 11 | #[ORM\Entity] |
| @@ -42,7 +43,7 @@ class Image | |||
| 42 | => Enregistrement dans la base de données : On enregistre les informations de l'image dans la base de données. */ | 43 | => Enregistrement dans la base de données : On enregistre les informations de l'image dans la base de données. */ |
| 43 | 44 | ||
| 44 | #[ORM\ManyToMany(targetEntity: Article::class, mappedBy: "images")] | 45 | #[ORM\ManyToMany(targetEntity: Article::class, mappedBy: "images")] |
| 45 | private $article; | 46 | private Collection $article; |
| 46 | 47 | ||
| 47 | public function __construct(string $name, ?string $path, ?string $path_mini, string $mime_type, string $alt) | 48 | public function __construct(string $name, ?string $path, ?string $path_mini, string $mime_type, string $alt) |
| 48 | { | 49 | { |
diff --git a/src/model/entities/NodeData.php b/src/model/entities/NodeData.php index 9db866e..47e7208 100644 --- a/src/model/entities/NodeData.php +++ b/src/model/entities/NodeData.php | |||
| @@ -39,21 +39,16 @@ class NodeData | |||
| 39 | #[ORM\Column(type: "integer", nullable: true)] | 39 | #[ORM\Column(type: "integer", nullable: true)] |
| 40 | private ?int $pagination_limit = null; // pour les post_block et news_block | 40 | private ?int $pagination_limit = null; // pour les post_block et news_block |
| 41 | 41 | ||
| 42 | #[ORM\ManyToMany(targetEntity: Asset::class, inversedBy: "node_data")] // cascade: ['remove'] = très dangereux! | 42 | #[ORM\OneToMany(mappedBy: 'node_data', targetEntity: NodeDataAsset::class, cascade: ['persist', 'remove'])] |
| 43 | #[ORM\JoinTable( | 43 | private Collection $nda_collection; |
| 44 | name: TABLE_PREFIX . "nodedata_asset", | ||
| 45 | joinColumns: [new ORM\JoinColumn(name: "node_data_id", referencedColumnName: "id_node_data", onDelete: "CASCADE")], // onDelete: "CASCADE": très utile | ||
| 46 | inverseJoinColumns: [new ORM\JoinColumn(name: "asset_id", referencedColumnName: "id_asset", onDelete: "CASCADE")] | ||
| 47 | )] | ||
| 48 | private Collection $assets; | ||
| 49 | 44 | ||
| 50 | private int $nb_pages = 1; | 45 | private int $nb_pages = 1; |
| 51 | 46 | ||
| 52 | public function __construct(array $data, Node $node, Collection $assets = new ArrayCollection, ?string $presentation = null, ?bool $chrono_order = null) | 47 | public function __construct(array $data, Node $node, Collection $nda_collection = new ArrayCollection, ?string $presentation = null, ?bool $chrono_order = null) |
| 53 | { | 48 | { |
| 54 | $this->data = $data; | 49 | $this->data = $data; |
| 55 | $this->node = $node; | 50 | $this->node = $node; |
| 56 | $this->assets = $assets; | 51 | $this->nda_collection = $nda_collection; |
| 57 | if(!empty($presentation) && $presentation === 'grid'){ | 52 | if(!empty($presentation) && $presentation === 'grid'){ |
| 58 | $this->grid_cols_min_width = 250; | 53 | $this->grid_cols_min_width = 250; |
| 59 | } | 54 | } |
| @@ -132,22 +127,54 @@ class NodeData | |||
| 132 | { | 127 | { |
| 133 | $this->node = $node; | 128 | $this->node = $node; |
| 134 | }*/ | 129 | }*/ |
| 135 | public function getAssets(): Collection | 130 | |
| 131 | |||
| 132 | public function getNodeDataAssets(): Collection | ||
| 136 | { | 133 | { |
| 137 | return $this->assets; | 134 | return $this->nda_collection; |
| 138 | } | 135 | } |
| 139 | public function addAsset(Asset $asset): void | 136 | public function getNodeDataAssetByRole(string $role): ?NodeDataAsset |
| 140 | { | 137 | { |
| 141 | if(!$this->assets->contains($asset)){ | 138 | foreach($this->nda_collection as $nda){ |
| 142 | $this->assets->add($asset); | 139 | if($nda->getRole() === $role){ |
| 143 | //$asset->addNodeData($this); // autre sens | 140 | return $nda; |
| 141 | } | ||
| 144 | } | 142 | } |
| 143 | return null; | ||
| 145 | } | 144 | } |
| 146 | public function removeAsset(Asset $asset): void | 145 | public function getAssetByRole(string $role): ?Asset |
| 147 | { | 146 | { |
| 148 | $this->assets->removeElement($asset); | 147 | $nda = $this->getNodeDataAssetByRole($role); |
| 149 | /*if($this->assets->removeElement($asset)){ // autre sens | 148 | if($nda === null){ |
| 150 | $asset->removeNodeData($this); | 149 | return null; |
| 151 | }*/ | 150 | } |
| 151 | return $nda->getAsset() ?? null; | ||
| 152 | } | 152 | } |
| 153 | } | 153 | /*public function addNodeDataAsset(NodeDataAsset $nda): self |
| 154 | { | ||
| 155 | if(!$this->nda_collection->contains($nda)){ // sécurité contrainte UNIQUE | ||
| 156 | $this->nda_collection->add($nda); | ||
| 157 | } | ||
| 158 | return $this; | ||
| 159 | }*/ | ||
| 160 | /*public function removeNodeDataAsset(NodeDataAsset $nda): self // inutile on peut faire: $node_data->getNodeDataAssets()->removeElement($nda); | ||
| 161 | { | ||
| 162 | $this->nda_collection->removeElement($nda); | ||
| 163 | // pas de synchro dans NodeDataAsset, les champs de cette table ne sont pas nullables | ||
| 164 | return $this; | ||
| 165 | }*/ | ||
| 166 | |||
| 167 | // LE setter, sélectionne l'asset à utiliser en remplaçant l'entrée dans NodeDataAsset en fonction du rôle | ||
| 168 | // à mettre théoriquement dans une classe metier dans "service" | ||
| 169 | /*public function replaceAssetForRole(string $role, Asset $asset): void | ||
| 170 | { | ||
| 171 | foreach($this->nda_collection as $nda){ | ||
| 172 | if($nda->getRole() === $role){ | ||
| 173 | $this->removeNodeDataAsset($nda); | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | $this->new_nda = new NodeDataAsset($this, $asset, $role); | ||
| 178 | $this->addNodeDataAsset($this->new_nda); | ||
| 179 | }*/ | ||
| 180 | } \ No newline at end of file | ||
diff --git a/src/model/entities/NodeDataAsset.php b/src/model/entities/NodeDataAsset.php new file mode 100644 index 0000000..7f7008e --- /dev/null +++ b/src/model/entities/NodeDataAsset.php | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | <?php | ||
| 2 | // src/model/entities/NodeDataAsset.php | ||
| 3 | // | ||
| 4 | // entité intermédiaire avec 3 colonnes | ||
| 5 | |||
| 6 | declare(strict_types=1); | ||
| 7 | |||
| 8 | namespace App\Entity; | ||
| 9 | |||
| 10 | use Doctrine\ORM\Mapping as ORM; | ||
| 11 | |||
| 12 | #[ORM\Entity] | ||
| 13 | #[ORM\Table(name: TABLE_PREFIX . 'nodedata_asset')] | ||
| 14 | #[ORM\UniqueConstraint(name: 'unique_role_per_node', columns: ['node_data_id', 'role'])] // un rôle UNIQUE pour chaque node_data_id, excellent! | ||
| 15 | class NodeDataAsset | ||
| 16 | { | ||
| 17 | // clé primaire double | ||
| 18 | // inconvénient: impossible d'utiliser deux fois la même paire node_data/asset, même pour des rôles différents | ||
| 19 | #[ORM\Id] | ||
| 20 | #[ORM\ManyToOne(targetEntity: NodeData::class, inversedBy: 'nda_collection')] | ||
| 21 | #[ORM\JoinColumn(name: 'node_data_id', referencedColumnName: 'id_node_data', onDelete: 'CASCADE')] | ||
| 22 | private NodeData $node_data; | ||
| 23 | |||
| 24 | #[ORM\Id] | ||
| 25 | #[ORM\ManyToOne(targetEntity: Asset::class)] | ||
| 26 | #[ORM\JoinColumn(name: 'asset_id', referencedColumnName: 'id_asset', onDelete: 'CASCADE')] | ||
| 27 | private Asset $asset; | ||
| 28 | |||
| 29 | #[ORM\Column(type: 'string', length: 50)] | ||
| 30 | private string $role; | ||
| 31 | |||
| 32 | public function __construct(NodeData $node_data, Asset $asset, string $role){ | ||
| 33 | $this->node_data = $node_data; | ||
| 34 | $this->asset = $asset; | ||
| 35 | $this->role = $role; | ||
| 36 | } | ||
| 37 | |||
| 38 | /*public function getNodeData(): NodeData | ||
| 39 | { | ||
| 40 | return $this->node_data; | ||
| 41 | }*/ | ||
| 42 | public function getAsset(): Asset | ||
| 43 | { | ||
| 44 | return $this->asset; | ||
| 45 | } | ||
| 46 | public function setAsset(Asset $asset): self | ||
| 47 | { | ||
| 48 | $this->asset = $asset; | ||
| 49 | return $this; | ||
| 50 | } | ||
| 51 | public function getRole(): string | ||
| 52 | { | ||
| 53 | return $this->role; | ||
| 54 | } | ||
| 55 | } | ||
