protected function keyValueFromString($text)
{
// Match colon separator outside of quoted substrings
// Fallback to nearest semicolon outside of quoted substrings, if colon cannot be found
// Do not try and match within the value paired with the keyword
preg_match('/(.*?)(?::(?=(?:[^"]*"[^"]*")*[^"]*$)|;(?=[^:]*$))([\\w\\W]*)/', htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'), $matches);
if (count($matches) == 0) {
return false;
}
if (preg_match('/^([A-Z-]+)([;][\\w\\W]*)?$/', $matches[1])) {
$matches = array_splice($matches, 1, 2);
// Remove first match and re-align ordering
// Process properties
if (preg_match('/([A-Z-]+)[;]([\\w\\W]*)/', $matches[0], $properties)) {
// Remove first match
array_shift($properties);
// Fix to ignore everything in keyword after a ; (e.g. Language, TZID, etc.)
$matches[0] = $properties[0];
array_shift($properties);
// Repeat removing first match
$formatted = array();
foreach ($properties as $property) {
// Match semicolon separator outside of quoted substrings
preg_match_all('~[^\\r\\n";]+(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"[^\\r\\n";]*)*~', $property, $attributes);
// Remove multi-dimensional array and use the first key
$attributes = sizeof($attributes) == 0 ? array($property) : reset($attributes);
if (is_array($attributes)) {
foreach ($attributes as $attribute) {
// Match equals sign separator outside of quoted substrings
preg_match_all('~[^\\r\\n"=]+(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"[^\\r\\n"=]*)*~', $attribute, $values);
// Remove multi-dimensional array and use the first key
$value = sizeof($values) == 0 ? null : reset($values);
if (is_array($value) && isset($value[1])) {
// Remove double quotes from beginning and end only
$formatted[$value[0]] = trim($value[1], '"');
}
}
}
}
// Assign the keyword property information
$properties[0] = $formatted;
// Add match to beginning of array
array_unshift($properties, $matches[1]);
$matches[1] = $properties;
}
return $matches;
} else {
return false;
// Ignore this match
}
}