Completed
Branch feature/pre-split (a521a3)
by Anton
03:28
created

Serializer::packValue()   C

Complexity

Conditions 11
Paths 8

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 16
nc 8
nop 1
dl 0
loc 32
rs 5.2653
c 0
b 0
f 0

How to fix   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
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Support;
9
10
use Spiral\Reactor\DeclarationInterface;
11
use Spiral\Support\Exceptions\SerializeException;
12
13
/**
14
 * Provides very simple api for serializing values. Attention, this is helper class, it's not
15
 * intended for processing user input.
16
 */
17
class Serializer
18
{
19
    /**
20
     * Fixed 4 spaces indent.
21
     */
22
    const INDENT = DeclarationInterface::INDENT;
23
24
    /**
25
     * Serialize array.
26
     *
27
     * @param mixed $array
28
     *
29
     * @return string
30
     */
31
    public function serialize($array): string
32
    {
33
        if (is_array($array)) {
34
            return $this->packArray($array);
35
        }
36
37
        return $this->packValue($array);
38
    }
39
40
    /**
41
     * @param array $array
42
     * @param int   $level
43
     *
44
     * @return string
45
     */
46
    protected function packArray(array $array, int $level = 0): string
47
    {
48
        if ($array === []) {
49
            return '[]';
50
        }
51
52
        //Delimiters between rows and sub-arrays.
53
        $subIndent = "\n" . str_repeat(self::INDENT, $level + 2);
54
        $keyIndent = "\n" . str_repeat(self::INDENT, $level + 1);
55
56
        //No keys for associated array
57
        $associated = array_diff_key($array, array_keys(array_keys($array)));
58
59
        $result = [];
60
        $innerIndent = 0;
61
        if (!empty($associated)) {
62
            foreach ($array as $key => $value) {
63
                //Based on biggest key length
64
                $innerIndent = max(strlen(var_export($key, true)), $innerIndent);
65
            }
66
        }
67
68
        foreach ($array as $key => $value) {
69
            $prefix = '';
70
            if (!empty($associated)) {
71
                //Key prefix
72
                $prefix = str_pad(
73
                        var_export($key, true),
74
                        $innerIndent, ' ',
75
                        STR_PAD_RIGHT
76
                    ) . " => ";
77
            }
78
79
            if (!is_array($value)) {
80
                $result[] = $prefix . $this->packValue($value);
81
                continue;
82
            }
83
84
            if ($value === []) {
85
                $result[] = $prefix . "[]";
86
                continue;
87
            }
88
89
            $subArray = $this->packArray($value, $level + 1);
90
            $result[] = $prefix . "[{$subIndent}" . $subArray . "{$keyIndent}]";
91
        }
92
93
        if ($level !== 0) {
94
            return $result ? join(",{$keyIndent}", $result) : "";
95
        }
96
97
        return "[{$keyIndent}" . join(",{$keyIndent}", $result) . "\n]";
98
    }
99
100
    /**
101
     * Pack array key value into string.
102
     *
103
     * @param mixed $value
104
     *
105
     * @return string
106
     * @throws SerializeException
107
     */
108
    protected function packValue($value): string
109
    {
110
        if ($value instanceof DeclarationInterface) {
111
            //No indentation here
112
            return $value->render();
113
        }
114
115
        if (is_null($value)) {
116
            return "null";
117
        }
118
119
        if (is_bool($value)) {
120
            return ($value ? "true" : "false");
121
        }
122
123
        if (is_object($value) && method_exists($value, '__set_state')) {
124
            return var_export($value, true);
125
        }
126
127
        if (!is_string($value) && !is_numeric($value)) {
128
            print_r($value);
129
            throw new SerializeException("Unable to pack non scalar value");
130
        }
131
132
        if (is_string($value) && class_exists($value)) {
133
            $reflection = new \ReflectionClass($value);
134
135
            return '\\' . $reflection->getName() . '::class';
136
        }
137
138
        return var_export($value, true);
139
    }
140
}