Jelenlegi hely

CCK beviteli elem és megjelenítő programozása

CSÉCSY László képe

Már nem az első webhely építésénél kell megoldanom a következőt: az egyik tartalomtípusban fel kell venni egy többértékű, nemkötelező szövegmezőt, melynek automatikus kiegészítéssel kell rendelkeznie a már felvitt értékekre és egy másik típusú tartalmak címeire. Ha ez a mező létező tartalom címét tartalmazza, akkor azt hivatkozásként kell megjeleníteni az adott tartalomra, egyébként egyszerű szövegként. Konkrét példa: egy egyetemi tanszék oldalán a publikációkhoz fel kell tudni vinni a szerzőket (tetszőleges, rendezhető sorrendben, amit ugye a többértékű CCK mező lehetővé is tesz), de ha a szerző a tanszék alkalmazottja, akkor megjeleníteni már hivatkozásként kell az adott alkalmazott oldalára mutatva. A felvitelt segíti az automatikus kiegészítés.

Ebben a feladatban több komplikáció van. Nem lehet egyszerű szövegmezőt használni, mert abból nem lesz hivatkozás. Nem lehet egyszerűen tartalomra hivatkozást (nodereference mezőt) használni, mert azzal csak már létező tartalmakra lehet hivatkozni, azaz nem tud egyszerű szöveget megjeleníteni. Nem lehet egyszerűen az Autocomplete Widgets for CCK Text and Number modult használni, mert azzal nem tudunk olyan tartalmakra automatikusan kiegészíteni, melyekre még nem történt hivatkozás.

A megoldás magától adódik: készítsünk egy CCK kiegészítő modult, mely az adatbázisban való tárolásra nézve ugyanúgy dolgozik, mint a CCK által szállított szöveg típusú mező (ergo a text.module a függősége); a felhasználói felülete tudja a számunkra szükséges automatikus kiegészítést; a megjelenítése pedig tudja a hivatkozások automatikus kezelését. Ehhez két dolog szükséges:

  • CCK widget (UI elem),
  • CCK formatter (megjelenítő).

Widget (UI elem)

Widgetet (UI elemet) a hook_widget_info() segítségével definiálunk. Ez egy asszociatív tömböt ad vissza, melynek kulcsa(i) a definiálni kívánt widget(ek) gépi neve(i), értékei ismét asszociatív tömb(ök), mely(ek)nek a label és field types kulcsai kell legyenek. Ez utóbbi ismét egy tömb, mely felsorolja, hogy az adott widgetet milyen mezőtípus(ok)nál lehet használni.

Mivel szeretnénk kiválasztani, milyen típusú tartalmakra legyen egyáltalán automatikus kiegészítés, ezért meg kell valósítanunk a hook_widget_settings($op, $widget) példányát is. Az op paraméter értéke a következők valamelyike:

  • form: egyszerű FAPI form builderként visszaad egy asszociatív tömböt: a widgetbeállító űrlap definícióját, gombok nélkül.
  • save: egyetlen tömbben visszaadja azon űrlapelem(ek) nevét, mely(ek) a beállításokat tartalmazzák.

Ha saját widgetet hozunk létre, akkor azt a Form API számára is definiálnunk kell a hook_elements() segítségével. Ez egy asszociatív tömböt ad vissza, melynek kulcsa(i) a definiálni kívánt widget(ek) gépi neve(i) (ezeknek nyilván meg kell egyezniük a hook_widget_info() kulcsaival), értéke(i) ismét asszociatív tömb(ök), mely(ek)nek leírását a Form API doksiban megtalálhatjuk. A legfontosabb a #process kulcsú tömb, mert itt meg kell adnunk (legalább) egy olyan függvényt, ami a szükséges Form API elemet előállítja nekünk. (Ne felejtkezzünk meg arról sem, hogy ha a hook_elements() segítségével egy űrlapelemet definiálunk, ahhoz a hook_theme() segítségével el kell készítenünk a megfelelő megjelenítést is.)

Hogy a widgetünk meg is jelenjen, a hook_widget(&$form, &$form_state, $field, $items, $delta = 0) használatára is szükség lesz. Ez annyira általános, hogy szinte minden CCK modulban egyforma.

Az automatikus kiegészítés beüzemeléséhez szükség lesz hook_menu() implementációra is, ezt (sok más aprósághoz hasonlóan) a már említett Autocomplete Widgets for CCK Text and Number modul alapján írtam meg. A különböző esetleges (tartalom, vagy akár mező szintű) hozzáférés-szabályozó lehetőségek miatt célszerű ezt a callbacket megvédeni egy megfelelő mechanizmussal. Mivel nem akarjuk, hogy a tartalom felvitelekor beállítható legyen a mező beviteli formája, ezért az erre vonatkozó rádiógombot eltüntetjük a widgetbeállító űrlapról egy hook_form_FORM_ID_alter() implementációval; ahhoz viszont, hogy ez megfelelően működjön, a hook_install() implementációnkban a modulunkat a CCK utánra kell súlyoznunk. Ugyanitt, valamint a hook_uninstall(), a hook_enable() és a hook_disable() implementációinkban értesíteni kell a CCK-t is a modulunk telepítéséről, törléséről, be- illetve kikapcsolásáról.

Formatter (megjelenítő)

