diff --git a/phpstan.neon b/phpstan.neon index b67c8d47..75da21cf 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2782,7 +2782,7 @@ parameters: - message: "#^Parameter \\#1 \\$haystack of function stripos expects string, mixed given\\.$#" - count: 5 + count: 4 path: src/Invoice/Renderer/AbstractSpreadsheetRenderer.php - diff --git a/src/Export/Package/SpoutSpreadsheet.php b/src/Export/Package/SpoutSpreadsheet.php index 014c5fd9..94382bde 100644 --- a/src/Export/Package/SpoutSpreadsheet.php +++ b/src/Export/Package/SpoutSpreadsheet.php @@ -11,6 +11,7 @@ namespace App\Export\Package; use App\Constants; use OpenSpout\Common\Entity\Cell; +use OpenSpout\Common\Entity\Cell\StringCell; use OpenSpout\Common\Entity\Row; use OpenSpout\Common\Entity\Style\Border; use OpenSpout\Common\Entity\Style\BorderPart; @@ -98,7 +99,8 @@ class SpoutSpreadsheet implements SpreadsheetPackage $style->setShouldWrapText(false); $style->setShouldShrinkToFit(true); - if (\array_key_exists('totals', $options) && $options['totals'] === true) { + $isTotalsRow = \array_key_exists('totals', $options) && $options['totals'] === true; + if ($isTotalsRow) { if ($this->writer instanceof CSVWriter) { return; } @@ -109,7 +111,11 @@ class SpoutSpreadsheet implements SpreadsheetPackage $tmp = []; $i = 0; foreach ($columns as $column) { - $tmp[] = Cell::fromValue($column, $this->styles[$i++]); // @phpstan-ignore argument.type + if (!$isTotalsRow && \is_string($column)) { + $tmp[] = new StringCell($column, $style); + } else { + $tmp[] = Cell::fromValue($column, $this->styles[$i++]); // @phpstan-ignore argument.type + } } $this->writer->addRow(new Row($tmp, $style)); diff --git a/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php b/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php index 78401369..8edd42dd 100644 --- a/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php +++ b/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php @@ -67,10 +67,6 @@ abstract class AbstractSpreadsheetRenderer extends AbstractRenderer continue; } $replacer = null; - $firstReplacerPos = stripos($value, '${'); - if ($firstReplacerPos === false) { - continue; - } if (stripos($value, '${entry.') !== false) { if ($sheetValues === false && isset($entries[$entryRow])) { @@ -94,13 +90,14 @@ abstract class AbstractSpreadsheetRenderer extends AbstractRenderer if (stripos($value, $searchKey) === false) { continue; } - if (\is_string($content) && str_starts_with($content, '=')) { + // we ONLY check if the given replacer content contains a formula character + if (\is_string($content) && \in_array($content[0], ['=', '-', '+', '@', "\t", "\r"])) { $contentLooksLikeFormula = true; } $value = str_replace($searchKey, $content ?? '', $value); } - if ($contentLooksLikeFormula && $firstReplacerPos === 0) { + if ($contentLooksLikeFormula) { // see https://github.com/kimai/kimai/pull/2054 $cell->setValueExplicit($value, DataType::TYPE_STRING); } else {