wxt-8.x-3.011/src/IniEncoder.php
src/IniEncoder.php
<?php
namespace Drupal\wxt;
/**
* Contains methods for parsing and dumping data in the legacy info file format.
*
* Leveraged from code provided by Acquia for the Lightning distribution.
*/
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.
*
* @param string $data
* A string to parse.
*
* @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_parse_info_format/7.x
*
* @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] : '';
}
$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;
}
}
