mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-04 17:21:39 +09:00
Complete unit tests for all the features of template parser v2
This commit is contained in:
parent
7fd916a81e
commit
b0d288cb18
1 changed files with 646 additions and 9 deletions
|
|
@ -173,6 +173,16 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
$target = "<?php \Context::loadFile(['./tests/_data/template/otherdir/hello.js', 'body', '', 20]); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// External script
|
||||
$source = '<load src="//cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.min.js" />';
|
||||
$target = "<?php \Context::loadFile(['//cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.min.js', '', 'tests', '']); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// External webfont
|
||||
$source = '<load src="https://fonts.googleapis.com/css2?family=Roboto&display=swap" />';
|
||||
$target = "<?php \Context::loadFile(['https://fonts.googleapis.com/css2?family=Roboto&display=swap', '', 'tests', '', []]); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Path relative to Rhymix installation directory
|
||||
$source = '<load src="^/common/js/foobar.js" />';
|
||||
$target = "<?php \Context::loadFile(['./common/js/foobar.js', '', '', '']); ?>";
|
||||
|
|
@ -214,6 +224,16 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
$target = "<?php \Context::loadFile(['./tests/_data/template/assets/hello.js', '', '', '']); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style external script
|
||||
$source = "@load ('//cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.min.js')";
|
||||
$target = "<?php \Context::loadFile(['//cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.min.js', '', 'tests', '']); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style external webfont
|
||||
$source = "@load('https://fonts.googleapis.com/css2?family=Roboto&display=swap')";
|
||||
$target = "<?php \Context::loadFile(['https://fonts.googleapis.com/css2?family=Roboto&display=swap', '', 'tests', '', []]); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style path relative to Rhymix installation directory
|
||||
$source = '@load ("^/common/js/foobar.js")';
|
||||
$target = "<?php \Context::loadFile(['./common/js/foobar.js', '', '', '']); ?>";
|
||||
|
|
@ -289,52 +309,669 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
|
|||
|
||||
public function testOutputFilters()
|
||||
{
|
||||
// Filters with no whitespace
|
||||
$source = '{$foo|upper|noescape}';
|
||||
$target = "<?php echo strtoupper(\$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Randomly distributed whitespace
|
||||
$source = '{$foo | upper |noescape }';
|
||||
$target = "<?php echo strtoupper(\$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Pipe character in filter option
|
||||
$source = "{\$foo|join:'|'|noescape}";
|
||||
$target = "<?php echo implode('|', \$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Pipe character in filter option, escaped
|
||||
$source = "{\$foo|join:'foo\|bar'|noescape}";
|
||||
$target = "<?php echo implode('foo|bar', \$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Pipe character in OR operator
|
||||
$source = '{$foo || $bar | noescape}';
|
||||
$target = "<?php echo \$__Context->foo || \$__Context->bar; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Autoescape
|
||||
$source = '{{ $foo|autoescape }}';
|
||||
$target = "<?php echo htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Autolang
|
||||
$source = '{{ $foo|autolang }}';
|
||||
$target = "<?php echo (preg_match('/^$(?:user_)?lang->\w+$/', \$__Context->foo ?? '') ? (\$__Context->foo ?? '') : htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Escape
|
||||
$source = '{{ $foo|escape }}';
|
||||
$target = "<?php echo htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', true); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Noescape
|
||||
$source = '{{ $foo|escape|noescape }}';
|
||||
$target = "<?php echo \$__Context->foo ?? ''; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Escape for Javascript
|
||||
$source = '{{ $foo|js }}';
|
||||
$target = "<?php echo escape_js(\$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Escape for Javascript (alternate name)
|
||||
$source = '{{ $foo|escapejs }}';
|
||||
$target = "<?php echo escape_js(\$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// JSON using context-aware escape
|
||||
$source = '{{ $foo|json }}';
|
||||
$target = implode('', [
|
||||
"<?php echo \$this->config->context === 'JS' ? ",
|
||||
"(json_encode(\$__Context->foo ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES)) : ",
|
||||
"htmlspecialchars(json_encode(\$__Context->foo ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, 'UTF-8', false); ?>",
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// strip_tags
|
||||
$source = '{{ $foo|strip }}';
|
||||
$target = "<?php echo htmlspecialchars(strip_tags(\$__Context->foo ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// strip_tags (alternate name)
|
||||
$source = '{{ $foo|upper|strip_tags }}';
|
||||
$target = "<?php echo htmlspecialchars(strip_tags(strtoupper(\$__Context->foo ?? '')), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Trim
|
||||
$source = '{{ $foo|trim|noescape }}';
|
||||
$target = "<?php echo trim(\$__Context->foo ?? ''); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// URL encode
|
||||
$source = '{{ $foo|trim|urlencode }}';
|
||||
$target = "<?php echo htmlspecialchars(rawurlencode(trim(\$__Context->foo ?? '')), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Lowercase
|
||||
$source = '{{ $foo|trim|lower }}';
|
||||
$target = "<?php echo htmlspecialchars(strtolower(trim(\$__Context->foo ?? '')), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Uppercase
|
||||
$source = '{{ $foo|upper|escape }}';
|
||||
$target = "<?php echo htmlspecialchars(strtoupper(\$__Context->foo ?? ''), \ENT_QUOTES, 'UTF-8', true); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// nl2br()
|
||||
$source = '{{ $foo|nl2br }}';
|
||||
$target = "<?php echo nl2br(htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// nl2br() with gratuitous escape
|
||||
$source = '{{ $foo|nl2br|escape }}';
|
||||
$target = "<?php echo htmlspecialchars(nl2br(htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)), \ENT_QUOTES, 'UTF-8', true); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Array join (default joiner is comma)
|
||||
$source = '{{ $foo|join }}';
|
||||
$target = "<?php echo htmlspecialchars(implode(', ', \$__Context->foo ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Array join (custom joiner)
|
||||
$source = '{{ $foo|join:"!@!" }}';
|
||||
$target = "<?php echo htmlspecialchars(implode(\"!@!\", \$__Context->foo ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Date conversion (default format)
|
||||
$source = '{{ $item->regdate | date }}';
|
||||
$target = "<?php echo htmlspecialchars(getDisplayDateTime(ztime(\$__Context->item->regdate ?? ''), 'Y-m-d H:i:s'), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Date conversion (custom format)
|
||||
$source = "{{ \$item->regdate | date:'n/j H:i' }}";
|
||||
$target = "<?php echo htmlspecialchars(getDisplayDateTime(ztime(\$__Context->item->regdate ?? ''), 'n/j H:i'), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Date conversion (custom format in variable)
|
||||
$source = "{{ \$item->regdate | date:\$format }}";
|
||||
$target = "<?php echo htmlspecialchars(getDisplayDateTime(ztime(\$__Context->item->regdate ?? ''), \$__Context->format), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number format
|
||||
$source = '{{ $num | format }}';
|
||||
$target = "<?php echo htmlspecialchars(number_format(\$__Context->num ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number format (alternate name)
|
||||
$source = '{{ $num | number_format }}';
|
||||
$target = "<?php echo htmlspecialchars(number_format(\$__Context->num ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number format (custom format)
|
||||
$source = '{{ $num | number_format:6 }}';
|
||||
$target = "<?php echo htmlspecialchars(number_format(\$__Context->num ?? '', '6'), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number format (custom format in variable)
|
||||
$source = '{{ $num | number_format:$digits }}';
|
||||
$target = "<?php echo htmlspecialchars(number_format(\$__Context->num ?? '', \$__Context->digits), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number shorten
|
||||
$source = '{{ $num | shorten }}';
|
||||
$target = "<?php echo htmlspecialchars(number_shorten(\$__Context->num ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number shorten (alternate name)
|
||||
$source = '{{ $num | number_shorten }}';
|
||||
$target = "<?php echo htmlspecialchars(number_shorten(\$__Context->num ?? ''), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Number shorten (custom format)
|
||||
$source = '{{ $num | number_shorten:1 }}';
|
||||
$target = "<?php echo htmlspecialchars(number_shorten(\$__Context->num ?? '', '1'), \ENT_QUOTES, 'UTF-8', false); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Link
|
||||
$source = '{{ $foo|link }}';
|
||||
$target = "<?php echo '<a href=\"' . (htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)) . '\">' . (htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)) . '</a>'; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Link (custom link text)
|
||||
$source = '{{ $foo|link:"Hello World" }}';
|
||||
$target = "<?php echo '<a href=\"' . (htmlspecialchars(\"Hello World\", \ENT_QUOTES, 'UTF-8', false)) . '\">' . (htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)) . '</a>'; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Link (custom link text in variable)
|
||||
$source = '{{ $foo|link:$bar->baz[0] }}';
|
||||
$target = "<?php echo '<a href=\"' . (htmlspecialchars(\$__Context->bar->baz[0], \ENT_QUOTES, 'UTF-8', false)) . '\">' . (htmlspecialchars(\$__Context->foo ?? '', \ENT_QUOTES, 'UTF-8', false)) . '</a>'; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testVariableScopeConversion()
|
||||
{
|
||||
// Local variable
|
||||
$source = '{$foo|noescape}';
|
||||
$target = "<?php echo \$__Context->foo ?? ''; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Class and array keys
|
||||
$source = '{!! ClassName::getInstance()->$foo[$bar] !!}';
|
||||
$target = "<?php echo ClassName::getInstance()->{\$__Context->foo}[\$__Context->bar]; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Superglobals
|
||||
$source = "{!! \$_SERVER['HTTP_USER_AGENT'] . \$GLOBALS[\$_GET['foo']] !!}";
|
||||
$target = "<?php echo \$_SERVER['HTTP_USER_AGENT'] . \$GLOBALS[\$_GET['foo']]; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// $this
|
||||
$source = "{!! \$this->func(\$args) !!}";
|
||||
$target = "<?php echo \$this->func(\$__Context->args); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// $lang
|
||||
$source = "{!! \$lang->cmd_yes !!}";
|
||||
$target = "<?php echo \$__Context->lang->cmd_yes ?? ''; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// $loop
|
||||
$source = "{!! \$loop->first !!}";
|
||||
$target = "<?php echo \$loop->first ?? ''; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Escaped dollar sign
|
||||
$source = "{!! \\\$escaped !!}";
|
||||
$target = "<?php echo \$escaped; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Escaped and unescaped variables used together in closure
|
||||
$source = "{!! (function(\\\$i) use(\$__Context) { return \\\$i * \$j; })(\$k); !!}";
|
||||
$target = "<?php echo (function(\$i) use(\$__Context) { return \$i * \$__Context->j; })(\$__Context->k);; ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testPathConversion()
|
||||
{
|
||||
// Image
|
||||
$source = '<img class="foo" src="foo.jpg" alt="foo" />';
|
||||
$target = '<img class="foo" src="' . $this->baseurl . 'tests/_data/template/foo.jpg" alt="foo" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// <video>
|
||||
$source = '<video id="video" src="dir/foo.mp4"></video>';
|
||||
$target = '<video id="video" src="' . $this->baseurl . 'tests/_data/template/dir/foo.mp4"></video>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// <video> with poster attribute and <source> inside
|
||||
$source = '<video poster="bar.jpg"><source src="../foo.mp4" /></video>';
|
||||
$target = '<video poster="' . $this->baseurl . 'tests/_data/template/bar.jpg"><source src="' . $this->baseurl . 'tests/_data/foo.mp4" /></video>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// <audio> with path relative to the Rhymix installation directory
|
||||
$source = '<audio controls src="^/assets/foo.ogg" autoplay loop></audio>';
|
||||
$target = '<audio controls src="' . $this->baseurl . 'assets/foo.ogg" autoplay loop></audio>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// <input type="image"> with src
|
||||
$source = '<input type="image" src="foo/bar.jpg" />';
|
||||
$target = '<input type="image" src="' . $this->baseurl . 'tests/_data/template/foo/bar.jpg" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Script tag with local path
|
||||
$source = '<script src="assets/foo.js" async>';
|
||||
$target = '<script src="' . $this->baseurl . 'tests/_data/template/assets/foo.js" async<?php $this->config->context = "JS"; ?>>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Script tag with external path
|
||||
$source = '<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.0/js/bootstrap.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>';
|
||||
$target = '<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.0/js/bootstrap.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"<?php $this->config->context = "JS"; ?>><?php $this->config->context = "HTML"; ?></script>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Absolute URL
|
||||
$source = '<img src="/foo/bar.jpg" />';
|
||||
$target = '<img src="/foo/bar.jpg" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// External URL
|
||||
$source = '<img src="http://example.com/foo/bar.jpg" />';
|
||||
$target = '<img src="http://example.com/foo/bar.jpg" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// data: URL
|
||||
$source = '<img src="data:image/png;base64,AAAAAAAAAAA=" />';
|
||||
$target = '<img src="data:image/png;base64,AAAAAAAAAAA=" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// file: URL
|
||||
$source = '<img src="file:///C:/inetpub/foobar.jpg" />';
|
||||
$target = '<img src="file:///C:/inetpub/foobar.jpg" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// srcset
|
||||
$source = '<img srcset="bar/foo@4x.png 4x, ../foo@2x.png 2x ,./foo.jpg" />';
|
||||
$target = '<img srcset="' . $this->baseurl . 'tests/_data/template/bar/foo@4x.png 4x, ' . $this->baseurl . 'tests/_data/foo@2x.png 2x, ' . $this->baseurl . 'tests/_data/template/foo.jpg" />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testBlockConditions()
|
||||
{
|
||||
// @if in comments
|
||||
$source = '<!--@if($cond)--><p>Hello World</p><!--@endif-->';
|
||||
$target = '<?php if ($__Context->cond): ?><p>Hello World</p><?php endif; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @if in its own line, with @elseif and @else
|
||||
$source = implode("\n", [
|
||||
'@if($foo)',
|
||||
'<p>Hello World</p>',
|
||||
'@elseif($bar)',
|
||||
'<p>Goodbye World</p>',
|
||||
'@else',
|
||||
'<p>So long and thx 4 all the fish</p>',
|
||||
'@endif',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if ($__Context->foo): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php elseif ($__Context->bar): ?>',
|
||||
'<p>Goodbye World</p>',
|
||||
'<?php else: ?>',
|
||||
'<p>So long and thx 4 all the fish</p>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// nested @if and @unless with inconsistent spacing before parenthesis
|
||||
$source = implode("\n", [
|
||||
'@if($cond)',
|
||||
'@unless ($cond)',
|
||||
'<p>Hello World</p>',
|
||||
'@endunless',
|
||||
'@endif',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if ($__Context->cond): ?>',
|
||||
'<?php if (!($__Context->cond)): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php endif; ?>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// nested @if, @unless, and @for with legacy @end
|
||||
$source = implode("\n", [
|
||||
'@if ($cond)',
|
||||
'@for ($i = 0; $i < 10; $i++)',
|
||||
'<!--@unless($cond)-->',
|
||||
'<p>Hello World</p>',
|
||||
'@end',
|
||||
'@end',
|
||||
'<!--@end-->',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if ($__Context->cond): ?>',
|
||||
'<?php for ($__Context->i = 0; $__Context->i < 10; $__Context->i++): ?>',
|
||||
'<?php if (!($__Context->cond)): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php endif; ?>',
|
||||
'<?php endfor; ?>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @while with legacy @end
|
||||
$source = '<!--@while(Context::getFoo()->isBar("baz"))--><p>Hello World</p><!--@end-->';
|
||||
$target = '<?php while (Context::getFoo()->isBar("baz")): ?><p>Hello World</p><?php endwhile; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @switch with @case, @default, @continue, and @break
|
||||
$source = implode("\n", [
|
||||
'@switch ($str)',
|
||||
'@case (1)',
|
||||
'<!--@case(2)-->',
|
||||
'@continue',
|
||||
'@case(3)',
|
||||
'@break',
|
||||
'@default',
|
||||
'@if (42)',
|
||||
'<p>Hello World</p>',
|
||||
'@end',
|
||||
'@end',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php switch ($__Context->str): ?>',
|
||||
'<?php case 1: ?>',
|
||||
'<?php case 2: ?>',
|
||||
'<?php continue; ?>',
|
||||
'<?php case 3: ?>',
|
||||
'<?php break; ?>',
|
||||
'<?php default: ?>',
|
||||
'<?php if (42): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php endif; ?>',
|
||||
'<?php endswitch; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @foreach
|
||||
$source = implode("\n", [
|
||||
'<!--@foreach ($list as $key => $val) -->',
|
||||
'<p>Hello World</p>',
|
||||
'<!--@endforeach -->',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php $__tmp = $__Context->list ?? []; foreach ($__tmp as $__Context->key => $__Context->val): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php endforeach; ?>',
|
||||
]);
|
||||
$parsed = $this->_parse($source);
|
||||
$tmpvar = preg_match('/(\$__tmp_[0-9a-f]{14})/', $parsed, $m) ? $m[1] : '';
|
||||
$target = strtr($target, ['$__tmp' => $tmpvar]);
|
||||
$this->assertEquals($target, $parsed);
|
||||
|
||||
// @forelse with @empty
|
||||
$source = implode("\n", [
|
||||
'@forelse ($list as $key => $val)',
|
||||
'<p>Hello World</p>',
|
||||
'@empty',
|
||||
'<p>Nothing Here!</p>',
|
||||
'@end',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php $__tmp = $__Context->list ?? []; if($__tmp): foreach ($__tmp as $__Context->key => $__Context->val): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php endforeach; else: ?>',
|
||||
'<p>Nothing Here!</p>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$parsed = $this->_parse($source);
|
||||
$tmpvar = preg_match('/(\$__tmp_[0-9a-f]{14})/', $parsed, $m) ? $m[1] : '';
|
||||
$target = strtr($target, ['$__tmp' => $tmpvar]);
|
||||
$this->assertEquals($target, $parsed);
|
||||
|
||||
// @once
|
||||
$source = implode("\n", [
|
||||
'@once',
|
||||
'<p>Hello World</p>',
|
||||
'@endonce',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if (!isset($GLOBALS[\'tplv2_once\'][\'$UNIQ\'])): ?>',
|
||||
'<p>Hello World</p>',
|
||||
'<?php $GLOBALS[\'tplv2_once\'][\'$UNIQ\'] = true; endif; ?>',
|
||||
]);
|
||||
$parsed = $this->_parse($source);
|
||||
$tmpvar = preg_match('/\'([0-9a-f]{14})\'/', $parsed, $m) ? $m[1] : '';
|
||||
$target = strtr($target, ['$UNIQ' => $tmpvar]);
|
||||
$this->assertEquals($target, $parsed);
|
||||
|
||||
// @isset and @unset
|
||||
$source = '<!--@isset($foo)--><!--@unset($bar)--><p></p><!--@end--><!--@endisset-->';
|
||||
$target = '<?php if (isset($__Context->foo)): ?><?php if (!isset($__Context->bar)): ?><p></p><?php endif; ?><?php endif; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @empty
|
||||
$source = '<!--@empty ($foo) --><p></p><!--@endempty-->';
|
||||
$target = '<?php if (empty($__Context->foo)): ?><p></p><?php endif; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @admin
|
||||
$source = implode("\n", [
|
||||
'@admin',
|
||||
'<p>Welcome!</p>',
|
||||
'@endadmin',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if ($this->user->isAdmin()): ?>',
|
||||
'<p>Welcome!</p>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @auth, @member and @guest
|
||||
$source = implode("\n", [
|
||||
'@auth',
|
||||
'@member',
|
||||
'<p>Welcome back!</p>',
|
||||
'@endmember',
|
||||
'@end',
|
||||
'@guest',
|
||||
'<p>Please join!</p>',
|
||||
'@endguest',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if ($this->user->isMember()): ?>',
|
||||
'<?php if ($this->user->isMember()): ?>',
|
||||
'<p>Welcome back!</p>',
|
||||
'<?php endif; ?>',
|
||||
'<?php endif; ?>',
|
||||
'<?php if (!$this->user->isMember()): ?>',
|
||||
'<p>Please join!</p>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @desktop and @mobile
|
||||
$source = implode("\n", [
|
||||
'@desktop',
|
||||
'<p>4K or GTFO!</p>',
|
||||
'@end',
|
||||
'@mobile',
|
||||
'<p>USB C is the way to go~</p>',
|
||||
'@endmobile',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'<?php if (!$__Context->m): ?>',
|
||||
'<p>4K or GTFO!</p>',
|
||||
'<?php endif; ?>',
|
||||
'<?php if ($__Context->m): ?>',
|
||||
'<p>USB C is the way to go~</p>',
|
||||
'<?php endif; ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testInlineConditions()
|
||||
{
|
||||
// XE-style pipe with 'if' attribute
|
||||
$source = '<input type="text" readonly="readonly"|if="$oDocument->isSecret()" />';
|
||||
$target = '<input type="text"<?php if ($__Context->oDocument->isSecret()): ?> readonly="readonly"<?php endif; ?> />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// With boolean (valueless) attribute
|
||||
$source = '<input type="text" disabled|if="$oDocument->isSecret()" />';
|
||||
$target = '<input type="text"<?php if ($__Context->oDocument->isSecret()): ?> disabled="disabled"<?php endif; ?> />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Support 'cond' attribute for backward compatibility
|
||||
$source = '<option value="1" selected="selected"|cond="$foo">ONE</option>';
|
||||
$target = '<option value="1"<?php if ($__Context->foo): ?> selected="selected"<?php endif; ?>>ONE</option>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Support 'when' and 'unless' attributes
|
||||
$source = '<option value="1" selected|when="$foo" disabled|unless="$bar">ONE</option>';
|
||||
$target = '<option value="1"<?php if ($__Context->foo): ?> selected="selected"<?php endif; ?><?php if (!($__Context->bar)): ?> disabled="disabled"<?php endif; ?>>ONE</option>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style @checked
|
||||
$source = '<input type="checkbox" @checked($oDocument->isAccessible() && in_array($this->user->member_srl, [1, 2, 3])) />';
|
||||
$target = '<input type="checkbox"<?php if ($__Context->oDocument->isAccessible() && in_array($this->user->member_srl, [1, 2, 3])): ?> checked="checked"<?php endif; ?> />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style @selected
|
||||
$source = '<option value="2" @selected($foo)>TWO</option>';
|
||||
$target = '<option value="2"<?php if ($__Context->foo): ?> selected="selected"<?php endif; ?>>TWO</option>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style @disabled
|
||||
$source = '<textarea class="foobar" @disabled(trim($foo) === $bar("baz"))></textarea>';
|
||||
$target = '<textarea class="foobar"<?php if (trim($__Context->foo) === $__Context->bar("baz")): ?> disabled="disabled"<?php endif; ?>></textarea>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style @readonly and @required
|
||||
$source = '<input type="text" @readonly(!!false) @required($member_info->require_title) />';
|
||||
$target = '<input type="text"<?php if (!!false): ?> readonly="readonly"<?php endif; ?><?php if ($__Context->member_info->require_title): ?> required="required"<?php endif; ?> />';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testMiscDirectives()
|
||||
{
|
||||
// Insert CSRF token
|
||||
$source = '<form>@csrf</form>';
|
||||
$target = '<form><input type="hidden" name="_rx_csrf_token" value="<?php echo \Rhymix\Framework\Session::getGenericToken(); ?>" /></form>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// JSON with variable
|
||||
$source = '@json($var)';
|
||||
$target = implode('', [
|
||||
'<?php echo $this->config->context === \'JS\' ? ',
|
||||
'json_encode($__Context->var, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES) : ',
|
||||
'htmlspecialchars(json_encode($__Context->var, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, \'UTF-8\', false); ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// JSON with literal array
|
||||
$source = '@json(["foo" => 1, "bar" => 2])';
|
||||
$target = implode('', [
|
||||
'<?php echo $this->config->context === \'JS\' ? ',
|
||||
'json_encode(["foo" => 1, "bar" => 2], \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES) : ',
|
||||
'htmlspecialchars(json_encode(["foo" => 1, "bar" => 2], \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, \'UTF-8\', false); ?>',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Lang code with variable
|
||||
$source = '@lang($var->name)';
|
||||
$target = '<?php echo $this->config->context === \'JS\' ? escape_js(lang($__Context->var->name)) : lang($__Context->var->name); ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Lang code with literal name
|
||||
$source = "@lang('board.cmd_list_items')";
|
||||
$target = "<?php echo \$this->config->context === 'JS' ? escape_js(lang('board.cmd_list_items')) : lang('board.cmd_list_items'); ?>";
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Lang code with class alias
|
||||
$source = "@use('Rhymix\Framework\Lang', 'Lang')\n" . '<p>@lang(Lang::getLang())</p>';
|
||||
$target = "\n" . '<p><?php echo $this->config->context === \'JS\' ? escape_js(lang(Rhymix\Framework\Lang::getLang())) : lang(Rhymix\Framework\Lang::getLang()); ?></p>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testComments()
|
||||
{
|
||||
// XE-style comment
|
||||
$source = '<div><!--// This is a comment --></div>';
|
||||
$target = '<div></div>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style comment
|
||||
$source = '<div>{{-- This is a comment --}}</div>';
|
||||
$target = '<div></div>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Not deleted
|
||||
$source = '<div><!-- This is a comment --></div>';
|
||||
$target = '<div><!-- This is a comment --></div>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Not deleted
|
||||
$source = '<div><!--/* This is a comment */--></div>';
|
||||
$target = '<div><!--/* This is a comment */--></div>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testVerbatim()
|
||||
{
|
||||
// Don't convert this expression, but remove the @
|
||||
$source = '@{{ $foobar }}';
|
||||
$target = '{{ $foobar }}';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Don't convert this expression, but remove the extra @
|
||||
$source = implode("\n", [
|
||||
'@@if(true)',
|
||||
'@@endif',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'@if(true)',
|
||||
'@endif',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// @verbatim block
|
||||
$source = implode("\n", [
|
||||
'@verbatim',
|
||||
'@if (true)',
|
||||
'<p>{{ $foobar }}</p>',
|
||||
'@endif',
|
||||
'@endverbatim',
|
||||
]);
|
||||
$target = implode("\n", [
|
||||
'',
|
||||
'@if (true)',
|
||||
'<p>{{ $foobar }}</p>',
|
||||
'@endif',
|
||||
'',
|
||||
]);
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testRawPhpCode()
|
||||
{
|
||||
// Regular PHP tags
|
||||
$source = '<?php $foo = 42; ?>';
|
||||
$target = '<?php $__Context->foo = 42; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
}
|
||||
|
||||
public function testAutoEscape()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function testCurlyBracesAndVars()
|
||||
{
|
||||
// XE-style {@ ... } notation
|
||||
$source = '{@ $foo = 42; }';
|
||||
$target = '<?php $__Context->foo = 42; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
|
||||
// Blade-style @php and @endphp directives
|
||||
$source = '@php $foo = 42; @endphp';
|
||||
$target = '<?php $__Context->foo = 42; ?>';
|
||||
$this->assertEquals($target, $this->_parse($source));
|
||||
}
|
||||
|
||||
public function testCompile()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue