From 9d98bab2e33c9301118fd21f592577674a4eaffa Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Fri, 3 Nov 2023 10:32:37 +0100 Subject: [PATCH] Let ArrayGenerator generate prettier PHP code --- src/Generator/ArrayGenerator.php | 72 +++++++++++++++++++++++++++++++- tests/ArrayGeneratorTest.php | 32 ++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/Generator/ArrayGenerator.php b/src/Generator/ArrayGenerator.php index 28c7a8f..60dfe9f 100644 --- a/src/Generator/ArrayGenerator.php +++ b/src/Generator/ArrayGenerator.php @@ -9,8 +9,26 @@ final class ArrayGenerator extends Generator { + /** + * @private + */ + const PRETTY_INDENT = ' '; + + /** + * @var bool + */ private $includeEmpty; + /** + * @var bool + */ + private $strictTypes; + + /** + * @var bool + */ + private $pretty; + /** * Constructs a new ArrayGenerator * @param array|null $options @@ -20,13 +38,21 @@ final class ArrayGenerator extends Generator public function __construct(?array $options = null) { $this->includeEmpty = (bool) ($options['includeEmpty'] ?? false); + $this->strictTypes = (bool) ($options['strictTypes'] ?? false); + $this->pretty = (bool) ($options['pretty'] ?? false); } public function generateString(Translations $translations): string { $array = $this->generateArray($translations); + $result = 'pretty) { + $result .= $this->strictTypes ? "\n\ndeclare(strict_types=1);\n\n" : "\n\n"; + } else { + $result .= $this->strictTypes ? ' declare(strict_types=1); ' : ' '; + } - return sprintf('pretty ? self::prettyExport($array) : (var_export($array, true) . ';')); } public function generateArray(Translations $translations): array @@ -66,4 +92,48 @@ private static function hasPluralTranslations(Translation $translation): bool { return implode('', $translation->getPluralTranslations()) !== ''; } + + private static function prettyExport(array &$array): string + { + return self::prettyExportArray($array, 0) . ";\n"; + } + + private static function prettyExportArray(array &$array, int $depth): string + { + if ($array === []) { + return '[]'; + } + $result = '['; + $isList = self::isList($array); + foreach ($array as $key => $value) { + $result .= "\n" . str_repeat(self::PRETTY_INDENT, $depth + 1); + if (!$isList) { + $result .= var_export($key, true) . ' => '; + } + if (is_array($value)) { + $result .= self::prettyExportArray($value, $depth + 1); + } else { + $result .= self::prettyExportScalar($value); + } + $result .= ','; + } + return $result . "\n" . str_repeat(self::PRETTY_INDENT, $depth) . ']'; + } + + private static function prettyExportScalar($value): string + { + return $value === null ? 'null' : var_export($value, true); + } + + private static function isList(array &$value): bool + { + if ($value === []) { + return true; + } + if (function_exists('array_is_list')) { + return \array_is_list($value); + } + + return array_keys($value) === range(0, count($value) - 1); + } } diff --git a/tests/ArrayGeneratorTest.php b/tests/ArrayGeneratorTest.php index 0313e4b..b41d42c 100644 --- a/tests/ArrayGeneratorTest.php +++ b/tests/ArrayGeneratorTest.php @@ -42,6 +42,8 @@ public function testArrayGenerator() ]; $this->assertSame($expected, $array); + + $this->checkFormatting($expected, $translations); } public function testArrayGeneratorWithEmptyTranslations() @@ -70,5 +72,35 @@ public function testArrayGeneratorWithEmptyTranslations() ]; $this->assertSame($expected, $array); + + $this->checkFormatting($expected, $translations, ['includeEmpty' => true]); + } + + private function checkFormatting(array $expected, Translations $translations, array $otherOptions = []) + { + foreach ([ + [], + ['strictTypes' => true], + ['pretty' => true], + ['strictTypes' => true, 'pretty' => true], + ] as $options) { + $phpCode = (new ArrayGenerator($options + $otherOptions))->generateString($translations); + if (empty($options['strictTypes'])) { + $this->assertStringNotContainsString('declare(strict_types=1);', $phpCode); + } else { + $this->assertStringContainsString('declare(strict_types=1);', $phpCode); + } + if (empty($options['pretty'])) { + $this->assertStringEndsWith(');', $phpCode); + $prefix = 'assertStringEndsWith("];\n", $phpCode); + $prefix = "assertStringStartsWith($prefix, $phpCode); + $array = eval(substr($phpCode, strlen($prefix))); + $this->assertIsArray($array); + $this->assertSame($expected, $array); + } } }