f83f21936f
API CI/CD / Validate (composer + pint) (push) Successful in 3m30s
API CI/CD / Test (PHPUnit) (push) Failing after 5m4s
API CI/CD / Build frontend assets (push) Successful in 1m1s
API CI/CD / Security audit (push) Failing after 49s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
107 lines
4.0 KiB
PHP
107 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use App\Services\SchoolYears\SelectedSchoolYearContextService;
|
|
use App\Services\SchoolYears\SchoolYearWriteGuard;
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class EnsureSchoolYearEditable
|
|
{
|
|
public function __construct(
|
|
private SchoolYearWriteGuard $guard,
|
|
private SelectedSchoolYearContextService $selectedSchoolYear
|
|
) {}
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
if (! in_array(strtoupper($request->method()), ['POST', 'PUT', 'PATCH', 'DELETE'], true)) {
|
|
return $next($request);
|
|
}
|
|
|
|
try {
|
|
$this->guard->assertEditable($this->resolveSchoolYears($request));
|
|
} catch (HttpExceptionInterface $e) {
|
|
return response()->json([
|
|
'ok' => false,
|
|
'message' => $e->getMessage(),
|
|
], $e->getStatusCode());
|
|
} catch (\RuntimeException $e) {
|
|
return response()->json([
|
|
'ok' => false,
|
|
'message' => $e->getMessage(),
|
|
], Response::HTTP_CONFLICT);
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
private function resolveSchoolYears(Request $request): array
|
|
{
|
|
$years = [];
|
|
|
|
try {
|
|
$years[] = $this->selectedSchoolYear->fromRequest($request)->name;
|
|
} catch (HttpExceptionInterface $e) {
|
|
if ($e->getStatusCode() !== Response::HTTP_UNPROCESSABLE_ENTITY
|
|
|| $e->getMessage() !== 'A school_year value is required.') {
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
$currentSchoolYear = $request->input('current_school_year', $request->query('current_school_year'));
|
|
if (is_string($currentSchoolYear) && trim($currentSchoolYear) !== '') {
|
|
$years[] = trim($currentSchoolYear);
|
|
}
|
|
|
|
$routeYears = [
|
|
['param' => 'invoiceId', 'table' => 'invoices', 'column' => 'school_year'],
|
|
['param' => 'invoice', 'table' => 'invoices', 'column' => 'school_year'],
|
|
['param' => 'paymentId', 'table' => 'payments', 'column' => 'school_year'],
|
|
['param' => 'payment', 'table' => 'payments', 'column' => 'school_year'],
|
|
['param' => 'refundId', 'table' => 'refunds', 'column' => 'school_year'],
|
|
['param' => 'refund', 'table' => 'refunds', 'column' => 'school_year'],
|
|
['param' => 'promotionId', 'table' => 'student_promotion_records', 'column' => 'current_school_year'],
|
|
['param' => 'promotion', 'table' => 'student_promotion_records', 'column' => 'current_school_year'],
|
|
['param' => 'eventCharge', 'table' => 'event_charges', 'column' => 'school_year'],
|
|
['param' => 'eventId', 'table' => 'events', 'column' => 'school_year'],
|
|
['param' => 'classSection', 'table' => 'classSection', 'column' => 'school_year'],
|
|
['param' => 'classSectionId', 'table' => 'classSection', 'column' => 'school_year'],
|
|
];
|
|
|
|
foreach ($routeYears as $mapping) {
|
|
$value = $request->route($mapping['param']);
|
|
if ($value === null || $value === '') {
|
|
continue;
|
|
}
|
|
|
|
$resolved = $this->lookupYear((string) $value, $mapping['table'], $mapping['column']);
|
|
if ($resolved !== null) {
|
|
$years[] = $resolved;
|
|
}
|
|
}
|
|
return $years;
|
|
}
|
|
|
|
private function lookupYear(string $id, string $table, string $column): ?string
|
|
{
|
|
if (! ctype_digit($id) || ! DB::getSchemaBuilder()->hasTable($table)) {
|
|
return null;
|
|
}
|
|
|
|
$primaryKey = match ($table) {
|
|
'classSection' => 'class_section_id',
|
|
'student_promotion_records' => 'promotion_id',
|
|
default => 'id',
|
|
};
|
|
|
|
$value = DB::table($table)->where($primaryKey, (int) $id)->value($column);
|
|
|
|
return is_string($value) && trim($value) !== '' ? trim($value) : null;
|
|
}
|
|
}
|