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 @@
+
+
+
+
+
+