Komponenta uvnitř dynamicky vkládaného textu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Růžička
Člen | 43
+
0
-

Měl by někdo nějaký nápad, jak by se v nette dal vyřešit následující problém?: Generuji stránku s článkem. V textu článku mohou být porůznu vložené značky, na jejichž místo by se při vykreslování vložila nějaká vykreslitelná componenta/control (například značka {gallery 15} pro vykreslení obrázkové galerie s id=15). Lze to za pomoci nette nějak rozumně udělat? V textu článku navíc mohou být vloženy značky stejného typu vícekrát (např dvě galerie s různým nebo i stejným id)

Foowie
Člen | 269
+
0
-

Podívej se jak funguje a co generuje makro {control xyz}

Následně bych postupoval takto:

  • Získal bych text z databáze
  • Vyescapoval bych ho
  • Nahradil bych značky za php kód na vykreslení komponent
David Růžička
Člen | 43
+
0
-

Díky, ale bohužel pořád tápu. Zkoumal jsem kód nette a došel jsem k tomu, že bych asi měl volat $parser->expandMacroexpandMacro(‚widget‘, ‚jmeno_controlu‘). Což by mi snad mělo vyhodit vygenerovaný kód prvku. Nepodařilo se mi ale zjistit, kde získám parser. Zkoušel jsem v presenteru přepsat metodu templatePrepareFilters, ve které se vytváří a registruje Engine přes $template->registerFilter(), ale z nějakého důvodu se nikdy nezavolá.

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Nešlo by použít StringTemplate, respektive teď už obyčejnou Nette\Templating\Template? Tedy vytvořit si ji, předat jí získaný text z databáze a následně tuto šablonu předat jako proměnnou do standardní šablony toho kterého viewů, ve kterém se to provádí. A tam ji prostě vypsat. Jediné co je třeba je té nové Template znovu zaregistrovat potřebné filtry, helpery a předat potřebné proměnné (viz Nette\Application\UI\Control::createTemplate().

Jo, a samozřejmě ty zvláštní značky: přidání vlastního makra.

Foowie
Člen | 269
+
0
-

Nástin:

preg_replace_callback(
	"/{gallery [0-9]+}/",
	function($match) {
		$id = ziskej nejak z $match id;
		$control = $this->getWidget("gallery");
		if ($control instanceof Nette\Application\UI\IPartiallyRenderable)
			$control->validateControl();
		return $control->render($id);
	},
	$string
);

Edit: Uvědomil jsem si, že $control->render() nevrací ale přímo vykresluje, takže výstup musíš zachytit a vrátit (pomocí ob_start, …) ;)

Editoval Foowie (23. 6. 2011 20:03)

Filip Procházka
Moderator | 4668
+
0
-

Složitěji by to nešlo? Co to udělat trošku univerzálně a třeba použít StringTemplate na ten výstup s vlastním macrem? Mám pocit že i obyčejný template by to měl nyní zvládnout, pomocí setSource.

Mimochodem to řešení je nic moc, nejlepší by bylo udělat si modul do Texy!.

Editoval HosipLan (24. 6. 2011 7:54)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Dovolím si také nástin :).

Kód v presenteru (třeba nějaká metoda render<Something>):

use Nette\Latte;
use Nette\Templating\Template;

$latte = new Latte\Engine;
$template = new Template;
$template->source = $article->content; // content obsahuje vpodstatě Latte šablonu
$template->registerFilter($latte);

Šablona již rozumí latte, další řádek zprovozní makra control a link, resp. n:href (možná by to ještě chtělo zprovoznit helpery, přidat svoje další makra, viz příspěvek výše). A následně šablonu šupnem do „hlavní“ šablony, kterou používá presenter.

$template->presenter = $template->control = $this;
$this->template->articleContent = $template;

A v šabloně:

{!$articleContent}

Editoval vojtech.dobes (23. 6. 2011 20:26)

mkoubik
Člen | 728
+
0
-

Ten buffer taky není potřeba, stačí $html = (string) $control.

David Růžička
Člen | 43
+
0
-

Díky všem za příspěvky. Použil jsem Vojtěchovu variantu, jenom jsem použil StringTemplate:

use Nette\Latte;
use Nette\Templating\StringTemplate;

$latte = new Latte\Engine;
$template = new StringTemplate();
$template->content = "{widget gallery 10}"; // content obsahuje vpodstatě Latte šablonu
$template->registerFilter($latte);

$template->presenter = $template->control = $this;
$this->template->myVar = $template;
Foowie
Člen | 269
+
0
-

Pokud bude psát články třetí osoba tak nezapomeň, že jsou povoleny všechny latte makra. (A navíc budou dělat neplechu složené závorky)

Bernard Williams
Člen | 207
+
0
-

Nazdárek,

může mi někdo poradit, proč mi to nejde? Mám to úplně stejně jako v postech výš a nic se nevygeneruje:

$text = 'Nejaky muj text

{control example}

konec meho textu';

$latte = new LatteFilter;
$template = new StringTemplate();
$template->content = $text;
$template->registerFilter($latte);
$template->presenter = $template->control = $this;
$this->template->text = $template;

Zkoušel jsem to i s pouhým Template(), ale bez výsledku. Není potřeba zavolat __toString()? Nebo se to volá automaticky v šabloně při {!$text}? V šabloně se navíc vůbec nezobrazí jakýkoliv text – ani s ani bez dané komponenty.

Vyvíjím na PHP 5.3 (na serveru je 5.2) a bez jmenných prostorů. Nette 2.0-beta, d2c39f5 released on 2011–07–02.

Budu rád za jakoukoliv radu. Už nad tím sedím několik hodin.
Bernard

David Růžička
Člen | 43
+
0
-

Mně funguje tohle:

$latte = new Latte\Engine;
$template = new StringTemplate();
$template->content = "xx {widget neco} xx";
$template->registerFilter($latte);

$template->presenter = $template->control = $this;
$this->template->myVar = $template;
Bernard Williams
Člen | 207
+
0
-

@David Růžička: Můžeš sem hodit kód StringTemplate?

Bernard Williams
Člen | 207
+
0
-

Tak jsem to zkusil i se jmennými prostory a stejný výsledek. Jakou verzi Nette používáš? Podle „widget“ bych řekl, že ještě nějakou starou, ne?

Chyba bude nejspíš ve StringTemplate() ve spojení s Nette 2 beta. Funguje někomu správně v nové verzi?

hAssassin
Člen | 293
+
0
-

@Bernard Williams > ano, StringTemplate v nove verzi nefunguje a potreba ho upravit. Staci vsak trochu hledat zde na foru a funkcni(!) reseni je v tomto vlakne.

Editoval hAssassin (31. 8. 2011 19:01)

Filip Procházka
Moderator | 4668
+
0
-

Doplnil bych šikovnější variantu, kde není potřeba nic nastavovat, protože to udělá výchozí továrnička v komponentě.

// v presenter nebo controlu
$template = $this->createTemplate('Nette\Templating\Template');
$template->setSource($tvojeLatteStringSablona);
$template->render();
Bernard Williams
Člen | 207
+
0
-

@hAssassin: O tom vlákně jsem věděl a taky jsem ho použil.. bohužel jsem jeden řádek přehlédl, a proto mi to nejelo.. Tolik hodil v pr.. pro takovou blbost :-/