You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.8 KiB

<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreFormSchemaDefinitionRequest;
use App\Http\Requests\Admin\UpdateFormSchemaDefinitionRequest;
use App\Models\Competition;
use App\Models\FormSchemaDefinition;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class FormSchemaDefinitionController extends Controller
{
public function index(Request $request, Competition $competition): JsonResponse
{
$purpose = $request->query('purpose');
$q = FormSchemaDefinition::query()->where('competition_id', $competition->id);
if (in_array($purpose, [FormSchemaDefinition::PURPOSE_SIGNUP, FormSchemaDefinition::PURPOSE_REVIEW], true)) {
$q->where('purpose', $purpose);
}
$rows = $q->orderByDesc('version')->orderByDesc('id')->get();
return response()->json([
'data' => $rows->map(fn (FormSchemaDefinition $s) => $this->toBrief($s, $competition))->values(),
]);
}
public function store(StoreFormSchemaDefinitionRequest $request, Competition $competition): JsonResponse
{
$purpose = $request->validated('purpose');
$nextVersion = (int) FormSchemaDefinition::query()
->where('competition_id', $competition->id)
->where('purpose', $purpose)
->max('version') + 1;
$schema = FormSchemaDefinition::query()->create([
'competition_id' => $competition->id,
'purpose' => $purpose,
'name' => $request->validated('name'),
'version' => $nextVersion,
'schema_json' => $request->validated('schema_json'),
'is_published' => (bool) $request->validated('is_published', false),
]);
return response()->json($this->toDetail($schema, $competition), 201);
}
public function show(Competition $competition, FormSchemaDefinition $formSchema): JsonResponse
{
$this->assertSchemaBelongs($competition, $formSchema);
return response()->json($this->toDetail($formSchema, $competition));
}
public function update(UpdateFormSchemaDefinitionRequest $request, Competition $competition, FormSchemaDefinition $formSchema): JsonResponse
{
$this->assertSchemaBelongs($competition, $formSchema);
$formSchema->fill($request->validated());
$formSchema->save();
return response()->json($this->toDetail($formSchema->fresh(), $competition));
}
public function destroy(Competition $competition, FormSchemaDefinition $formSchema): Response
{
$this->assertSchemaBelongs($competition, $formSchema);
if ((int) $competition->form_schema_id === $formSchema->id
|| (int) $competition->review_form_schema_id === $formSchema->id) {
return response()->json([
'message' => '该版本正被本场赛事使用,请先更换绑定后再删除。',
], 422);
}
$formSchema->delete();
return response()->noContent();
}
private function assertSchemaBelongs(Competition $competition, FormSchemaDefinition $formSchema): void
{
if ((int) $formSchema->competition_id !== (int) $competition->id) {
abort(404);
}
}
/**
* @return array<string, mixed>
*/
private function toBrief(FormSchemaDefinition $s, Competition $competition): array
{
return [
'id' => $s->id,
'competition_id' => $s->competition_id,
'purpose' => $s->purpose,
'name' => $s->name,
'version' => $s->version,
'is_published' => $s->is_published,
'is_current_signup' => (int) $competition->form_schema_id === (int) $s->id,
'is_current_review' => (int) $competition->review_form_schema_id === (int) $s->id,
'field_labels' => $this->extractFieldLabels($s->schema_json ?? []),
'created_at' => $s->created_at?->toIso8601String(),
'updated_at' => $s->updated_at?->toIso8601String(),
];
}
/**
* @return array<string, mixed>
*/
private function toDetail(FormSchemaDefinition $s, Competition $competition): array
{
$row = $this->toBrief($s, $competition);
$row['schema_json'] = $s->schema_json ?? [];
return $row;
}
/**
* @param array<int, mixed> $schemaJson
* @return array<int, string>
*/
private function extractFieldLabels(array $schemaJson): array
{
$labels = [];
foreach ($schemaJson as $item) {
if (is_array($item) && isset($item['label']) && is_string($item['label']) && $item['label'] !== '') {
$labels[] = $item['label'];
}
if (count($labels) >= 12) {
break;
}
}
return $labels;
}
}