Мы принимаем строки из шаблонов в механизм разметки, который позволяет передавать конфигурацию в «простой» форме.
Механизм анализирует строки через PHP, используя адаптированную версию Функция parse_str () - чтобы мы могли проанализировать любую комбинацию строк ниже:
config=posts_per_page:"5",default:"No questions yet -- once created they will appear here."&markup->template="{{ questions }}"
дает:
Array(
[config] => Array
(
[posts_per_page] => 5
[default] => No questions yet -- once created they will appear here.
)
[markup] => Array
(
[template] => {{ questions }}
)
)
OR:
config->default=all:"<p class='ml-3'>No members here yet...</p>"
Чтобы получить:
Array
[config] => Array
(
[default] => Array
(
[all] => <p class='ml-3'>No members here yet...</p>
)
)
)
Другой:
config=>handle:"medium"
Возвращает:
Array (
[config] => Array
(
[>handle] => medium
)
)
Строки могут передаваться с пробелами (и многострочными пробелами), и должны передаваться строковые параметры между "двойными кавычками", чтобы сохранить естественный интервал - мы запускаем следующую preg_replace в строке, прежде чем она будет передана методу parse_str:
// strip white spaces from data that is not passed inside double quotes ( "data" ) ##
$string = preg_replace( '~"[^"]*"(*SKIP)(*F)|\s+~', "", $string );
Пока все хорошо - пока мы не попытаемся передать "разделитель" "внутри строкового значения, то оно обрабатывается буквально - например, следующая строка возвращает поврежденный массив:
config=posts_per_page:"5",default:"No questions yet -- once created, they will appear here."&markup->template="{{ questions }}"
Возвращает следующий массив:
Array (
[config] => Array
(
[posts_per_page] => 5
[default] => No questions yet -- once created
[ they will appear here."] =>
)
[markup] => Array
(
[template] => {{ questions }}
)
)
Знак«, »был обрабатывались буквально, и строка была сломана int o дополнительная часть массива.
Одним из простых решений является создание разделителей и операторов с меньшей вероятностью конфликта со строковыми значениями - например, изменение "," на "@@@" - но одной важной частью используемая разметка заключается в том, что ее легко писать и читать - это предполагаемый вариант использования для интерфейсных разработчиков, чтобы передать простые аргументы синтаксическому анализатору шаблона - это одна из причин, по которой мы пытались избежать JSON - что, конечно, является хорошо подходит с точки зрения передачи данных, но его трудно читать и писать - конечно, это утверждение субъективно и открыто для мнений :)
Вот метод parse_str:
public static function parse_str( $string = null ) {
// h::log($string);
// delimiters ##
$operator_assign = '=';
$operator_array = '->';
$delimiter_key = ':';
$delimiter_and_property = ',';
$delimiter_and_key = '&';
// check for "=" delimiter ##
if( false === strpos( $string, $operator_assign ) ){
h::log( 'e:>Passed string format does not include asssignment operator "'.$operator_assign.'" -- '.$string );
return false;
}
# result array
$array = [];
# split on outer delimiter
$pairs = explode( $delimiter_and_key, $string );
# loop through each pair
foreach ( $pairs as $i ) {
# split into name and value
list( $key, $value ) = explode( $operator_assign, $i, 2 );
// what about array values ##
// example -- sm:medium, lg:large
if( false !== strpos( $value, $delimiter_key ) ){
// temp array ##
$value_array = [];
// split value into an array at "," ##
$value_pairs = explode( $delimiter_and_property, $value );
// h::log( $value_pairs );
# loop through each pair
foreach ( $value_pairs as $v_pair ) {
// h::log( $v_pair ); // 'sm:medium'
# split into name and value
list( $value_key, $value_value ) = explode( $delimiter_key, $v_pair, 2 );
$value_array[ $value_key ] = $value_value;
}
// check if we have an array ##
if ( is_array( $value_array ) ){
$value = $value_array;
}
}
// $key might be in part__part format, so check ##
if( false !== strpos( $key, $operator_array ) ){
// explode, max 2 parts ##
$md_key = explode( $operator_array, $key, 2 );
# if name already exists
if( isset( $array[ $md_key[0] ][ $md_key[1] ] ) ) {
# stick multiple values into an array
if( is_array( $array[ $md_key[0] ][ $md_key[1] ] ) ) {
$array[ $md_key[0] ][ $md_key[1] ][] = $value;
} else {
$array[ $md_key[0] ][ $md_key[1] ] = array( $array[ $md_key[0] ][ $md_key[1] ], $value );
}
# otherwise, simply stick it in a scalar
} else {
$array[ $md_key[0] ][ $md_key[1] ] = $value;
}
} else {
# if name already exists
if( isset($array[$key]) ) {
# stick multiple values into an array
if( is_array($array[$key]) ) {
$array[$key][] = $value;
} else {
$array[$key] = array($array[$key], $value);
}
# otherwise, simply stick it in a scalar
} else {
$array[$key] = $value;
}
}
}
// h::log( $array );
# return result array
return $array;
}
Я постараюсь пропустить разделение строки между «двойными кавычками» - возможно, с помощью другого регулярного выражения, но, возможно, есть другие потенциальные подводные камни, которые могут не сделать этот подход жизнеспособным в долгосрочной перспективе - любая помощь с радостью принимается!