PresenterTree – Kompletní strom presenterů – už dost nářků!

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip Procházka
Moderator | 4668
+
0
-

Zdravím,
dneska v noci jsem dopsal https://gist.github.com/705975 ale už jsem neměl sílu to sem posílat, takže se podělím trochu opožděně… :)

config, pokud jsme paranoidní, zapsat až za definici robot loaderu :)

service.Kdyby-PresenterTree = "Kdyby\\PresenterTree"

použití

$pt = Nette\Environment::getApplication->getContext()->getService("Kdyby\\PresenterTree");

dump($pt->presenters); // všechny presentery

dump($pt->getPresenters('Front')); // všechny presentery přímo ve `Front`
dump($pt->getPresenters('Front', TRUE)); // tohle tam přidá i ty, které jsou v submodulech

dump($pt->getPresenters('Front:Forum')); // všechny přímé potomky `FrontModule\ForumModule`

akce presenterů (načítá i podle šablon)

dump($pt->getActions('Front:Homepage')); // homepage actions?
dump($pt->getActions('Front:Client')); // damn that's a module... too bad, returns NULL

moduly

dump($pt->modules); // root modules
dump($pt->getModules('Front')); // directry in front
dump($pt->getModules('Front:Client')); // avalaible submodules?

možnosti jak zakázat indexování presenterů a akcí

abstract class BasePresenter extends Nette\Application\Presenter {  } // one

/** @hideInTree */
class BasePresenter extends Nette\Application\Presenter {  } // two

class BasePresenter extends Nette\Application\Presenter
{

	/** @hideInTree */
	public function actionDefault() { } // three

	/** @hideInTree */
	public function renderSomethink() { } // three

}

Při inicializaci se ověří platnost cache a popř. se vygeneruje nový strom, to znamená, že pokud nějaké třídy, které nejsou načtené v robot loaderu zavoláte až po prvním zavolání PresenterTree tak je prostě nevypíše. Ale to na localhostu nevadí, protože tam stačí dát 2× F5 a na produkčním je to fuk :)

TODO:

  • formát, v jakém je uložený strom presenterů se možná ještě změní, protože jsem to ještě nepoužil v cílové komponentě (ano menu) a proto pokud to někomu nebude vyhovovat tak šup sem s protesty ať to dáme dohromady :)

Editoval HosipLan (18. 12. 2010 11:57)

Aurielle
Člen | 1281
+
0
-

Pěkná věcička, jen mi $pt->getPresenters() vrací z nepochopitelných důvodů NULL, takže se jdu hrabat ve zdrojácích :P
(getPresenters na modul mi funguje…)

Aurielle
Člen | 1281
+
0
-

Tak první bug (metoda getPresenters):

if (strpos(':', $nettePath) == 1) {
	$nettePath = substr($nettePath, 1);
}

if (strpos(':', $nettePath) == strlen($nettePath)) {
	$nettePath = substr($nettePath, 0, -1);
}

if ($all || $nettePath === NULL) {
	return isset($this->cache['presenters']['all'][$nettePath]) ? $this->tree['presenters']['all'][$nettePath] : NULL;
}

V podmínkách mají být === (to samé v getMethods a getActions) a v return má místo špatného tree být cache – poté getPresenters funguje. Máš taky přehozené pořadí parametrů strpos funkcí. volání metody buildPresenterTree – moje chyba, přidal jsem si ji pro testování a pak na to zapomněl :D

Abych nespamoval, tak tady je opravená verze (+ jsem si přepsal namespace…) Změny by měly být všechny a pouze z tohoto příspěvku. https://gist.github.com/706828

  • jsem napsal jednodušší implementaci buildActionTree, která spoléhá jen na přítomnost render a action metod při detekci akcí (neprohledává šablony), ale za to se pak ve výsledku neobjevují blbosti typu :BaseAdmin:Auth:@layout:
/**
 * @return array
 */
private function buildActionTree($presenters)
{
	$tree = array();

	foreach ($presenters['all'][NULL] as $fullPath => $presenter) {
		$ref = $presenter->getPresenterReflection();

		$views = array();
		$methods = array();

		foreach($ref->getMethods() as $k => $v) {
			if(!$v->hasAnnotation('hideInTree') && $v->isPublic())
				$methods[] = $v->name;
		}

		foreach($i = new \RegexIterator(new \ArrayIterator($methods), '~^(action|render)(.*)~i', \RegexIterator::GET_MATCH) as $view) {
			$views[] = $view[2];
		}

		$actions = array();
		foreach ($views as $view) {
			$view = lcfirst($view);
			$actions[$view] = $fullPath.':'.$view;
		}

		if ($actions) {
			$tree['all'][$presenter->presenterClass] = array_flip($actions);

			$t =& $tree['byPresenter'];
			foreach (String::split($presenter->module, '~:~') as $step) {
				$t[$step] = isset($t[$step]) ? $t[$step] : array();
				$t =& $t[$step];
			}

			$t[$presenter->name] = array_flip($actions);
		}
	}

	return $tree;
}

Editoval gmvasek (19. 11. 2010 19:43)

Filip Procházka
Moderator | 4668
+
0
-

Škoda že gist neumí diff :)
S tím že si přepíšeš namespace tak nějak počítám :)
A jsem rád že to použil aspoň jeden člověk. Když jsem to sem hodil, bylo slyšet hodně skepticismu :)

pYro
Člen | 29
+
0
-

ja ho taky pouzivam pomerne hodne :)

bude upraveno pro novy nette? haze to chyby v

<?php
private function getContext() {
	return Nette\Environment::getApplication()->getContext();
?>

bohuzel nestiham moc sledovat zmeny v Nette a tak nevim na co se ted context zmenil

Aurielle
Člen | 1281
+
0
-

Nahraď getApplication()->getContext() jen za getContext() a poběží to.

Filip Procházka
Moderator | 4668
+
0
-

Trošku jsem poladil https://gist.github.com/705975, snad by to teď mělo šlapat v betě.

pYro
Člen | 29
+
0
-

zkusim a dam vedet. diky ;)

MIKI
Člen | 34
+
0
-

Zdravim,

mam Nette verziu „Nette Framework 2.0-dev (revision 7616569 released on 2011–03–10)“, a ked som si vlozil najnovsiu verziu tohto doplnku, tak mi ladenka krici:

Service ‚robotLoader‘ not found.

private function getRobotLoader()
338:        {
339:            return $this->getContext()->getService("robotLoader");
340:        }

tak som pridal do config.neon toto:

common:
  service:
    RobotLoader: Nette\Loaders\RobotLoader

a aktualne mi to krici:
ksort() expects parameter 1 to be array, null given

private function buildPresenterTree()
...
100:            ksort($tree['all']);

premenna $tree je prazdne pole, array(0) {}

Viete co mam konkretne spravit aby to fungovalo, alebo si to mam zistovat sam? :)

Aurielle
Člen | 1281
+
0
-

Aktualizuj si Nette.

Filip Procházka
Moderator | 4668
+
0
-

Nebo stáhni předchozí verzi :) vedle toho gistu je historie.