<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\ElExamQuestionTranslation;
use ApiPlatform\Core\Annotation\ApiFilter;
use App\Entity\Traits\TimestampableEntity;
use Doctrine\Common\Collections\Collection;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\ElExamQuestionRepository;
use App\Entity\Interfaces\OrderMappedInterface;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Interfaces\ContainerMappedInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use Locastic\ApiPlatformTranslationBundle\Model\AbstractTranslatable;
use Locastic\ApiPlatformTranslationBundle\Model\TranslationInterface;
/**
* @ApiResource(
* attributes={"security"="is_granted('ROLE_OPERATOR')", "filters"={"translation.groups"}},
* normalizationContext={"groups"={"ElExamQuestion:Read"}, "skip_null_values"=false},
* denormalizationContext={"groups"={"ElExamQuestion:Write", "ElExamQuestionTranslationGroup", "ElExamOptionTranslationGroup"}},
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"ElExamQuestion:Read","ElExamQuestion:With-Answer"}, "skip_null_values"=false},
* "security"="is_granted('ROLE_OPERATOR') or is_granted('ROLE_INSTRUCTOR')"
* },
* "get_public"={
* "path"="/el_exam_questions/get-public",
* "method"="GET",
* "normalization_context"={"groups"={"ElExamQuestion:Read"}, "skip_null_values"=false},
* "security"="is_granted('IS_AUTHENTICATED_FULLY')"
* },
* "get_for_exam_complete"={
* "path"="/el_exam_questions/get-for-exam-complete",
* "method"="GET",
* "normalization_context"={"groups"={"ElExamQuestion:Read", "ElExamQuestion:Exam-Complete"}, "skip_null_values"=false},
* "security"="is_granted('IS_AUTHENTICATED_FULLY')"
* },
* "post"={
* "security"="is_granted('ROLE_OPERATOR') or is_granted('ROLE_INSTRUCTOR')"
* }
* },
* itemOperations={
* "get"={
* "security"="is_granted('IS_CO_ANY', object)"
* },
* "put"={"security"="is_granted('IS_CO_OPR', object) or is_granted('IS_CO_INS_SPE_COURSE', object.elExam.elCourseAlways)"},
* "patch"={"security"="is_granted('IS_CO_OPR', object) or is_granted('IS_CO_INS_SPE_COURSE', object.elExam.elCourseAlways)"},
* "patch_change_ord"={
* "path"="/el_exam_questions/{id}/change-ord",
* "method"="PATCH",
* "denormalization_context"={"groups"={"ElExamQuestion:ChangeOrd"}},
* "security"="is_granted('IS_CO_OPR', object) or is_granted('IS_CO_INS_SPE_COURSE', object.elExam.elCourseAlways)"
* },
* "delete"
* }
* )
* @ApiFilter(SearchFilter::class, properties={"container.id": "exact", "elExam.id": "exact", "questionType": "exact", "translations.question": "partial"})
* @ApiFilter(OrderFilter::class, properties={"id", "translations.question", "ord": "ASC"})
* @ORM\Entity(repositoryClass=ElExamQuestionRepository::class)
*/
class ElExamQuestion extends AbstractTranslatable implements ContainerMappedInterface, OrderMappedInterface
{
/**
* Hook timestampable behavior
* updates createdAt, updatedAt fields
*/
use TimestampableEntity;
/**
* @ORM\OneToMany(targetEntity="ElExamQuestionTranslation", mappedBy="translatable", fetch="EXTRA_LAZY", indexBy="locale", cascade={"PERSIST"}, orphanRemoval=true)
*
* @Groups({"ElExamQuestion:Write", "ElExamQuestionTranslationGroup"})
* @Assert\Valid()
*/
protected $translations;
/**
* @Groups({"ElExamQuestion:Read", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
*/
private $question;
/**
* @Groups({"ElExamQuestion:Read", "ElExamAnswer:Assessment"})
*/
private $description;
/**
* @Groups({"ElExamQuestion:With-Answer", "ElExamAnswer:Assessment", "ElExamQuestion:Exam-Complete"})
*/
private $answerExplanation;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"ElExamQuestion:Read", "ElExamAnswer:Assessment"})
*/
private $id;
/**
* @ORM\Column(type="string", length=16)
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
*/
private $questionType;
public const QUESTIONTYPE_SINGLE = "SINGLE";
public const QUESTIONTYPE_MULTI = "MULTI";
public const QUESTIONTYPE_TEXT = "TEXT";
public const QUESTIONTYPE_FILE = "FILE";
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
*/
private $correctPoint;
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
*/
private $wrongPoint;
/**
* @ORM\ManyToOne(targetEntity=Container::class)
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Groups({"ElExamQuestion:Write"})
*/
private $container;
/**
* @ORM\ManyToOne(targetEntity=ElExam::class, inversedBy="elExamQuestions")
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write"})
*/
public $elExam;
/**
* @ORM\OneToMany(targetEntity=ElExamOption::class, mappedBy="elExamQuestion", orphanRemoval=true, cascade={"persist"})
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:With-Answer", "ElExamQuestion:Write", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
* @Assert\Valid()
*/
private $elExamOptions;
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write", "ElExamAnswer:Assessment"})
*/
private $ord;
/**
* @Groups({"ElExamQuestion:ChangeOrd"})
*/
private int $newOrd;
private $ordChangeDirection;
/**
* @ORM\OneToMany(targetEntity=ElExamQuestionImage::class, mappedBy="elExamQuestion", orphanRemoval=true, cascade={"persist"})
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:With-Answer", "ElExamQuestion:Write", "ElExamAnswer:Assessment", "ElExamAnswer:Exam-Report"})
* @Assert\Valid()
*/
private $elExamQuestionImages;
/**
* @ORM\Column(type="boolean", nullable=true)
* @Groups({"ElExamQuestion:Read", "ElExamQuestion:Write"})
*/
private $isRequired;
public function __construct()
{
parent::__construct();
$this->elExamOptions = new ArrayCollection();
$this->elExamQuestionImages = new ArrayCollection();
}
protected function createTranslation(): TranslationInterface
{
return new ElExamQuestionTranslation();
}
public function getQuestion(): ?string
{
return $this->getTranslation()->getQuestion();
}
public function setQuestion(string $question): self
{
$this->getTranslation()->setQuestion($question);
return $this;
}
public function getDescription(): ?string
{
return $this->getTranslation()->getDescription();
}
public function setDescription(string $description): self
{
$this->getTranslation()->setDescription($description);
return $this;
}
public function getAnswerExplanation(): ?string
{
return $this->getTranslation()->getAnswerExplanation();
}
public function setAnswerExplanation(string $answerExplanation): self
{
$this->getTranslation()->setAnswerExplanation($answerExplanation);
return $this;
}
public function getId(): ?int
{
return $this->id;
}
public function getQuestionType(): ?string
{
return $this->questionType;
}
public function setQuestionType(string $questionType): self
{
$this->questionType = $questionType;
return $this;
}
public function getCorrectPoint(): ?int
{
return $this->correctPoint;
}
public function setCorrectPoint(?int $correctPoint): self
{
$this->correctPoint = $correctPoint;
return $this;
}
public function getWrongPoint(): ?int
{
return $this->wrongPoint;
}
public function setWrongPoint(?int $wrongPoint): self
{
$this->wrongPoint = $wrongPoint;
return $this;
}
public function getContainer(): ?Container
{
return $this->container;
}
public function setContainer(?Container $container): self
{
$this->container = $container;
return $this;
}
public function getElExam(): ?ElExam
{
return $this->elExam;
}
public function setElExam(?ElExam $elExam): self
{
$this->elExam = $elExam;
return $this;
}
/**
* @return Collection|ElExamOption[]
*/
public function getElExamOptions(): Collection
{
return $this->elExamOptions;
}
public function addElExamOption(ElExamOption $elExamOption): self
{
if (!$this->elExamOptions->contains($elExamOption)) {
$this->elExamOptions[] = $elExamOption;
$elExamOption->setElExamQuestion($this);
}
return $this;
}
public function removeElExamOption(ElExamOption $elExamOption): self
{
if ($this->elExamOptions->removeElement($elExamOption)) {
// set the owning side to null (unless already changed)
if ($elExamOption->getElExamQuestion() === $this) {
$elExamOption->setElExamQuestion(null);
}
}
return $this;
}
public function removeAllElExamOptions(): self
{
foreach ($this->elExamOptions as $elExamOption) {
$this->removeElExamOption($elExamOption);
}
return $this;
}
public function getClone(ElExamQuestion $source = null): self
{
if (empty($source)) {
$source = $this;
}
$target = new ElExamQuestion();
$target
->setQuestionType($source->getQuestionType())
->setCorrectPoint($source->getCorrectPoint())
->setWrongPoint($source->getWrongPoint())
->setContainer($source->getContainer())
->setElExam($source->getElExam())
->setOrd($source->getOrd())
;
foreach ($source->getTranslations() as $s) {
$newT = new ElExamQuestionTranslation();
$newT
->setQuestion($s->getQuestion())
->setDescription($s->getDescription())
->setAnswerExplanation($s->getAnswerExplanation())
->setLocale($s->getLocale())
;
$target->addTranslation($newT);
}
foreach ($source->getElExamOptions() as $s) {
$target->addElExamOption($s->getClone());
}
return $target;
}
public function getOrd(): ?int
{
return $this->ord;
}
public function setOrd(?int $ord): self
{
$this->ord = $ord;
return $this;
}
public function getOrdParents(): array
{
return [
'container' => $this->getContainer(),
'elExam' => $this->getElExam()
];
}
public function getOrdChangeDirection()
{
return $this->ordChangeDirection;
}
public function getNewOrd(): int
{
return $this->newOrd ?? 0;
}
public function setNewOrd(int $newOrd): self
{
$oldOrd = $this->ord;
$this->newOrd = $newOrd;
$this->ord = $newOrd;
$this->ordChangeDirection = ($this->newOrd < $oldOrd) ? 'desc' : 'asc';
return $this;
}
/**
* @return Collection<int, ElExamQuestionImage>
*/
public function getElExamQuestionImages(): Collection
{
return $this->elExamQuestionImages;
}
public function addElExamQuestionImage(ElExamQuestionImage $elExamQuestionImage): self
{
if (!$this->elExamQuestionImages->contains($elExamQuestionImage)) {
$this->elExamQuestionImages[] = $elExamQuestionImage;
$elExamQuestionImage->setElExamQuestion($this);
}
return $this;
}
public function removeElExamQuestionImage(ElExamQuestionImage $elExamQuestionImage): self
{
if ($this->elExamQuestionImages->removeElement($elExamQuestionImage)) {
// set the owning side to null (unless already changed)
if ($elExamQuestionImage->getElExamQuestion() === $this) {
$elExamQuestionImage->setElExamQuestion(null);
}
}
return $this;
}
public function removeAllElQuestionImages(): self
{
foreach ($this->elExamQuestionImages as $elExamQuestionImage) {
$this->removeElExamQuestionImage($elExamQuestionImage);
}
return $this;
}
public function isIsRequired(): ?bool
{
return $this->isRequired;
}
public function setIsRequired(?bool $isRequired): self
{
$this->isRequired = $isRequired;
return $this;
}
}