Most, hogy gőzerővel készülök az Integral Vision Workshop rendezvénysorozatunkra, úgy gondoltam megosztok egy pár érdekességet, gondolatot a Drupal 7 verziójáról.

Első körben beszéljünk az entitásokról.

A Drupalban eddig mindenki tudta, hogy ha tartalom kezelésről volt szó, akkor azt a legkönnyebben a nodeok segítségével tudta megoldani. Az elgondolás lényege az volt, hogy adott a node, melyet a különböző modulok adatelemekkel és funkciókkal tudnak bővíteni. Ez nagyszerű volt, hisz ha volt egy oldal típusú tartalmam, vagy egy hír típusú, akkor ha az egyikhez megírtam a hozzászólás funkciót akkor az a másikkal is működött. Csak arra kellett figyelnem, hogy ezt úgy tegyem meg, hogy azt a típus nélküli nodehoz írjam meg. Ettől fogva a hírhez is és az oldalhoz is hozzá tudtam szólni, hisz mindkettő node volt. Sőt, amennyiben létrehoztam egy új tartalom típust, mondjuk képet, vagy képgalériát, akkor már azokhoz is igénybe vehettem ezt a nagyszerű szolgáltatást.

Azonban, maradt számos olyan tartalmi elemem, melyek nem voltak nodeok. Ilyenek voltak a kategóriák, a hozzászólások, felhasználók stb. Amennyiben ezekhez is igénybe kívántam venni azokat a szolgáltatásokat amiket a nodeokhoz kidolgoztak, trükköznöm kellett. (Ilyen szolgáltatás volt például az, hogy az adott tartalmi elemhez újabb mezőket adjak hozzá, vagy megjelenítsem egy listában. Vagyis a CCK és Views modul)

A legalapabb trükk az volt, hogy az adott adatelemből nodeot gyártottunk. Ezzel aztán meg is oldottuk a problémánkat. Amennyiben társkereső oldalt akartunk készíteni, semmi más dolgunk nem volt, mint feltenni a Usernode(4.7.x, 5.x), vagy Content Profile(6.x) modulok egyikét. Ekkor minden egyes felhasználóhoz létrejött egy megfelelő típusú node. Semmi mást nem kellett tennünk, mint felvenni egy újabb CCK választó mezőt, melyben bejelölhették a delikvensek, hogy ők a focit szeretik vagy a baseballt és egy ügyes views lista segítségével már egymásra is találtak.

Azonban bármilyen szépen működött is ez a dolog, volt pár árnyoldal.

Először is, mivel két külön adattáblába, két külön modul írogatta azokat az adatokat amelyeket egy táblában kellett volna tárolnunk, igen magasra szökött az inkonzisztencia veszélye. Keletkeztek olyan felhasználók, akikhez nem tartozott node és keletkeztek olyan user nodeok, amikhez nem tartozott felhasználó. Amennyiben nem figyeltünk oda, könnyedén létrehozhattunk egy felhasználóhoz több tartalmat is. Egyszóval, volt egy olyan szuper bárhogyan konfigurálható rendszerünk amihez igazából jobb volt, ha nem nyúltunk hozzá.

A másik probléma ezzel a megoldással, hogy ha kevés hírünk volt, de sok felhasználónk, akkor is keményen dolgozott az adatbázisunk, hisz a hírek megjelenítéséhez először ki kellett szűrnie a felhasználókat az adattáblából és csak utána tudta rendezni és kilistázni a híreinket. Amint egyre több és több felhasználónk lett, úgy lett egyre nehezebb és nehezebb kilistázni a híreinket.

