Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #13459: Removed tags that accept multiple args from array helper #13695

Merged
merged 1 commit into from
Jan 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fixes #13459: Removed tags that accept multiple args from array helper
Removed `select`, and `select_static` from array helper.
  • Loading branch information
CameronHall committed Jan 12, 2019
commit eb2e482fcb6878f77b7a99f7758e61041bd6927c
2 changes: 1 addition & 1 deletion CHANGELOG-4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
- Fixed `Phalcon\Mvc\Models` magic method (setter) is fixed for arrays [#13661](https://github.com/phalcon/cphalcon/issues/13661)
- Fixed `Phalcon\Mvc\Model::skipAttributes` and `Phalcon\Mvc\Model::allowEmptyColumns` allowEmptyStrings & skipAttributes repsect the column mapping. [#12975](https://github.com/phalcon/cphalcon/issues/12975), [#13477](https://github.com/phalcon/cphalcon/issues/13477)
- Fixed `\Phalcon\Cache\Backend\Libmemcached` returning "empty" values being as `null` when they could be `0`, `false` or empty `string`. [#13497](https://github.com/phalcon/cphalcon/issues/13497)
- Fixed `Phalcon\Mvc\View\Engine\Volt\Compiler::functionCall` building the incorrect code for the following tags; `select`, and `select_static` [#13459](https://github.com/phalcon/cphalcon/issues/13459)

## Removed
- PHP < 7.2 no longer supported
Expand Down Expand Up @@ -186,4 +187,3 @@
- Removed `Phalcon\Validation\Message` and `Phalcon\Mvc\Model\Message` in favor of `Phalcon\Messages\Message`
- Removed `Phalcon\Validation\Message\Group` in favor of `Phalcon\Messages\Messages`
- Removed calling `Phalcon\Mvc\Collection::validate` with object of type `Phalcon\Mvc\Model\ValidatorInterface`

2 changes: 0 additions & 2 deletions phalcon/mvc/view/engine/volt/compiler.zep
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,6 @@ class Compiler implements InjectionAwareInterface
"link_to": true,
"image": true,
"form": true,
"select": true,
"select_static": true,
"submit_button": true,
"radio_field": true,
"check_field": true,
Expand Down
289 changes: 289 additions & 0 deletions tests/unit/Mvc/View/Engine/Volt/Compiler/CompileStringCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
<?php
declare(strict_types=1);

/**
* This file is part of the Phalcon Framework.
*
* (c) Phalcon Team <team@phalconphp.com>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

namespace Phalcon\Test\Unit\Mvc\View\Engine\Volt\Compiler;

use Phalcon\Mvc\View\Engine\Volt\Compiler;
use Phalcon\Mvc\View\Exception;
use UnitTester;

/**
* Class CompileStringCest
*/
class CompileStringCest
{
/**
* Tests Phalcon\Mvc\View\Engine\Volt\Compiler :: compileString()
*
* @param UnitTester $I
*
* @author Phalcon Team <team@phalconphp.com>
* @since 2017-01-17
*/
public function mvcViewEngineVoltCompilerCompileString(UnitTester $I)
{
$I->wantToTest("Mvc\View\Engine\Volt\Compiler - compileString()");
$examples = $this->getVoltCompileString();
foreach ($examples as $item) {
$param = $item[0];
$expected = $item[1];
$volt = new Compiler();

$actual = $volt->compileString($param);
$I->assertEquals($expected, $actual);
};
}

/**
* @return array
*/
private function getVoltCompileString(): array
{
return [
['', ''],
//Comments
['{# hello #}', ''],
['{# hello #}{# other comment #}', ''],
//Common Expressions
['hello', 'hello'],
['{{ "hello" }}', "<?= 'hello' ?>"],
['{{ "hello" }}{{ "hello" }}', "<?= 'hello' ?><?= 'hello' ?>"],
['{{ "hello" }}-{{ "hello" }}', "<?= 'hello' ?>-<?= 'hello' ?>"],
['-{{ "hello" }}{{ "hello" }}-', "-<?= 'hello' ?><?= 'hello' ?>-"],
['-{{ "hello" }}-{{ "hello" }}-', "-<?= 'hello' ?>-<?= 'hello' ?>-"],
['Some = {{ 100+50 }}', "Some = <?= 100 + 50 ?>"],
['Some = {{ 100-50 }}', "Some = <?= 100 - 50 ?>"],
['Some = {{ 100*50 }}', "Some = <?= 100 * 50 ?>"],
['Some = {{ 100/50 }}', "Some = <?= 100 / 50 ?>"],
['Some = {{ 100%50 }}', "Some = <?= 100 % 50 ?>"],
['Some = {{ 100~50 }}', "Some = <?= 100 . 50 ?>"],
//Unary operators
['{{ -10 }}', "<?= -10 ?>"],
['{{ !10 }}', "<?= !10 ?>"],
['{{ !a }}', '<?= !$a ?>'],
['{{ not a }}', '<?= !$a ?>'],
//Arrays
['{% set a = [1, 2, 3, 4] %}', '<?php $a = [1, 2, 3, 4]; ?>'],
['{% set a = ["hello", 2, 1.3, false, true, null] %}', '<?php $a = [\'hello\', 2, 1.3, false, true, null]; ?>'],
[
'{% set a = ["hello", 2, 3, false, true, null, [1, 2, "hola"]] %}',
'<?php $a = [\'hello\', 2, 3, false, true, null, [1, 2, \'hola\']]; ?>',
],
[
"{% set a = ['first': 1, 'second': 2, 'third': 3] %}",
'<?php $a = [\'first\' => 1, \'second\' => 2, \'third\' => 3]; ?>',
],
//Array access
['{{ a[0 ]}}', '<?= $a[0] ?>'],
['{{ a[0 ] [ 1]}}', '<?= $a[0][1] ?>'],
['{{ a[0] [ "hello"] }}', '<?= $a[0][\'hello\'] ?>'],
['{{ a[0] [1.2] [false] [true] }}', '<?= $a[0][1.2][false][true] ?>'],
//Attribute access
['{{ a.b }}', '<?= $a->b ?>'],
['{{ a.b.c }}', '<?= $a->b->c ?>'],
//Ranges
['{{ 1..100 }}', '<?= range(1, 100) ?>'],
['{{ "Z".."A" }}', '<?= range(\'Z\', \'A\') ?>'],
["{{ 'a'..'z' }}", '<?= range(\'a\', \'z\') ?>'],
["{{ 'a' .. 'z' }}", '<?= range(\'a\', \'z\') ?>'],
//Calling functions
['{{ content() }}', '<?= $this->getContent() ?>'],
['{{ get_content() }}', '<?= $this->getContent() ?>'],
["{{ partial('hello/x') }}", '<?= $this->partial(\'hello/x\') ?>'],
['{{ dump(a) }}', '<?= var_dump($a) ?>'],
["{{ date('Y-m-d', time()) }}", '<?= date(\'Y-m-d\', time()) ?>'],
['{{ robots.getPart(a) }}', '<?= $robots->getPart($a) ?>'],
//Phalcon\Tag helpers
["{{ link_to('hello', 'some-link') }}", '<?= $this->tag->linkTo([\'hello\', \'some-link\']) ?>'],
[
"{{ form('action': 'save/products', 'method': 'post') }}",
'<?= $this->tag->form([\'action\' => \'save/products\', \'method\' => \'post\']) ?>',
],
[
'{{ stylesheet_link(config.cdn.css.bootstrap, config.cdn.local) }}',
'<?= $this->tag->stylesheetLink($config->cdn->css->bootstrap, $config->cdn->local) ?>',
],
["{{ javascript_include('js/some.js') }}", '<?= $this->tag->javascriptInclude(\'js/some.js\') ?>'],
["{{ image('img/logo.png', 'width': 80) }}", "<?= \$this->tag->image(['img/logo.png', 'width' => 80]) ?>"],
[
"{{ email_field('email', 'class': 'form-control', 'placeholder': 'Email Address') }}",
"<?= \$this->tag->emailField(['email', 'class' => 'form-control', 'placeholder' => 'Email Address']) ?>",
],
//Filters
['{{ "hello"|e }}', '<?= $this->escaper->escapeHtml(\'hello\') ?>'],
['{{ "hello"|escape }}', '<?= $this->escaper->escapeHtml(\'hello\') ?>'],
['{{ "hello"|trim }}', '<?= trim(\'hello\') ?>'],
['{{ "hello"|striptags }}', '<?= strip_tags(\'hello\') ?>'],
['{{ "hello"|json_encode }}', '<?= json_encode(\'hello\') ?>'],
['{{ "hello"|url_encode }}', '<?= urlencode(\'hello\') ?>'],
['{{ "hello"|uppercase }}', '<?= Phalcon\Text::upper(\'hello\') ?>'],
['{{ "hello"|lowercase }}', '<?= Phalcon\Text::lower(\'hello\') ?>'],
['{{ ("hello" ~ "lol")|e|length }}', '<?= $this->length($this->escaper->escapeHtml((\'hello\' . \'lol\'))) ?>'],
//Filters with parameters
['{{ "My name is %s, %s"|format(name, "thanks") }}', "<?= sprintf('My name is %s, %s', \$name, 'thanks') ?>"],
[
'{{ "some name"|convert_encoding("utf-8", "latin1") }}',
"<?= \$this->convertEncoding('some name', 'utf-8', 'latin1') ?>",
],
//if statement
['{% if a==b %} hello {% endif %}', '<?php if ($a == $b) { ?> hello <?php } ?>'],
['{% if a!=b %} hello {% endif %}', '<?php if ($a != $b) { ?> hello <?php } ?>'],
['{% if a is not b %} hello {% endif %}', '<?php if ($a != $b) { ?> hello <?php } ?>'],
['{% if a<b %} hello {% endif %}', '<?php if ($a < $b) { ?> hello <?php } ?>'],
['{% if a>b %} hello {% endif %}', '<?php if ($a > $b) { ?> hello <?php } ?>'],
['{% if a>=b %} hello {% endif %}', '<?php if ($a >= $b) { ?> hello <?php } ?>'],
['{% if a<=b %} hello {% endif %}', '<?php if ($a <= $b) { ?> hello <?php } ?>'],
['{% if a===b %} hello {% endif %}', '<?php if ($a === $b) { ?> hello <?php } ?>'],
['{% if a!==b %} hello {% endif %}', '<?php if ($a !== $b) { ?> hello <?php } ?>'],
['{% if a==b and c==d %} hello {% endif %}', '<?php if ($a == $b && $c == $d) { ?> hello <?php } ?>'],
['{% if a==b or c==d %} hello {% endif %}', '<?php if ($a == $b || $c == $d) { ?> hello <?php } ?>'],
['{% if a is odd %} hello {% endif %}', '<?php if (((($a) % 2) != 0)) { ?> hello <?php } ?>'],
['{% if a is even %} hello {% endif %}', '<?php if (((($a) % 2) == 0)) { ?> hello <?php } ?>'],
['{% if a is empty %} hello {% endif %}', '<?php if (empty($a)) { ?> hello <?php } ?>'],
['{% if a is not empty %} hello {% endif %}', '<?php if (!empty($a)) { ?> hello <?php } ?>'],
['{% if a is numeric %} hello {% endif %}', '<?php if (is_numeric($a)) { ?> hello <?php } ?>'],
['{% if a is not numeric %} hello {% endif %}', '<?php if (!is_numeric($a)) { ?> hello <?php } ?>'],
['{% if a is scalar %} hello {% endif %}', '<?php if (is_scalar($a)) { ?> hello <?php } ?>'],
['{% if a is not scalar %} hello {% endif %}', '<?php if (!is_scalar($a)) { ?> hello <?php } ?>'],
[
'{% if a is iterable %} hello {% endif %}',
'<?php if ((is_array($a) || ($a) instanceof Traversable)) { ?> hello <?php } ?>',
],
[
'{% if a is not iterable %} hello {% endif %}',
'<?php if (!(is_array($a) || ($a) instanceof Traversable)) { ?> hello <?php } ?>',
],
['{% if a is sameas(false) %} hello {% endif %}', '<?php if (($a) === (false)) { ?> hello <?php } ?>'],
['{% if a is sameas(b) %} hello {% endif %}', '<?php if (($a) === ($b)) { ?> hello <?php } ?>'],
['{% if a is divisibleby(3) %} hello {% endif %}', '<?php if (((($a) % (3)) == 0)) { ?> hello <?php } ?>'],
['{% if a is divisibleby(b) %} hello {% endif %}', '<?php if (((($a) % ($b)) == 0)) { ?> hello <?php } ?>'],
['{% if a is defined %} hello {% endif %}', '<?php if (isset($a)) { ?> hello <?php } ?>'],
['{% if a is not defined %} hello {% endif %}', '<?php if (!isset($a)) { ?> hello <?php } ?>'],
[
'{% if a==b %} hello {% else %} not hello {% endif %}',
'<?php if ($a == $b) { ?> hello <?php } else { ?> not hello <?php } ?>',
],
[
'{% if a==b %} {% if c==d %} hello {% endif %} {% else %} not hello {% endif %}',
'<?php if ($a == $b) { ?> <?php if ($c == $d) { ?> hello <?php } ?> <?php } else { ?> not hello <?php } ?>',
],
[
'{% if a==b %} {% if c==d %} hello {% else %} not hello {% endif %}{% endif %}',
'<?php if ($a == $b) { ?> <?php if ($c == $d) { ?> hello <?php } else { ?> not hello <?php } ?><?php } ?>',
],
[
'{% if a==b %} hello {% else %} {% if c==d %} not hello {% endif %} {% endif %}',
'<?php if ($a == $b) { ?> hello <?php } else { ?> <?php if ($c == $d) { ?> not hello <?php } ?> <?php } ?>',
],
[
'{% if a is empty or a is defined %} hello {% else %} not hello {% endif %}',
'<?php if (empty($a) || isset($a)) { ?> hello <?php } else { ?> not hello <?php } ?>',
],
[
'{% if a is even or b is odd %} hello {% else %} not hello {% endif %}',
'<?php if (((($a) % 2) == 0) || ((($b) % 2) != 0)) { ?> hello <?php } else { ?> not hello <?php } ?>',
],
//for statement
['{% for a in b %} hello {% endfor %}', '<?php foreach ($b as $a) { ?> hello <?php } ?>'],
['{% for a in b[0] %} hello {% endfor %}', '<?php foreach ($b[0] as $a) { ?> hello <?php } ?>'],
['{% for a in b.c %} hello {% endfor %}', '<?php foreach ($b->c as $a) { ?> hello <?php } ?>'],
[
'{% for key, value in [0, 1, 3, 5, 4] %} hello {% endfor %}',
'<?php foreach ([0, 1, 3, 5, 4] as $key => $value) { ?> hello <?php } ?>',
],
[
'{% for key, value in [0, 1, 3, 5, 4] if key!=3 %} hello {% endfor %}',
'<?php foreach ([0, 1, 3, 5, 4] as $key => $value) { if ($key != 3) { ?> hello <?php } ?><?php } ?>',
],
['{% for a in 1..10 %} hello {% endfor %}', '<?php foreach (range(1, 10) as $a) { ?> hello <?php } ?>'],
[
'{% for a in 1..10 if a is even %} hello {% endfor %}',
'<?php foreach (range(1, 10) as $a) { if (((($a) % 2) == 0)) { ?> hello <?php } ?><?php } ?>',
],
[
'{% for a in 1..10 %} {% for b in 1..10 %} hello {% endfor %} {% endfor %}',
'<?php foreach (range(1, 10) as $a) { ?> <?php foreach (range(1, 10) as $b) { ?> hello <?php } ?> <?php } ?>',
],
['{% for a in 1..10 %}{% break %}{% endfor %}', '<?php foreach (range(1, 10) as $a) { ?><?php break; ?><?php } ?>'],
[
'{% for a in 1..10 %}{% continue %}{% endfor %}',
'<?php foreach (range(1, 10) as $a) { ?><?php continue; ?><?php } ?>',
],
//set statement
['{% set a = 1 %}', '<?php $a = 1; ?>'],
['{% set a = a-1 %}', '<?php $a = $a - 1; ?>'],
['{% set a = 1.2 %}', '<?php $a = 1.2; ?>'],
['{% set a = 1.2+1*(20/b) and c %}', '<?php $a = 1.2 + 1 * (20 / $b) && $c; ?>'],
// Cache statement
[
'{% cache somekey %} hello {% endcache %}',
'<?php $_cache[$somekey] = $this->di->get(\'viewCache\'); $_cacheKey[$somekey] = $_cache[$somekey]->start($somekey); if ($_cacheKey[$somekey] === null) { ?> hello <?php $_cache[$somekey]->save($somekey); } else { echo $_cacheKey[$somekey]; } ?>',
],
[
'{% set lifetime = 500 %}{% cache somekey lifetime %} hello {% endcache %}',
'<?php $lifetime = 500; ?><?php $_cache[$somekey] = $this->di->get(\'viewCache\'); $_cacheKey[$somekey] = $_cache[$somekey]->start($somekey, $lifetime); if ($_cacheKey[$somekey] === null) { ?> hello <?php $_cache[$somekey]->save($somekey, null, $lifetime); } else { echo $_cacheKey[$somekey]; } ?>',
],
[
'{% cache somekey 500 %} hello {% endcache %}',
'<?php $_cache[$somekey] = $this->di->get(\'viewCache\'); $_cacheKey[$somekey] = $_cache[$somekey]->start($somekey, 500); if ($_cacheKey[$somekey] === null) { ?> hello <?php $_cache[$somekey]->save($somekey, null, 500); } else { echo $_cacheKey[$somekey]; } ?>',
],
//Autoescape mode
[
'{{ "hello" }}{% autoescape true %}{{ "hello" }}{% autoescape false %}{{ "hello" }}{% endautoescape %}{{ "hello" }}{% endautoescape %}{{ "hello" }}',
"<?= 'hello' ?><?= \$this->escaper->escapeHtml('hello') ?><?= 'hello' ?><?= \$this->escaper->escapeHtml('hello') ?><?= 'hello' ?>",
],
//Mixed
['{# some comment #}{{ "hello" }}{# other comment }}', "<?= 'hello' ?>"],
// Select
['{{ select_static(["name": "kek"], ["Y": "Yes", "N": "No"]) }}', "<?= \$this->tag->selectStatic(['name' => 'kek'], ['Y' => 'Yes', 'N' => 'No']) ?>"],
['{{ select(["name": "kek"], ["Y": "Yes", "N": "No"]) }}', "<?= \$this->tag->select(['name' => 'kek'], ['Y' => 'Yes', 'N' => 'No']) ?>"]
];
}

/**
* Tests Phalcon\Mvc\View\Engine\Volt\Compiler :: compileString() - syntax
* error
*
* @param UnitTester $I
*
* @author Phalcon Team <team@phalconphp.com>
* @since 2017-01-17
*/
public function mvcViewEngineVoltCompilerCompileStringSyntaxError(UnitTester $I)
{
$I->wantToTest("Mvc\View\Engine\Volt\Compiler - compileString() - syntax error");
$examples = $this->getVoltCompileStringErrors();
foreach ($examples as $item) {
$code = $item[0];
$message = $item[1];
$volt = new Compiler();
$I->expectThrowable(
new Exception($message),
function () use ($volt, $code) {
$volt->compileString($code);
}
);
}
}

/**
* @return array
*/
private function getVoltCompileStringErrors(): array
{
return [
['{{ "hello"|unknown }}', 'Unknown filter "unknown" in eval code on line 1'],
['{{ "hello"|unknown(1, 2, 3) }}', 'Unknown filter "unknown" in eval code on line 1'],
['{{ "hello"|(a-1) }}', 'Unknown filter type in eval code on line 1'],
];
}
}