/**
  * フィールド単体の構文解析を行います。
  * @param string $fieldName フィールド名。未知のフィールド名が指定された場合はそのまま返します。
  * @param string $field フィールド値。
  * @return string|string[]|float|null 矯正したフィールド値を返します。矯正の結果フィールドの削除が生じるときは null を返します。
  */
 protected function parseField(string $fieldName, string $field)
 {
     switch ($fieldName) {
         case 'image':
         case 'audio':
         case 'video':
             $validator = new FileLocationValidator($fieldName, $this->filenames);
             $validator->setLogger($this->logger);
             $output = $validator->correct($field);
             break;
         case 'image-source':
         case 'audio-source':
         case 'video-source':
             $validator = new LightweightMarkupValidator(true);
             $validator->setLogger($this->logger);
             $output = $validator->correct($field);
             if ($output !== '') {
                 $output = ['lml' => $output, 'html' => (new HTMLFilter())->filter((new CommonMarkConverter())->convertToHtml($output))];
             }
             break;
         case 'answer':
         case 'option':
             $validator = new AnswerValidator();
             $validator->setLogger($this->logger);
             $output = $validator->correct($field);
             break;
         case 'description':
         case '@summary':
             $validator = new LightweightMarkupValidator(false, $this->filenames);
             $validator->setLogger($this->logger);
             $output = $validator->correct($field);
             if ($output !== '') {
                 $output = ['lml' => $output, 'html' => (new HTMLFilter())->filter((new CommonMarkConverter())->convertToHtml($output))];
             }
             break;
         case 'weight':
             $validator = new NumberValidator(true);
             $validator->setLogger($this->logger);
             $number = $validator->correct($field);
             if ($number > 0) {
                 $output = $number;
             } else {
                 $this->logger->error(sprintf(_('「%s」は0より大きい実数として扱えません。'), $field));
                 $output = '';
             }
             if ($output !== '') {
                 $output = (double) $output;
             }
             break;
         case 'specifics':
             $validator = new SpecificsValidator();
             $validator->setLogger($this->logger);
             $output = $validator->correct($field);
             break;
         case '@regard':
             if (preg_match('/^\\[.{3,}]$/u', $field) === 1 && (new AnswerValidator())->validateRegexp("/{$field}/")) {
                 $output = $field;
             } else {
                 $this->logger->error(sprintf(_('「%s」は妥当な正規表現文字クラスではありません。'), $field));
                 $output = '';
             }
             break;
         default:
             $output = $field;
     }
     $correctedField = is_array($output) ? $output['lml'] : $output;
     $fieldLength = mb_strlen($correctedField, 'UTF-8');
     $maxFieldLength = in_array($fieldName, self::MARKUP_FIELD_NAMES) ? self::MAX_MARKUP_FIELD_LENGTH : self::MAX_FIELD_LENGTH;
     if ($fieldLength > $maxFieldLength) {
         throw new SyntaxException(sprintf(_('「%1$s」フィールドの値は%2$d文字です。%3$d文字以内にしなければなりません:'), $fieldName, $fieldLength, $maxFieldLength) . "\n{$correctedField}");
     }
     return $output === '' ? null : $output;
 }
 public function correct(string $input) : string
 {
     $nameValues = $this->parse($input);
     if ($nameValues) {
         $params = new URLSearchParams();
         foreach ($nameValues as $name => $values) {
             foreach ($values as $value) {
                 switch ($name) {
                     // 空文字列
                     case 'pixelization':
                     case 'require-all-right':
                     case 'no-random':
                         $params->append($name, '');
                         break;
                         // 0より大きい実数
                     // 0より大きい実数
                     case 'magnification':
                     case 'last-magnification':
                     case 'length':
                     case 'speed':
                     case 'volume':
                         $validator = new NumberValidator(true);
                         $validator->setLogger($this->logger);
                         $number = $validator->correct($value);
                         if ($number !== '' && $number > 0) {
                             $params->append($name, $number);
                         } else {
                             $this->logger->error(sprintf(_('「%s」は0より大きい実数として扱えません。'), $value));
                         }
                         break;
                         // 0以上の実数
                     // 0以上の実数
                     case 'start':
                         $validator = new NumberValidator(true);
                         $validator->setLogger($this->logger);
                         $number = $validator->correct($value);
                         if ($number !== '' && $number >= 0) {
                             $params->append($name, $number);
                         } else {
                             $this->logger->error(sprintf(_('「%s」は0以上の実数として扱えません。'), $value));
                         }
                         break;
                         // 1以上の整数
                     // 1以上の整数
                     case 'repeat':
                     case 'score':
                     case 'last-score':
                         $validator = new NumberValidator();
                         $validator->setLogger($this->logger);
                         $number = $validator->correct($value);
                         if ($number !== '' && $number >= 1) {
                             $params->append($name, $number);
                         } else {
                             $this->logger->error(sprintf(_('「%s」は1以上の整数として扱えません。'), $value));
                         }
                         break;
                         // 整数
                     // 整数
                     case 'bonus':
                         $validator = new NumberValidator();
                         $validator->setLogger($this->logger);
                         $number = $validator->correct($value);
                         if ($number !== '') {
                             $params->append($name, $number);
                         } else {
                             $this->logger->error(sprintf(_('「%s」は整数として扱えません。'), $value));
                         }
                         break;
                     default:
                         $params->append($name, $value);
                 }
             }
         }
         foreach (self::DEPENDENCES as $source => $destination) {
             if ($params->has($source) && !$params->has($destination)) {
                 $params->delete($source);
                 // TRANRATORS: %1$s、%2$s はapplication/x-www-form-urlencoded形式の名前部分
                 $this->logger->error(sprintf(_('「%1$s」を指定するときは、「%2$s」も指定しておく必要があります。'), $source, $destination));
             }
         }
         $output = (string) $params;
     } else {
         $this->logger->error(_('解析した結果空文字列になりました。'));
     }
     return $output ?? '';
 }