Form: Možnost změnit název trackeru (repost dat při odhlášení)

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

Ahoj Davide, jak jsem slíbil, tak činím a jsem tady s prvním návrhem na úpravu :)

Hodilo by se nám, kdyby se dal ovlivnit název formulářového pole trackeru, který je momentálně napevno nastaven konstantou na _form_. Na první pohled to možná zní dost zbytečně, ale jde nám o následující případ:

  • uživatel vyplňuje formulář (říkejme mu F) a než činnost dokončí, vyprší mu platnost přihlášení
  • po odeslání formuláře F se tato skutečnost zjistí a pomocí presenter->forward() je uživatel vnitřně přesměrován na přihlašovací stránku
  • ta vezme aktuální POST data a vloží je do hidden polí přihlašovacího formuláře (říkejme mu L)
  • action formuláře L vede na stejnou adresu, kam vedla action formuláře F
  • kdesi v metodě startup všech presenterů vstupuje do hry náš uživatelský systém, který si z POSTu vyzobne to, co ho zajímá, a uživatele případně přihlásí
  • životní cyklus presenteru pokračuje dál a dostane se normálně k patřičnému view, kde se opět vytváří formulář F, ověřuje se jeho odeslání, validita dat a jejich případné další zpracování

A teď problém:

  • pokud nemá formulář L svůj tracker, domnívá se již při odeslání formuláře F, že byl odeslán, což vede k vyprázdnění formulářových polí (protože v POSTu nejsou jejich hodnoty) a případně i vyhození validačních chyb
  • pokud formulář L má svůj tracker, ignoruje POST z prvního formuláře (OK), ale zároveň jej také odešle po vyplnění jména a hesla do formuláře F, který nenajde svůj tracker a pracně přenášená data tiše ignoruje

Kdyby formulář F neměl tracker, tak by to zřejmě fungovalo, ale to bohužel v našem případě také nejde, protože v dané stránce je občas formulářů víc. Zabudoval jsem do formuláře L a našeho uživatelského systému podporu pro uložení původního trackeru bokem do dalšího hidden pole a po úspěšném přihlášení jeho vrácení zpět do $_POST pod patřičným klíčem _form_ (zde už to nevadí, protože v danou chvíli už formulář L nepřijde ke slovu), ale ani to ještě nestačí, protože formulář pracuje s instancí třídy HttpRequest, kde jsou tou dobou už POST data zkopírovaná (od použití routeru, tedy daleko před tím, než přijdou presentery k lizu). Definitivní řešení je pak až v tom, že se v cílovém presenteru před voláním $formF->isSubmitted() provede toto:

		Environment::getServiceLocator()
			->removeService('Nette\Web\IHttpRequest');
		Environment::getServiceLocator()
				->addService(new HttpRequest(),
						'Nette\Web\IHttpRequest');

díky čemuž dojde k opětovné propagaci (již upraveného) POSTu do HttpRequestu – je to ovšem velmi nepěkné řešení.

Momentálně mě nenapadá žádný hezký způsob, jak jinak zabránit ztrátě dat z formuláře F, je-li uživatel v průběhu práce odhlášen. Pokud by bylo jméno pole s trackerem volitelné, pak by každý formulář měl svůj s ničím nekolidující tracker, podle kterého by poznal, že POST je pro něj (při odeslání formuláře F by se zobrazil formulář L s vlastním trackerem, který by POST data ignoroval při propagaci, ale uchoval je v hidden polích, při jeho odeslání by se z hidden pole odeslal i původní nekolidující tracker, který by vzal v potaz formulář F). Nicméně nebráním se ani jiným návrhům, jak podobnou situaci řešit.