|
27 | 27 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
28 | 28 | use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; |
29 | 29 | use Symfony\Component\PropertyAccess\PropertyAccess; |
| 30 | +use Symfony\Component\PropertyAccess\PropertyAccessor; |
30 | 31 | use Symfony\Component\Validator\ConstraintViolationInterface; |
31 | 32 | use Symfony\Component\Validator\Validator\ValidatorInterface; |
32 | 33 | use Symfony\Component\Yaml\Yaml; |
@@ -261,72 +262,12 @@ public function importZippedProblem( |
261 | 262 | return null; |
262 | 263 | } |
263 | 264 |
|
264 | | - if ($problemYaml !== false) { |
265 | | - $yamlData = Yaml::parse($problemYaml); |
266 | | - |
267 | | - if (!empty($yamlData)) { |
268 | | - $yamlProblemProperties = []; |
269 | | - if (isset($yamlData['name'])) { |
270 | | - if (is_array($yamlData['name'])) { |
271 | | - foreach ($yamlData['name'] as $name) { |
272 | | - // TODO: select a specific instead of the first language. |
273 | | - $yamlProblemProperties['name'] = $name; |
274 | | - break; |
275 | | - } |
276 | | - } else { |
277 | | - $yamlProblemProperties['name'] = $yamlData['name']; |
278 | | - } |
279 | | - } |
280 | | - |
281 | | - if (isset($yamlData['type'])) { |
282 | | - $types = explode(' ', $yamlData['type']); |
283 | | - // Validation happens later when we set the properties. |
284 | | - $yamlProblemProperties['typesAsString'] = $types; |
285 | | - } else { |
286 | | - $yamlProblemProperties['typesAsString'] = ['pass-fail']; |
287 | | - } |
288 | | - |
289 | | - if (isset($yamlData['validator_flags'])) { |
290 | | - $yamlProblemProperties['special_compare_args'] = $yamlData['validator_flags']; |
291 | | - } |
292 | | - |
293 | | - if (isset($yamlData['validation']) |
294 | | - && ($yamlData['validation'] == 'custom' || |
295 | | - $yamlData['validation'] == 'custom interactive' || |
296 | | - $yamlData['validation'] == 'custom multi-pass')) { |
297 | | - if (!$this->searchAndAddValidator($zip, $messages, $externalId, $yamlData['validation'], $problem)) { |
298 | | - return null; |
299 | | - } |
300 | | - |
301 | | - if ($yamlData['validation'] == 'custom multi-pass') { |
302 | | - $yamlProblemProperties['typesAsString'][] = 'multi-pass'; |
303 | | - } |
304 | | - if ($yamlData['validation'] == 'custom interactive') { |
305 | | - $yamlProblemProperties['typesAsString'][] = 'interactive'; |
306 | | - } |
307 | | - } |
308 | | - |
309 | | - if (isset($yamlData['limits'])) { |
310 | | - if (isset($yamlData['limits']['memory'])) { |
311 | | - $yamlProblemProperties['memlimit'] = 1024 * $yamlData['limits']['memory']; |
312 | | - } |
313 | | - if (isset($yamlData['limits']['output'])) { |
314 | | - $yamlProblemProperties['outputlimit'] = 1024 * $yamlData['limits']['output']; |
315 | | - } |
316 | | - if (isset($yamlData['limits']['validation_passes'])) { |
317 | | - $problem->setMultipassLimit($yamlData['limits']['validation_passes']); |
318 | | - } |
319 | | - } |
320 | | - |
321 | | - foreach ($yamlProblemProperties as $key => $value) { |
322 | | - try { |
323 | | - $propertyAccessor->setValue($problem, $key, $value); |
324 | | - } catch (Exception $e) { |
325 | | - $messages['danger'][] = sprintf('Error: problem.%s: %s', $key, $e->getMessage()); |
326 | | - return null; |
327 | | - } |
328 | | - } |
329 | | - } |
| 265 | + $validationMode = 'default'; |
| 266 | + if (!$this->parseYaml($problemYaml, $messages, $validationMode, $propertyAccessor, $problem)) { |
| 267 | + return null; |
| 268 | + } |
| 269 | + if ($validationMode != 'default' && !$this->searchAndAddValidator($zip, $messages, $externalId, $validationMode, $problem)) { |
| 270 | + return null; |
330 | 271 | } |
331 | 272 |
|
332 | 273 | // Add problem statement, also look in obsolete location. |
@@ -1047,4 +988,82 @@ private function searchAndAddValidator(ZipArchive $zip, ?array &$messages, strin |
1047 | 988 | } |
1048 | 989 | return true; |
1049 | 990 | } |
| 991 | + |
| 992 | + // Returns true iff the yaml could be parsed correctly. |
| 993 | + public static function parseYaml(bool|string $problemYaml, array &$messages, string &$validationMode, PropertyAccessor $propertyAccessor, Problem $problem): bool |
| 994 | + { |
| 995 | + if ($problemYaml === false) { |
| 996 | + // While there was no problem.yaml, there was also no error in parsing. |
| 997 | + return true; |
| 998 | + } |
| 999 | + |
| 1000 | + $yamlData = Yaml::parse($problemYaml); |
| 1001 | + if (empty($yamlData)) { |
| 1002 | + // Empty yaml is OK. |
| 1003 | + return true; |
| 1004 | + } |
| 1005 | + |
| 1006 | + $yamlProblemProperties = []; |
| 1007 | + if (isset($yamlData['name'])) { |
| 1008 | + if (is_array($yamlData['name'])) { |
| 1009 | + foreach ($yamlData['name'] as $name) { |
| 1010 | + // TODO: select a specific instead of the first language. |
| 1011 | + $yamlProblemProperties['name'] = $name; |
| 1012 | + break; |
| 1013 | + } |
| 1014 | + } else { |
| 1015 | + $yamlProblemProperties['name'] = $yamlData['name']; |
| 1016 | + } |
| 1017 | + } |
| 1018 | + |
| 1019 | + if (isset($yamlData['type'])) { |
| 1020 | + $types = explode(' ', $yamlData['type']); |
| 1021 | + // Validation happens later when we set the properties. |
| 1022 | + $yamlProblemProperties['typesAsString'] = $types; |
| 1023 | + } else { |
| 1024 | + $yamlProblemProperties['typesAsString'] = ['pass-fail']; |
| 1025 | + } |
| 1026 | + |
| 1027 | + if (isset($yamlData['validator_flags'])) { |
| 1028 | + $yamlProblemProperties['special_compare_args'] = $yamlData['validator_flags']; |
| 1029 | + } |
| 1030 | + |
| 1031 | + $validationMode = 'default'; |
| 1032 | + if (isset($yamlData['validation']) |
| 1033 | + && ($yamlData['validation'] == 'custom' || |
| 1034 | + $yamlData['validation'] == 'custom interactive' || |
| 1035 | + $yamlData['validation'] == 'custom multi-pass')) { |
| 1036 | + $validationMode = $yamlData['validation']; |
| 1037 | + |
| 1038 | + if ($yamlData['validation'] == 'custom multi-pass') { |
| 1039 | + $yamlProblemProperties['typesAsString'][] = 'multi-pass'; |
| 1040 | + } |
| 1041 | + if ($yamlData['validation'] == 'custom interactive') { |
| 1042 | + $yamlProblemProperties['typesAsString'][] = 'interactive'; |
| 1043 | + } |
| 1044 | + } |
| 1045 | + |
| 1046 | + if (isset($yamlData['limits'])) { |
| 1047 | + if (isset($yamlData['limits']['memory'])) { |
| 1048 | + $yamlProblemProperties['memlimit'] = 1024 * $yamlData['limits']['memory']; |
| 1049 | + } |
| 1050 | + if (isset($yamlData['limits']['output'])) { |
| 1051 | + $yamlProblemProperties['outputlimit'] = 1024 * $yamlData['limits']['output']; |
| 1052 | + } |
| 1053 | + if (isset($yamlData['limits']['validation_passes'])) { |
| 1054 | + $yamlProblemProperties['multipassLimit'] = $yamlData['limits']['validation_passes']; |
| 1055 | + } |
| 1056 | + } |
| 1057 | + |
| 1058 | + foreach ($yamlProblemProperties as $key => $value) { |
| 1059 | + try { |
| 1060 | + $propertyAccessor->setValue($problem, $key, $value); |
| 1061 | + } catch (Exception $e) { |
| 1062 | + $messages['danger'][] = sprintf('Error: problem.%s: %s', $key, $e->getMessage()); |
| 1063 | + return false; |
| 1064 | + } |
| 1065 | + } |
| 1066 | + |
| 1067 | + return true; |
| 1068 | + } |
1050 | 1069 | } |
0 commit comments