diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 1597190..2692499 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -5,7 +5,7 @@ sqlite.xerial true org.sqlite.JDBC - jdbc:sqlite:\\wsl$\Ubuntu\home\ziani\ProjetCC\dev\cc34\var\data.db + jdbc:sqlite:$PROJECT_DIR$/var/data.db $ProjectFileDir$ diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..d644fd4 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 6807273..fd58c52 100644 --- a/README.md +++ b/README.md @@ -104,4 +104,11 @@ symfony console doctrine:fixtures:load ```bash symfony console make:controller InstructeurController symfony console make:controller ApprentiController +``` + +### Question 17 +```bash +symfony console make:entity FormationUser +symfony console make:migration +symfony console d:m:m ``` \ No newline at end of file diff --git a/migrations/Version20230209164915.php b/migrations/Version20230209164915.php new file mode 100644 index 0000000..3ddcd6f --- /dev/null +++ b/migrations/Version20230209164915.php @@ -0,0 +1,40 @@ +addSql('CREATE TABLE formation_user (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, atelier_id INTEGER NOT NULL, eleve_id INTEGER NOT NULL, note SMALLINT DEFAULT NULL, CONSTRAINT FK_DA4C330982E2CF35 FOREIGN KEY (atelier_id) REFERENCES atelier (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_DA4C3309A6CC7B2 FOREIGN KEY (eleve_id) REFERENCES user (id) NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql( + "INSERT INTO formation_user(atelier_id, eleve_id, note) SELECT atelier_id, user_id, null FROM user_atelier" + ); + $this->addSql('CREATE INDEX IDX_DA4C330982E2CF35 ON formation_user (atelier_id)'); + $this->addSql('CREATE INDEX IDX_DA4C3309A6CC7B2 ON formation_user (eleve_id)'); + $this->addSql('DROP TABLE user_atelier'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE user_atelier (user_id INTEGER NOT NULL, atelier_id INTEGER NOT NULL, PRIMARY KEY(user_id, atelier_id), CONSTRAINT FK_B9B60629A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_B9B6062982E2CF35 FOREIGN KEY (atelier_id) REFERENCES atelier (id) ON UPDATE NO ACTION ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('CREATE INDEX IDX_B9B6062982E2CF35 ON user_atelier (atelier_id)'); + $this->addSql('CREATE INDEX IDX_B9B60629A76ED395 ON user_atelier (user_id)'); + $this->addSql('DROP TABLE formation_user'); + } +} diff --git a/src/Controller/ApprentiController.php b/src/Controller/ApprentiController.php index a4c5800..371ed44 100644 --- a/src/Controller/ApprentiController.php +++ b/src/Controller/ApprentiController.php @@ -3,7 +3,9 @@ namespace App\Controller; use App\Entity\Atelier; +use App\Entity\FormationUser; use App\Repository\AtelierRepository; +use App\Repository\FormationUserRepository; use App\Services\MarkdownAtelier; use Doctrine\Persistence\ManagerRegistry; use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; @@ -20,24 +22,41 @@ class ApprentiController extends AbstractController public function inscription(Request $request, Atelier $atelier, ManagerRegistry $doctrine): Response { $entityManager = $doctrine->getManager(); - $atelier->addEleve($this->getUser()); + + $relation = new FormationUser(); + $relation + ->setNote(null) + ->setAtelier($atelier) + ->setEleve($this->getUser()); + $entityManager->persist($relation); + $atelier->addElevesSuivantFormation($relation); + $entityManager->flush(); - return $this->redirectToRoute('app_atelier_show', ["id"=>$atelier->getId()], Response::HTTP_SEE_OTHER); + return $this->redirectToRoute('app_atelier_show', ["id" => $atelier->getId()], Response::HTTP_SEE_OTHER); } #[Route('/atelier/{id}/desinscrire', name: 'app_atelier_desinscrire', methods: ['POST'])] - public function desinscrire(Request $request, Atelier $atelier, ManagerRegistry $doctrine): Response + public function desinscrire(Request $request, Atelier $atelier, ManagerRegistry $doctrine, FormationUserRepository $formationUserRepository): Response { $entityManager = $doctrine->getManager(); - $atelier->removeEleve($this->getUser()); + + $relation = $formationUserRepository->findOneBy( + [ + 'atelier' => $atelier, + 'eleve' => $this->getUser() + ] + ); + $atelier->removeElevesSuivantFormation($relation); + $entityManager->flush(); - return $this->redirectToRoute('app_atelier_show', ["id"=>$atelier->getId()], Response::HTTP_SEE_OTHER); + return $this->redirectToRoute('app_atelier_show', ["id" => $atelier->getId()], Response::HTTP_SEE_OTHER); } #[Route('/', name: 'app_atelier_inscrit', methods: ['GET'])] public function index_inscrit(AtelierRepository $atelierRepository, MarkdownAtelier $markdown): Response { - $ateliers = $this->getUser()->getFormationsSuivies()->toArray(); + + $ateliers = $atelierRepository->getFormationsSuivies($this->getUser())->toArray(); return $this->render('atelier/index_inscrit.html.twig', [ 'ateliers' => $markdown->parseArray($ateliers), ]); diff --git a/src/Controller/AtelierController.php b/src/Controller/AtelierController.php index 5dbdb98..dddaea5 100644 --- a/src/Controller/AtelierController.php +++ b/src/Controller/AtelierController.php @@ -3,15 +3,12 @@ namespace App\Controller; use App\Entity\Atelier; -use App\Form\AtelierType; use App\Repository\AtelierRepository; +use App\Repository\UserRepository; use App\Services\MarkdownAtelier; -use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route('/atelier')] class AtelierController extends AbstractController @@ -25,11 +22,14 @@ class AtelierController extends AbstractController } #[Route('/{id}', name: 'app_atelier_show', methods: ['GET'])] - public function show(Atelier $atelier, MarkdownAtelier $markdownAtelier): Response + public function show(Atelier $atelier, MarkdownAtelier $markdownAtelier, UserRepository $userRepository): Response { + $eleves = $userRepository->getEleves($atelier); + $user = $this->getUser(); return $this->render('atelier/show.html.twig', [ 'atelier' => $markdownAtelier->parse($atelier), - 'inscrit' => $atelier->getEleves()->contains($this->getUser()), + 'eleves' => $eleves, + 'inscrit' => $user != null && $eleves->contains($this->getUser()), ]); } } diff --git a/src/Entity/Atelier.php b/src/Entity/Atelier.php index 2035da6..f6a57df 100644 --- a/src/Entity/Atelier.php +++ b/src/Entity/Atelier.php @@ -25,12 +25,12 @@ class Atelier #[ORM\JoinColumn(nullable: false)] private ?User $instructeur = null; - #[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'formationsSuivies')] - private Collection $eleves; + #[ORM\OneToMany(mappedBy: 'atelier', targetEntity: FormationUser::class, orphanRemoval: true)] + private Collection $elevesSuivantFormations; public function __construct() { - $this->eleves = new ArrayCollection(); + $this->elevesSuivantFormations = new ArrayCollection(); } public function getId(): ?int @@ -75,27 +75,30 @@ class Atelier } /** - * @return Collection + * @return Collection */ - public function getEleves(): Collection + public function getElevesSuivantFormations(): Collection { - return $this->eleves; + return $this->elevesSuivantFormations; } - public function addEleve(User $eleve): self + public function addElevesSuivantFormation(FormationUser $elevesSuivantFormation): self { - if (!$this->eleves->contains($eleve)) { - $this->eleves->add($eleve); - $eleve->addFormationsSuivie($this); + if (!$this->elevesSuivantFormations->contains($elevesSuivantFormation)) { + $this->elevesSuivantFormations->add($elevesSuivantFormation); + $elevesSuivantFormation->setAtelier($this); } return $this; } - public function removeEleve(User $eleve): self + public function removeElevesSuivantFormation(FormationUser $elevesSuivantFormation): self { - if ($this->eleves->removeElement($eleve)) { - $eleve->removeFormationsSuivie($this); + if ($this->elevesSuivantFormations->removeElement($elevesSuivantFormation)) { + // set the owning side to null (unless already changed) + if ($elevesSuivantFormation->getAtelier() === $this) { + $elevesSuivantFormation->setAtelier(null); + } } return $this; diff --git a/src/Entity/FormationUser.php b/src/Entity/FormationUser.php new file mode 100644 index 0000000..4d01d1a --- /dev/null +++ b/src/Entity/FormationUser.php @@ -0,0 +1,68 @@ +id; + } + + public function getNote(): ?int + { + return $this->note; + } + + public function setNote(?int $note): self + { + $this->note = $note; + + return $this; + } + + public function getAtelier(): ?Atelier + { + return $this->atelier; + } + + public function setAtelier(?Atelier $atelier): self + { + $this->atelier = $atelier; + + return $this; + } + + public function getEleve(): ?User + { + return $this->eleve; + } + + public function setEleve(?User $eleve): self + { + $this->eleve = $eleve; + + return $this; + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php index 9db0d01..3a5ee84 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -40,13 +40,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\OneToMany(mappedBy: 'instructeur', targetEntity: Atelier::class, orphanRemoval: true)] private Collection $ateliersForm���es; - #[ORM\ManyToMany(targetEntity: atelier::class, inversedBy: 'eleves')] - private Collection $formationsSuivies; + #[ORM\OneToMany(mappedBy: 'eleve', targetEntity: FormationUser::class, orphanRemoval: true)] + private Collection $formationsInscrits; public function __construct() { $this->ateliersForm���es = new ArrayCollection(); - $this->formationsSuivies = new ArrayCollection(); + $this->formationsInscrits = new ArrayCollection(); } public function getId(): ?int @@ -73,7 +73,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface */ public function getUserIdentifier(): string { - return (string) $this->email; + return (string)$this->email; } /** @@ -176,25 +176,31 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface } /** - * @return Collection + * @return Collection */ - public function getFormationsSuivies(): Collection + public function getFormationsInscrits(): Collection { - return $this->formationsSuivies; + return $this->formationsInscrits; } - public function addFormationsSuivie(atelier $formationsSuivie): self + public function addFormationsInscrit(FormationUser $formationsInscrit): self { - if (!$this->formationsSuivies->contains($formationsSuivie)) { - $this->formationsSuivies->add($formationsSuivie); + if (!$this->formationsInscrits->contains($formationsInscrit)) { + $this->formationsInscrits->add($formationsInscrit); + $formationsInscrit->setEleve($this); } return $this; } - public function removeFormationsSuivie(atelier $formationsSuivie): self + public function removeFormationsInscrit(FormationUser $formationsInscrit): self { - $this->formationsSuivies->removeElement($formationsSuivie); + if ($this->formationsInscrits->removeElement($formationsInscrit)) { + // set the owning side to null (unless already changed) + if ($formationsInscrit->getEleve() === $this) { + $formationsInscrit->setEleve(null); + } + } return $this; } diff --git a/src/Repository/AtelierRepository.php b/src/Repository/AtelierRepository.php index 079567b..3dafe19 100644 --- a/src/Repository/AtelierRepository.php +++ b/src/Repository/AtelierRepository.php @@ -3,7 +3,9 @@ namespace App\Repository; use App\Entity\Atelier; +use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Persistence\ManagerRegistry; /** @@ -39,6 +41,16 @@ class AtelierRepository extends ServiceEntityRepository } } + public function getFormationsSuivies(User $user): ArrayCollection + { + return new ArrayCollection($this->createQueryBuilder('a') + ->innerJoin('\App\Entity\FormationUser', 'fu', 'WITH', 'fu.atelier = a') + ->where('fu.eleve = :eleve') + ->setParameter('eleve', $user) + ->getQuery() + ->execute()); + } + // /** // * @return Atelier[] Returns an array of Atelier objects // */ diff --git a/src/Repository/FormationUserRepository.php b/src/Repository/FormationUserRepository.php new file mode 100644 index 0000000..7d421b7 --- /dev/null +++ b/src/Repository/FormationUserRepository.php @@ -0,0 +1,66 @@ + + * + * @method FormationUser|null find($id, $lockMode = null, $lockVersion = null) + * @method FormationUser|null findOneBy(array $criteria, array $orderBy = null) + * @method FormationUser[] findAll() + * @method FormationUser[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class FormationUserRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, FormationUser::class); + } + + public function save(FormationUser $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(FormationUser $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return FormationUser[] Returns an array of FormationUser objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('f') +// ->andWhere('f.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('f.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?FormationUser +// { +// return $this->createQueryBuilder('f') +// ->andWhere('f.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 9b60483..32c20fd 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -2,8 +2,11 @@ namespace App\Repository; +use App\Entity\Atelier; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\Persistence\ManagerRegistry; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; @@ -24,15 +27,6 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader parent::__construct($registry, User::class); } - public function save(User $entity, bool $flush = false): void - { - $this->getEntityManager()->persist($entity); - - if ($flush) { - $this->getEntityManager()->flush(); - } - } - public function remove(User $entity, bool $flush = false): void { $this->getEntityManager()->remove($entity); @@ -56,6 +50,25 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader $this->save($user, true); } + public function save(User $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function getEleves(Atelier $atelier) : ArrayCollection + { + return new ArrayCollection($this->createQueryBuilder('e') + ->innerJoin('\App\Entity\FormationUser', 'fu', 'WITH', 'fu.eleve = e') + ->where('fu.atelier = :atelier') + ->setParameter('atelier', $atelier) + ->getQuery() + ->execute()); + } + // /** // * @return User[] Returns an array of User objects // */ diff --git a/templates/atelier/show.html.twig b/templates/atelier/show.html.twig index 773a786..272ef0c 100644 --- a/templates/atelier/show.html.twig +++ b/templates/atelier/show.html.twig @@ -27,7 +27,7 @@ Elèves inscrits
    - {% for eleve in atelier.eleves %} + {% for eleve in eleves %}
  • {{ eleve.prenom }} {{ eleve.nom }} - {{ eleve.email }}
  • {% endfor %}