nette/application

Link with captured variable and latte strict mode not working

lulco opened this issue · 6 comments

lulco commented

Version: 3.1.11

Bug Description

Found by efabrica-team/phpstan-latte#398

Link accepts only string as first argument, but if we use captured variable in link its type can be Latte\Runtime\Html|string|false which is not working with latte strict types enabled and we get error Nette\Application\UI\Component::link(): Argument #1 ($destination) must be of type string, Latte\Runtime\Html given

Steps To Reproduce

Turn on latte strict types:

latte:
    strictTypes: true

Use captured variable in n:href:

{capture $link}Foo:bar{/capture}
<a n:href="$link">Foo bar</a>

Expected Behavior

No error

Possible Solution

Cast input of link to string if it is not string?

mabar commented

Input of link must be string and casting would only hide errors. Even casting just Html would hide errors -> Html instance usually does not make sense to be an input for link.
Capture is mostly for html context so it's also correct to return Html. Maybe it could be made context-aware and always output string for non-html input.
Otherwise I would use explicit casting to string in user code.

lulco commented

Basically I agree, I mentioned it in original @spaze’s issue efabrica-team/phpstan-latte#398

spaze commented

A similar problem was reported (and fixed) in nette/latte#326, passing Html to img src caused troubles.

Code taken from that issue that didn't work before but not works:

{capture $test}https://nette.org{/capture}
<img src="{$test}">

It's similar enough that I'd say it would make sense for the code used in this issue to also work. What do you think?

dg commented

The difference is in the n:href and src. The former contains PHP code and unicode strings, the latter HTML.

{capture $link}foo&#43;bar{/capture}
<img src="{$link}">   ->   <img src="foo&#43;bar">     OK
<a n:href="$link">    ->   <?php $link = 'foo&#43;bar';  // BAD!!!
                                 $link = 'foo+bar';      // THIS IS OK 
spaze commented

I see, thanks. So just to make sure I understand it correctly, \Nette\Bridges\ApplicationLatte\Nodes\LinkNode should ideally check whether $destination is a string and not an Html object to make sure it works as intended even with $strictTypes = false, is that correct?

dg commented

Yeah. But you'd have to do a lot of checks in a lot of places. It would probably be more practical to switch to strictTypes = true in general, or remove Html::__toString(), or modify __toString() to return ASCII.