Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(admin/submission): add export command filter by expression #1085

Merged
merged 10 commits into from
Dec 2, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
117 changes: 117 additions & 0 deletions EMS/core-bundle/src/Command/Submission/ExportCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

declare(strict_types=1);

namespace EMS\CoreBundle\Command\Submission;

use EMS\CommonBundle\Common\Command\AbstractCommand;
use EMS\CommonBundle\Contracts\SpreadsheetGeneratorServiceInterface;
use EMS\CommonBundle\Service\ExpressionService;
use EMS\CoreBundle\Commands;
use EMS\CoreBundle\Service\Form\Submission\FormSubmissionService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class ExportCommand extends AbstractCommand
{
protected static $defaultName = Commands::SUBMISSION_EXPORT;
public const ARG_FIELDS = 'fields';
public const OPTION_FILTER = 'filter';
public const OPTION_FILENAME = 'filename';

/** @var string[] */
private array $fields;
private ?string $filter;
private ?string $filename;

public function __construct(
private readonly FormSubmissionService $formSubmissionService,
private readonly ExpressionService $expressionService,
private readonly SpreadsheetGeneratorServiceInterface $spreadsheetGeneratorService,
) {
parent::__construct();
}

protected function configure(): void
{
$this
->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;
}
}
1 change: 1 addition & 0 deletions EMS/core-bundle/src/Commands.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
4 changes: 2 additions & 2 deletions EMS/core-bundle/src/Repository/FormSubmissionRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions EMS/core-bundle/src/Resources/config/command.xml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@
<argument type="service" id="ems.form_submission"/>
<tag name="console.command"/>
</service>
<service id="ems.submission.export" class="EMS\CoreBundle\Command\Submission\ExportCommand">
<argument type="service" id="ems.form_submission"/>
<argument type="service" id="ems_common.service.expression_service"/>
<argument type="service" id="EMS\CommonBundle\Contracts\SpreadsheetGeneratorServiceInterface"/>
<tag name="console.command"/>
</service>
<service id="ems.environment.updatemetafield" class="EMS\CoreBundle\Command\UpdateMetaFieldCommand">
<argument type="service" id="doctrine"/>
<argument type="service" id="logger"/>
Expand Down
Loading