Passed
Push — master ( affae1...bf1da0 )
by stéphane
10:14
created

Dumper::dumpArray()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 5
nop 2
dl 0
loc 12
rs 9.9666
c 0
b 0
f 0
1
<?php
2
namespace Dallgoot\Yaml;
3
4
use Dallgoot\Yaml as Y;
5
use \SplDoublyLinkedList as DLL;
6
7
/**
8
 *
9
 * @author  Stéphane Rebai <[email protected]>
10
 * @license Apache 2.0
11
 * @link    TODO : url to specific online doc
12
 */
13
class Dumper //extends AnotherClass
14
{
15
    private const INDENT = 2;
16
    private const WIDTH = 120;
17
    private const OPTIONS = 00000;
18
    private const DATE_FORMAT = 'Y-m-d';
19
20
    /** @var null|\SplDoublyLinkedList */
21
    private static $result;
22
    private static $options;
23
    //options
24
    public const EXPAND_SHORT = 00001;
25
    public const SERIALIZE_CUSTOM_OBJECTS = 00010;
26
    public static $floatPrecision = 4;
27
28
    // public function __construct(int $options = null)
29
    // {
30
    //     if (is_int($options)) self::$options = $options;
31
    // }
32
33
    /**
34
     * Returns (as a string) the YAML representation of the $dataType provided
35
     *
36
     * @param mixed    $dataType The data type
37
     * @param int|null $options  The options
38
     *
39
     * @throws \Exception datatype cannot be null
40
     *
41
     * @return string The Yaml string content
42
     */
43
    public static function toString($dataType, int $options = null):string
44
    {
45
        if (is_null($dataType)) throw new \Exception(self::class.": No content to convert to Yaml", 1);
46
        self::$options = is_int($options) ? $options : self::OPTIONS;
47
        self::$result = new DLL;
48
        if ($dataType instanceof YamlObject) {
49
            self::dumpYamlObject($dataType);
50
        } elseif (is_array($dataType) && $dataType[0] instanceof YamlObject) {
51
            array_map([self::class, 'dumpYamlObject'], $dataType);
52
        } else {
53
            self::dump($dataType, 0);
54
        }
55
        $out = implode("\n", iterator_to_array(self::$result));//var_dump(iterator_to_array(self::$result));
56
        self::$result = null;
57
        return $out;
58
    }
59
60
    /**
61
     * Calls and saves the result of Dumper::toString to the file $filePath provided
62
     *
63
     * @param string   $filePath The file path
64
     * @param mixed    $dataType The data type
65
     * @param int|null $options  The options
66
     *
67
     * @throws \Exception datatype cannot be null
68
     *
69
     * @return boolean  true = if the file has been correctly saved  (according to return from 'file_put_contents')
70
     */
71
    public static function toFile(string $filePath, $dataType, int $options = null):bool
72
    {
73
        return !is_bool(file_put_contents($filePath, self::toString($dataType, $options)));
74
    }
75
76
    private static function dump($dataType, int $indent)
77
    {
78
        if (is_scalar($dataType)) {
79
            if ($dataType === INF) return '.inf';
80
            if ($dataType === -INF) return '-.inf';
81
            switch (gettype($dataType)) {
82
                case 'boolean': return $dataType ? 'true' : 'false';
83
                case 'float': //fall through
84
                case 'double': return is_nan($dataType) ? '.nan' : sprintf('%.'.self::$floatPrecision.'F', $dataType);
85
                default:
86
                    return $dataType;
87
            }
88
        } elseif (is_object($dataType)) {
89
            return self::dumpObject($dataType, $indent);
90
        } elseif (is_array($dataType)) {
91
            return self::dumpArray($dataType, $indent);
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::dumpArray($dataType, $indent) targeting Dallgoot\Yaml\Dumper::dumpArray() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
92
        }
93
    }
94
95
    private static function dumpYamlObject(YamlObject $obj)
96
    {
97
        if ($obj->hasDocStart() && self::$result instanceof DLL) self::$result->push("---");
98
        // self::dump($obj, 0);
99
        if (count($obj) > 0) {
100
            self::dumpArray($obj->getArrayCopy(), 0);
101
        } else {
102
            self::dumpObject($obj, 0);
103
        }
104
        // self::insertComments($obj->getComment());
105
        //TODO: $references = $obj->getAllReferences();
106
    }
107
108
    private static function add($value, $indent)
109
    {
110
        $newVal = str_repeat(" ", $indent).$value;
111
        foreach (str_split($newVal, self::WIDTH) as $chunks) {
112
            self::$result->push($chunks);
0 ignored issues
show
Bug introduced by
The method push() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

112
            self::$result->/** @scrutinizer ignore-call */ 
113
                           push($chunks);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
113
        }
114
    }
115
116
    private static function dumpArray(array $array, int $indent)
117
    {
118
        $refKeys = range(0, count($array));
119
        foreach ($array as $key => $item) {
120
            $lineStart = current($refKeys) === $key ? "- " : "- $key: ";
121
            if (is_scalar($item)) {
122
                self::add($lineStart.self::dump($item,0), $indent);
123
            } else {
124
                self::add(rtrim($lineStart), $indent);
125
                self::dump($item, $indent + self::INDENT);
126
            }
127
            next($refKeys);
128
        }
129
    }
130
131
    private static function insertComments(array $commentsArray)
0 ignored issues
show
Unused Code introduced by
The method insertComments() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
132
    {
133
        foreach ($commentsArray as $lineNb => $comment) {
134
            self::$result->add($lineNb, $comment);
135
        }
136
    }
137
138
    private static function dumpObject(object $obj, int $indent)
139
    {
140
        if ($obj instanceof Tag) {
141
            if (is_scalar($obj->value)) {
142
                self::add("!".$obj->tagName.' '.$obj->value, $indent);
143
            } else {
144
                self::add("!".$obj->tagName, $indent);
145
                self::add(self::dump($obj->value, $indent + self::INDENT), $indent + self::INDENT);
146
            }
147
        }
148
        if ($obj instanceof Compact) return self::dumpCompact($obj, $indent);
149
        //TODO:  consider dumping datetime as date strings according to a format provided by user or default
150
        if ($obj instanceof \DateTime) return $obj->format(self::DATE_FORMAT);
151
        // if ($obj instanceof \SplString) {var_dump('splstrin',$obj);return '"'.$obj.'"';}
152
        $propList = get_object_vars($obj);//var_dump($propList);
153
        foreach ($propList as $property => $value) {
154
            if (is_scalar($value) || $value instanceof Compact || $value instanceof \DateTime) {
155
                self::add("$property: ".self::dump($value, $indent), $indent);//var_dump('IS SCALAR', $value);
156
            } else {
157
                self::add("$property:", $indent);
158
                // self::add(self::dump($value, $indent + self::INDENT), $indent + self::INDENT);var_dump('NOT SCALAR');
159
                self::dump($value, $indent + self::INDENT);//var_dump('NOT SCALAR');
160
            }
161
        }
162
    }
163
164
    public static function dumpCompact($subject, int $indent)
165
    {//var_dump('ICI');
166
        $pairs = [];
167
        if (is_array($subject) || $subject instanceof \ArrayIterator) {
168
            $max = count($subject);
169
            $objectAsArray = is_array($subject) ? $subject : $subject->getArrayCopy();//var_dump(array_keys($objectAsArray), range(0, $max));
170
            if(array_keys($objectAsArray) !== range(0, $max-1)) {
171
                $pairs = $objectAsArray;
172
            } else {
173
                $valuesList = [];
174
                foreach ($objectAsArray as $value) {
175
                    $valuesList[] = is_scalar($value) ? self::dump($value, $indent) : self::dumpCompact($value, $indent);
176
                }
177
                return '['.implode(', ', $valuesList).']';
178
            }
179
        } else {
180
            $pairs = get_object_vars($subject);
181
        }
182
        $content = [];
183
        foreach ($pairs as $key => $value) {
184
            $content[] = "$key: ".(is_scalar($value) ? self::dump($value, $indent) : self::dumpCompact($value, $indent));
185
        }
186
        return '{'.implode(', ', $content).'}';
187
    }
188
}
189