<?php
namespace App\Entity\Core\Peer;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use JsonSerializable;
#[ORM\Table('peer_solution')]
#[ORM\Entity(repositoryClass: PeerSolutionRepository::class)]
class PeerSolution implements JsonSerializable
{
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
private int $id;
#[ORM\JoinColumn(name: 'peer_unit', referencedColumnName: 'id', onDelete: 'CASCADE')]
#[ORM\OneToOne(targetEntity: PeerUnit::class, inversedBy: 'peerSolution')]
private PeerUnit $peerUnit;
#[ORM\OneToMany(targetEntity: PeerFeedback::class, mappedBy: 'peerSolution', cascade: ['persist', 'remove'])]
private Collection $peerFeedbacks;
#[ORM\Column(name: 'solution_text', type: 'text', nullable: true)]
private ?string $solutionText;
#[ORM\OneToMany(targetEntity: PeerSolutionFile::class, mappedBy: 'peerSolution', cascade: ['persist'])]
private Collection $peerSolutionFiles;
#[ORM\Column(type: 'datetime', nullable: true)]
private ?DateTimeInterface $updatedAt;
#[ORM\Column(name: 'solution_result', type: 'text', nullable: true)]
private ?string $solutionResult;
public function __construct()
{
$this->peerFeedbacks = new ArrayCollection();
$this->peerSolutionFiles = new ArrayCollection();
}
public function getId(): int
{
return $this->id;
}
public function getPeerUnit(): PeerUnit
{
return $this->peerUnit;
}
public function setPeerUnit(PeerUnit $peerUnit)
{
$this->peerUnit = $peerUnit;
}
public function getSolutionText(): ?string
{
return $this->solutionText;
}
/**
* @throws \Exception
*/
public function setSolutionText(string $solutionText)
{
$this->solutionText = $solutionText;
$this->updatedAt = new DateTimeImmutable('now', new DateTimeZone('Europe/Copenhagen'));
}
/**
* @return ArrayCollection | PeerFeedback[]
*/
public function getPeerFeedbacks(): Collection
{
return $this->peerFeedbacks;
}
public function hasAnswer(): bool
{
return (bool)strlen($this->solutionText) || !$this->peerSolutionFiles->isEmpty();
}
public function hasRatingByPeerUnit(PeerUnit $peerUnit): bool
{
foreach ($this->peerFeedbacks as $feedback) {
/** @var $feedback PeerFeedback */
if ($feedback->getPeerUnit() === $peerUnit && (bool)$feedback->getRating()) {
return true;
}
}
return false;
}
public function getUpdatedAt(): ?DateTimeInterface
{
return $this->updatedAt;
}
public function addPeerSolutionFile(PeerSolutionFile $peerSolutionFile)
{
if (null !== $peerSolutionFile->getFile()) {
$peerSolutionFile->setPeerSolution($this);
$this->peerSolutionFiles->add($peerSolutionFile);
}
}
public function removePeerSolutionFile(PeerSolutionFile $peerSolutionFile)
{
$this->peerSolutionFiles->removeElement($peerSolutionFile);
}
public function getPeerSolutionFiles(): Collection
{
return $this->peerSolutionFiles;
}
public function getSolutionResult(): ?string
{
return $this->solutionResult;
}
public function setSolutionResult(?string $solutionResult): void
{
$this->solutionResult = $solutionResult;
}
public function jsonSerialize(): mixed
{
$feedback = $this->peerFeedbacks->map(fn(PeerFeedback $fb) => [
"id" => $fb->getId(),
"txt" => $fb->getFeedbackText(),
"studentNames" => $fb->getPeerUnit()->getPeerStudents()
->map(fn(PeerStudent $ps) => $ps->getStudent()->getFullName())->toArray(),
"stars" => $fb->getRating(),
"rating" => !empty($fb->getPeerFeedback2nd()) ? $fb->getPeerFeedback2nd()->getRating() : null,
]);
return [
"id" => $this->id,
"txt" => $this->solutionText,
"files" => $this->peerSolutionFiles->toArray(),
"result" => $this->solutionResult,
"updatedAt" => $this->updatedAt,
"feedback" => $feedback->toArray(),
];
}
}