Add support for nested if conditions (#6829)

* add support for nested if conditions
* add tests for condition parsing in templates
* make [space][slash] ending of condition objects optional (#6954)
pull/6453/head^2
johndoh 5 years ago committed by Aleksander Machniak
parent 530b53d92f
commit d51352b9cb

@ -1048,32 +1048,45 @@ EOF;
*/
protected function parse_conditions($input)
{
$matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>\n?/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
while (preg_match('/<roundcube:if\s+[^>]+>(((?!<roundcube:(if|endif)).)*)<roundcube:endif[^>]*>/is', $input, $conditions)) {
$result = $this->eval_condition($conditions[0]);
$input = str_replace($conditions[0], $result, $input);
}
return $input;
}
/**
* Process & evaluate conditional tags
*/
protected function eval_condition($input)
{
$matches = preg_split('/<roundcube:(if|elseif|else|endif)\s*([^>]*)>\n?/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($matches && count($matches) == 4) {
if (preg_match('/^(else|endif)$/i', $matches[1])) {
return $matches[0] . $this->parse_conditions($matches[3]);
return $matches[0] . $this->eval_condition($matches[3]);
}
$attrib = html::parse_attrib_string($matches[2]);
if (isset($attrib['condition'])) {
$condmet = $this->check_condition($attrib['condition']);
$submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>\n?/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
$condmet = $this->check_condition($attrib['condition']);
$condparts = preg_split('/<roundcube:((elseif|else|endif)[^>]*)>\n?/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
if ($condmet) {
$result = $submatches[0];
if ($submatches[1] != 'endif') {
$result .= preg_replace('/.*<roundcube:endif\s+[^>]+>\n?/Uis', '', $submatches[3], 1);
$result = $condparts[0];
if ($condparts[2] != 'endif') {
$result .= preg_replace('/.*<roundcube:endif[^>]*>\n?/Uis', '', $condparts[3], 1);
}
else {
$result .= $submatches[3];
$result .= $condparts[3];
}
}
else {
$result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
$result = "<roundcube:$condparts[1]>" . $condparts[3];
}
return $matches[0] . $this->parse_conditions($result);
return $matches[0] . $this->eval_condition($result);
}
rcube::raise_error(array(

@ -1,4 +1,5 @@
<?php
/**
* Test class to test rcmail_output_html class
*
@ -144,4 +145,36 @@ class Rcmail_OutputHtml extends PHPUnit\Framework\TestCase
$result = $get_template_logo->invokeArgs($output, array());
$this->assertSame('img16', $result);
}
/**
* Data for test_conditions()
*/
function data_conditions()
{
return array(
array("_start_<roundcube:if condition='1' />A<roundcube:endif />_end_", "_start_A_end_"),
array("_start_<roundcube:if condition='0' />A<roundcube:else />B<roundcube:endif />_end_", "_start_B_end_"),
array("_start_<roundcube:if condition='0'/>A<roundcube:else/>B<roundcube:endif/>_end_", "_start_B_end_"),
array("_start_<roundcube:if condition='0'>A<roundcube:else>B<roundcube:endif>_end_", "_start_B_end_"),
array("_start_<roundcube:if condition='0' />A<roundcube:elseif condition='1' />B<roundcube:else />C<roundcube:endif />_end_", "_start_B_end_"),
array("_start_<roundcube:if condition='1' /><roundcube:if condition='0' />A<roundcube:else />B<roundcube:endif />C<roundcube:else />D<roundcube:endif />_end_", "_start_BC_end_"),
array("_start_<roundcube:if condition='1' /><roundcube:if condition='1' />A<roundcube:else />B<roundcube:endif />C<roundcube:else />D<roundcube:endif />_end_", "_start_AC_end_"),
array("_start_<roundcube:if condition='1' /><roundcube:if condition='0' />A<roundcube:elseif condition='1' />B<roundcube:else />C<roundcube:endif />D<roundcube:else />E<roundcube:endif />_end_", "_start_BD_end_"),
array("_start_<roundcube:if condition='0' />A<roundcube:elseif condition='1' /><roundcube:if condition='0' />B<roundcube:else /><roundcube:if condition='1' />C<roundcube:endif />D<roundcube:endif /><roundcube:else />E<roundcube:endif />_end_", "_start_CD_end_"),
array("_start_<roundcube:if condition='0'>A<roundcube:elseif condition='1'><roundcube:if condition='0'>B<roundcube:else><roundcube:if condition='1'>C<roundcube:endif>D<roundcube:endif><roundcube:else>E<roundcube:endif>_end_", "_start_CD_end_")
);
}
/**
* Test text to html conversion
*
* @dataProvider data_conditions
*/
function test_conditions($input, $output)
{
$object = new rcmail_output_html;
$result = $object->just_parse($input);
$this->assertEquals($output, $result);
}
}

Loading…
Cancel
Save