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
141 lines
4.8 KiB
|
1 month ago
|
<?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;
|
||
|
|
}
|
||
|
|
}
|