getLogger(); $decorator = new CvsToQtiTemplateDecorator($csvTemplate); $validationConfig = $decorator->getCsvColumns(); $errors = []; foreach ($validationConfig as $headerRegex => $validations) { $validations = explode('|', $validationConfig[$headerRegex]['header']); $isRequired = $this->isRequired($validations); $minOccurrences = $this->getMinOccurrences($validations); $occurrences = $this->findOccurrences($content, $headerRegex); $totalOccurrences = count($occurrences); foreach ($this->getMissingMatches($headerRegex, $validations, $content, $occurrences) as $missingMatch) { $errors[] = new ErrorValidationException( 'Header `%s` is required', [ $missingMatch, ] ); $logger->debug(sprintf('Tabular import: Header `%s` is required', $missingMatch)); } if ($isRequired && $totalOccurrences === 0) { $errors[] = new ErrorValidationException( 'Header `%s` is required', [ $headerRegex ] ); $logger->debug(sprintf('Tabular import: Header `%s` is required', $headerRegex)); } if ($totalOccurrences < $minOccurrences) { $errors[] = new ErrorValidationException( 'Header `%s` must be provided at least `%s` times', [ $headerRegex, $minOccurrences, ] ); $logger->debug( sprintf( 'Tabular import: Header `%s` must be provided at least `%s` times', $headerRegex, $minOccurrences ) ); } } if (count($errors) > 0) { throw new AggregatedValidationException($errors, []); } } private function isRequired(array $validations): bool { return in_array('required', $validations); } private function getMinOccurrences(array $validations): int { foreach ($validations as $validation) { if (strpos($validation, 'min_occurrences:') !== false) { return (int)str_replace('min_occurrences:', '', $validation); } } return 0; } private function getMissingMatches( string $headerRegex, array $validations, array $headers, array $occurrences ): array { $matchHeader = $this->getMatchHeader($validations); if ($matchHeader === null) { return []; } $missingColumns = []; foreach ($occurrences as $occurrence) { $search = $this->getSearchMatch($headerRegex, $matchHeader, $occurrence); $found = false; foreach ($headers as $header) { if ($header === $search) { $found = true; break; } } if (!$found) { $missingColumns[] = $search; } } return $missingColumns; } private function getSearchMatch(string $headerRegex, string $matchHeader, string $occurrence): string { $open = strpos($headerRegex, '['); $close = strpos($headerRegex, ']'); $regex = substr($headerRegex, $open + 1, $close - $open - 1); $number = (int)preg_replace('/[^' . $regex . ']/', '', $occurrence); return str_replace('[' . $regex . ']', $number, $matchHeader); } private function getMatchHeader(array $validations): ?string { foreach ($validations as $validation) { if (strpos($validation, 'match_header:') !== false) { return str_replace('match_header:', '', $validation); } } return null; } private function findOccurrences(array $header, string $headerRegex): array { $occurrences = []; foreach ($header as $headerName) { if (preg_match('/\b(' . $headerRegex . ')\b/', (string)$headerName) === 1) { $occurrences[] = $headerName; } } return $occurrences; } }