4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\VarDumper\Dumper;
14 use Symfony\Component\VarDumper\Cloner\Data;
15 use Symfony\Component\VarDumper\Cloner\DumperInterface;
18 * Abstract mechanism for dumping a Data object.
20 * @author Nicolas Grekas <p@tchwork.com>
22 abstract class AbstractDumper implements DataDumperInterface, DumperInterface
24 const DUMP_LIGHT_ARRAY = 1;
25 const DUMP_STRING_LENGTH = 2;
26 const DUMP_COMMA_SEPARATOR = 4;
27 const DUMP_TRAILING_COMMA = 8;
29 public static $defaultOutput = 'php://output';
32 protected $lineDumper;
33 protected $outputStream;
34 protected $decimalPoint; // This is locale dependent
35 protected $indentPad = ' ';
41 * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput
42 * @param string $charset The default character encoding to use for non-UTF8 strings
43 * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation
45 public function __construct($output = null, $charset = null, $flags = 0)
47 $this->flags = (int) $flags;
48 $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
49 $this->decimalPoint = localeconv();
50 $this->decimalPoint = $this->decimalPoint['decimal_point'];
51 $this->setOutput($output ?: static::$defaultOutput);
52 if (!$output && \is_string(static::$defaultOutput)) {
53 static::$defaultOutput = $this->outputStream;
58 * Sets the output destination of the dumps.
60 * @param callable|resource|string $output A line dumper callable, an opened stream or an output path
62 * @return callable|resource|string The previous output destination
64 public function setOutput($output)
66 $prev = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
68 if (\is_callable($output)) {
69 $this->outputStream = null;
70 $this->lineDumper = $output;
72 if (\is_string($output)) {
73 $output = fopen($output, 'wb');
75 $this->outputStream = $output;
76 $this->lineDumper = array($this, 'echoLine');
83 * Sets the default character encoding to use for non-UTF8 strings.
85 * @param string $charset The default character encoding to use for non-UTF8 strings
87 * @return string The previous charset
89 public function setCharset($charset)
91 $prev = $this->charset;
93 $charset = strtoupper($charset);
94 $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
96 $this->charset = $charset;
102 * Sets the indentation pad string.
104 * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level
106 * @return string The previous indent pad
108 public function setIndentPad($pad)
110 $prev = $this->indentPad;
111 $this->indentPad = $pad;
117 * Dumps a Data object.
119 * @param Data $data A Data object
120 * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump
122 * @return string|null The dump as string when $output is true
124 public function dump(Data $data, $output = null)
126 $this->decimalPoint = localeconv();
127 $this->decimalPoint = $this->decimalPoint['decimal_point'];
129 if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(LC_NUMERIC, 0) : null) {
130 setlocale(LC_NUMERIC, 'C');
133 if ($returnDump = true === $output) {
134 $output = fopen('php://memory', 'r+b');
137 $prevOutput = $this->setOutput($output);
144 $result = stream_get_contents($output, -1, 0);
151 $this->setOutput($prevOutput);
154 setlocale(LC_NUMERIC, $locale);
160 * Dumps the current line.
162 * @param int $depth The recursive depth in the dumped structure for the line being dumped,
163 * or -1 to signal the end-of-dump to the line dumper callable
165 protected function dumpLine($depth)
167 \call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
172 * Generic line dumper callback.
174 * @param string $line The line to write
175 * @param int $depth The recursive depth in the dumped structure
176 * @param string $indentPad The line indent pad
178 protected function echoLine($line, $depth, $indentPad)
181 fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n");
186 * Converts a non-UTF-8 string to UTF-8.
188 * @param string $s The non-UTF-8 string to convert
190 * @return string The string converted to UTF-8
192 protected function utf8Encode($s)
194 if (preg_match('//u', $s)) {
198 if (!\function_exists('iconv')) {
199 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.');
202 if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
205 if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) {
209 return iconv('CP850', 'UTF-8', $s);