Sziasztok!
Elakadtam. Szeretnék segítséget kérni FORM API-val kapcsolatban.
A probléma leegyszerűsítve:
Van egy "munkaajanlat" nevű tartalomtípus a köv mezőkkel:
A felvitt ajánlatok 'Felvitt' státuszt kapnak. A munkavállalok bejelentkeznek és kapnak egy listát a 'felvitt', azaz elvállalható ajánlatokból. Ez a lista gyakorlatilag generált FORM-ok. A FORM tartalmazza hidden input elemben az ajánlat NID-jét és egy 'Elvállalom' submit gombot.
Ha a user rákattint az 'Elvállalom' gombra akkor a myform_form_submit() függvényben átírom az adott NID-ű ajánlatnak taxonomy term-jét 'Elvállalt' értékre.
Ez eddig kiválóan működik is.
Viszont lehet olyan eset, hogy egyszerre 2 user is be van jelentkezve és mindegyik egyszerre betölti a listát, majd az egyik az 'Elvállalom' gombra kattint, majd pár mp után a másik is, mivel még ott van a listájában az adott ajánlat.
Ebben az esetben ki szeretném írni a user-nek, hogy elkésett, más már elvállalta előtte.
Úgy gondoltam, hogy ez roppant egyszerűen megoldható úgy, hogy myform_form_submit()-ban mielőtt státust váltok megvizsgálom, hogy nem volt-e már státuszváltás. Ha volt akkor üzenetben (drupal_set_message) értesítem az elkésett usert.
A gond az, hogy az elkésett user, ha az 'elvállalom' gombra kattint, akkor nem jutok el a myform_form_submit() függvénybe, azaz nem történik semmi. Egyszerűen újratöltődik az oldal a már elvállalt ajánlatok nélkül. De akkor így hogy tudassam a userrel hogy elkésett?
Köszönöm.
Validate, amit keresel: https
Validate, amit keresel: https://api.drupal.org/api/drupal/developer%21topics%21forms_api_referen...
A myform_form_validate()-ben csinálod meg ugyanazt a vizsgálatot, ami most a form submitban van. Ha közben elfogadták az ajánlatot, a validate az egész form_submit folyamatot megszakítja, ha form_set_error-t állítasz rá - és az üzeneted is kész.
----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.
Ezzel próbálkoztam, hogy a
Ezzel próbálkoztam, hogy a validate lefut-e, de sajnos ez sem.
Úgy ellenőriztem, hogy csak egy drupal_set_message('mizú?')-t raktam a validate függvénybe. Az első usernél volt üzenet, a második elkésett user nem kapott mizú? üzenetet. Így úgy gondolom, hogy nem jutott el se a myform_form_validate()-be és se a myform_form_submit()-ba.
Kicsit részletesebben leírom,
Kicsit részletesebben leírom, hogy hogyan csináltam a dolgot, hátha koncepcionálisan rontottam el valamit :)
"Mivel egy oldalon így több
"Mivel egy oldalon így több form lesz, azt hogy az FormID-jűk ne legyen azonos, a hook_form()-al oldom meg: a formID végéhez hozzáírom az ajánlat NID-jet, hook_form()-ban minden FormID esetén callback-nek a myform_form()-ot adom meg
A myform_form()-ban definiálok egy hidden típusú mezőt az adott ajánlat NID-jével és egy submit gombot."
Itt már van némi zavar van az erőben, a hook_form nem erre való. Neked nem kell foglalkozni a form_id-vel, a form api lekezeli, hogyha egy form_id-jű formot többször jelenítesz meg, az ne legyen gond.
A nidet simán
drupal_get_form('my_form', $nid)
-ként add át, a formodban ezt a nidet megtalálod a$form_state['build_info']['args'][0]
helyen, vagy még jobb, hadrupal_get_form('my_form', array('nid' => $nid))
-ként hívod, és még jobban látszik majd a build infoban, hogy ez egy nid. (['build_info']['args'][0]['nid'])Nézzük meg, ezután hogy állsz, mert simán el tudom képzelni, hogy a hook_form vudu borítja az egész processt, főleg, hogy ezzel még jóformán az összes node_edit formba sikerült beletrollkodni. :)
Amúgy én ezt az egészet flag + rules-szal csinálnám, kell egy flag, hogy accept_offer, kell egy rule a content is flagged accept_offer eseményre, ahol a condition valami ilyesmi, hogy node-flag-counter > 0, action meg drupal_set_message + unflag node. Így mindig egy darab nodeod lesz flaggelve, és készen kapsz egy ui-t az ajánlat visszavonására. A page-t meg megcsinálod views-al.
----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.
Legelőszőr úgy csináltam,
Legelőszőr úgy csináltam, ahogy írtad, nem foglalkoztam a FormID-el. Viszont ebben az esetben mindig az oldalon lévő legelső form lett elküldve, teljesen mindegy melyik submit gombra kattintottam, ezért jött be a hook_form(), mégpedig így:
Ezzel a többi node_edit form-ba (szerintem) nem trollkodtam bele :)
A NID-et (is) amúgy átadom a drupal_get_form-nal, hogy tudjak értéket adni a hidden field-nek. De ettől még azonosak lesznek a FormID-ek.
Flag modult még nem használtam, de úgy nézem hogy ez csak igen/nem lehetőségre jó. Az én feladatom ennél viszont komplexebb, az itt felvázolt rész csak egy töredéke. Nem csak ez a két ajánlat státusz van hanem jóval több.
A page generálása is bonyisabb, írtó sok field-em van + field collectionok, pláne field collectionokban is vannak field collectionok + if feltételek hogy mikor mit írjak ki :) Szóval elég egyedi a listázási mód, amit views-al nem tudok megoldani szerintem.
hook_form vs hook_forms
Ohh, emlegetted ezt a hook_form-t, közben a hook_forms használtad, két nagyon külön dolog ám, szóval amit ott csináltál, az teljesen rendben van. Akkor már csak az a kódrészlet kell, ahol drupal_get_form()-al összeszeded a formot.
----
Rájöttem, miért kérdezek olyan ritkán a drupal.hu-n. Amíg szedem össze az infokat a kérdéshez, mindig rájövök a megoldásra.
óó, bocsánat, ezt valóban
óó, bocsánat, ezt valóban összekavartam egy kicsit.
A drupal_get_form:
(ezt hívom meg a "page callback" függvényben többször.)
Azaz a Form id az: order_undertake_form_[nid]
plusz átadok egyéb paramétereket is.
A hook_form() pedig elég szokványos:
Tehát már form sincs, ha
Tehát már form sincs, ha elvállalták?
Az a helyzet, hogy amikor a második ember ráklikkel a form-ra akkor a böngésződ újratölti az oldalt (POST), ami ugye legenerálja a formokat azokhoz az elemekhez amiket még nem vállaltak el, de ugye amit már elvállaltak, ahhoz nem, ezért nem is fut le a validate hook-ja annak a formnak ami nincs is már.
Talán ha mindegyik elemhez raksz formot, csak amelyik már elvállalt, annál nem raksz submit gombot, vagy access false-ra rakod akkor már a validate függvény le fog futni. (vagy ha nem akkor a submti gombok divjébe egy display:none tud segíteni. :))
Praktikusabb lenne egy űrlap sok submit gombbal, ahol a gomb id-jébe kódolod a nid-et. Vagy még tovább menve, miért is kell Form ehhez? elég lenne egy link + token szerintem.
pp
Palócz István
https://palocz.hu | https://tanarurkerem.hu
Azt mondod, hogy amikor
Azt mondod, hogy amikor elküldök egy form-ot, akkor a böngésző először újratölti azt, majd utána küldi el a POST változókat? Én úgy gondoltam, h ez fordítva van.
Form azért kell, mert az elvállal gomb megnyomása előtt a user módosíthat egy az ajánlathoz csatolt date mezőt.
Gondolkodom azon amiket írtál, köszönöm.
Nem, nagyon rosszul
Nem, nagyon rosszul fogalmaztam, ha így értetted, megpróbálom világosabban:
Az űrlap feldolgozás úgy néz ki, hogy:
Jött-e adat?
igen
Valid-e?
igen
Feldolgozom | Ha nemjött, vagy nem valid akkor kiíratom a formot.
Valami ilyesmi van a drupal_get_form fv működése mögött. Mivel Te csak azokhoz a ajánlatokhoz gyártasz űrlapot amelyiket még nem fogadták el, ezért Te a fenti mechanizmust be se indítod, ezért azok az adatok nem is kerülnek feldolgozásra. Szóval a drupal_get_form az nem csak az űrlapot generálja le, hanem végighívogatja a ellenőrző és a feldolgozó függvényeket. (mert ugye nem csak a Te függvényeid fognak lefutni, hisz, ha felteszel pl. egy spamszűrőt, akkor az jól bele is alterelhet az űrlapodba)
pp
Palócz István
https://palocz.hu | https://tanarurkerem.hu
Akkor én már tényleg nem
Akkor én már tényleg nem értem.
Nem értem hogy az ebből a HTML kódban létező formból mér nem kapok adatot. A böngésző gondolom elküldi a POST adatokat. De akkor hol tűnik el?
Ugyanis a feldolgozás menete szerint szerintem:
"Jött-e adat?" -> IGEN
"Valid-e?" -> passz hiszen ide el sem jutok
Vagy a form elküldése után először újragenerálja a drupal az egész oldalt, és mivel újrageneráláskor az a Form eltűnik, aminek az adatait a böngésző elküldte, így figyelmen kívül hagyja azokat?
Ha így van, nincs valami hook, amiben mégis meg lehet azt nézni, hogy van-e elküldött "érvénytelen" form?
Elnézést, hogy ha lassú a felfogásom :)
Úgy érzem, hogy amíg ezt nem értem meg nem kéne továbbhaladnom, mert itt valami koncepcionális hiba van a gondolataimban :)
Akkor még részletesebben:
Akkor még részletesebben:
Ugorjunk az utolsó előtti lépéshez:
"B" usernek meg mindig 3 form van az oldalán, azaz az a form is ott van aminek már nem kéne.
Na itt megnyomja az elvállalom gombot a felhasználó, aminek hatására egy Post kérés küld a böngésző a szerver felé.
Ok, és most csukd be a szemed és képzeld el, hogy mindent elfelejtettél ami eddig volt, hisz az esetünkben is pont ez van, alapból a szerver nem tudja, hogy B küldte a kérést, és azt se, hogy egy összeállított űrlapból jön a kérés és nem egy robot tolja azt.
Emlékezet nélkül vagyunk!
A szerver kap egy Post kérést. Van hozzácsapva egy sütemény, ami tartalmazza a session id-t, Hurrá, betölti a session-ben tárolt adatokat.
Megnézi, hogy van-e q változó a GET tömbben, és megállapítja, hogy melyik függvényt kell meghívnia. (ezt szokták routingnak hívni, amikor egy adott útvonalhoz a keretrendszer meghatározza a végrehajtandó fv-t. Ezt kb. minden keretrendszerben így van, nem csak a Drupalban, sőt, a nem PHP-s keretrendszerekben is hasonló elven működik az útválasztás)
Ezen a ponton még nem tudja a szerver, hogy kell-e valamit kezdenie a POST adatokkal.
Meghívódik a formokat legeneráló kód.
Ez a kód szintén nem foglalkozik a POST-ban található adatokkal. (még mindig nem foglalkozott vele senki!!! Felháborító!!! :D minek küldözgetjük mi ezeket az adatokat, mit gondolnak ezek??? :D )
A kód kirakja az űrlapot. Na ez a kód megnézi, hogy jött-e adat. Látja, hogy a form_id az nem az ami az ő form_id-je. Nem foglalkozik vele. (még ő sem, hát akkor ki fog??? lusta egy banda ez vazzz!!! :D)
Mondjuk, jó hülyén is nézne ki, ha foglalkoznának a másiknak küldött adatokkal, mert ha kint van a keresés és a bejelentkezés űrlap, akkor nem tudnál bejelentkezni, mert a kereső űrlap kódja, folyton rákeresne a nevedre, ahelyett, hogy beléptetne. Ezért véletlenül se foglalkoznak egymás adataival.
Mivel, ha már elfogadtak egy ajánlatot, nem fogod kirakni az űrlapot, ezért senki nem fog a kéréseddel foglalkozni. (hálátlan egy banda na... :D)
Mivel a feldolgozás és az űrlap kirakását is a drupal_get_form végzi, ezért, ha nem rakod ki az űrlapot, akkor nem fogja a Drupal feldolgozni a kérést sem.
Szóval a lényeg, hogy a kommunikáció ezen formája (folyton a kliens kérdez a szervertől) emlékezet nélküli, szóval valahonnan ki kell találni mindig, hogy mi az amire a kliens mögött lévő felhasználó gondolt, amikor összeállította a böngésző és elküldte a kérést. Nincs űrlap, csak egy kérés, amiben a POST tömbben található adatok lehet, hogy egy böngészőben lerenderelt űrlapból érkeznek, de lehet, hogy nem.
pp
Palócz István
https://palocz.hu | https://tanarurkerem.hu
Köszönöm a részletes választ
Köszönöm a részletes választ és legfőképpen a türelmed :)
Arra jutottam elméletben,
Arra jutottam elméletben, hogy az ajánlatok listázási oldalán nem lesz egy form se. Hanem 'Elvállalom' linkek egy 'page callback'-re ami megkapja paraméterben az ajánlat azonosítóját. Itt meg tudom vizsgálni hogy már nem vállalták-e el. Ha még nem akkor kiírom a form-ot a módosítható date mezővel és a submit gombbal. Mivel ez a form nem fog sosem "eltűnni" így be fogok jutni a form_validate-be is és tudok újra ellenőrizni...
Remélem gyakorlatban is működni fog. :)
Köszönöm a segítségeket :)
Token nélkül ne is próbáld!!!
Mindenképpen legyen token a linkek végén, mert különben CSRF támadással el lehet fogadtatni ajánlatokat mással. (biztonság)
Ha regisztrációhoz se kötöd a link megjelenését, akkor pedig a keresők fogják "beindexelni" vagyis elvállalni az összes munkát. :) (koncepcionális probléma)
Palócz István
https://palocz.hu | https://tanarurkerem.hu
Elvileg a linkre kattintva
Elvileg a linkre kattintva még nincs elvállalás, hanem a link utáni form elküldése után lenne.
Az ajánlat elfogadása pedig regisztrációhoz kötött, sőt egy szerepkörhöz tartozáshoz is.
Így gondolom nem szükséges Token.
Bár ettől még utánanézek ennek, máskor jól jöhet.:)
Gondolom ezekre a függvényekre gondolsz:
drupal_get_token
drupal_valid_token
Jól gondolod.
Jól gondolod.
Igen ha csak egy akciót indítasz el, de nem maga az akció a link megnyomása, akkor nem kell token.
pp
Palócz István
https://palocz.hu | https://tanarurkerem.hu