Jak udělat podporu více šablon pro jeden modul – přepínání designu uživatelem?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
neznamy_uzivatel
Člen | 115
+
0
-

Ahoj,
potřeboval bych umožnit v jednom modulu uživateli přepnout na jiné šablony.

Mám strukturu:

app/EshopModule
	/presenters
		/templates
			/blue
				/Index/Default.latte
				@layout.latte
			/red
				/Index/Default.latte
				@layout.latte
		BaseEshopPresenter.php
		IndexPresenter.php

Jak udělat, aby nette hledalo v těch složkách blue a red?
Něco jako $this->setTemplate(‚red‘); // :)
Zkoušel jsem různé setView, apod, ale nějak mi to nejde, seskládá to „špatně“ cestu k souboru, tzn.
místo:
/app/EshopModule/presenters/templates/blue/Index/Default.latte (což bych potřeboval s blue jako „přepínatelné“)
mi to seskládá:
app\EshopModule\presenters\templates\Index\red\.latte'

Michal Vyšinský
Člen | 608
+
0
-

Ahoj,
něco takového dělám v https://github.com/…ework/themes (můžeš to třeba rovnou použít nebo nabrat inspiraci)

Edit: právě jsem updatnul dokumentaci a vydal verzi 2.1.0 :)

Editoval Michal Vyšinský (14. 6. 2015 11:40)

David Matějka
Moderator | 6445
+
+3
-

muzes prekryt metody formatLayoutTemplateFiles a formatTemplateFiles v presenteru: https://api.nette.org/…esenter.html#…

neznamy_uzivatel
Člen | 115
+
0
-

@DavidMatějka Přesně tohle jsem potřeboval, díky.

buffus
Člen | 101
+
0
-

Ahoj,

David Matějka napsal(a):

muzes prekryt metody formatLayoutTemplateFiles a formatTemplateFiles v presenteru: https://api.nette.org/…esenter.html#…

Mohl bych poprosit o malé rozvinutí, jak udělat v praxi překrytí těch Nette metod? Snažím se navrhnou aplikaci, ve které by si mohl Admin zvolit z několika málo přednastavených šablon (template-A, -B, -n). To vše při společných Front/*/Presenterech (logika aplikace stejná, jen různé vizuální kabáty).

Nejdříve mi stačilo ve Front/BasePresenter.php nastavit $this->layout např. na = "template-A" (vytažené z db)

protected function beforeRender()
{
	$this->layout = $setting->layout // Z db "template-A" nebo "template-B"
}

a Nette dohledalo výchozí @template-X.latte. To bylo super, ale teď bych potřeboval pro každou „tempate-X“ vlastní adresář, ve kterém budou pro každou šablonu konkrétní template-A/*/*.latte šablony.

Mám adresářový strom:

app
├── bootstrap.php
├── ...
├── modules
│   ├── Admin ...
│   ├── Base ...
│   └── Front
│       ├── BasePresenter.php
│       ├── ErrorPresenter.php
│       ├── HomepagePresenter.php
│       ├── PostPresenter.php
│       ├── templates
│       │   ├── @template-A.latte
│       │   ├── @template-B.latte
│       │   ├── @template-N.latte
│       │   ├── template-A
│       │   │   ├── Error
│       │   │   ├── Homepage
│       │   │   └── Post
│       │   ├── template-B
│       │   │   ├── Error
│       │   │   ├── Homepage
│       │   │   └── Post
│       └── ...
└── ...

Co znamená překrýt metody format*? Je kód, co tu ukazuji níže správně? On funguje, ale nejsem si jistý, jestli je postup OK.

Do Front/BasePresenter.php jsem zkopíroval original Nette metody (api)

  • formatLayoutTemplateFiles() a
  • formatTemplateFiles()

a do řádků komentovaných // add $this->layout jsem do cesty přidal /$this->layout/

/**
 * Formats layout template file names.
 * @return array
 */
public function formatLayoutTemplateFiles()
{
	$name = $this->getName();
	$presenter = substr($name, strrpos(':' . $name, ':'));
	$layout = $this->layout ? $this->layout : 'layout';
	$dir = dirname($this->getReflection()->getFileName());
	$dir = is_dir("$dir/templates") ? $dir : dirname($dir);
	$list = array(
		"$dir/templates/$this->layout/$presenter/@$layout.latte", // add $this->layout
		"$dir/templates/$this->layout/$presenter.@$layout.latte", // add $this->layout
	);
	do {
		$list[] = "$dir/templates/@$layout.latte";
		$dir = dirname($dir);
	} while ($dir && ($name = substr($name, 0, strrpos($name, ':'))));
	return $list;

}


/**
 * Formats view template file names.
 * @return array
 */
public function formatTemplateFiles()
{

	$name = $this->getName();
	$presenter = substr($name, strrpos(':' . $name, ':'));
	$dir = dirname($this->getReflection()->getFileName());
	$dir = is_dir("$dir/templates") ? $dir : dirname($dir);
	return array(
		"$dir/templates/$this->layout/$presenter/$this->view.latte", // add $this->layout
		"$dir/templates/$this->layout/$presenter.$this->view.latte", // add $this->layout
	);

}

Je výše uvedený postup v pořádku?

Předem děkuji.

Editoval buffus (22. 9. 2015 8:35)

Unlink
Člen | 298
+
+2
-

Prekrytie (overriding) metódy znamená, že v potomkovi upravuješ implementáciu nejakej metódy, ktorá je implementovaná v predkovi → https://en.wikipedia.org/…d_overriding
Čiže správne si to pochopil.

Čo sa týka tej tvojej implementácie, tak ono sa to dá značne zjednodušiť, pretože tamto je strašne univerzálne.

Tú štruktúru by som ale trochu poupravil:

app
├── bootstrap.php
├── ...
├── modules
│   ├── Admin ...
│   ├── Base ...
│   └── Front
│       ├── BasePresenter.php
│       ├── ErrorPresenter.php
│       ├── HomepagePresenter.php
│       ├── PostPresenter.php
│       ├── templates
│       │   ├── template-A
│       │   │   ├── Error
│       │   │   ├── Homepage
│       │   │   ├── Post
│       │   │   └── @layout.latte
│       │   ├── template-B
│       │   │   ├── Error
│       │   │   ├── Homepage
│       │   │   ├── Post
│       │   │   └── @layout.latte
│       └── ...
└── ...

Na názov témy by som nezneužíval atribút layout ale v base presentery si sprav napr.
protected $theme;

A potom by tá implementácia mohla vyzerať nejako takto (netestované)

/**
 * Formats layout template file names.
 * @return array
 */
public function formatLayoutTemplateFiles()
{
    $name = $this->getName();
    $presenter = substr($name, strrpos(':' . $name, ':'));
    $dir = dirname($this->getReflection()->getFileName());
    return = array(
        "$dir/templates/$this->theme/$presenter/@layout.latte",
		"$dir/templates/$this->theme/@$layout.latte"
    );
}


/**
 * Formats view template file names.
 * @return array
 */
public function formatTemplateFiles()
{

    $name = $this->getName();
    $presenter = substr($name, strrpos(':' . $name, ':'));
    $dir = dirname($this->getReflection()->getFileName());
    return array(
        "$dir/templates/$this->theme/$presenter/$this->view.latte",
    );

}
buffus
Člen | 101
+
0
-

Děkuji, přesně tohle jsem potřeboval slyšet.