ErrorPresenter v modulech

d@rkWolf
Člen | 163
+
0
-

Zdravím,
poradil by mi někdo, jak dostat Error Presentery do jednotlivých modulů? Mám základ ze sandboxu Nette 2.4 a nedaří se mi dohledat nic aktuálního, jak to vyřešit. Teď mám ten výchozí ErrorPresenter ze Sandboxu mimo moduly(Admin/Front), ale potřeboval bych to nějak nasměrovat do modulů tak, abych mohl mít šablony Errorů oddělené zvlášť pro Admin a zvlášť pro Front(nebo eventuelně i něco jiného), hlavně aby 4×x errory využívaly výchozí layout.latte danného modulu a zároveň, abych mohl ty ErrorPresentery zdědit z basePresenterů daného modulu(budu tam potřebovat překlady kdyby/translation, nějaké komponenty typu hledání…).

Při hledání jsem narazil na zjistění a nasměrování pomocí:

<?php
if (Strings::startsWith($request->presenterName, 'Front:')) {
            $this->forward(':Front:Error:', [
                'exception' => $exception,
                'request' => $request,
            ]);
        }
?>

To mi přišlo nadějné, ale ukázalo se, že $request->presenterName vrací „Error“, nikoliv něco jako „Front:NeexistujiciCesta“, takže z toho ten routovaný modul nezjistím.

Jak zjistit modul a přesměrovat to? Nebo je nějaké jiné řešení, jak docílit toho co potřebuju?

David Matějka
Moderator | 6445
+
0
-

ahoj, odkud si vzal ten request? je potřeba jej vzít z parametrů aktuálního requestu přes $this->getParameter('request'), resp si jej vyžádat v argumentech action metody

Kamil Valenta
Člen | 762
+
0
-

V ErrorPresenteru si vyžádej z DI router a HttpRequest, z requestu si routerem matchni modul a na ten forwardni.

d@rkWolf
Člen | 163
+
0
-

@DavidMatějka ten request v tom ErrorPresenter sandboxu už byl, je tam tato funkce:

<?php
	public function run(Nette\Application\Request $request): Nette\Application\IResponse
	{
		$exception = $request->getParameter('exception');

		if ($exception instanceof Nette\Application\BadRequestException) {
            [$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
			return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
		}

		$this->logger->log($exception, ILogger::EXCEPTION);
		return new Responses\CallbackResponse(function (Http\IRequest $httpRequest, Http\IResponse $httpResponse): void {
			if (preg_match('#^text/html(?:;|$)#', $httpResponse->getHeader('Content-Type'))) {
				require __DIR__ . '/templates/Error/500.phtml';
			}
		});
	}
?>

Editoval d@rkWolf (20. 5. 2019 16:12)

Matey
Člen | 142
+
0
-

Ahoj, ja som to vyriešil tak že som si z $requestu ktorý prijíma ErrorPresenter vytiahol request (ten pôvodný na ktorom došlo k chybe). Vypadá to takto:

	public function run(Application\Request $request): Application\IResponse
	{
		$e = $request->getParameter('exception');

		if ($e instanceof Application\BadRequestException) {
			// $this->logger->log("HTTP code {$e->getCode()}: {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", 'access');
			$presenterName = $request->getParameter('request') ? $request->getParameter('request')->getPresenterName() : $request->getPresenterName();
			[$module, , $sep] = Application\Helpers::splitName($presenterName);
			$errorPresenter = $module . $sep . 'Error4xx';
			try {
				$this->presenterFactory->createPresenter($errorPresenter);
			} catch (Application\InvalidPresenterException $exception) {
				return new Application\Responses\ForwardResponse($request->setPresenterName('Error:Error4xx'));
			}
			return new Application\Responses\ForwardResponse($request->setPresenterName($errorPresenter));
		}

		$this->logger->log($e, ILogger::EXCEPTION);
		return new Application\Responses\CallbackResponse(function (Http\IRequest $httpRequest, Http\IResponse $httpResponse): void {
			if (preg_match('#^text/html(?:;|$)#', $httpResponse->getHeader('Content-Type'))) {
				require __DIR__ . '/templates/Error/500.phtml';
			}
		});
	}
d@rkWolf
Člen | 163
+
0
-

@Matey jo něco takového jsem zrovna zkoušel, jen sem si nebyl jistej, že je vhodný postup

Zdá se, že 404 se zobrazuje správně uvnitř šablon.

Ovšem 403ka v adminu se nechytá(potřebuju to donutit vyhazovat tu error page pokud přihlášený uživatel nemá práva), šablona tam je, jak to chápu, tak by to mělo na základě kódu vybrat tu 403 šablonu, místo toho mi to ale furt vyhazuje Nette\Application\ForbiddenRequestException #403 z Tracy – i s „catchException: true“.

Výjimku vyhazuju normálně ve f-ci checkRequirements a do toho ErrorPresenteru to neproleze.

<?php
if (!$this->user->isLoggedIn()) {
...
} elseif (!$this->user->isAllowed($resource)) {
            throw new Nette\Application\ForbiddenRequestException;
}
?>
Matey
Člen | 142
+
0
-

Odskúšal som a u mňa je to ok. S catchException: true dostávam správnu 403 šablónu zo správneho modulu. Máš pre každý modul Error4×xPresenter? Ja to mám takto:

Error:ErrorPresenter implements IPresenter - hlavný error presenter
Error:Error4xxPresenter extends Nette\Application\UI\Presenter + šablóny
Front:Error4xxPresenter extends BaseFrontPresenter + šablóny
Admin:Error4xxPresenter extends BaseAdminPresenter + šablóny
d@rkWolf
Člen | 163
+
0
-

Mám to stejně, jen jsem úplně ten výchozí Error4×x(2.řádek), nastavil jsem to tak, že to vždycky spadne buď do admin, nebo front ten Error4×x, nevím, zda na to nemůže mít vliv, že mám ten admin načítanej ajaxem, nicméně nefunguje to ani, když si adresu té nepřístupné stránky zapíšu do adresy, ani když ju vyvolám přes ajaxové tlač. v menu, vždycky skončím na Tracy, vůbec nevím, kde ten problém hledat.

Kamil Valenta
Člen | 762
+
-1
-

No ale to už řešíš jinou otázku, ne? V debug mode končí exceptiony v tracy. Buď si vypni debug, nebo si do neonu dej catchExceptions: true

d@rkWolf
Člen | 163
+
0
-

Právě, že jde o to, že catchExceptions: true v Neonu mám, když zkusím neexistující stránku pro 404 tak se správně objeví v obsahu, ať už adminu, nebo front-endu, ale 403 když kliknu v adminu na odkaz, do kterého nemám práva, se mi ukáže v Tracy, pořád, ať je v catchException cokoliv(mazat cache jsem zkoušel). Při vypnutém debugu se Tracy neukáže, ale místo toho se mi v Ajax dotazu zobrazí 500 a do log se uloží Tracy s tím samým, co se zobrazuje když mám ten debug zapnutý.