3 namespace Prophecy\Util;
5 use Prophecy\Prophecy\ProphecyInterface;
6 use SebastianBergmann\RecursionContext\Context;
9 * This file is part of the Prophecy.
10 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
11 * Marcello Duarte <marcello.duarte@gmail.com>
13 * For the full copyright and license information, please view the LICENSE
14 * file that was distributed with this source code.
18 * This class is a modification from sebastianbergmann/exporter
19 * @see https://github.com/sebastianbergmann/exporter
24 * Exports a value as a string
26 * The output of this method is similar to the output of print_r(), but
27 * improved in various aspects:
29 * - NULL is rendered as "null" (instead of "")
30 * - TRUE is rendered as "true" (instead of "1")
31 * - FALSE is rendered as "false" (instead of "")
32 * - Strings are always quoted with single quotes
33 * - Carriage returns and newlines are normalized to \n
34 * - Recursion and repeated rendering is treated properly
37 * @param int $indentation The indentation level of the 2nd+ line
40 public static function export($value, $indentation = 0)
42 return self::recursiveExport($value, $indentation);
46 * Converts an object to an array containing all of its private, protected
47 * and public properties.
52 public static function toArray($value)
54 if (!is_object($value)) {
55 return (array) $value;
60 foreach ((array) $value as $key => $val) {
61 // properties are transformed to keys in the following way:
62 // private $property => "\0Classname\0property"
63 // protected $property => "\0*\0property"
64 // public $property => "property"
65 if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) {
69 // See https://github.com/php/php-src/commit/5721132
70 if ($key === "\0gcdata") {
77 // Some internal classes like SplObjectStorage don't work with the
78 // above (fast) mechanism nor with reflection in Zend.
79 // Format the output similarly to print_r() in this case
80 if ($value instanceof \SplObjectStorage) {
81 // However, the fast method does work in HHVM, and exposes the
82 // internal implementation. Hide it again.
83 if (property_exists('\SplObjectStorage', '__storage')) {
84 unset($array['__storage']);
85 } elseif (property_exists('\SplObjectStorage', 'storage')) {
86 unset($array['storage']);
89 if (property_exists('\SplObjectStorage', '__key')) {
90 unset($array['__key']);
93 foreach ($value as $key => $val) {
94 $array[spl_object_hash($val)] = array(
96 'inf' => $value->getInfo(),
105 * Recursive implementation of export
107 * @param mixed $value The value to export
108 * @param int $indentation The indentation level of the 2nd+ line
109 * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects
111 * @see SebastianBergmann\Exporter\Exporter::export
113 protected static function recursiveExport(&$value, $indentation, $processed = null)
115 if ($value === null) {
119 if ($value === true) {
123 if ($value === false) {
127 if (is_float($value) && floatval(intval($value)) === $value) {
131 if (is_resource($value)) {
133 'resource(%d) of type (%s)',
135 get_resource_type($value)
139 if (is_string($value)) {
140 // Match for most non printable chars somewhat taking multibyte chars into account
141 if (preg_match('/[^\x09-\x0d\x20-\xff]/', $value)) {
142 return 'Binary String: 0x' . bin2hex($value);
146 str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) .
150 $whitespace = str_repeat(' ', 4 * $indentation);
153 $processed = new Context;
156 if (is_array($value)) {
157 if (($key = $processed->contains($value)) !== false) {
158 return 'Array &' . $key;
162 $key = $processed->add($value);
165 if (count($array) > 0) {
166 foreach ($array as $k => $v) {
168 '%s %s => %s' . "\n",
170 self::recursiveExport($k, $indentation),
171 self::recursiveExport($value[$k], $indentation + 1, $processed)
175 $values = "\n" . $values . $whitespace;
178 return sprintf('Array &%s (%s)', $key, $values);
181 if (is_object($value)) {
182 $class = get_class($value);
184 if ($value instanceof ProphecyInterface) {
185 return sprintf('%s Object (*Prophecy*)', $class);
186 } elseif ($hash = $processed->contains($value)) {
187 return sprintf('%s:%s Object', $class, $hash);
190 $hash = $processed->add($value);
192 $array = self::toArray($value);
194 if (count($array) > 0) {
195 foreach ($array as $k => $v) {
197 '%s %s => %s' . "\n",
199 self::recursiveExport($k, $indentation),
200 self::recursiveExport($v, $indentation + 1, $processed)
204 $values = "\n" . $values . $whitespace;
207 return sprintf('%s:%s Object (%s)', $class, $hash, $values);
210 return var_export($value, true);