diff --git a/EMS/common-bundle/src/Contracts/SpreadsheetGeneratorServiceInterface.php b/EMS/common-bundle/src/Contracts/SpreadsheetGeneratorServiceInterface.php index 959cf515c..96b05466a 100644 --- a/EMS/common-bundle/src/Contracts/SpreadsheetGeneratorServiceInterface.php +++ b/EMS/common-bundle/src/Contracts/SpreadsheetGeneratorServiceInterface.php @@ -12,6 +12,7 @@ interface SpreadsheetGeneratorServiceInterface public const WRITER = 'writer'; public const XLSX_WRITER = 'xlsx'; public const CSV_WRITER = 'csv'; + public const FORMAT_WRITERS = [self::CSV_WRITER, self::XLSX_WRITER]; public const CSV_SEPARATOR = 'csv_separator'; public const SHEETS = 'sheets'; public const CONTENT_FILENAME = 'filename'; diff --git a/EMS/core-bundle/src/Command/Submission/ExportCommand.php b/EMS/core-bundle/src/Command/Submission/ExportCommand.php new file mode 100644 index 000000000..c52b46a2b --- /dev/null +++ b/EMS/core-bundle/src/Command/Submission/ExportCommand.php @@ -0,0 +1,117 @@ +setDescription('Extract form submissions') + ->addArgument( + self::ARG_FIELDS, + InputArgument::IS_ARRAY, + 'Fields to export' + )->addOption( + self::OPTION_FILTER, + null, + InputOption::VALUE_OPTIONAL, + 'Expression to filter submissions, e.g. "\'true\' == (data[\'recontact-optin\'] ?? \'false\')". The following variables are available: data (array), instance (string), name (string), locale (string), submission_date (date in the ISO 8601 format)' + )->addOption( + self::OPTION_FILENAME, + null, + InputOption::VALUE_OPTIONAL, + 'Export filename, xlsx or csv formats are supported', + ); + } + + protected function initialize(InputInterface $input, OutputInterface $output): void + { + parent::initialize($input, $output); + $this->fields = $this->getArgumentStringArray(self::ARG_FIELDS); + $this->filter = $this->getOptionStringNull(self::OPTION_FILTER); + $this->filename = $this->getOptionStringNull(self::OPTION_FILENAME); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->io->section('Export the form submissions'); + $sheet = []; + + $this->io->progressStart($this->formSubmissionService->count()); + foreach ($this->formSubmissionService->getUnprocessed() as $submission) { + $data = [ + 'instance' => $submission->getInstance(), + 'name' => $submission->getName(), + 'locale' => $submission->getLocale(), + 'submission_date' => $submission->getCreated()->format('c'), + 'data' => $submission->getData() ?? [], + ]; + if (null !== $this->filter && !$this->expressionService->evaluateToBool($this->filter, $data)) { + $this->io->progressAdvance(); + continue; + } + $line = []; + foreach ($this->fields as $field) { + $line[] = $data['data'][$field] ?? $data[$field] ?? ''; + } + $sheet[] = $line; + $this->io->progressAdvance(); + } + $this->io->progressFinish(); + + if (null === $this->filename) { + $this->io->table([...$this->fields], $sheet); + + return self::EXECUTE_SUCCESS; + } + + $extension = \pathinfo($this->filename)['extension'] ?? ''; + if (!\in_array($extension, SpreadsheetGeneratorServiceInterface::FORMAT_WRITERS)) { + $this->io->error(\sprintf('File format %s is not supported', $extension)); + } + + $config = [ + SpreadsheetGeneratorServiceInterface::SHEETS => [[ + 'rows' => [[...$this->fields], ...$sheet], + 'name' => 'submissions', + ]], + SpreadsheetGeneratorServiceInterface::CONTENT_FILENAME => 'submissions', + SpreadsheetGeneratorServiceInterface::WRITER => $extension, + ]; + $this->spreadsheetGeneratorService->generateSpreadsheetFile($config, $this->filename); + $this->io->success(\sprintf('The file %s has been successfully generated', $this->filename)); + + return self::EXECUTE_SUCCESS; + } +} diff --git a/EMS/core-bundle/src/Commands.php b/EMS/core-bundle/src/Commands.php index 22c239381..0f4d5a769 100644 --- a/EMS/core-bundle/src/Commands.php +++ b/EMS/core-bundle/src/Commands.php @@ -43,4 +43,5 @@ final class Commands public const MANAGED_ALIAS_ADD_ENVIRONMENT = 'emsco:managed-alias:add-environment'; public const ASSET_REFRESH_FILE_FIELD = 'emsco:asset:refresh-file-fields'; final public const SUBMISSION_FORWARD = 'emsco:submissions:forward'; + final public const SUBMISSION_EXPORT = 'emsco:submissions:export'; } diff --git a/EMS/core-bundle/src/Repository/FormSubmissionRepository.php b/EMS/core-bundle/src/Repository/FormSubmissionRepository.php index 8e74613e1..2ce93f1d2 100644 --- a/EMS/core-bundle/src/Repository/FormSubmissionRepository.php +++ b/EMS/core-bundle/src/Repository/FormSubmissionRepository.php @@ -57,7 +57,7 @@ public function findAllUnprocessed(): array ->andWhere($qb->expr()->isNotNull('fs.data')) ->orderBy('fs.created', 'desc'); - return $qb->getQuery()->getArrayResult(); + return $qb->getQuery()->execute(); } public function countAllUnprocessed(string $searchValue): int @@ -105,7 +105,7 @@ public function findFormSubmissions(?string $formInstance = null): array ->andWhere($qb->expr()->isNotNull('fs.data')) ->orderBy('fs.created', 'desc'); - return $qb->getQuery()->getArrayResult(); + return $qb->getQuery()->execute(); } public function persist(FormSubmission $formSubmission): void diff --git a/EMS/core-bundle/src/Resources/config/command.xml b/EMS/core-bundle/src/Resources/config/command.xml index 9ecf67348..4b3465b08 100644 --- a/EMS/core-bundle/src/Resources/config/command.xml +++ b/EMS/core-bundle/src/Resources/config/command.xml @@ -260,6 +260,12 @@ + + + + + +