1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Part of the Joomla Framework Registry Package |
4
|
|
|
* |
5
|
|
|
* @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved. |
6
|
|
|
* @license GNU General Public License version 2 or later; see LICENSE |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace Joomla\Registry\Format; |
10
|
|
|
|
11
|
|
|
use Joomla\Registry\AbstractRegistryFormat; |
12
|
|
|
use Joomla\Utilities\ArrayHelper; |
13
|
|
|
use stdClass; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* INI format handler for Registry. |
17
|
|
|
* |
18
|
|
|
* @since 1.0 |
19
|
|
|
*/ |
20
|
|
|
class Ini extends AbstractRegistryFormat |
|
|
|
|
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* Default options array |
24
|
|
|
* |
25
|
|
|
* @var array |
26
|
|
|
* @since 1.3.0 |
27
|
|
|
*/ |
28
|
|
|
protected static $options = array( |
29
|
|
|
'supportArrayValues' => false, |
30
|
|
|
'parseBooleanWords' => false, |
31
|
|
|
'processSections' => false, |
32
|
|
|
); |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* A cache used by stringToobject. |
36
|
|
|
* |
37
|
|
|
* @var array |
38
|
|
|
* @since 1.0 |
39
|
|
|
*/ |
40
|
|
|
protected static $cache = array(); |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Converts an object into an INI formatted string |
44
|
|
|
* - Unfortunately, there is no way to have ini values nested further than two |
45
|
|
|
* levels deep. Therefore we will only go through the first two levels of |
46
|
|
|
* the object. |
47
|
|
|
* |
48
|
|
|
* @param object $object Data source object. |
49
|
|
|
* @param array $options Options used by the formatter. |
50
|
|
|
* |
51
|
|
|
* @return string INI formatted string. |
52
|
|
|
* |
53
|
|
|
* @since 1.0 |
54
|
|
|
*/ |
55
|
|
|
public function objectToString($object, $options = array()) |
56
|
|
|
{ |
57
|
|
|
$options = array_merge(self::$options, $options); |
58
|
|
|
|
59
|
|
|
$local = array(); |
60
|
|
|
$global = array(); |
61
|
|
|
|
62
|
|
|
$variables = get_object_vars($object); |
63
|
|
|
|
64
|
|
|
$last = count($variables); |
65
|
|
|
|
66
|
|
|
// Assume that the first element is in section |
67
|
|
|
$in_section = true; |
68
|
|
|
|
69
|
|
|
// Iterate over the object to set the properties. |
70
|
|
|
foreach ($variables as $key => $value) |
71
|
|
|
{ |
72
|
|
|
// If the value is an object then we need to put it in a local section. |
73
|
|
|
if (is_object($value)) |
74
|
|
|
{ |
75
|
|
|
// Add an empty line if previous string wasn't in a section |
76
|
|
|
if (!$in_section) |
77
|
|
|
{ |
78
|
|
|
$local[] = ''; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
// Add the section line. |
82
|
|
|
$local[] = '[' . $key . ']'; |
83
|
|
|
|
84
|
|
|
// Add the properties for this section. |
85
|
|
|
foreach (get_object_vars($value) as $k => $v) |
86
|
|
|
{ |
87
|
|
|
if (is_array($v) && $options['supportArrayValues']) |
88
|
|
|
{ |
89
|
|
|
$assoc = ArrayHelper::isAssociative($v); |
90
|
|
|
|
91
|
|
|
foreach ($v as $array_key => $item) |
92
|
|
|
{ |
93
|
|
|
$array_key = ($assoc) ? $array_key : ''; |
94
|
|
|
$local[] = $k . '[' . $array_key . ']=' . $this->getValueAsIni($item); |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
else |
98
|
|
|
{ |
99
|
|
|
$local[] = $k . '=' . $this->getValueAsIni($v); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
// Add empty line after section if it is not the last one |
104
|
|
|
if (0 != --$last) |
105
|
|
|
{ |
106
|
|
|
$local[] = ''; |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
elseif (is_array($value) && $options['supportArrayValues']) |
110
|
|
|
{ |
111
|
|
|
$assoc = ArrayHelper::isAssociative($value); |
112
|
|
|
|
113
|
|
|
foreach ($value as $array_key => $item) |
114
|
|
|
{ |
115
|
|
|
$array_key = ($assoc) ? $array_key : ''; |
116
|
|
|
$global[] = $key . '[' . $array_key . ']=' . $this->getValueAsIni($item); |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
else |
120
|
|
|
{ |
121
|
|
|
// Not in a section so add the property to the global array. |
122
|
|
|
$global[] = $key . '=' . $this->getValueAsIni($value); |
123
|
|
|
$in_section = false; |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return implode("\n", array_merge($global, $local)); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Parse an INI formatted string and convert it into an object. |
132
|
|
|
* |
133
|
|
|
* @param string $data INI formatted string to convert. |
134
|
|
|
* @param array $options An array of options used by the formatter, or a boolean setting to process sections. |
135
|
|
|
* |
136
|
|
|
* @return object Data object. |
137
|
|
|
* |
138
|
|
|
* @since 1.0 |
139
|
|
|
*/ |
140
|
|
|
public function stringToObject($data, array $options = array()) |
141
|
|
|
{ |
142
|
|
|
$options = array_merge(self::$options, $options); |
143
|
|
|
|
144
|
|
|
// Check the memory cache for already processed strings. |
145
|
|
|
$hash = md5($data . ':' . (int) $options['processSections']); |
146
|
|
|
|
147
|
|
|
if (isset(self::$cache[$hash])) |
148
|
|
|
{ |
149
|
|
|
return self::$cache[$hash]; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
// If no lines present just return the object. |
153
|
|
|
if (empty($data)) |
154
|
|
|
{ |
155
|
|
|
return new stdClass; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
$obj = new stdClass; |
159
|
|
|
$section = false; |
160
|
|
|
$array = false; |
161
|
|
|
$lines = explode("\n", $data); |
162
|
|
|
|
163
|
|
|
// Process the lines. |
164
|
|
|
foreach ($lines as $line) |
165
|
|
|
{ |
166
|
|
|
// Trim any unnecessary whitespace. |
167
|
|
|
$line = trim($line); |
168
|
|
|
|
169
|
|
|
// Ignore empty lines and comments. |
170
|
|
|
if (empty($line) || ($line{0} == ';')) |
171
|
|
|
{ |
172
|
|
|
continue; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
if ($options['processSections']) |
176
|
|
|
{ |
177
|
|
|
$length = strlen($line); |
178
|
|
|
|
179
|
|
|
// If we are processing sections and the line is a section add the object and continue. |
180
|
|
|
if (($line[0] == '[') && ($line[$length - 1] == ']')) |
181
|
|
|
{ |
182
|
|
|
$section = substr($line, 1, $length - 2); |
183
|
|
|
$obj->$section = new stdClass; |
184
|
|
|
continue; |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
elseif ($line{0} == '[') |
188
|
|
|
{ |
189
|
|
|
continue; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
// Check that an equal sign exists and is not the first character of the line. |
193
|
|
|
if (!strpos($line, '=')) |
194
|
|
|
{ |
195
|
|
|
// Maybe throw exception? |
196
|
|
|
continue; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
// Get the key and value for the line. |
200
|
|
|
list ($key, $value) = explode('=', $line, 2); |
201
|
|
|
|
202
|
|
|
// If we have an array item |
203
|
|
|
if (substr($key, -1) == ']' && ($open_brace = strpos($key, '[', 1)) !== false) |
204
|
|
|
{ |
205
|
|
|
if ($options['supportArrayValues']) |
206
|
|
|
{ |
207
|
|
|
$array = true; |
208
|
|
|
$array_key = substr($key, $open_brace + 1, -1); |
209
|
|
|
|
210
|
|
|
// If we have a multi-dimensional array or malformed key |
211
|
|
|
if (strpos($array_key, '[') !== false || strpos($array_key, ']') !== false) |
212
|
|
|
{ |
213
|
|
|
// Maybe throw exception? |
214
|
|
|
continue; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
$key = substr($key, 0, $open_brace); |
218
|
|
|
} |
219
|
|
|
else |
220
|
|
|
{ |
221
|
|
|
continue; |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
// Validate the key. |
226
|
|
|
if (preg_match('/[^A-Z0-9_]/i', $key)) |
227
|
|
|
{ |
228
|
|
|
// Maybe throw exception? |
229
|
|
|
continue; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
// If the value is quoted then we assume it is a string. |
233
|
|
|
$length = strlen($value); |
234
|
|
|
|
235
|
|
|
if ($length && ($value[0] == '"') && ($value[$length - 1] == '"')) |
236
|
|
|
{ |
237
|
|
|
// Strip the quotes and Convert the new line characters. |
238
|
|
|
$value = stripcslashes(substr($value, 1, ($length - 2))); |
239
|
|
|
$value = str_replace('\n', "\n", $value); |
240
|
|
|
} |
241
|
|
|
else |
242
|
|
|
{ |
243
|
|
|
// If the value is not quoted, we assume it is not a string. |
244
|
|
|
|
245
|
|
|
// If the value is 'false' assume boolean false. |
246
|
|
|
if ($value == 'false') |
247
|
|
|
{ |
248
|
|
|
$value = false; |
249
|
|
|
} |
250
|
|
|
elseif ($value == 'true') |
251
|
|
|
// If the value is 'true' assume boolean true. |
252
|
|
|
{ |
253
|
|
|
$value = true; |
254
|
|
|
} |
255
|
|
|
elseif ($options['parseBooleanWords'] && in_array(strtolower($value), array('yes', 'no'))) |
256
|
|
|
// If the value is 'yes' or 'no' and option is enabled assume appropriate boolean |
257
|
|
|
{ |
258
|
|
|
$value = (strtolower($value) == 'yes'); |
259
|
|
|
} |
260
|
|
|
elseif (is_numeric($value)) |
261
|
|
|
// If the value is numeric than it is either a float or int. |
262
|
|
|
{ |
263
|
|
|
// If there is a period then we assume a float. |
264
|
|
|
if (strpos($value, '.') !== false) |
265
|
|
|
{ |
266
|
|
|
$value = (float) $value; |
267
|
|
|
} |
268
|
|
|
else |
269
|
|
|
{ |
270
|
|
|
$value = (int) $value; |
271
|
|
|
} |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
// If a section is set add the key/value to the section, otherwise top level. |
276
|
|
|
if ($section) |
|
|
|
|
277
|
|
|
{ |
278
|
|
|
if ($array) |
279
|
|
|
{ |
280
|
|
|
if (!isset($obj->$section->$key)) |
281
|
|
|
{ |
282
|
|
|
$obj->$section->$key = array(); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
View Code Duplication |
if (!empty($array_key)) |
|
|
|
|
286
|
|
|
{ |
287
|
|
|
$obj->$section->{$key}[$array_key] = $value; |
288
|
|
|
} |
289
|
|
|
else |
290
|
|
|
{ |
291
|
|
|
$obj->$section->{$key}[] = $value; |
292
|
|
|
} |
293
|
|
|
} |
294
|
|
|
else |
295
|
|
|
{ |
296
|
|
|
$obj->$section->$key = $value; |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
else |
300
|
|
|
{ |
301
|
|
|
if ($array) |
302
|
|
|
{ |
303
|
|
|
if (!isset($obj->$key)) |
304
|
|
|
{ |
305
|
|
|
$obj->$key = array(); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
View Code Duplication |
if (!empty($array_key)) |
|
|
|
|
309
|
|
|
{ |
310
|
|
|
$obj->{$key}[$array_key] = $value; |
311
|
|
|
} |
312
|
|
|
else |
313
|
|
|
{ |
314
|
|
|
$obj->{$key}[] = $value; |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
else |
318
|
|
|
{ |
319
|
|
|
$obj->$key = $value; |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
$array = false; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
// Cache the string to save cpu cycles -- thus the world :) |
327
|
|
|
self::$cache[$hash] = clone $obj; |
328
|
|
|
|
329
|
|
|
return $obj; |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Method to get a value in an INI format. |
334
|
|
|
* |
335
|
|
|
* @param mixed $value The value to convert to INI format. |
336
|
|
|
* |
337
|
|
|
* @return string The value in INI format. |
338
|
|
|
* |
339
|
|
|
* @since 1.0 |
340
|
|
|
*/ |
341
|
|
|
protected function getValueAsIni($value) |
342
|
|
|
{ |
343
|
|
|
$string = ''; |
344
|
|
|
|
345
|
|
|
switch (gettype($value)) |
346
|
|
|
{ |
347
|
|
|
case 'integer': |
348
|
|
|
case 'double': |
349
|
|
|
$string = $value; |
350
|
|
|
break; |
351
|
|
|
|
352
|
|
|
case 'boolean': |
353
|
|
|
$string = $value ? 'true' : 'false'; |
354
|
|
|
break; |
355
|
|
|
|
356
|
|
|
case 'string': |
357
|
|
|
// Sanitize any CRLF characters.. |
358
|
|
|
$string = '"' . str_replace(array("\r\n", "\n"), '\\n', $value) . '"'; |
359
|
|
|
break; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $string; |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.