Ajout notes dans relation entre eleve et atelier

This commit is contained in:
Aymeric SERRA 2023-02-09 18:44:35 +01:00
parent b187497970
commit e49689338c
Signed by: oupson
GPG Key ID: 3BD88615552EFCB7
13 changed files with 289 additions and 48 deletions

View File

@ -5,7 +5,7 @@
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:\\wsl$\Ubuntu\home\ziani\ProjetCC\dev\cc34\var\data.db</jdbc-url>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/var/data.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>

7
.idea/sqldialects.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/migrations/Version20230209164915.php" dialect="GenericSQL" />
<file url="PROJECT" dialect="SQLite" />
</component>
</project>

View File

@ -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
```

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230209164915 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->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');
}
}

View File

@ -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),
]);

View File

@ -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()),
]);
}
}

View File

@ -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<int, User>
* @return Collection<int, FormationUser>
*/
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;

View File

@ -0,0 +1,68 @@
<?php
namespace App\Entity;
use App\Repository\FormationUserRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: FormationUserRepository::class)]
class FormationUser
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::SMALLINT, nullable: true)]
private ?int $note = null;
#[ORM\ManyToOne(inversedBy: 'elevesSuivantFormations')]
#[ORM\JoinColumn(nullable: false)]
private ?Atelier $atelier = null;
#[ORM\ManyToOne(inversedBy: 'formationsInscrits')]
#[ORM\JoinColumn(nullable: false)]
private ?User $eleve = null;
public function getId(): ?int
{
return $this->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;
}
}

View File

@ -40,13 +40,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\OneToMany(mappedBy: 'instructeur', targetEntity: Atelier::class, orphanRemoval: true)]
private Collection $ateliersForm<72><6D><EFBFBD>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<EFBFBD><EFBFBD><EFBFBD>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<int, atelier>
* @return Collection<int, FormationUser>
*/
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;
}

View File

@ -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
// */

View File

@ -0,0 +1,66 @@
<?php
namespace App\Repository;
use App\Entity\FormationUser;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<FormationUser>
*
* @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()
// ;
// }
}

View File

@ -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
// */

View File

@ -27,7 +27,7 @@
<th>Elèves inscrits</th>
<td>
<ul>
{% for eleve in atelier.eleves %}
{% for eleve in eleves %}
<li>{{ eleve.prenom }} {{ eleve.nom }} - {{ eleve.email }}</li>
{% endfor %}
</ul>