Analogie pluginu ve smarty

- xmn
 - Člen | 6
 
Zdravim vlky, pokousime se proniknout do nette a zalozit na nem nas novy redakcni system. Stavajici je zalozen, mimo jine na smarty ve kterem hojne pouzivame pluginy jakozto samostatne komponenty, ktere nezavisi na „hlavnim“ presenteru (napr anketa, vytahy z rubrik, zobrazovane napric celym webem v pravem sloupecku a pod.). Domnival jsem se, ze podobna funkcionalita jsou makra v CurlyBracketsFilter-u nicmene se mi nedari toto zprovoznit. Postupuju nasledovne
- jako pokusnou komponentu jsem si vybral TagCloud, ktery je ke stazeni tady v diskusi. Je naprogramovan v duchu nette a to vyhovuje.
 - v bootstrap jsem pridal radek
 
	NCurlyBracketsFilter::$macros['mod'] = '<?php $presenter->createMod("%%")->render();?>';
- vytvoril jsem si BasePresenter a v nem metodu createMod, ktera se postara o vytvoreni a vraceni komponenty
 
	function createMod($param){
		list($cname,$cparams) = explode(' ',$param,2);
		switch($cname){
			default:
				$arr = explode(',',$cparams);
				$pole = array();
				foreach($arr as $a){
					list($i,$f) = explode(':',$a);
					$pole[$i] = $f;
				}
				$c = new $cname();
				if(!is_null($cparams))$c->setData($pole);
				return $c;
			break;
		}
	}
- v sablone, kde chci zobrazit data komponenty zadam kod
 
{mod tagCloud  Auto:1,Letadlo:3,Slon:5}
metoda createMod se postara o rozparsovani parametru a spravnou aktivaci
komponenty
5)komponenta TagCloud pouziva taktez CurlyBracketsFilter a objekt temlate
ziskava v metode render pres $this->createTemplate(); registruje potrebny
filter, zavola render nad sablonou … a dojde k vyjimce, ze ktere vyplyva, ze
v aktualnim kontextu neexistuje $presenter … ktery je nutny pro
sestaveni linku
	$presenter->link('Article:', array(array('tag' => $tag->url)))
je ta cast, kde dojde k havarii.
Z toho vyplyva, ze jsem zrejme zvolil spatnou cestu. Existuje tedy v nette nejaka analogie smarty pluginu?
Dik za info,
M.

- jasir
 - Člen | 746
 
xmn napsal(a):
<?php function createMod($param){ list($cname,$cparams) = explode(' ',$param,2); switch($cname){ default: $arr = explode(',',$cparams); $pole = array(); foreach($arr as $a){ list($i,$f) = explode(':',$a); $pole[$i] = $f; } $c = new $cname(); if(!is_null($cparams))$c->setData($pole); return $c; break; } } ?>
Podle mě je chyba tady: $c = new $cname(), komponenta musí
být připojená k presenteru
pokud chce používat link(). Mělo by tam být buď
<?php
$c = new $cname($name,$this);
?>
anebo přidat komponentu do stromu takto:
<?php
$c = new $cname();
$this->addComponent($name,$c);
?>
Chce to tedy tu komponentu ještě pojmenovat, to jest naplnit to
$name (třeba čítač komponent ve statické proměnné),
třeba tak:
<?php
function createMod(...)
   static $created = array();
   if(isset($created[$cname])) {
	$created[$cname] = $created[$cname]+1;
   } else {
	$created[$cname] = 1;
   }
   $name = $cname . $created[$cname];
   ...
?>
Jednu věc by jsi ale měl zvážit – tímto způsobem se komponenta připojí (a vytváří) až v render fázi, čili nemůže být příjemcem signálů.
Editoval jasir (3. 6. 2009 13:51)

- Patrik Votoček
 - Člen | 2221
 
Ještě bych to řešení malinko doplnil/upravil a v presenteru v metodě
createComponent($name):
public function createComponentTagCload($name)
{
			return new TagCload();
}
A šablona by to přeložila na toto:
$presenter['tagCload']->render($params);
Je jesné že pak musís upravit i samotnou komponentu.
Nevím jestli je to pochopitelné. Kdyby něco tak piš.

- xmn
 - Člen | 6
 
Parada – rada pomohla, stacilo komponentu zaregistrovat :-* Jinak k te namitce, ze komponenta vznikne v okamziku renderovani a nebude mit moznost prijimat signaly – vubec to nevadi (prozatim), spise jsem nenasel zpusob jak to udelat. Jde mi o to abych mel moznost vkladat do stranky moduly pouze pres sablonu – muze to udelat „sablonar/designer“ , neni k tomu treba asistence programatora a zmena kodu. A dopredu aktivovat kod, ktery nebude vyuzit se mi take nezda jako rozumne. Je na toto nejaky jiny zpusob?

- nAS
 - Člen | 277
 
To co popisuješ ty jsou aktivní šablony. Tedy, že se nejprve parsují šablony a podle nich se volá příslušný kód. V Nette jsou naopak šablony pasivní, tzn. že se nejprve provede kód a ten se doplní do šablon.
Pokud bys opravdu potřeboval tuto funkčnost, tak můžeš zaregistrovat všechny připravené komponenty třeba v BasePresenteru a jejich funkčnost provádět v metodě, která se bude volat přímo ze šablony. Ale moc čisté mi to nepřipadá…

- David Grudl
 - Nette Core | 8285
 
Připravím na toto téma obsáhlejší článek, ale asi až po víkendu.
Každopádně k řešení podobné situace bude sloužit makro
{control ...} a rozšiřování
NCurlyBracketsFilter::$macrosNCurlyBracketsMacros::$defaultMacros by se mělo zjednodušit.

- David Grudl
 - Nette Core | 8285
 
Nějak mi to časově nevychází, alespoň tedy příklad rozšiřování $macros