routeParser->urlFor('admin_quiz_list'); } protected function submitLabel(): string { return '作成'; } /** * @return list */ protected function items(): array { return [ new FormItem( name: 'title', type: 'text', label: 'タイトル', isRequired: true, ), new FormItem( name: 'slug', type: 'text', label: 'スラグ', isRequired: true, ), new FormItem( name: 'description', type: 'textarea', label: '説明', isRequired: true, extra: 'rows=3 cols=80', ), new FormItem( name: 'example_code', type: 'textarea', label: '実装例', isRequired: true, extra: 'rows=10 cols=80', ), new FormItem( name: 'birdie_code_size', type: 'text', label: 'バーディになるコードサイズ (byte)', ), new FormItem( name: 'started_at', type: 'datetime-local', label: '開始日時 (JST)', isRequired: true, ), new FormItem( name: 'ranking_hidden_at', type: 'datetime-local', label: 'ランキングが非表示になる日時 (JST)', isRequired: true, ), new FormItem( name: 'finished_at', type: 'datetime-local', label: '終了日時 (JST)', isRequired: true, ), ]; } public function submit(): void { $title = $this->state->get('title') ?? ''; $slug = $this->state->get('slug') ?? ''; $description = $this->state->get('description') ?? ''; $example_code = $this->state->get('example_code') ?? ''; $birdie_code_size = $this->state->get('birdie_code_size') ?? ''; $started_at = $this->state->get('started_at') ?? ''; $ranking_hidden_at = $this->state->get('ranking_hidden_at') ?? ''; $finished_at = $this->state->get('finished_at') ?? ''; $errors = []; if ($birdie_code_size !== '' && !is_numeric($birdie_code_size)) { $errors['birdie_code_size'] = '数値を入力してください'; $birdie_code_size = ''; // dummy } if ($started_at === '') { $errors['started_at'] = '開始日時は必須です'; } else { $started_at = DateTimeImmutable::createFromFormat( 'Y-m-d\TH:i', $started_at, new DateTimeZone('Asia/Tokyo'), ); if ($started_at === false) { $errors['started_at'] = '開始日時の形式が不正です'; } else { $started_at = $started_at->setTimezone(new DateTimeZone('UTC')); } } if (!$started_at instanceof DateTimeImmutable) { $started_at = new DateTimeImmutable('now', new DateTimeZone('UTC')); // dummy } if ($ranking_hidden_at === '') { $errors['ranking_hidden_at'] = 'ランキングが非表示になる日時は必須です'; } else { $ranking_hidden_at = DateTimeImmutable::createFromFormat( 'Y-m-d\TH:i', $ranking_hidden_at, new DateTimeZone('Asia/Tokyo'), ); if ($ranking_hidden_at === false) { $errors['ranking_hidden_at'] = 'ランキングが非表示になる日時の形式が不正です'; } else { $ranking_hidden_at = $ranking_hidden_at->setTimezone(new DateTimeZone('UTC')); } } if (!$ranking_hidden_at instanceof DateTimeImmutable) { $ranking_hidden_at = new DateTimeImmutable('now', new DateTimeZone('UTC')); // dummy } if ($finished_at === '') { $errors['finished_at'] = '終了日時は必須です'; } else { $finished_at = DateTimeImmutable::createFromFormat( 'Y-m-d\TH:i', $finished_at, new DateTimeZone('Asia/Tokyo'), ); if ($finished_at === false) { $errors['finished_at'] = '終了日時の形式が不正です'; } else { $finished_at = $finished_at->setTimezone(new DateTimeZone('UTC')); } } if (!$finished_at instanceof DateTimeImmutable) { $finished_at = new DateTimeImmutable('now', new DateTimeZone('UTC')); // dummy } if (0 < count($errors)) { $this->state->setErrors($errors); throw new FormSubmissionFailureException(); } try { $this->quizRepo->create( $title, $slug, $description, $example_code, $birdie_code_size === '' ? null : (int)$birdie_code_size, $started_at, $ranking_hidden_at, $finished_at, ); } catch (EntityValidationException $e) { $this->state->setErrors($e->toFormErrors()); throw new FormSubmissionFailureException(previous: $e); } } }