mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-01 14:36:13 +00:00
Refactor SpreadsheetListFormatter
to avoid race condition
improve label caching, enhance type safety, and streamline header generation and value handling.
This commit is contained in:
parent
d4704dc2ef
commit
95ccfff868
@ -2154,11 +2154,6 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php
|
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadSheetFormatter.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Instanceof between string and DateTimeInterface will always evaluate to false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^PHPDoc tag @var for property Chill\\\\MainBundle\\\\Export\\\\Helper\\\\ExportAddressHelper\\:\\:\\$unitNamesKeysCache contains unresolvable type\\.$#"
|
message: "#^PHPDoc tag @var for property Chill\\\\MainBundle\\\\Export\\\\Helper\\\\ExportAddressHelper\\:\\:\\$unitNamesKeysCache contains unresolvable type\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -24,6 +24,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
|||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Contracts\Translation\TranslatableInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,21 +34,6 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
{
|
{
|
||||||
use ExportManagerAwareTrait;
|
use ExportManagerAwareTrait;
|
||||||
|
|
||||||
protected $exportAlias;
|
|
||||||
|
|
||||||
protected $exportData;
|
|
||||||
|
|
||||||
protected $formatterData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This variable cache the labels internally.
|
|
||||||
*
|
|
||||||
* @var string[]
|
|
||||||
*/
|
|
||||||
protected $labelsCache;
|
|
||||||
|
|
||||||
protected $result;
|
|
||||||
|
|
||||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,29 +95,25 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
|
|
||||||
public function generate($result, $formatterData, string $exportAlias, array $exportData, array $filtersData, array $aggregatorsData, ExportGenerationContext $context): FormattedExportGeneration
|
public function generate($result, $formatterData, string $exportAlias, array $exportData, array $filtersData, array $aggregatorsData, ExportGenerationContext $context): FormattedExportGeneration
|
||||||
{
|
{
|
||||||
$this->result = $result;
|
|
||||||
$this->exportAlias = $exportAlias;
|
|
||||||
$this->exportData = $exportData;
|
|
||||||
$this->formatterData = $formatterData;
|
|
||||||
|
|
||||||
$spreadsheet = new Spreadsheet();
|
$spreadsheet = new Spreadsheet();
|
||||||
$worksheet = $spreadsheet->getActiveSheet();
|
$worksheet = $spreadsheet->getActiveSheet();
|
||||||
|
$cacheLabels = $this->prepareCacheLabels($result, $exportAlias, $exportData);
|
||||||
|
|
||||||
$this->prepareHeaders($worksheet);
|
$this->prepareHeaders($cacheLabels, $worksheet, $result, $formatterData, $exportAlias, $exportData);
|
||||||
|
|
||||||
$i = 1;
|
$i = 1;
|
||||||
|
|
||||||
foreach ($result as $row) {
|
foreach ($result as $row) {
|
||||||
if (true === $this->formatterData['numerotation']) {
|
if (true === $formatterData['numerotation']) {
|
||||||
$worksheet->setCellValue('A'.($i + 1), (string) $i);
|
$worksheet->setCellValue('A'.($i + 1), (string) $i);
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = $this->formatterData['numerotation'] ? 'B' : 'A';
|
$a = $formatterData['numerotation'] ? 'B' : 'A';
|
||||||
|
|
||||||
foreach ($row as $key => $value) {
|
foreach ($row as $key => $value) {
|
||||||
$row = $a.($i + 1);
|
$row = $a.($i + 1);
|
||||||
|
|
||||||
$formattedValue = $this->getLabel($key, $value);
|
$formattedValue = $this->getLabel($cacheLabels, $key, $value, $result, $exportAlias, $exportData);
|
||||||
|
|
||||||
if ($formattedValue instanceof \DateTimeInterface) {
|
if ($formattedValue instanceof \DateTimeInterface) {
|
||||||
$worksheet->setCellValue($row, Date::PHPToExcel($formattedValue));
|
$worksheet->setCellValue($row, Date::PHPToExcel($formattedValue));
|
||||||
@ -145,6 +127,8 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
->getNumberFormat()
|
->getNumberFormat()
|
||||||
->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME);
|
->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME);
|
||||||
}
|
}
|
||||||
|
} elseif ($formattedValue instanceof TranslatableInterface) {
|
||||||
|
$worksheet->setCellValue($row, $formattedValue->trans($this->translator));
|
||||||
} else {
|
} else {
|
||||||
$worksheet->setCellValue($row, $formattedValue);
|
$worksheet->setCellValue($row, $formattedValue);
|
||||||
}
|
}
|
||||||
@ -154,7 +138,7 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
++$i;
|
++$i;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->formatterData['format']) {
|
switch ($formatterData['format']) {
|
||||||
case 'ods':
|
case 'ods':
|
||||||
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Ods');
|
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Ods');
|
||||||
$contentType = 'application/vnd.oasis.opendocument.spreadsheet';
|
$contentType = 'application/vnd.oasis.opendocument.spreadsheet';
|
||||||
@ -177,7 +161,7 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
default:
|
default:
|
||||||
// this should not happen
|
// this should not happen
|
||||||
// throw an exception to ensure that the error is catched
|
// throw an exception to ensure that the error is catched
|
||||||
throw new \OutOfBoundsException('The format '.$this->formatterData['format'].' is not supported');
|
throw new \OutOfBoundsException('The format '.$formatterData['format'].' is not supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
$tempfile = \tempnam(\sys_get_temp_dir(), '');
|
$tempfile = \tempnam(\sys_get_temp_dir(), '');
|
||||||
@ -230,34 +214,34 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
/**
|
/**
|
||||||
* Give the label corresponding to the given key and value.
|
* Give the label corresponding to the given key and value.
|
||||||
*
|
*
|
||||||
* @param string $key
|
|
||||||
* @param string $value
|
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string|\DateTimeInterface|int|null|float|TranslatableInterface
|
||||||
*
|
*
|
||||||
* @throws \LogicException if the label is not found
|
* @throws \LogicException if the label is not found
|
||||||
*/
|
*/
|
||||||
protected function getLabel($key, $value)
|
private function getLabel(array $labelsCache, $key, $value, array $result, string $exportAlias, array $exportData)
|
||||||
{
|
{
|
||||||
if (null === $this->labelsCache) {
|
if (!\array_key_exists($key, $labelsCache)) {
|
||||||
$this->prepareCacheLabels();
|
throw new \OutOfBoundsException(sprintf('The key "%s" is not present in the list of keys handled by this query. Check your `getKeys` and `getLabels` methods. Available keys are %s.', $key, \implode(', ', \array_keys($labelsCache))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\array_key_exists($key, $this->labelsCache)) {
|
return $labelsCache[$key]($value);
|
||||||
throw new \OutOfBoundsException(sprintf('The key "%s" is not present in the list of keys handled by this query. Check your `getKeys` and `getLabels` methods. Available keys are %s.', $key, \implode(', ', \array_keys($this->labelsCache))));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->labelsCache[$key]($value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the label cache which will be used by getLabel. This function
|
* Prepare the label cache which will be used by getLabel.
|
||||||
* should be called only once in the generation lifecycle.
|
*
|
||||||
|
* @param array $result
|
||||||
|
* @param string $exportAlias
|
||||||
|
* @param array $exportData
|
||||||
|
*
|
||||||
|
* @return array The labels cache
|
||||||
*/
|
*/
|
||||||
protected function prepareCacheLabels()
|
private function prepareCacheLabels(array $result, string $exportAlias, array $exportData): array
|
||||||
{
|
{
|
||||||
$export = $this->getExportManager()->getExport($this->exportAlias);
|
$labelsCache = [];
|
||||||
$keys = $export->getQueryKeys($this->exportData);
|
$export = $this->getExportManager()->getExport($exportAlias);
|
||||||
|
$keys = $export->getQueryKeys($exportData);
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
// get an array with all values for this key if possible
|
// get an array with all values for this key if possible
|
||||||
@ -267,29 +251,37 @@ class SpreadsheetListFormatter implements FormatterInterface, ExportManagerAware
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $v[$key];
|
return $v[$key];
|
||||||
}, $this->result);
|
}, $result);
|
||||||
// store the label in the labelsCache property
|
// store the label in the labelsCache
|
||||||
$this->labelsCache[$key] = $export->getLabels($key, $values, $this->exportData);
|
$labelsCache[$key] = $export->getLabels($key, $values, $exportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $labelsCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add the headers to the csv file.
|
* add the headers to the csv file.
|
||||||
|
*
|
||||||
|
* @param Worksheet $worksheet
|
||||||
|
* @param array $result
|
||||||
|
* @param array $formatterData
|
||||||
|
* @param string $exportAlias
|
||||||
|
* @param array $exportData
|
||||||
*/
|
*/
|
||||||
protected function prepareHeaders(Worksheet $worksheet)
|
protected function prepareHeaders(array $labelsCache, Worksheet $worksheet, array $result, array $formatterData, string $exportAlias, array $exportData)
|
||||||
{
|
{
|
||||||
$keys = $this->getExportManager()->getExport($this->exportAlias)->getQueryKeys($this->exportData);
|
$keys = $this->getExportManager()->getExport($exportAlias)->getQueryKeys($exportData);
|
||||||
// we want to keep the order of the first row. So we will iterate on the first row of the results
|
// we want to keep the order of the first row. So we will iterate on the first row of the results
|
||||||
$first_row = \count($this->result) > 0 ? $this->result[0] : [];
|
$first_row = \count($result) > 0 ? $result[0] : [];
|
||||||
$header_line = [];
|
$header_line = [];
|
||||||
|
|
||||||
if (true === $this->formatterData['numerotation']) {
|
if (true === $formatterData['numerotation']) {
|
||||||
$header_line[] = $this->translator->trans('Number');
|
$header_line[] = $this->translator->trans('Number');
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($first_row as $key => $value) {
|
foreach ($first_row as $key => $value) {
|
||||||
$header_line[] = $this->translator->trans(
|
$header_line[] = $this->translator->trans(
|
||||||
$this->getLabel($key, '_header')
|
$this->getLabel($labelsCache, $key, '_header', $result, $exportAlias, $exportData)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user