*/
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
{
+ const DUMP_LIGHT_ARRAY = 1;
+ const DUMP_STRING_LENGTH = 2;
+ const DUMP_COMMA_SEPARATOR = 4;
+ const DUMP_TRAILING_COMMA = 8;
+
public static $defaultOutput = 'php://output';
protected $line = '';
protected $outputStream;
protected $decimalPoint; // This is locale dependent
protected $indentPad = ' ';
+ protected $flags;
private $charset;
/**
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput
* @param string $charset The default character encoding to use for non-UTF8 strings
+ * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation
*/
- public function __construct($output = null, $charset = null)
+ public function __construct($output = null, $charset = null, $flags = 0)
{
+ $this->flags = (int) $flags;
$this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
- $this->decimalPoint = (string) 0.5;
- $this->decimalPoint = $this->decimalPoint[1];
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
$this->setOutput($output ?: static::$defaultOutput);
- if (!$output && is_string(static::$defaultOutput)) {
+ if (!$output && \is_string(static::$defaultOutput)) {
static::$defaultOutput = $this->outputStream;
}
}
{
$prev = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
- if (is_callable($output)) {
+ if (\is_callable($output)) {
$this->outputStream = null;
$this->lineDumper = $output;
} else {
- if (is_string($output)) {
+ if (\is_string($output)) {
$output = fopen($output, 'wb');
}
$this->outputStream = $output;
/**
* Sets the indentation pad string.
*
- * @param string $pad A string the will be prepended to dumped lines, repeated by nesting level
+ * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level
*
- * @return string The indent pad
+ * @return string The previous indent pad
*/
public function setIndentPad($pad)
{
/**
* Dumps a Data object.
*
- * @param Data $data A Data object
- * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path
+ * @param Data $data A Data object
+ * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump
+ *
+ * @return string|null The dump as string when $output is true
*/
public function dump(Data $data, $output = null)
{
- $exception = null;
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
+
+ if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(LC_NUMERIC, 0) : null) {
+ setlocale(LC_NUMERIC, 'C');
+ }
+
+ if ($returnDump = true === $output) {
+ $output = fopen('php://memory', 'r+b');
+ }
if ($output) {
$prevOutput = $this->setOutput($output);
}
try {
$data->dump($this);
$this->dumpLine(-1);
- } catch (\Exception $exception) {
- // Re-thrown below
- } catch (\Throwable $exception) {
- // Re-thrown below
- }
- if ($output) {
- $this->setOutput($prevOutput);
- }
- if (null !== $exception) {
- throw $exception;
+
+ if ($returnDump) {
+ $result = stream_get_contents($output, -1, 0);
+ fclose($output);
+
+ return $result;
+ }
+ } finally {
+ if ($output) {
+ $this->setOutput($prevOutput);
+ }
+ if ($locale) {
+ setlocale(LC_NUMERIC, $locale);
+ }
}
}
/**
* Dumps the current line.
*
- * @param int $depth The recursive depth in the dumped structure for the line being dumped
+ * @param int $depth The recursive depth in the dumped structure for the line being dumped,
+ * or -1 to signal the end-of-dump to the line dumper callable
*/
protected function dumpLine($depth)
{
- call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
+ \call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
$this->line = '';
}
*/
protected function utf8Encode($s)
{
+ if (preg_match('//u', $s)) {
+ return $s;
+ }
+
+ if (!\function_exists('iconv')) {
+ throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.');
+ }
+
if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
return $c;
}