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); |
|
|
|
|
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); |
|
|
|
|
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) |
|
|
|
|
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
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
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.