/** * @param CheckAction $action */ public function perform(CheckAction $action) { $parser = new Parser(); foreach ($this->getFiles($action->getBasePath()) as $file) { try { $parser->parse(file_get_contents($file->getRealPath())); } catch (ParseException $e) { $action->addError('parser', $e->getMessage(), ['file_name' => $file->getFileName(), 'file_path' => $file->getPathName(), 'training' => $this->getCurrentTraining($file), 'discriminator' => 'training']); $action->addSkip('file', $file->getFileName()); } } }
/** * @param CheckAction $action */ public function perform(CheckAction $action) { $files = $this->getFiles($action->getBasePath()); $parser = new Parser(); foreach ($files as $file) { if (in_array($file->getFileName(), $action->getSkip('file'))) { continue; } $data = $parser->parse(file_get_contents($file->getRealPath())); $context = ['file_name' => $file->getFileName(), 'file_path' => $file->getPathName(), 'discriminator' => 'category', 'training' => $this->getCurrentTraining($file)]; if (!is_array($data)) { $action->addError('structure', 'Output must be type of array, given ' . gettype($data), $context); $action->addSkip('category', $file->getFileName()); continue; } if (empty($data)) { $action->addError('structure', 'Resource file cannot be empty', $context); continue; } //Structure without data can pass if (1 === count($data) && isset($data['category'])) { $action->addSkip('category', $data['category']); continue; } if (empty($data['category'])) { $action->addError('structure', 'Cannot have empty label', $context); } if (!isset($data['questions']) || empty($data['questions'])) { $action->addError('structure', 'Missing questions', $context); $action->addSkip('category', $data['category']); continue; } foreach ($data['questions'] as $questionNode) { $context['discriminator'] = 'question'; if (!isset($questionNode['question'])) { $action->addError('structure', 'Required a question', $context); continue 2; } if (!is_string($questionNode['question'])) { $action->addError('structure', 'Should be a string', $context); continue 2; } if (empty($questionNode['question'])) { $action->addError('structure', 'Cannot have empty label', $context); } if (!isset($questionNode['answers']) || count($questionNode['answers']) <= 1) { $action->addError('structure', 'Must contains at least 2 answers to be valid', $context); continue 2; } $good = 0; foreach ($questionNode['answers'] as $answerNode) { $context['discriminator'] = 'answer'; if (!isset($answerNode['value']) || !is_string($answerNode['value'])) { $action->addError('structure', 'Missing or invalid [value] field', $context); continue 3; } if (empty($answerNode['value'])) { $action->addError('structure', sprintf('Cannot have empty label, related question : "%s"', $questionNode['question']), $context); } if (!isset($answerNode['correct']) || !is_bool($answerNode['correct'])) { $action->addError('structure', 'Missing or invalid [correct] field', $context); continue 3; } if (true === $answerNode['correct']) { $good++; } } if (0 === $good) { $action->addError('structure', 'Must have at least one valid answer', $context); continue 2; } } } }
/** * @param CheckAction $action * * @return Finder */ public function perform(CheckAction $action) { $finder = new Finder(); $files = $finder->in($action->getBasePath() . '/*')->name('context.yml'); $parser = new Parser(); $collector = []; foreach ($files as $context) { $errorContext = ['file_name' => $context->getFileName(), 'file_path' => $context->getPathName(), 'discriminator' => 'context', 'training' => $this->getCurrentTraining($context)]; try { $contextData = $parser->parse(file_get_contents($context->getRealPath())); } catch (ParseException $e) { $action->addError('parser', $e->getMessage(), $errorContext); $action->addSkip('file', $context->getFileName()); continue; } $mandatory = ['name', 'icons', 'label', 'availableLanguages', 'customize', 'threshold', 'defaults']; foreach ($mandatory as $key) { if (!isset($contextData[$key])) { $action->addError('structure', sprintf('Missing required key "%s"', $key), $errorContext); } } if (isset($contextData['name']) && isset($contextData['label'])) { $collector[$this->getCurrentTraining($context) . '=name'][] = $contextData['name']; $collector[$this->getCurrentTraining($context) . '=label'][] = $contextData['label']; } foreach ($contextData as $key => $value) { if (in_array($key, ['name', 'label'])) { if (!is_string($key) || empty($key)) { $action->addError('structure', sprintf('Key "%s" must be type of "string" and not empty', $key), $errorContext); } continue; } if ('availableLanguages' === $key) { if (!is_array($value)) { $action->addError('structure', sprintf('Key "%s" must be type of array with at least one element', $key), $errorContext); continue; } if (0 === count($value)) { $action->addError('structure', sprintf('Key "%s" must contain at least one element', $key), $errorContext); continue; } foreach ($value as $vlKey => $vlValue) { if (!is_string($vlValue)) { $action->addError('structure', sprintf('Child %s of key "%s" must be a string, given "%s"', $vlKey, $key, gettype($vlValue)), $errorContext); continue 2; } } } if ('availableLevels' === $key && null !== $value) { foreach ($value as $vlKey => $vlValue) { if (!is_string($vlValue)) { $action->addError('structure', $errorContext); continue 2; } } } if ('customize' === $key) { $requiredKeys = ['exclude_categories', 'number_of_questions']; foreach ($requiredKeys as $vlValue) { if (!array_key_exists($vlValue, $value)) { $action->addError('structure', sprintf('Mandatory key "%s" missing for parameter "%s"', $vlValue, $key), $errorContext); continue 2; } if (!is_bool($value[$vlValue])) { $action->addError('structure', sprintf('Child "%s" of "%s" must be type of "bool", given "%s"', $vlValue, $key, gettype($value)), $errorContext); continue 2; } } } if ('threshold' === $key && null !== $value) { if (!is_array($value) || empty($value)) { $action->addError('structure', sprintf('Key "%s" must be type of array with at least one element, given "%s"', $key, gettype($value)), $errorContext); continue; } foreach ($value as $vlKey => $vlValue) { if (!is_string($vlKey) || !is_int($vlValue)) { $action->addError('structure', sprintf('Threshold must be like "(string) level_id => (int) score_trigger, given %s => %s"', $vlKey, $vlValue), $errorContext); } } } if ('defaults' === $key) { if (!is_array($value)) { $action->addError('structure', sprintf('Key "%s" must be type of array, given "%s"', $key, gettype($value)), $errorContext); continue; } $childrenRequired = ['language', 'questions_peer_category']; foreach ($childrenRequired as $mandatoryKey) { if (!array_key_exists($mandatoryKey, $value)) { $action->addError('structure', sprintf('Child %s of %s is required', $mandatoryKey, $key), $errorContext); } } foreach ($value as $vlKey => $vlValue) { if (!in_array($vlKey, $childrenRequired)) { $action->addError('structure', sprintf('Unknown %s key', $vlKey), $errorContext); continue 2; } if ('language' === $vlKey) { if (!is_string($vlValue)) { if (!in_array($vlKey, $childrenRequired)) { $action->addError('structure', sprintf('Child %s of %s must be type of "string", given %s', $vlKey, $key, gettype($value)), $errorContext); } } continue 2; } if ('questions_peer_category' === $vlKey) { if (!is_int($vlValue)) { $action->addError('structure', sprintf('Child %s of %s must be type of "integer", given %s', $vlKey, $key, gettype($value)), $errorContext); } continue 2; } } } } } foreach ($collector as $properties => $elements) { list($training, $property) = explode('=', $properties); foreach (array_count_values($elements) as $count) { if ($count > 1) { $action->addError('integrity', sprintf('A training has already the same %s', $property), ['file_name' => 'context.yml', 'training' => $training]); } } } }
/** * @param CheckAction $action */ public function perform(CheckAction $action) { $files = $this->getFiles($action->getBasePath()); $parser = new Parser(); $collector = ['category' => [], 'question' => [], 'answer' => []]; foreach ($files as $file) { if (in_array($file->getFileName(), $action->getSkip('file'))) { continue 1; } $data = $parser->parse(file_get_contents($file->getRealPath())); if (in_array($data['category'], $action->getSkip('category'))) { continue 1; } $trainingName = $this->getCurrentTraining($file); $identifier = implode('=', [$trainingName, $file->getFileName()]); $collector['category'][$identifier] = $data['category']; foreach ($data['questions'] as $questionNode) { if (in_array($questionNode['question'], $action->getSkip('question'))) { continue 2; } $collector['question'][$identifier][] = $questionNode['question']; foreach ($questionNode['answers'] as $answerNode) { if (in_array($answerNode['value'], $action->getSkip('answer'))) { continue 3; } $collector['answer'][$identifier][$questionNode['question']][] = $answerNode['value']; } } } foreach ($collector as $type => $node) { if ($type === 'category') { //flatten foreach (array_count_values($collector[$type]) as $category => $count) { if ($count > 1) { $affected = array_keys($collector[$type], $category); $errorFiles = []; foreach ($affected as $value) { list($training, $file) = explode('=', $value); $errorFiles[] = $file; } $action->addError('integrity', sprintf('Category "%s" was find several times', $category), ['file_name' => $errorFiles, 'discriminator' => 'category', 'training' => $training]); } } } if ($type === 'question') { //nested foreach ($node as $context => $questionsNodes) { list($training, $fileName) = explode('=', $context); foreach (array_count_values($questionsNodes) as $question => $count) { if ($count > 1) { $action->addError('integrity', sprintf('Question "%s" was find several times', $question), ['file_name' => $fileName, 'discriminator' => 'question', 'training' => $training]); } } } } if ($type === 'answer') { //nested foreach ($node as $context => $answerNode) { list($training, $fileName) = explode('=', $context); foreach ($answerNode as $question => $answers) { foreach (array_count_values($answers) as $answer => $count) { if ($count > 1) { $action->addError('integrity', sprintf('Answer "%s" was find several times for question "%s"', $answer, $question), ['file_name' => $fileName, 'discriminator' => 'answer', 'training' => $training]); } } } } } } }