<?php
namespace App\Entity;
use App\Repository\SubjectReferenceRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Traits\Timestampable;
/**
* Référentiel national d'une matière pour une ClassOption donnée,
* pour une "version du programme" (SchoolYear) donnée.
*
* Exemple : "Mathématiques" pour la ClassOption "3ème", coef 4,
* version programme 2025-2026 → 1 SubjectReference.
*
* Reprend volontairement les mêmes propriétés que Subject (name, nameEn,
* coef, year, subjectGroup) à l'exception de tout ce qui rattache Subject
* à une instance concrète (school, classe, prof, notes...).
*
* Le superadmin crée ces référentiels et leurs Chapter associés.
* Chaque Subject réel "hérite" de la progression via
* SubjectReferenceRepository::findForSubject().
*/
#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: SubjectReferenceRepository::class)]
class SubjectReference
{
use Timestampable;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $nameEn = null;
/**
* Coefficient de référence de la matière pour cette ClassOption.
* Sert d'indication / valeur par défaut ; chaque Subject réel garde
* son propre coef (qui peut différer selon l'école).
*/
#[ORM\Column(nullable: true)]
private ?float $coef = null;
#[ORM\ManyToOne(inversedBy: 'subjectReferences')]
#[ORM\JoinColumn(nullable: false)]
private ?ClassOption $classOption = null;
/**
* Groupe de matières national (équivalent national de SubjectGroup).
*/
#[ORM\ManyToOne(inversedBy: 'subjectReferences')]
private ?SubjectGroupReference $subjectGroupReference = null;
/**
* "Version du programme national" : permet de faire évoluer le
* programme d'une année à l'autre sans perdre l'historique.
* Ex : SubjectReference "Maths - 3ème" version 2025-2026
* vs "Maths - 3ème" version 2026-2027.
*/
#[ORM\ManyToOne(inversedBy: 'subjectReferences')]
#[ORM\JoinColumn(nullable: false)]
private ?SchoolYear $year = null;
#[ORM\OneToMany(mappedBy: 'subjectReference', targetEntity: Chapter::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['position' => 'ASC'])]
private Collection $chapters;
#[ORM\ManyToOne]
private ?User $author = null;
#[ORM\OneToMany(mappedBy: 'reference', targetEntity: Subject::class)]
private Collection $subjects;
public function __construct()
{
$this->chapters = new ArrayCollection();
$this->subjects = new ArrayCollection();
}
public function __toString(): string
{
return $this->name . ' (' . ($this->classOption?->getName() ?? '') . ')';
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getNameEn(): ?string
{
return $this->nameEn;
}
public function setNameEn(?string $nameEn): static
{
$this->nameEn = $nameEn;
return $this;
}
public function getCoef(): ?float
{
return $this->coef;
}
public function setCoef(?float $coef): static
{
$this->coef = $coef;
return $this;
}
public function getClassOption(): ?ClassOption
{
return $this->classOption;
}
public function setClassOption(?ClassOption $classOption): static
{
$this->classOption = $classOption;
return $this;
}
public function getSubjectGroupReference(): ?SubjectGroupReference
{
return $this->subjectGroupReference;
}
public function setSubjectGroupReference(?SubjectGroupReference $subjectGroupReference): static
{
$this->subjectGroupReference = $subjectGroupReference;
return $this;
}
public function getYear(): ?SchoolYear
{
return $this->year;
}
public function setYear(?SchoolYear $year): static
{
$this->year = $year;
return $this;
}
/**
* @return Collection<int, Chapter>
*/
public function getChapters(): Collection
{
return $this->chapters;
}
public function addChapter(Chapter $chapter): static
{
if (!$this->chapters->contains($chapter)) {
$this->chapters->add($chapter);
$chapter->setSubjectReference($this);
}
return $this;
}
public function removeChapter(Chapter $chapter): static
{
if ($this->chapters->removeElement($chapter)) {
if ($chapter->getSubjectReference() === $this) {
$chapter->setSubjectReference(null);
}
}
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): static
{
$this->author = $author;
return $this;
}
/**
* @return Collection<int, Subject>
*/
public function getSubjects(): Collection
{
return $this->subjects;
}
public function addSubject(Subject $subject): static
{
if (!$this->subjects->contains($subject)) {
$this->subjects->add($subject);
$subject->setReference($this);
}
return $this;
}
public function removeSubject(Subject $subject): static
{
if ($this->subjects->removeElement($subject)) {
// set the owning side to null (unless already changed)
if ($subject->getReference() === $this) {
$subject->setReference(null);
}
}
return $this;
}
}