presto-8.x-2.2/src/IniEncoder.php
src/IniEncoder.php
<?php namespace Drupal\presto; /** * Contains methods for parsing and dumping data in the legacy info file format. * * Based on code by Acquia in acquia/lightning, copyright (c) 2017. * Distributed under the GNU GPL v2 or higher. For full terms see the LICENSE * file. */ 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) { $serialisedData = $this->doEncode($input); // Create a new line at the end of the file. $serialisedData[] = ''; return implode("\n", $serialisedData); } /** * 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) . ']'; } 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; $key = ''; $value1 = ''; $value2 = ''; $value3 = ''; 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; } }