auditionadmin/app/Actions/Entries/UpdateEntry.php

143 lines
5.1 KiB
PHP

<?php
namespace App\Actions\Entries;
use App\Exceptions\ManageEntryException;
use App\Models\Audition;
use App\Models\Entry;
use function array_key_exists;
class UpdateEntry
{
protected Entry $entry;
public function __construct()
{
}
/**
* @throws ManageEntryException
*/
public function __invoke(Entry $entry, array $updateData): void
{
$this->updateEntry($entry, $updateData);
}
/**
* @throws ManageEntryException
*/
public function updateEntry(Entry|int $entry, array $updateData): void
{
if (is_int($entry)) {
$entry = Entry::find($entry);
}
if (! $entry || ! $entry->exists) {
throw new ManageEntryException('Invalid entry provided');
}
$this->entry = $entry;
if (array_key_exists('for_seating', $updateData)) {
$this->updateForSeating($updateData['for_seating']);
}
if (array_key_exists('for_advancement', $updateData)) {
$this->updateForAdvancement($updateData['for_advancement']);
}
if (array_key_exists('audition', $updateData)) {
$this->updateAudition($updateData['audition']);
}
$this->entry->save();
}
/**
* @throws ManageEntryException
*/
private function updateAudition(Audition|int $audition): void
{
if (is_int($audition)) {
$audition = Audition::find($audition);
}
if (! $audition || ! $audition->exists) {
throw new ManageEntryException('Invalid audition provided');
}
if ($this->entry->audition->hasFlag('seats_published')) {
throw new ManageEntryException('Cannot change the audition for an entry where seating for that entry\'s current audition is published');
}
if ($this->entry->audition->hasFlag('advancement_published')) {
throw new ManageEntryException('Cannot change the audition for an entry where advancement for that entry\'s current audition is published');
}
if ($audition->hasFlag('seats_published')) {
throw new ManageEntryException('Cannot change the entry to an audition with published seating');
}
if ($audition->hasFlag('advancement_published')) {
throw new ManageEntryException('Cannot change the entry to an audition with published advancement');
}
if ($this->entry->student->grade > $audition->maximum_grade) {
throw new ManageEntryException('The grade of the student exceeds the maximum for that audition');
}
if ($this->entry->student->grade < $audition->minimum_grade) {
throw new ManageEntryException('The grade of the student does not meet the minimum for that audition');
}
if ($this->entry->scoreSheets()->count() > 0) {
throw new ManageEntryException('Cannot change the audition for an entry with scores');
}
if (Entry::where('student_id', $this->entry->student_id)->where('audition_id', $audition->id)->exists()) {
throw new ManageEntryException('That student is already entered in that audition');
}
// OK we're allowed to change the audition
$this->entry->audition_id = $audition->id;
// Deal with our draw number
if ($audition->hasFlag('drawn')) {
$draw_number = $audition->entries()->max('draw_number');
$this->entry->draw_number = $draw_number + 1;
} else {
$this->entry->draw_number = null;
}
}
/**
* @throws ManageEntryException
*/
private function updateForSeating($forSeating): void
{
if ($this->entry->for_seating == $forSeating) {
return;
}
if ($forSeating) {
if ($this->entry->audition->hasFlag('seats_published')) {
throw new ManageEntryException('Cannot add seating to an entry in an audition where seats are published');
}
$this->entry->for_seating = 1;
} else {
if ($this->entry->audition->hasFlag('seats_published')) {
throw new ManageEntryException('Cannot remove seating from an entry in an audition where seats are published');
}
$this->entry->for_seating = 0;
}
}
/**
* @throws ManageEntryException
*/
private function updateForAdvancement($forAdvancement): void
{
if ($this->entry->for_advancement == $forAdvancement) {
return;
}
if ($forAdvancement) {
if ($this->entry->audition->hasFlag('advancement_published')) {
throw new ManageEntryException('Cannot add advancement to an entry in an audition where advancement is published');
}
$this->entry->for_advancement = 1;
} else {
if ($this->entry->audition->hasFlag('advancement_published')) {
throw new ManageEntryException('Cannot remove advancement from an entry in an audition where advancement is published');
}
$this->entry->for_advancement = 0;
}
}
}