Šablona z databáze spustí a komponenty + open_basedir
- mrazek85
- Člen | 9
Ahoj, mám presenter ve kterém se z databáze načte HTML obsah do
$content – v tomto HTML potřebuji nahradit nějaké znaky za volání a
spuštění komponenty a posléze tento obsah poslat do renderu presenteru (aby
se komponenty vykonaly).
V současnosti mi funguje toto (zjednodušeně):
public function actionDetail($id) {
$article = $this->database->table('clanek')->get($id);
$this->template->content = $this->decodeText($article->text);
}
function decodeText($text) {
$template = $this->createTemplate();
$template->getLatte()->setLoader(new \Latte\Loaders\StringLoader);
$content = $text;
$content = preg_replace_callback("/*****/", function($matches) {
return "{control " . $matches[1] . "}";
}, $content);
return $template->getLatte()->renderToString($content, $template->getParameters());
}
toto fyzicky funguje, ale v případě, že to nahraju na
hosting, kde je zaplé open_basedir, píše mi Tracy
(v oblasti „latte templates“).
1× Rendered Templates
a druhá je chyba:
Error: Latte\Bridges\Tracy\LattePanel-2
ErrorException: is_file(): open_basedir restriction in effect. File(<div
class=„col-sm-5“ sty…html kod
Na localhostu s XAMPP, kde jej mám vyplé vše běhá v pořádku a zobrazí se v Tracy panelu 2× vedle sebe Rendered Templates :
renderToString zjevně vyžaduje cestu k souboru s latte, nicméně zde žádná šablona není (HTML je generován z db) – zřejmě funkci používám blbě, lze nějak opravit tento kód ?
- m.brecher
- Generous Backer | 873
@mrazek85
V dokumentaci je metoda renderToString() popsaná jako nástroj k vykreslení šablony latte která je v souboru do proměnné jako string, který se později vykreslí do jiné šablony – metoda je určena spíš pro použití Latte bez Nette, protože v Nette se šablony vykreslují přímo bez nutnosti šablonu vykreslit do proměnné:
https://latte.nette.org/cs/develop#…
Ty ale máš HTML již z databáze jako string rovnou a tak metodu renderToString() možná vůbec nepotřebuješ !!
Co na to jít jednodušeji nějak takto:
public function actionDetail($id) {
$article = $this->database->table('clanek')->get($id);
$this->template->content = $this->decodeText($article->text);
}
function decodeText($text) {
return preg_replace_callback("/*****/", function($matches) {
return "{control " . $matches[1] . "}";
}, $text);
}
- m.brecher
- Generous Backer | 873
@dakur
renderToString() je v pořádku, pokud používáš StringLoader, soubor to neřeší, ale bere právě ten první parametr jako vstup
v dokumentaci, jsem nikde poznámku, že metoda renderToString() soubor neřeší neviděl, třeba jsem se ale jenom díval na nesprávná místa:
https://latte.nette.org/cs/develop#…
https://latte.nette.org/…ending-latte#…
Pokud je skutečně možné, že StringLoader modifikuje první parametr metody renderToString(), bylo by vhodné to do dokumentace srozumitelně doplnit – pokud to tam už někde není. Popř. doplnit poznámku přímo do odstavce o StringLoader.
Klidně PR do dokumentace podám, ale rád bych znal názor zkušenějších ;).
- jeremy
- Člen | 54
@m.brecher
v dokumentaci, jsem nikde poznámku, že metoda
renderToString()
soubor neřeší neviděl
renderToString()
je v pořádku, pokud používášStringLoader
, soubor to neřeší
Myslim, ze to bylo mysleno tak, ze to soubor neresi pouze pokud se pouziva
StringLoader
. Je jedno jestli se pouzije metoda
render()
nebo renderToString()
, plati to pro oboje.
V takovem pripade je primo ten string
sablona a nehleda se zadny
soubor.
Co se tyce dokumentace, tak mi to prijde celkem jasne popsany prave v sekci
o StringLoader
: https://latte.nette.org/…ending-latte#…
- mrazek85
- Člen | 9
@m.brecher
Pokud by se to řešilo takto, tak šablona (samozřejmě při |noescape)
textově vypíše <p>text z db... {control.. }</p>
→ komponenta se nevykoná
@dakur
Nevím o tom, v komponentě používám klasické render metody. Teď jsem
zjistil, že chybu Tracy hlásí, i když string žádnou komponentu
neobsahuje, je to např. jen :
public function actionDetail() {
$this->template->content = $this->decodeText("<p>jen text</p>");
}
function decodeText($text) {
$template = $this->createTemplate();
$template->getLatte()->setLoader(new \Latte\Loaders\StringLoader);
return $template->getLatte()->renderToString($text, $template->getParameters());
}
v latte je jen {$content|noescape}
Náhled na Tracy : link
V případě, že to pošlu bez toho StringLoaderu, renderToString tak to funguje samozřejmě bez chyb v Tracy, ale potřebuju zpracovat případné komponenty ještě před tím, než to dám do hlavní šablony (aby to nepsalo „{control formular }“ ale vypsalo HTML té komponenty <form>…</form> ).
- Marek Bartoš
- Nette Blogger | 1281
A které volání is_file() ti padá? is_file rozlišuje mezi souborem a složkou a nejspíš je tam kvůli tomu. Case, kdy se do volání dostane html by se nejspíš v kódu měl ošetřit. Ideálně poslat odkaz na konkrétní řádek na GitHubu
Editoval Marek Bartoš (18. 9. 2023 16:40)
- stepos2
- Člen | 53
Bez StringLoaderu by to mohlo jít takhle:
public function actionDetail($id)
{
$article = $this->database->table('clanek')->get($id);
$content = $this->decodeText($article->text);
$this->template->content = preg_replace_callback(
'/\{control ([a-zA-Z0-9_-]+)}/',
fn(array $m) => $this->renderComponent($m[1]),
$content
);
}
function decodeText($text)
{
return preg_replace_callback("/*****/", function($matches) {
return "{control " . $matches[1] . "}";
}, $text);
}
function renderComponent(string $name)
{
ob_start();
$this->getComponent($name)->render();
return ob_get_clean();
}
- m.brecher
- Generous Backer | 873
@jeremy
Co se tyce dokumentace, tak mi to prijde celkem jasne popsany prave v sekci o StringLoader: https://latte.nette.org/…ending-latte#…
Když se v tom hrabeš delší dobu, tak to jasné je, ale mě jako nově příchozímu do problematiky StringLoaderu v dokumentaci chybí popis funkce u druhého příkladu:
Zjednodušené použití:
$template = '{if true} {$var} {/if}';
$latte->setLoader(new Latte\Loaders\StringLoader);
$latte->render($template);
Člověk tak nějak odhadne, že se asi Latte dovtípí, že soubor šablony ‚{if true} {$var} {/if}‘ neexistuje a tedy bude jméno souboru považovat za kód šablony, co ale jiné šablony, které existují, bude je Latte načítat ze souboru i když je nastaven StringLoader?? To už z dokumentace nevyčtu a musím to v reálu otestovat. Myslím, že podrobnější vysvětlení v dokumentaci k StringLoaderu by bylo ku prospěchu celé komunitě.
A co se stane, když PHP vyhodnotí ‚{if true} {$var} {/if}‘ jako cestu, která vede mimo base restriction oblast ?? Zřejmě vyhodí Exception o které je tady řeč. Asi by se toto mělo v Latte nějak fixnout, aby k tomu nedocházelo.
- m.brecher
- Generous Backer | 873
@mrazek85
Teď jsem zjistil, že chybu Tracy hlásí, i když string žádnou komponentu neobsahuje
Vzpomněl sem si, že před časem jsem s podobnoiu exception zápasil také. PHP prostě zjistí, že ‚<div…‘ není v cestě uvedené v base restriction. Nepozná, že je to HTML !!! Latte zřejmě magicky načte šablonu ze stringu pokud je nastaven StringLoader a pokud první parametr není cesta k šabloně – což testuje pomocí is_file(). Jenže base restriction se bezpochyby testuje dříve než se zavolá is_file() takže se vyhodí výjimka porušení base restriction.
Jak tohle vyřešit netuším, je to ale problém, který by se měl řešit ! Latte by mělo umožnit striktně deklarovat, že chci načítat šablonu z proměnné a ne to řešit magicky pomocí is_file(). Tedy doplnit do metod ->render() a renderToString() parametr pro vynucení načítání z řetězce, kdy by se nevolalo is_file() a base restriction by nevadilo, třeba:
$latte->renderToString($code, $parameters, loadFromString: true);
$latte->render($code, $parameters, loadFromString: true);
Co na to ostatní ??
- jeremy
- Člen | 54
@m.brecher
A co se stane, když PHP vyhodnotí ‚{if true} {$var} {/if}‘ jako cestu
Nestane, StringLoader bere vsechen text jako content sablony. Takze, pokud se
napise cesta k souboru, napr: /path/to/template.latte
, tak to
i tak nevyhleda ten soubor, rovnou compilne ten text. is_file()
se
u StringLoader nepouziva, pouze pro nacteni cache. To, ale problem neni. Mam
teorii popsanou dole.
Načítá šablony z řetězců.
Toto je hned prvni veta v dokumentaci o StringLoader. Mozna by to chtelo zmenit nebo vic vysvetlit co se tu mysli jako sablona, ale i tak mi to prijde celkem jasny.
Mozna bych zmenil v dokumentaci
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file');
na
$latte->setLoader(new Latte\Loaders\StringLoader([
'main' => '{include other}',
'other' => '{if true} {$var} {/if}',
]));
$latte->render('main');
Kdyz jsem to cetl po prvy tak me to taky trochu na chvili zmatlo.
Co se tyce te chyby s is_file()
, podle screenshotu to vypada na
chybu primo v tracy panelu, ne latte. Tracy panel pouziva
is_file()
na nekolika mistech, je mozny ze prave tam se snazi
nacist html jako cestu k souboru.
@mrazek85 mozna by to chtelo ukazat celou tu chybu, cast je zakryta druhym panelem.
Editoval jeremy (19. 9. 2023 0:03)
- jeremy
- Člen | 54
@mrazek85 jakou verzi Tracy a Latte pouzivas?
V Tracy\Helpers
v metode editorUri()
se pouziva
is_file()
bez @
. Je to jediny misto (ktere jsem
nasel), kde by to pri chybe vyhodilo exception. is_file()
se tu
pouziva na vyhledani souboru pro vytvoreni odkazu na editor. V pripade sablony
vyrenderovane pres StringLoader to tam hodi obsah ty sablony. Pouzivam
nejaktualnejsi verze a v mem pripade to nejdriv z obsahu odstrani html.
Edit: verze je asi celkem jedno vzhledem k tomu ze na localu to funguje. Z nejakyho duvodu to vypada, ze se na produkci neodstrani html.
Duvod, proc myslim ze tam je problem je, ze chyba nastane v
Rendered Templates
panelu hned na zacatku. V druhem Latte panelu
jsou normalne odkazy na latte soubory, ale tady je prave nazev sablony
html text.
Editoval jeremy (19. 9. 2023 1:04)
- m.brecher
- Generous Backer | 873
@jeremy
Jestli StringLoader nepoužívá is_file() a rovnou natvrdo načítá ze stringu, tak je v Latte všechno OK a chyba by mohla být ve volání is_file() ve vkládané šabloně – což bylo vyloučeno, takže by to mohlo být voláním is_file() v Tracy.
V ukázce kódu ‚main.file‘ by bylo vhodnější použít jak navrhuješ ‚main‘, protože přípona .file může vyvolávat nejasnosti – mě to mátlo v tom smyslu, že jsem nejdřív myslel, že jenom ‚main.file‘ a ‚other.file‘ se načítá z řetězce a ostatní hodnoty ze souboru + přidat do komentáře, že to funguje pro metody render() i renderToString().
Podám do dokumentace PR.
- Marek Bartoš
- Nette Blogger | 1281
Aby se tu ve slohovkách neztratilo to relevantní – je to fixnutelné,
stačí vědět kde.
https://forum.nette.org/…open-basedir#…
- nightfish
- Člen | 519
@MarekBartoš Odhaduji, že warning je vyhozen v https://github.com/…/Helpers.php#L61,
který se volá z https://github.com/….panel.phtml#L83,
do které propadá hodnota $item->phpFile
z https://github.com/…ttePanel.php#L106
OP teda používá mírně starší verzi, protože mu to chybu hlásí na řádku 60 a nikoliv 61.
- mrazek85
- Člen | 9
Díky za informace, jsem zase o trošku chytřejší.
Původní verze Tracy byla v2.9.0, pro sychr jsem to dnes přehrál na
v2.10.3 – chyba vyskakuje stále, ale už ne na řádku 60, ale na
řádku 61.
Kód na webu funguje v pořádku, chyba bude jen v té Tracy – zřejmě jak psal @nightfish link
ErrorException: is_file(): open_basedir restriction in effect. File(<div class="col-sm-5" style="decimal: LEFT;"></div>) is not within the allowed path(s): (/www/autoprep:/usr/share/pear:/usr/share/php:/www/test.cz:/php_sess_data/test.cz:/www/test.cz-tmpdir:/var/www/web5/test.cz:/var/www/web2/test.cz) in /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Helpers.php:61
Stack trace:
#0 [internal function]: Tracy\Bar->Tracy\{closure}(2, '...', '...', 61)
#1 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Helpers.php(61): is_file('...')
#2 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Helpers.php(26): Tracy\Helpers::editorUri('...', NULL)
#3 /www/test.cz/web.test.cz/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml(81): Tracy\Helpers::editorLink('...')
#4 /www/test.cz/web.test.cz/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php(95): require('...')
#5 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Helpers.php(364): Latte\Bridges\Tracy\LattePanel->Latte\Bridges\Tracy\{closure}()
#6 /www/test.cz/web.test.cz/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php(96): Tracy\Helpers::capture(Object(Closure))
#7 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Bar/Bar.php(143): Latte\Bridges\Tracy\LattePanel->getPanel()
#8 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Bar/Bar.php(115): Tracy\Bar->renderPanels('')
#9 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Bar/Bar.php(89): Tracy\Bar->renderPartial('...')
#10 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php(123): Tracy\Bar->render(Object(Tracy\DeferredContent))
#11 /www/test.cz/web.test.cz/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php(292): Tracy\DevelopmentStrategy->renderBar()
#12 [internal function]: Tracy\Debugger::shutdownHandler()
#13 {main}
- jeremy
- Člen | 54
Prave jsem si zapnul open_basedir
a hazi mi to stejnou chybu pri
pouziti StringLoader na nejaktualnejsi verzi Tracy. Je jasne, ze chyba je v
Tracy\Helpers::editorUri()
. Staci pridat ‚@‘ pred
is_file()
.
Git issue: https://github.com/…y/issues/572
@DavidGrudl @mrazek85
- m.brecher
- Generous Backer | 873
@MarekBartoš
Aby se tu ve slohovkách neztratilo to relevantní – je to fixnutelné, stačí vědět kde.
Máš pravdu, z uvedených příkladů u StringLoaderu je skoro úplně jasné jak to funguje a detaily si člověk vyzkouší. Jenom ta přípona .file není jasné co se tím chce říci. Není to tak, že by tam mělo být třeba main.latte načtení standardní šablony které se StringLoaderem přesměruje jinam během testů ?? Jiné koncovky u latte šablon asi těžko někdo používá. Takže asi jediné co by se mohlo v dokumentaci poopravit je nahradit koncovku .file koncovkou .latte. Jak píše @jeremy koncovku úplně vynechat by mohlo být také matoucí, protože v kódu nebudeme mít:
$latte->render('main');
nýbrž:
$latte->render('main.latte');
Dává mě smysl přesměrovat ‚main.latte‘ na nějaký string aniž bych musel měnit kód.