ExportUtil::recursiveExport()   F
last analyzed

Complexity

Conditions 18
Paths 21

Size

Total Lines 97

Duplication

Lines 24
Ratio 24.74 %

Importance

Changes 0
Metric Value
dl 24
loc 97
rs 3.9587
c 0
b 0
f 0
cc 18
nc 21
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Prophecy\Util;
4
5
use Prophecy\Prophecy\ProphecyInterface;
6
use SebastianBergmann\RecursionContext\Context;
7
8
/*
9
 * This file is part of the Prophecy.
10
 * (c) Konstantin Kudryashov <[email protected]>
11
 *     Marcello Duarte <[email protected]>
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
17
/**
18
 * This class is a modification from sebastianbergmann/exporter
19
 * @see https://github.com/sebastianbergmann/exporter
20
 */
21
class ExportUtil
22
{
23
    /**
24
     * Exports a value as a string
25
     *
26
     * The output of this method is similar to the output of print_r(), but
27
     * improved in various aspects:
28
     *
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
35
     *
36
     * @param  mixed  $value
37
     * @param  int    $indentation The indentation level of the 2nd+ line
38
     * @return string
39
     */
40
    public static function export($value, $indentation = 0)
41
    {
42
        return self::recursiveExport($value, $indentation);
43
    }
44
45
    /**
46
     * Converts an object to an array containing all of its private, protected
47
     * and public properties.
48
     *
49
     * @param  mixed $value
50
     * @return array
51
     */
52
    public static function toArray($value)
53
    {
54
        if (!is_object($value)) {
55
            return (array) $value;
56
        }
57
58
        $array = array();
59
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)) {
66
                $key = $matches[1];
67
            }
68
69
            // See https://github.com/php/php-src/commit/5721132
70
            if ($key === "\0gcdata") {
71
                continue;
72
            }
73
74
            $array[$key] = $val;
75
        }
76
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']);
87
            }
88
89
            if (property_exists('\SplObjectStorage', '__key')) {
90
                unset($array['__key']);
91
            }
92
93
            foreach ($value as $key => $val) {
94
                $array[spl_object_hash($val)] = array(
95
                    'obj' => $val,
96
                    'inf' => $value->getInfo(),
97
                );
98
            }
99
        }
100
101
        return $array;
102
    }
103
104
    /**
105
     * Recursive implementation of export
106
     *
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
110
     * @return string
111
     * @see    SebastianBergmann\Exporter\Exporter::export
112
     */
113
    protected static function recursiveExport(&$value, $indentation, $processed = null)
114
    {
115
        if ($value === null) {
116
            return 'null';
117
        }
118
119
        if ($value === true) {
120
            return 'true';
121
        }
122
123
        if ($value === false) {
124
            return 'false';
125
        }
126
127
        if (is_float($value) && floatval(intval($value)) === $value) {
128
            return "$value.0";
129
        }
130
131
        if (is_resource($value)) {
132
            return sprintf(
133
                'resource(%d) of type (%s)',
134
                $value,
135
                get_resource_type($value)
136
            );
137
        }
138
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);
143
            }
144
145
            return "'" .
146
            str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) .
147
            "'";
148
        }
149
150
        $whitespace = str_repeat(' ', 4 * $indentation);
151
152
        if (!$processed) {
153
            $processed = new Context;
154
        }
155
156
        if (is_array($value)) {
157
            if (($key = $processed->contains($value)) !== false) {
158
                return 'Array &' . $key;
159
            }
160
161
            $array  = $value;
162
            $key    = $processed->add($value);
163
            $values = '';
164
165 View Code Duplication
            if (count($array) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
                foreach ($array as $k => $v) {
167
                    $values .= sprintf(
168
                        '%s    %s => %s' . "\n",
169
                        $whitespace,
170
                        self::recursiveExport($k, $indentation),
171
                        self::recursiveExport($value[$k], $indentation + 1, $processed)
172
                    );
173
                }
174
175
                $values = "\n" . $values . $whitespace;
176
            }
177
178
            return sprintf('Array &%s (%s)', $key, $values);
179
        }
180
181
        if (is_object($value)) {
182
            $class = get_class($value);
183
184
            if ($hash = $processed->contains($value)) {
185
                return sprintf('%s:%s Object', $class, $hash);
186
            }
187
188
            $hash   = $processed->add($value);
189
            $values = '';
190
            $array  = self::toArray($value);
191
192 View Code Duplication
            if (count($array) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
                foreach ($array as $k => $v) {
194
                    $values .= sprintf(
195
                        '%s    %s => %s' . "\n",
196
                        $whitespace,
197
                        self::recursiveExport($k, $indentation),
198
                        self::recursiveExport($v, $indentation + 1, $processed)
199
                    );
200
                }
201
202
                $values = "\n" . $values . $whitespace;
203
            }
204
205
            return sprintf('%s:%s Object (%s)', $class, $hash, $values);
206
        }
207
208
        return var_export($value, true);
209
    }
210
}
211