Curlebrackets, vlastný filter a podivné @php:
- fiso
- Člen | 32
Ahojte,
Spravil som si vlastný filter, ktorý prechádza v šablóne všetky odkazy, a keď nájde niečo ako nette:Presenter:action?… tak to nahradí normálnym odkazom. Navyše zistí, či má užívateľ právo takúto stránku navštíviť, a ak nie, tak ho jednoducho nezobrazí.
Funguje to výborne, ale narazil som na jeden problém. Ak mám nasledovný kód:
<a href="!nette:Film:edit?id={$film->id}">Edit film</a>
tak sa {$film->id}
nahradí vo vygenerovanom template
konštrukciou
<a href="<?php echo $template->escape($component->link('Film:edit', array (
'id' => '_@php:p11@_',
)))?>">Edit film</a>
Takže id-čko tam nie je, iba _@php:p11@_
. Podarilo sa mi
zistiť, že toto používa filter removePhp
ale nedopátral som sa
kde sa toto nahrádzanie odohráva. Mohli by ste ma niekto usmerniť na čo sa
mám pozrieť, aby som si svoj filter mohol dobre upraviť?
Vďaka.
- David Grudl
- Nette Core | 8229
Tam zřejmě dochází ke konfliktu dvou filtrů, tvého a LatteFilter. Ono záleží i na pořadí registrování filtrů.
Že tam je to _@php:p11@_
, to je jen kvůli maskování PHP
kódu v textu šablony před filtrem.
- fiso
- Člen | 32
// links regarding on authorization
$this->template->registerFilter(function($s) {
return preg_replace_callback(
'#(?P<before>\<(h1|h2|h3|h4|h5|h6|li).*\>.*)?(?P<tagStart>\<(?P<tag>[^>]+)\s.*(?P<attr>src|href|action|on[a-z]+)\s*=\s*)"(?P<alwaysShow>\!)?(?P<uri>nette:.*?)(?P<tagEnd>[\#"].*\>(?(?=.*\<\/\\4\>).*\<\/\\4\>|.*\<\/\\4\>))(?P<after>.*\<\/\\2\>)?#',
function($m) {
// html definitions before link
$before = isset($m['before']) ? $m['before'] : '';
// tag (such as a, img, etc) that contains interesting attribute
$tagStart = $m['tagStart'];
// tag contents
$tag = $m['tag'];
// attribute name
$attr = $m['attr'];
// value of the attribute
$uri = $m['uri'];
// end of the containing tag
$tagEnd = $m['tagEnd'];
// html definitions after link
$after = isset($m['after']) ? $m['after'] : '';
// determines whether the link has to be always shown (it is ignoring authorization rules)
$alwaysShow = !empty($m['alwaysShow']);
// it is some other scheme
$parts = parse_url($uri);
if (!isset($parts['scheme']) || $parts['scheme'] !== 'nette') return $m[0];
// parse query parameters into array
if (isset($parts['query'])) {
parse_str($parts['query'], $params);
foreach ($params as $k => $v) {
if ($v === '') $params[$k] = NULL;
}
} else {
$params = array();
}
$path = isset($parts['path']) ? $parts['path'] : 'this!';
$return = "";
if(!$alwaysShow && $path != 'this!') {
// presenter represents resource, action represents privilege
$arr = explode(":", $path);
$actionName = end($arr);
$presenterName = prev($arr);
$return .= '<?php if(Environment::getUser()->isAllowed(\''.$presenterName.'\', \''.$actionName.'\')): ?>';
}
$return .= $before
. $tagStart
. '"<?php echo $template->escape($component->'
. (strncmp($attr, 'on', 2) ? 'link' : 'ajaxLink')
. '(\''
. $path
. '\', '
. var_export($params, TRUE)
. '))?>'
. $tagEnd
. $after;
if(!$alwaysShow && $path != 'this!') {
$return .= '<?php endif ?>';
}
return $return;
},
$s
);
});
- fiso
- Člen | 32
Zaujímavá vec, takéto kusy kódu
<a href="!nette:Film:view?id={$film->id}">View film</a> | <a href="!nette:Film:edit?id={$film->id}">Edit film</a>
<a href="!nette:Film:view?id={$film->id}">View film</a>
| <a href="!nette:Film:edit?id={$film->id}">Edit film</a>
generujú toto:
<a href="!nette:Film:view?id=<?php echo TemplateHelpers::escapeHtml($film->id) ?>">View film</a> | <a href="<?php echo $template->escape($component->link('Film:edit', array (
'id' => '{$film->id}',
)))?>">Edit film</a>
<a href="<?php echo $template->escape($component->link('Film:view', array (
'id' => '{$film->id}',
)))?>">View film</a>
| <a href="<?php echo $template->escape($component->link('Film:edit', array (
'id' => '{$film->id}',
)))?>">Edit film</a>
Rozdiel v šablóne je v pridanom riadku.
- fiso
- Člen | 32
Prišiel som na to, čo treba spraviť, nie je to ale nič príjemné a jednoduché.
Môj filter používa funkciu var_export, ktorá nejako pokazí UTF-8 znaky
\x02 a \x01 a nahradí ich znakom _, a preto fcia strtr toto správne
nespracuje. To je dôvod všetkých _@php
čo boli vyššie. Takže
zmenou týchto znakov na _
vo fcii extractPhp
som
docielil že var_export mi vyhodí niečo takéto:
<a href="<?php echo $template->escape($component->link('Film:view', array("id" => "<?php echo TemplateHelpers::escapeHtml($film->id) ?>")))?>">Viewa film</a>
Takže prvý nápad čo som dostal, je spraviť si vlastný „var_export“
s tým, že tie <?php
oseká. No to sa ale nedá, lebo tam
vlastne vtedy vôbec nie sú :-D je tam iba _@php
takže s tým sa
pohnúť nedá. Iné riešenie je použiť LatteFilter neskoršie ako ten môj,
a potom vo vlastnom var_exporte parsovať jednotlivé argumenty (prehnať to cez
nejaký BaseTemplate::parseTag alebo čo…)
Najlepšie čo ma zatiaľ napadlo, je použitie eval
:
<a href="<?php echo $template->escape($component->link('Film:view', array("id" => eval("<?php echo TemplateHelpers::escapeHtml($film->id) ?>"))))?>">Viewa film</a>
Edit: No ani ten poriadne nefunguje. Musí sa znovupoužiť deklarácia use Nette … a problém je v tom že je v tom kóde echo takže sa číslo id vypíše na nesprávnom mieste
Je to dobre hnusné, že?
Editoval fiso (25. 9. 2009 21:46)