diff --git a/src/Exporter.php b/src/Exporter.php index cf7efc1..69b6c62 100644 --- a/src/Exporter.php +++ b/src/Exporter.php @@ -38,6 +38,11 @@ final readonly class Exporter { + public function __construct( + private int $shortenArraysLongerThan = 10 + ) { + } + /** * Exports a value as a string. * @@ -58,30 +63,19 @@ public function export(mixed $value, int $indentation = 0): string public function shortenedRecursiveExport(array &$data, ?RecursionContext $processed = null): string { - $result = []; - if (!$processed) { $processed = new RecursionContext; } + $overallCount = count($data, COUNT_RECURSIVE); + $counter = 0; - $array = $data; + $export = $this->shortenedCountedRecursiveExport($data, $processed, $counter); - /* @noinspection UnusedFunctionResultInspection */ - $processed->add($data); - - foreach ($array as $key => $value) { - if (is_array($value)) { - if ($processed->contains($data[$key]) !== false) { - $result[] = '*RECURSION*'; - } else { - $result[] = '[' . $this->shortenedRecursiveExport($data[$key], $processed) . ']'; - } - } else { - $result[] = $this->shortenedExport($value); - } + if ($overallCount > $this->shortenArraysLongerThan) { + $export .= sprintf(', ...%d more elements', $overallCount - $this->shortenArraysLongerThan); } - return implode(', ', $result); + return $export; } /** @@ -195,6 +189,36 @@ public function toArray(mixed $value): array return $array; } + private function shortenedCountedRecursiveExport(array &$data, RecursionContext $processed, int &$counter): string + { + $result = []; + + $array = $data; + + /* @noinspection UnusedFunctionResultInspection */ + $processed->add($data); + + foreach ($array as $key => $value) { + if ($counter > $this->shortenArraysLongerThan) { + break; + } + + if (is_array($value)) { + if ($processed->contains($data[$key]) !== false) { + $result[] = '*RECURSION*'; + } else { + $result[] = '[' . $this->shortenedCountedRecursiveExport($data[$key], $processed, $counter) . ']'; + } + } else { + $result[] = $this->shortenedExport($value); + } + + $counter++; + } + + return implode(', ', $result); + } + private function recursiveExport(mixed &$value, int $indentation = 0, ?RecursionContext $processed = null): string { if ($value === null) { diff --git a/tests/ExporterTest.php b/tests/ExporterTest.php index e010f05..4eb52e0 100644 --- a/tests/ExporterTest.php +++ b/tests/ExporterTest.php @@ -321,6 +321,15 @@ public static function provideNonBinaryMultibyteStrings(): array public static function shortenedRecursiveExportProvider(): array { + $bigArray = []; + + for ($i = 0; $i < 20_000; $i++) { + $bigArray[] = 'cast(\'foo' . $i . '\' as blob)'; + } + + $array = [1, 2, 'hello', 'world', true, false]; + $deepArray = [$array, [$array, [$array, [$array, [$array, [$array, [$array, [$array, [$array, [$array]]]]]]]]]]; + return [ 'null' => [[null], 'null'], 'boolean true' => [[true], 'true'], @@ -333,6 +342,8 @@ public static function shortenedRecursiveExportProvider(): array 'with assoc array key' => [['foo' => 'bar'], '\'bar\''], 'multidimensional array' => [[[1, 2, 3], [3, 4, 5]], '[1, 2, 3], [3, 4, 5]'], 'object' => [[new stdClass], 'stdClass Object ()'], + 'big array' => [$bigArray, "'cast('foo0' as blob)', 'cast('foo1' as blob)', 'cast('foo2' as blob)', 'cast('foo3' as blob)', 'cast('foo4' as blob)', 'cast('foo5' as blob)', 'cast('foo6' as blob)', 'cast('foo7' as blob)', 'cast('foo8' as blob)', 'cast('foo9' as blob)', 'cast('foo10' as blob)', ...19990 more elements"], + 'deep array' => [$deepArray, "[1, 2, 'hello', 'world', true, false], [[1, 2, 'hello', 'world']], ...69 more elements"], ]; }