smarty-php / smarty

Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.
Other
2.24k stars 705 forks source link

[Unescape modifier] not working when call / use normal function #888

Closed ampmonteiro closed 1 year ago

ampmonteiro commented 1 year ago

Hi,

I was trying include smarty 4 in CodeIgniter 4 App where i have the $smarty->setEscapeHtml(true); and for some function of CI i dont want that to be escaped, so i used unescape modifier:

       {* Not working *}
        {form_open('news/delete',[],['news_id' => {$news['id']}])|unescape}
            <button>Delete</button>
        {form_close()|unescape}

the result is:

image

you can see the full code of CI4 + smarty 4 here

Also tried with a simple example:


<?php
    require 'vendor/autoload.php';
    $smarty = new Smarty;

    $smarty->setTemplateDir('templates/');
    $smarty->setCompileDir('templates_c/');
    $smarty->setConfigDir('configs/');
    $smarty->setCacheDir('cache/');

    #$smarty->default_modifiers = ['escape:"htmlall"'];
    $smarty->setEscapeHtml(true);

    $name = '<strong>HTML STRONGs</strong>';
    $list = ['<li>one</li>', 'two'];

    function test(): string
    {
        return "<h1> ola </h1>";
    }

    $smarty->assign(compact('name', 'list'));
    $smarty->display('index.tpl');

and the template:


  {* Smarty *}
  <p>Hello {$name}, welcome to Smarty!</p>

  {foreach $list as $item}
      <p>{$item}</p>
  {/foreach}

{* Not working *}
{test()|unescape} 

result:

image

thanks

wisskid commented 1 year ago

That is not was unescape is for.

Template designers can choose to selectively disable this feature by adding the nofilter flag: {$variable nofilter}.

ampmonteiro commented 1 year ago

image

   {* works No apply escaping *}
    {form_open('news/delete',[],['news_id' => {$news['id']}]) nofilter}
        <button>Delete</button>
    {form_close()  nofilter}

and

  {* Smarty *}
  <p>Hello {$name}, welcome to Smarty!</p>

  {foreach $list as $item}
      <p>{$item}</p>
  {/foreach}

{* no escape*}
{test()  nofilter} 

thanks, it works.

However the word unescape is misleading because it not related to escape. The correct naming should be decode as mention:

unescape is used to decode entity, html and htmlall. It counters the effects of the escape modifier for the given types.

Or as said it should counters the effects of the [escape modifier], which means revert the escaping, which it does not.

And nofilter key word should be a modifier as well, like raw ( which is what twig has) or using $smarty.nofilter to be more clear.

Thanks. I will close the issue tomorrow or Monday

ampmonteiro commented 1 year ago

And another thing that maybe i will create a issue:

this is not possible with smarty:


{form_open('news/delete',  hidden:['news_id' => {$news['id']}]) nofilter}
        <button>Delete</button>
{form_close() nofilter}

i am using php 8.0 feature called Named Arguments, in this case hidden name parameter and give me this error:

image

wisskid commented 1 year ago

Well, Smarty is not PHP. Although the syntax is clearly inspired by PHP, their syntaxes differ greatly. Thus, I would not consider this a bug, but it might be considered as a new feature.

ampmonteiro commented 1 year ago

@wisskid

ok, but in requirements said:

Requirements: Smarty can be run with PHP 7.1 to PHP 8.2.

however it is not fully compatible with few new features like Named Arguments which should be mention in the docs.

I still didn't try this with twig but tried with Nette/Latte template which works perfectly fine:


    {form_open(
        'news/delete',
        hidden: ['news_id' => esc($news['id'])]
    )|noescape}

you can see my full code here

wisskid commented 1 year ago

Smarty is not PHP. The fact that Smarty can be run with PHP 7.1 to PHP 8.2 does not mean that the Syntax of Smarty is equal to the syntax of PHP. It is not, in many respects. There are some PHP language constructs that also work in Smarty and vice versa, but the similarities are in fact very limited.