<?php
namespace App\Entity;
use App\Repository\LessonRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Traits\Timestampable;
/**
* Leçon du programme national (créé par le superadmin).
*
* Rattaché à un SubjectReference (= matière + ClassOption).
* `position` définit l'ordre d'apparition dans le programme.
* `deadlineQuarter` indique la séquence avant la fin de laquelle le
* leçon doit être terminé (ex : "avant la fin de la Séquence 2").
*
* La date réelle de la deadline se calcule via deadlineQuarter->getEndDate()
* si ce champ existe sur Quarter, sinon on affiche juste le nom de la séquence.
*/
#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: LessonRepository::class)]
class Lesson
{
use Timestampable;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $titleEn = null;
#[ORM\Column(type: 'text', nullable: true)]
private ?string $description = null;
/**
* Ordre de la leçon dans le programme (1, 2, 3...).
*/
#[ORM\Column]
private ?int $position = null;
#[ORM\ManyToOne(inversedBy: 'lessons')]
#[ORM\JoinColumn(nullable: false)]
private ?SubjectReference $subjectReference = null;
/**
* Séquence avant la fin de laquelle cette leçon doit être terminée.
* Nullable : une leçon peut ne pas avoir de deadline imposée.
*/
#[ORM\ManyToOne]
private ?Quarter $deadlineQuarter = null;
/**
* Date calendaire optionnelle, en complément ou alternative à deadlineQuarter.
* Permet une deadline fixe (ex: 15/11/2025) si le superadmin préfère.
*/
#[ORM\Column(type: 'date', nullable: true)]
private ?\DateTimeInterface $deadlineDate = null;
public const NATURE_THEORIQUE = 'LT';
public const NATURE_DIGITALISEE = 'LD';
public const NATURE_PRATIQUE = 'LP';
/**
* Module/Thème parent (nullable — certaines matières n'ont pas de Module).
*/
#[ORM\ManyToOne(inversedBy: 'lessons')]
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
private ?Module $module = null;
/**
* Unité d'Apprentissage parente (nullable — certaines matières n'ont pas d'UA).
*/
#[ORM\ManyToOne(inversedBy: 'lessons')]
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
private ?LearningUnit $learningUnit = null;
/**
* Énoncé de compétence associé (nullable). Au niveau Leçon et non UA :
* certaines fiches de progression (ex: histoire-géo) n'ont ni Module ni
* UA mais la compétence y change quand même leçon par leçon.
*/
#[ORM\Column(type: 'text', nullable: true)]
private ?string $competenceStatement = null;
/**
* Semaine du programme à laquelle cette leçon est prévue (nullable).
*/
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
private ?ExamWeek $week = null;
/**
* Nature par défaut définie par le national : Leçon Théorique (LT),
* Leçon Digitalisée (LD) ou Leçon Pratique (LP). Copiée comme valeur
* par défaut sur SubjectLesson::nature à la création, modifiable
* ensuite indépendamment par chaque école/prof.
*/
#[ORM\Column(length: 2, nullable: true)]
private ?string $nature = null;
/**
* Durée de référence en heures (ex: 2, 4).
*/
#[ORM\Column(nullable: true)]
private ?float $duration = null;
#[ORM\OneToMany(mappedBy: 'lesson', targetEntity: LessonProgress::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
private Collection $progresses;
#[ORM\ManyToOne]
private ?User $author = null;
public function __construct()
{
$this->progresses = new ArrayCollection();
}
public function __toString(): string
{
return $this->title;
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
public function getTitleEn(): ?string
{
return $this->titleEn;
}
public function setTitleEn(?string $titleEn): static
{
$this->titleEn = $titleEn;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
public function getPosition(): ?int
{
return $this->position;
}
public function setPosition(int $position): static
{
$this->position = $position;
return $this;
}
public function getSubjectReference(): ?SubjectReference
{
return $this->subjectReference;
}
public function setSubjectReference(?SubjectReference $subjectReference): static
{
$this->subjectReference = $subjectReference;
return $this;
}
public function getDeadlineQuarter(): ?Quarter
{
return $this->deadlineQuarter;
}
public function setDeadlineQuarter(?Quarter $deadlineQuarter): static
{
$this->deadlineQuarter = $deadlineQuarter;
return $this;
}
public function getDeadlineDate(): ?\DateTimeInterface
{
return $this->deadlineDate;
}
public function setDeadlineDate(?\DateTimeInterface $deadlineDate): static
{
$this->deadlineDate = $deadlineDate;
return $this;
}
public function getModule(): ?Module
{
return $this->module;
}
public function setModule(?Module $module): static
{
$this->module = $module;
return $this;
}
public function getLearningUnit(): ?LearningUnit
{
return $this->learningUnit;
}
public function setLearningUnit(?LearningUnit $learningUnit): static
{
$this->learningUnit = $learningUnit;
return $this;
}
public function getCompetenceStatement(): ?string
{
return $this->competenceStatement;
}
public function setCompetenceStatement(?string $competenceStatement): static
{
$this->competenceStatement = $competenceStatement;
return $this;
}
public function getWeek(): ?ExamWeek
{
return $this->week;
}
public function setWeek(?ExamWeek $week): static
{
$this->week = $week;
return $this;
}
public function getNature(): ?string
{
return $this->nature;
}
public function setNature(?string $nature): static
{
$this->nature = $nature;
return $this;
}
public function getDuration(): ?float
{
return $this->duration;
}
public function setDuration(?float $duration): static
{
$this->duration = $duration;
return $this;
}
/**
* @return Collection<int, LessonProgress>
*/
public function getProgresses(): Collection
{
return $this->progresses;
}
public function addProgress(LessonProgress $progress): static
{
if (!$this->progresses->contains($progress)) {
$this->progresses->add($progress);
$progress->setLesson($this);
}
return $this;
}
public function removeProgress(LessonProgress $progress): static
{
if ($this->progresses->removeElement($progress)) {
if ($progress->getLesson() === $this) {
$progress->setLesson(null);
}
}
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): static
{
$this->author = $author;
return $this;
}
}