Formattert (megjelenítőt) a hook_field_formatter_info() segítségével definiálunk. Ez egy asszociatív tömböt ad vissza, melynek kulcsa(i) formatter azonosító(k), értéke(i) ismét asszociatív tömb(ök), mely(ek)nek a label, field types és multiple values kulcsai kell legyenek. Az első érték jelenik meg a mező megjelenítésének kiválasztásakor; a második egy tömb, melyben fel kell sorolni, melyik típusú mezőkhöz lehessen ilyen formattert választani; a harmadik valószínűleg CONTENT_HANDLE_CORE lesz. Esetünkben csak 'text' kerül a field types tömbbe, hiszen nem definiáltunk saját mezőtípust, hanem csupán ehhez készítettünk widgetet és formattert. Formatter azonosítójának esetünkben nem célszerű a 'default' használata, lévén ezt a CCK text.module már definiálta, amit nem szeretnénk felülcsapni. Minden definiált formatterhez tartoznia kell egy sminkfüggvénynek ${my_module}_formatter_${my_formatter_id} névvel (ezt ne felejtsük el a hook_theme() implementációnkban sem megemlíteni, hogy a CCK-n kívül a smink réteg is tudjon róla).

Saját mezőtípus

Saját mezőtípusra nincs szükség, egyszerű szövegként tárolunk. Ha mégis volna, azt a hook_field_info() segítségével definiálunk. Ez egy asszociatív tömböt ad vissza, melynek kulcsa(i) a definiálni kívánt mezőtípus(ok) gépi neve(i), értéke(i) ismét asszociatív tömb(ök), mely(ek)nek label és description kulcsai kell legyenek.

A mezőtípus(ok) kezelését a hook_field($op, &$node, $field, &$items, $teaser, $page) végzi. Az op paraméter értéke a következők valamelyike: delete, delete revision, insert, load, prepare translation, presave, sanitize, update, validate.

Zárszó

Terveim között szerepel, hogy a tartalomcímek automatikus kiegészítése kikapcsolható legyen, és/vagy választható legyen egy tartalom típusú nézet ezek meghatározására. Bele lehet kötni abba az implementációs döntésbe is is, miért van szükség minden oldalletöltéskor újra és újra lekérdezni, hogy létezik-e már olyan címmel tartalom, amilyen szöveget megadtunk a tartalom rögzítésekor. Jobban belegondolva ennek vannak előnyei és hátrányai is; nem lenne rossz, ha ez is kapcsolható lenne – ehhez azonban nagy valószínűség szerint a CCK harmadik nagy fejezetére, a saját mezőtípusra is szükség lenne. E sorok írásáig ez nem volt még követelmény, bár magam is jogosnak vélem.

A modul – némi felhasználói leírás elkészítése után – hamarosan felkerül majd a drupal.org-ra is.

FRISSÍTVE: A mindenkori legfrissebb stabil verzió elérhető a modul drupal.org oldaláról.

CsatolmányMéret
Binary Data text_noderef-6.x-1.0.tar.gz4.12 KB
Technológia: 

Hozzászólások

Egész jó :)
Csak akkor van egy kis szívás ha megváltozik a hivatkozott tartalom címe.
Az adott feladatban emberekről van szó, és az embereknek ritkán változik a nevük. Kivéve a nőknek és a bűnözőknek. :-)

Valóban szívás, ha megváltozik a hivatkozott tartalom címe; ezen talán az segíthet, ha nem megjelenítéskor, hanem változtatáskor nézném meg a hivatkozás meglétét – ennek viszont ugye más problémája van. Egy másik webhelyen istentiszteleti helyszínekre lehet hivatkozni, amely esetben könnyen elképzelhető, hogy hamarabb tartanak istentiszteletet egy helyszínen, minthogy arról a helyszínről külön tartalmat hoznának létre – viszont jó lenne, hogy amint létrejön a helyszín tartalma, a régi istentiszteleteknél is azonnal hivatkozássá váljon az addigi egyszerű szöveg. A feladat általános megoldása tehát nehézkesnek tűnik. Ha van ésszerű javaslatod rá, megköszönnénk, és szívesen látnánk az issue queue-ban.

Ami meg a névváltozást illeti: tisztességes férfiembernek is megváltozhat a neve, pl. ha ledoktorál. ;) (Voltam már olyan közgyűlésen, ahol a cégbíróságon bejegyzett szervezetnek csak azért kellett összegyűlnie, mert a vezetője ledoktorált, és emiatt gyakorlatilag minden papírt újra el kellett készíteniük, ügyvéddel/(köz)jegyzővel láttamoztatniuk, cégbíróságra járniuk, stb.)

Irigylem az energiáidat. :)

Custom Formatters modulban írok rá egy pár sort, ami megnézi, hogy a van-e a szöveggel azonos nevű felhasználó, ha van, linkesíti.

Igazából ennél a modulnál arra voltam elsősorban kíváncsi, hogyan kell CCK-t programozni – s mint menet közben (!) kiderült, jelen feladathoz elég volt csak a widget meg a formatter. Mindazáltal ha rá is leltem volna erre a Custom Formatters modulra, akkor is csak a feladat egyik felével lettem volna meg, lévén a widgetnél akkor is meg kellett volna valósítani azt a fajta automatikus kiegészítést, amire (jelenlegi stabil formájában) az Autocomplete Widgets for CCK Text and Number nem képes.

Másik oldalról viszont jogos lenne az a felvetés, hogy ha a feladat egyik fele megoldható a Custom Formatters segítségével, akkor a másik felét miért nem küldöm be patchként az Autocomplete Widgets modulhoz. Talán egyszer ennek is eljön a napja…