Skip to content

Commit 96a3d64

Browse files
authored
Make the raw export opt-in (#374)
The new change to skip AbstractColumn::transform() during export seems to be a quite intrusive backwards-incompatible change, because we use the `render` option quite a lot construct the column value (even though we should probably use `data` for that). This commit makes it an opt-in feature on a per-column basis. I also add a `stripTags` option to ExcelOpenSpoutExporter.
1 parent 3991cf8 commit 96a3d64

File tree

4 files changed

+41
-22
lines changed

4 files changed

+41
-22
lines changed

src/Column/AbstractColumn.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function transform(mixed $value = null, mixed $context = null, bool $raw
6161
$value = $data;
6262
}
6363

64-
return ($raw) ? $value : $this->render($this->normalize($value), $context);
64+
return ($raw && $this->options['enableRawExport']) ? $value : $this->render($this->normalize($value), $context);
6565
}
6666

6767
/**
@@ -102,6 +102,7 @@ protected function configureOptions(OptionsResolver $resolver): static
102102
'leftExpr' => null,
103103
'operator' => '=',
104104
'rightExpr' => null,
105+
'enableRawExport' => false,
105106
'exporterOptions' => [],
106107
])
107108
->setAllowedTypes('label', ['null', 'string'])
@@ -119,7 +120,9 @@ protected function configureOptions(OptionsResolver $resolver): static
119120
->setAllowedTypes('operator', ['string'])
120121
->setAllowedTypes('leftExpr', ['null', 'string', 'callable'])
121122
->setAllowedTypes('rightExpr', ['null', 'string', 'callable'])
123+
->setAllowedTypes('enableRawExport', ['bool'])
122124
->setAllowedTypes('exporterOptions', ['array'])
125+
->setInfo('enableRawExport', 'When true, skips normalize() and render() during raw transforms.')
123126
->setInfo('exporterOptions', 'Specific exporter options can be specified here, where the key is the exporter name and the value is an array of options.')
124127
;
125128

src/Exporter/Excel/ExcelOpenSpoutExporter.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,15 @@ public function export(array $columnNames, \Iterator $data, array $columnOptions
5151
foreach ($rowValues as $value) {
5252
$options = current($columnOptions);
5353
if (false === $options) {
54-
throw new \LogicException('Mismatch in number of row values and number of column options');
54+
throw new \LogicException('Mismatch in number of row values and number of column options'); // (This prevents PHPStan complaining)
5555
}
5656

5757
if (is_string($value)) {
58-
// Previously, we stripped HTML tags and unescaped the value, because the value was passed through
59-
// AbstractColumn::render() which would have escaped special chars and could have added HTML tags.
60-
//
61-
// Now that we have raw data, we don't need to do that anymore.
62-
//
63-
// $value = htmlspecialchars_decode(strip_tags($value), ENT_QUOTES | ENT_SUBSTITUTE);
58+
// We strip HTML tags and unescape the value by default, because
59+
// TextColumn::normalize() will encode HTML special characters (unless `raw` is set).
60+
if ($options['stripTags']) {
61+
$value = htmlspecialchars_decode(strip_tags($value), ENT_QUOTES | ENT_SUBSTITUTE);
62+
}
6463

6564
// Excel has a limit of 32,767 characters per cell
6665
if (mb_strlen($value) > static::MAX_CHARACTERS_PER_CELL) {
@@ -148,9 +147,12 @@ public function configureColumnOptions(OptionsResolver $resolver): void
148147
->setDefaults([
149148
'style' => (new Style())->setShouldWrapText(false),
150149
'columnWidth' => 24,
150+
'stripTags' => true,
151151
])
152152
->setAllowedTypes('style', [Style::class, 'callable'])
153153
->setAllowedTypes('columnWidth', ['int', 'float'])
154+
->setAllowedTypes('stripTags', 'bool')
155+
->setInfo('stripTags', 'When true, will strip HTML tags and unescape special characters from string data.')
154156
;
155157
}
156158

tests/Fixtures/AppBundle/Controller/ExporterController.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,29 @@ public function exportSpecialChars(Request $request, DataTableFactory $dataTable
140140

141141
public function exportWithTypes(Request $request, DataTableFactory $factory): Response
142142
{
143+
$enableRawExport = ['enableRawExport' => true];
143144
$table = $factory
144145
->create()
145146
->add('stringColumn', TextColumn::class)
146-
->add('integerColumn', NumberColumn::class)
147-
->add('floatColumn', NumberColumn::class)
148-
->add('boolColumn', BoolColumn::class)
149-
->add('dateTimeColumn', DateTimeColumn::class)
150-
->add('nullColumn', TextColumn::class)
151-
->add('typeWithToStringColumn', TextColumn::class)
152-
->add('typeWithoutToStringColumn', TextColumn::class)
147+
->add('stringColumnWithTags', TextColumn::class, ['raw' => true])
148+
->add('integerColumn', NumberColumn::class, $enableRawExport)
149+
->add('floatColumn', NumberColumn::class, $enableRawExport)
150+
->add('boolColumn', BoolColumn::class, $enableRawExport)
151+
->add('dateTimeColumn', DateTimeColumn::class, $enableRawExport)
152+
->add('nullColumn', TextColumn::class, $enableRawExport)
153+
->add('typeWithToStringColumn', TextColumn::class, $enableRawExport)
154+
->add('typeWithoutToStringColumn', TextColumn::class, $enableRawExport)
155+
->add('stringColumnWithoutStripTags', TextColumn::class, [
156+
'exporterOptions' => [
157+
'excel-openspout' => [
158+
'stripTags' => false,
159+
],
160+
],
161+
])
153162
->createAdapter(ArrayAdapter::class, [
154163
[
155164
'stringColumn' => 'stringValue',
165+
'stringColumnWithTags' => '<a href="https://example.org">link with special character &lt;</a>',
156166
'integerColumn' => 1,
157167
'floatColumn' => 1.1,
158168
'boolColumn' => true,
@@ -165,6 +175,7 @@ public function __toString(): string
165175
}
166176
},
167177
'typeWithoutToStringColumn' => new class {},
178+
'stringColumnWithoutStripTags' => '<a href="https://example.org">link with special character &lt;</a>',
168179
],
169180
])
170181
;

tests/Functional/Exporter/Excel/ExcelOpenSpoutExporterTest.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,20 @@ public function testWithTypes(): void
158158

159159
// Test columns
160160
static::assertEquals('stringValue', $sheet->getCell('A2')->getValue()->getPlainText());
161-
static::assertSame(1, $sheet->getCell('B2')->getValue());
162-
static::assertSame(1.1, $sheet->getCell('C2')->getValue());
163-
static::assertTrue($sheet->getCell('D2')->getValue());
161+
static::assertEquals('link with special character <', $sheet->getCell('B2')->getValue()->getPlainText());
162+
static::assertSame(1, $sheet->getCell('C2')->getValue());
163+
static::assertSame(1.1, $sheet->getCell('D2')->getValue());
164+
static::assertTrue($sheet->getCell('E2')->getValue());
164165

165166
// Excel stores dates as a float where the integer part is the number of days since 1900-01-01 and the decimal part is the fraction of the day
166167
$expectedDateValue = (new \DateTimeImmutable('2021-01-01 00:00:00'))->diff(new \DateTimeImmutable('1900-01-01 00:00:00'))->days + 2; // (Have to add 2 due to boundaries)
167-
static::assertSame($expectedDateValue, $sheet->getCell('E2')->getValue());
168-
static::assertSame(null, $sheet->getCell('F2')->getValue());
169-
static::assertSame('toStringValue', $sheet->getCell('G2')->getValue()->getPlainText());
168+
static::assertSame($expectedDateValue, $sheet->getCell('F2')->getValue());
169+
static::assertSame(null, $sheet->getCell('G2')->getValue());
170+
static::assertSame('toStringValue', $sheet->getCell('H2')->getValue()->getPlainText());
170171

171172
// This cell contains the exception message thrown when trying to cast an object without a __toString method to a string
172-
static::assertSame('Object of class class@anonymous could not be converted to string', $sheet->getCell('H2')->getValue()->getPlainText());
173+
static::assertSame('Object of class class@anonymous could not be converted to string', $sheet->getCell('I2')->getValue()->getPlainText());
174+
175+
static::assertEquals('&lt;a href=&quot;https://example.org&quot;&gt;link with special character &amp;lt;&lt;/a&gt;', $sheet->getCell('J2')->getValue()->getPlainText());
173176
}
174177
}

0 commit comments

Comments
 (0)