A „Csináljunk mindenből nodeot” megoldásnak ezen felül még volt egy árnyoldala. A node számos olyan frankó funkcióval rendelkezett, amire nem minden esetben lett volna igényünk. Ilyen szolgáltatások voltak azok, hogy egy node az verziókezelt, lehetett tudni melyik tartalmat melyik felhasználó látta már, lehetett szabályozni különböző szempontrendszerek szerint, hogy mely tartalmat mely felhasználó nézhess stb. Egyszóval számos olyan, ami egy tartalom kezelésekor jól jött de nem igazán volt szükségünk akkor erre, ha mondjuk felhasználókról, vagy csoportokról volt szó.

Drupal hetesben bevezetésre került az entitás fogalma, melyet egy node feletti egységként kéne elképzelni. Így lehetővé vált az, hogy a megvalósítani kívánt funkcióknál eldönthessük, hogy az melyik tartalmi szinten lesz számunkra érdekes. Ezek egy részét ráadásul az entitás létrehozásakor mi magunk is szabályozhatjuk. Pl. azt, hogy lehessen-e hozzá mezőket kapcsolni vagy legyen-e verziókezelt.

Minden entitásnak vannak olyan altípusai – úgynevezett bundle –, melyekhez a FieldAPI segítségével különböző mezőcsokrokat kapcsolhatunk. A node-nál ez a node típus, a kategóriáknál a szótár a felhasználóknál meg a … hopp és itt a rés a pajzson, mert nincsenek a felhasználónak altípusai. Természetesen, nem lenne Drupal a Drupal, ha nem lenne egy alter hook amivel ne lehetne ezen a szörnyű helyzeten is változtatni.

De ne szaladjunk ennyire előre, ezt majd a workshopon. Készítsünk egy olyan Drupal 7 modult, ami egy olyan pehelysúlyú tartalmi elemet – egy entitást – valósít meg, mely semmi más mint egy darab táblában egy darab mező. Nézzük az én megoldásomat!

Először is kelleni fog egy info fájl:

name = Entity Próba
core = 7.x
files[] = entity_proba.module
files[] = entity_proba.test

Figyeljük meg, hogy a hetesben meg lehet adni az info fájlban, hogy a modulunknak melyik fájlokra lesz majd szüksége. Az .install fájl nem szerepel a listában, hisz a benne található kódokra csak akkor van szükség, amikor először bekapcsoljuk a modult, vagy eltávolítjuk. Itt fogjuk megadni az adatbázis séma definicíóját:

function entity_proba_schema() {
  $schema['entity_proba'] = array(
    'description' => 'The base table for entitys.',
    'fields' => array(
      'epid' => array(
        'description' => 'The primary identifier for a Entity proba.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
     'title' => array(
        'description' => 'The title of this entity.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
    ),
    'primary key' => array('epid'),
  );
  return $schema;
}

Mint látható, egyetlen egy táblát hozunk létre, melyben két mező van. Az epid, amely az egyedi kulcsa lesz az egyes soroknak és a title amiben a tulajdonképpeni adatot fogjuk tárolni. No akkor nézzük a modult:

function entity_proba_entity_info() {
  $return = array(
    'entity_proba' => array(
      'label' => t('Entity Próba'),
      'base table' => 'entity_proba',
      'entity keys' => array(
        'id' => 'epid',
        'label' => 'title',
      ),
    ),
  );
  return $return;
}

Egyetlen egy hookot valósít csak meg a modulunk, ez pedig a hook_entity_info(). Ennek a segítségével tudjuk megadni, hogy milyen entitást vagy entitásokat valósít meg a modulunk. Mivel ez egy kis tanuló modul, ezért csak egyetlen egy entitást valósítunk meg, annak is csak a legminimálisabb adatait adjuk itt meg. Pont annyi adatot, amennyivel a táblában található adatokat az entity_load() függvény segítségével be lehet majd tölteni.

Felmerülhet bennünk a kérdés, hogy hogyan tudjuk ezt kipróbálni, hogyan bizonyosodunk meg arról, hogy ez helyesen működik, vagy működik-e egyáltalán. Erről lesz szó holnap. Addig is a csatolt modult lehet nézegetni, módosítani, próbálgatni.