Skip to content

Commit

Permalink
Add argument to control the indentation level. (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
ADmad authored Feb 10, 2021
1 parent f70f929 commit f79be08
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 10 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,31 @@ VarExporter::export(

Export the current value of each `use()` variable as expression inside the exported closure.

## Indentation

You can use the 3rd argument of `VarExporter::export()` to control the indentation level.
This is useful when you want to use the generated code string to replace a placeholder in a template used to generate code files.

So using output of `VarExporter::export(['foo' => 'bar'], 0, 1)` in the template below to replace `{{exported}}`

```
public foo()
{
$data = {{exported}};
}
```

would result in

```php
public foo()
{
$data = [
'foo' => 'bar'
];
}
```

## Error handling

Any error occurring on `export()` will throw an `ExportException`:
Expand Down
12 changes: 11 additions & 1 deletion src/Internal/GenericExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,18 @@ final class GenericExporter
*/
public $trailingCommaInArray;

/**
* @psalm-readonly
*
* @var int
*/
public $indentLevel;

/**
* @param int $options
* @param int Indentation level
*/
public function __construct(int $options)
public function __construct(int $options, int $indentLevel = 0)
{
$this->objectExporters[] = new ObjectExporter\StdClassExporter($this);

Expand All @@ -97,6 +105,8 @@ public function __construct(int $options)
$this->inlineNumericScalarArray = (bool) ($options & VarExporter::INLINE_NUMERIC_SCALAR_ARRAY);
$this->closureSnapshotUses = (bool) ($options & VarExporter::CLOSURE_SNAPSHOT_USES);
$this->trailingCommaInArray = (bool) ($options & VarExporter::TRAILING_COMMA_IN_ARRAY);

$this->indentLevel = $indentLevel;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/ObjectExporter/ClosureExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function export($object, \ReflectionObject $reflectionObject, array $path
$closure = $this->getClosure($reflectionFunction, $ast, $file, $line, $path);

$prettyPrinter = new ClosureExporter\PrettyPrinter();
$prettyPrinter->setVarExporterNestingLevel(count($path));
$prettyPrinter->setVarExporterNestingLevel(count($path) + $this->exporter->indentLevel);

$code = $prettyPrinter->prettyPrintExpr($closure);

Expand Down
26 changes: 18 additions & 8 deletions src/VarExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,33 @@ final class VarExporter
public const TRAILING_COMMA_IN_ARRAY = 1 << 9;

/**
* @param mixed $var The variable to export.
* @param int $options A bitmask of options. Possible values are `VarExporter::*` constants.
* Combine multiple options with a bitwise OR `|` operator.
* @param mixed $var The variable to export.
* @param int $options A bitmask of options. Possible values are `VarExporter::*` constants.
* Combine multiple options with a bitwise OR `|` operator.
* @param int $indentLevel Indentation level.
*
* @return string
*
* @throws ExportException
*/
public static function export($var, int $options = 0) : string
public static function export($var, int $options = 0, int $indentLevel = 0) : string
{
$exporter = new GenericExporter($options);

$exporter = new GenericExporter($options, $indentLevel);
$lines = $exporter->export($var, [], []);
$export = implode(PHP_EOL, $lines);

if ($indentLevel < 1 || count($lines) < 2) {
$export = implode(PHP_EOL, $lines);
} else {
$firstLine = array_shift($lines);
$lines = array_map(function ($line) use ($indentLevel) {
return str_repeat(' ', $indentLevel) . $line;
}, $lines);

$export = $firstLine . PHP_EOL . implode(PHP_EOL, $lines);
}

if ($options & self::ADD_RETURN) {
return 'return ' . $export . ';' . PHP_EOL;
return 'return ' . $export . ';' . PHP_EOL;
}

return $export;
Expand Down
121 changes: 121 additions & 0 deletions tests/VarExporterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,125 @@ public function testExportObjectWithCircularReference()
]
]);
}

/**
* @dataProvider providerExportIndented
*/
public function testExportIndented($var, $expected, $options)
{
$template = <<<'TPL'
public foo ()
{
$data = {{exported}};
}
TPL;

$exported = VarExporter::export($var, $options, 1);
$result = str_replace('{{exported}}', $exported, $template);

$this->assertEquals($expected, $result);
}

public function providerExportIndented()
{
// Array
$var = ['one' => ['hello', true], 'two' => 2];
$expected = <<<'PHP'
public foo ()
{
$data = [
'one' => [
'hello',
true
],
'two' => 2
];
}
PHP;
yield [$var, $expected, 0];

// Null
$var = null;
$expected = <<<'PHP'
public foo ()
{
$data = null;
}
PHP;
yield [$var, $expected, 0];

// Closure
$var = function () {
return 'Hello, world!';
};
$expected = <<<'PHP'
public foo ()
{
$data = function () {
return 'Hello, world!';
};
}
PHP;
yield [$var, $expected, 0];

$foo = 'bar';
$sub = function () use ($foo) {
return $foo;
};
$var = function () use ($sub) {
return $sub();
};

$expected = <<<'PHP'
public foo ()
{
$data = function () {
$sub = function () {
$foo = 'bar';
return $foo;
};
return $sub();
};
}
PHP;
yield [$var, $expected, VarExporter::CLOSURE_SNAPSHOT_USES];

$var = function () {
$a = 'Hello,
World!';

$b = <<<TXT
Hello,
world!
TXT;

$c = <<<'TXT'
Hello,
world!
TXT;

return $a . $b . $c;
};

$expected = <<<'PHP'
public foo ()
{
$data = function () {
$a = 'Hello,
World!';
$b = <<<TXT
Hello,
world!
TXT;
$c = <<<'TXT'
Hello,
world!
TXT;
return $a . $b . $c;
};
}
PHP;

yield [$var, $expected, 0];
}
}

0 comments on commit f79be08

Please sign in to comment.