Vlastní makro: Unknown macro

ludek
Člen | 83
+
0
-

Zdravím, přepisuju starý projekt z Nette 2.0.8 do 2.4. Používal jsem vlastní makro definované v BasePresenter pro všechny šablony takto:

// Nette 2.0.8
protected function startup() {
	$latte = new Nette\Latte\Engine;
	$macroSet = new Nette\Latte\Macros\MacroSet($latte->compiler);
	$macroSet->addMacro('moje_makro', function($node, $writer) {
		                 		// ...
			                    return $writer->write('...'); }
	        			);
	$this->template->registerFilter($latte);
	parent::startup();
}

Přepsal jsem podle návodu na

// Nete 2.4 / BasePresenter / startup()
use Latte;
$latte = new Latte\Engine;
$set = new Latte\Macros\MacroSet($latte->getCompiler());
$set->addMacro(...);

Na to ale dostanu chybu Unknown macro. V návodu není nic o tom, že bych musel ještě vytvořený $set nějak předat/registrovat v šabloně? Jestli, tak jak?

Dík.

Pavel Kravčík
Člen | 1180
+
+3
-

Mně to nejhezčí přijde takhle:

//config.neon

latte:
    macros:
        - Macros\CustomMacro
//Nějaká třída s makrem
class CustomMacro extends \Latte\Macros\MacroSet
{
    /**
     * Install macro
     *
     */
    public static function install(\Latte\Compiler $compiler)
    {
        $set = new static($compiler);

        $set->addMacro('icon', [$set, 'icon']);

        return $set;
    }

    public function icon(\Latte\MacroNode $node, \Latte\PhpWriter $writer)
    {
        return $writer->write(
            'echo \Macros\CustomMacro::renderIcon(%node.word, %node.array)'
        );
    }
ludek
Člen | 83
+
0
-

Pavel Kravčík napsal(a): Mně to nejhezčí přijde takhle…

Díky, toto funguje. Jen je třeba do configu přidat ::install:

latte:
	macros:
		- Macros\CustomMacro::install

a do třídy s makrem namespace:

namespace Macros;

Při ladění se taky musí mazat \temp\cache\latte, protože při změně makra se nepřegeneruje.

Pavel Kravčík
Člen | 1180
+
0
-

Jasně, psal jsem to tak nějak po „paměti“, tak za detaily se omlouvám. To s tou cache je nepříjemné, na to se zasekne každý poprvé.

ludek
Člen | 83
+
0
-

Ještě dotaz: jak do třídy s makry dostat proměnné. Např. $basePath. Chtěl bych pomocí makra vytvářet odkazy. Např
{mojemakro Popis souboru:soubor.jpg} se nahradí za
<a href='{$basePath}/obrazky/soubor.jpg'>Popis souboru</a>.

Ve staré aplikaci jsem to dělal pomocí $basePath = Nette\Environment::getHttpRequest()->getUrl()->getBasePath();. Ale teď nemůžu přijít nato, jak se k tomu dostat, abych to mohl ve funkci icon použít.

David Matějka
Moderator | 6445
+
+1
-

v makru nikdy nepristupuj k runtime promennym. makro vzdy vygeneruje php kod, ktery se pak provede. ty tedy z makra vrat retezec, ve kterem bude neco jako

return $writer->write(
    'echo \Macros\CustomMacro::renderIcon($basePath . %node.word, %node.array)'
);
Pavel Kravčík
Člen | 1180
+
0
-

Asi by to šlo parametrem, nevím jestli se to dá nějak připojit na DI.

Třeba tu ikonku nahoře pak používáme takhle, takže hádám, že si v parametru pošleš cestu ve chvíli vykreslení…

{icon star, red, 2, $basePath}

EDIT: Matěj je holt bůh, tohle je nesmysl. :)

Editoval Pavel Kravčík (29. 5. 2017 11:03)

ludek
Člen | 83
+
0
-

Díky. Takže to jde udělat takto

// šablona:
{mojemakro Popis souboru:soubor.jpg}

// metoda s makrem:
public function mojeMakro(\Latte\MacroNode $node, \Latte\PhpWriter $writer) {

        $file = explode(":", $node->args);
        return $writer->write('echo "<a href=\'".$basePath."/obrazky/' . $file[1] . '\'>' . $file[0] . '</a>"');
    }

Jenže když si přidám test na existenci souboru, stejně to nefunguje, protože šablona se načítá z cache, takže o existenci odkazovaného souboru neví. Nakonec mi funguje toto (testuje existenci, počítá velikost):

public function mojeMakro(\Latte\MacroNode $node, \Latte\PhpWriter $writer) {

        $ds = DIRECTORY_SEPARATOR;
        $adresar = $ds.'obrazky'.$ds;
        $cesta = getcwd().$adresar;
        $soubor = explode(":", $node->args);
        $komplet = $cesta.$soubor[1];

		// PHP kód do šablony:
        return '
        if (file_exists(\'' . $komplet . '\')) {
                echo "<a href=\'" . $basePath . "/obrazky/' . $soubor[1] . '\'>' . $soubor[0] .
                ' <span class=\'text-muted\'>(" . round((filesize(\'' . $komplet . '\')/1048576),2) . "&nbsp;MB)</span</a>";
            }else{
             echo "<strong class=\"text-danger\">SOUBOR [' . $soubor[1] .'] NEEXISTUJE</strong>";
        }
        ';

    }