forked from govCMS/GovCMS8
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIniEncoder.php
166 lines (146 loc) · 4.25 KB
/
IniEncoder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
namespace govCMS\Core;
/**
* Class IniEncoder
*
* @package govCMS\Core
*/
class IniEncoder {
/**
* Serializes an array to legacy make format.
*
* @param array $input
* The data to serialize.
*
* @return string
* The serialized data.
*/
public function encode(array $input) {
return implode("\n", $this->doEncode($input));
}
/**
* Recursively serializes data to legacy make format.
*
* @param array $input
* The data to serialize.
* @param array $keys
* The current key path.
*
* @return string[]
* The serialized data as a flat array of lines.
*/
protected function doEncode(array $input, array $keys = []) {
$output = [];
foreach ($input as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
if ($this->isAssociative($value)) {
$output = array_merge($output, $this->doEncode($value, $keys));
}
else {
foreach ($value as $j) {
$output[] = $this->keysToString($keys) . '[] = ' . $j;
}
}
}
else {
$output[] = $this->keysToString($keys) . ' = ' . $value;
}
array_pop($keys);
}
return $output;
}
/**
* Transforms an key path to a string.
*
* @param string[] $keys
* The key path.
*
* @return string
* The flattened key path.
*/
protected function keysToString(array $keys) {
$head = array_shift($keys);
if ($keys) {
return $head . '[' . implode('][', $keys) . ']';
}
else {
return $head;
}
}
/**
* Tests if an array is associative.
*
* @param array $input
* The array to test.
*
* @return bool
* Whether or not the array has non-numeric keys.
*/
protected function isAssociative(array $input) {
$keys = implode('', array_keys($input));
return !is_numeric($keys);
}
/**
* Parses data in Drupal's .info format.
*
* @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_parse_info_format/7.x
*
* @param string $data
* A string to parse.
*
* @return array
* The parsed data.
*/
public function parse($data) {
$info = [];
if (preg_match_all('
@^\s* # Start at the beginning of a line, ignoring leading whitespace
((?:
[^=;\[\]]| # Key names cannot contain equal signs, semi-colons or square brackets,
\[[^\[\]]*\] # unless they are balanced and not nested
)+?)
\s*=\s* # Key/value pairs are separated by equal signs (ignoring white-space)
(?:
("(?:[^"]|(?<=\\\\)")*")| # Double-quoted string, which may contain slash-escaped quotes/slashes
(\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
([^\r\n]*?) # Non-quoted string
)\s*$ # Stop at the next end of a line, ignoring trailing whitespace
@msx', $data, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
// Fetch the key and value string.
$i = 0;
foreach (['key', 'value1', 'value2', 'value3'] as $var) {
$$var = isset($match[++$i]) ? $match[$i] : '';
}
if (isset($key) && isset($value1) && isset($value2) && isset($value3)) {
$value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
// Parse array syntax.
$keys = preg_split('/\]?\[/', rtrim($key, ']'));
$last = array_pop($keys);
$parent = &$info;
// Create nested arrays.
foreach ($keys as $key) {
if ($key == '') {
$key = count($parent);
}
if (!isset($parent[$key]) || !is_array($parent[$key])) {
$parent[$key] = [];
}
$parent = &$parent[$key];
}
// Handle PHP constants.
if (preg_match('/^\w+$/i', $value) && defined($value)) {
$value = constant($value);
}
// Insert actual value.
if ($last == '') {
$last = count($parent);
}
$parent[$last] = $value;
}
}
}
return $info;
}
}