node_save() e drupal_execute()

8 contenuti / 0 new
Ultimo contenuto
node_save() e drupal_execute()

ho sviluppato un semplice modulino che non fa altro che passare alcuni campi nodereference da un nodo all'altro in base a certe condizioni.
Il modulo utilizza hook_nodeapi ed interviene all'update del nodo.
Su d.o. ho imparato che in queste condizioni (cioè se si modifica un nodo programmaticamente) è sempre meglio utilizzare drupal_execute() piuttosto che node_save() perchè la prima funzione compie tutto il processo di validazione prima di salvare, mentre la seconda salva e basta.
Ora, siccome il mio modulo non fa altro che passare dei nid da un nodo all'altro e questi sono immessi dall'utente attraverso i widgets di nodereftrence cck e non direttamente, ho optato per node_save().
Domanda: è in qualche modo meno sicuro? potrei espormi a ulteriori problemi?
Grazie!

<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
ho sviluppato un semplice modulino che non fa altro che passare alcuni campi nodereference da un nodo all'altro in base a certe condizioni.
Il modulo utilizza hook_nodeapi ed interviene all'update del nodo.

Mannaggia, se impari anche a programmare, nessuno ti fermi più...

<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
Su d.o. ho imparato che in queste condizioni (cioè se si modifica un nodo programmaticamente) è sempre meglio utilizzare drupal_execute() piuttosto che node_save() perchè la prima funzione compie tutto il processo di validazione prima di salvare, mentre la seconda salva e basta.

Logica imbattibile - presumendo che controllano se ci sono stati errori di validazione...
Per esempio: http://drupal.org/node/115522 Vedi i controlli? Neanch'io. Povero form_get_errors()
Almeno Eaton lo spiega bene in http://www.lullabot.com/articles/quick_and_dirty_cck_imports e nei commenti.

<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
Ora, siccome il mio modulo non fa altro che passare dei nid da un nodo all'altro e questi sono immessi dall'utente attraverso i widgets di nodereftrence cck e non direttamente, ho optato per node_save().
Domanda: è in qualche modo meno sicuro? potrei espormi a ulteriori problemi?
Grazie!

Fai questi due domande:

  1. E' possibile sbagliare questi campi nel form 'sorgente'?
  2. E' possibile che questi campi nel form 'sorgente' sono sbagliati per il form 'destinazione'?

Se rispondi no e no - allora node_save(), perchè più semplice, più efficace, e perchè sei sicuro che è, er, sicuro. Altrimenti drupal_execute().

Ma... Attenzione dove fai l'operazione. Saltiamo la fase di creazione di questi due nodi (come hai fatto tu nella domanda), per guardare la fase update.

Se hai concluso che node_save() va bene, allora va bene intercettare node_api(update), perchè l'intervento sta nella fase di salvataggio.

Se invece devi usare drupal_execute(), le cose si complicano perchè sei nella fase di validazione del form:

  1. Devi 'intercettare' la chiamata al validate 'originale'
  2. Chiamare il validate originale
  3. Se non ci sono errori:
    1. copiare i campi
    2. chiama drupal_execute() per il form 'destinazione'
  4. E basta - il precedente codice salverà il nodo 'originale', o se fermerà prima se c'erano errori

Non ho guardato, ma immagino che il codice in CCK fa qualcosa del genere per intervenire su node.

Più imparo, più dubito.

Grazie John, consigli preziosi come al solito!

Quote:
Mannaggia, se impari anche a programmare, nessuno ti fermi più...

Non ho imparato a programmare, ho imparato a copiare...
Quote:
Almeno Eaton lo spiega bene in http://www.lullabot.com/articles/quick_and_dirty_cck_imports e nei commenti.

...e non copio neanche tanto bene, visto che ho studiato quell'articolo da cima a fondo ma non mi sono accorto del punto 2 di questo commento
Quote:
Fai questi due domande:
1. E' possibile sbagliare questi campi nel form 'sorgente'?
2. E' possibile che questi campi nel form 'sorgente' sono sbagliati per il form 'destinazione'?

No e no perchè il widget di immissione dati può essere solo noderef url (e quindi il nid è caricato automaticamente e non modificabile in node form) o nodereference create* (e quindi, se il nodo da referenziare non esiste, viene creato).
In aggiunta, ogni campo nodereference ha una sua controparte (un altro nodereference) nel nodo di destinazione, e le due (ref/backref) sono mantenute in sync da backreference. e quindi il tutto è abbastanza blindato.

Un'ultima domanda: potrei eseguire il mio modulo anche quando $op == 'insert'; ovvero alla creazione del nodo?

Ri-grazie!

a cosa serve precisamente questo modulo bohz? esempio pratico

agli ordini.
supponi di avere tre tipi di nodo:

  • artista
  • album
  • brano

supponi che gli utenti possano inserire solo album associati ad un artista e che nella form del tipo album possano inserire /aggiungere brani;
il mio modulo (assieme agli altri citati) fa in modo che al salvataggio del nodo album:
il nodo artista contenga tutti gli album E i brani associati;
il nodo album contenga l'artista E i brani associati
il nodo brano contenga l' album e artista associati.
in pratica uso i nodi come campi

<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
Non ho imparato a programmare, ho imparato a copiare...

Ma anche a 'leggere' il codice - già un passo importante direi.
<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
...e non copio neanche tanto bene, visto che ho studiato quell'articolo da cima a fondo ma non mi sono accorto del punto 2 di questo commento

Eh si, avrei dovuto mettere il link al commento giusto io. Comunque hai superato la prova ;-)
<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
...In aggiunta, ogni campo nodereference ha una sua controparte (un altro nodereference) nel nodo di destinazione, e le due (ref/backref) sono mantenute in sync da backreference. e quindi il tutto è abbastanza blindato.

Bene, adesso che hai sufficiente corda, non rimane altro che...
<a href="mailto:[email protected]" rel="nofollow">[email protected]</a> wrote:
Un'ultima domanda: potrei eseguire il mio modulo anche quando $op == 'insert'; ovvero alla creazione del nodo?

Perchè lasciamo sempre la domandina 'facile' per ultima?

Allora dal modello che hai descritto ad asdomar, esiste già un artista (magia), ma l'utente può inserire un album e da li un brano. Presumo:

  1. Se sta creando un'album, da qualche parte ha specificato l'artist(s)?
  2. Se sta creando un brano, da qualche parte ha specificato l'artist(s) e album(s)

Ho messo il plurale per rendere la tua vita più difficile avvicinare il problema alla realtà - ci sono album con più di un'artist, e lo stesso brano (remix?) su più album...

Nella maggioranza dei sistemi, un nuovo record (ancora da salvare) non ha ancora un identificatore - perchè fornito dal DBMS. Ma guardando il codice di node_save() (modules/node/node.module: 857) vedo che Drupal usa un trucco: prima salva il nodo 'base', quindi prende il nid, poi chiama 'insert'. Thought you'd like to know.

Ti servirà un po di codice in più, ma e possibilissimo:

  1. Prendi un riferimento al artist/album
  2. Carica l'artist/album dal riferimento
  3. Inserire il riferimento inverso (nuovo campo CCK)
  4. Salvare l'artist/album
  5. Wash, rinse, repeat (finchè non ci sono più riferimenti da controllare nella lista - plurale)

Il punto 3/4 è il più delicato, perchè bisogna vedere (cioè testare il codice) se aggiungendo il nuovo campo nel node è sufficiente per salvarlo tramite CCK e node_save() - altrimenti sarà necessario seguire la pista di drupal_execute()...

OT: Questo (abbastanza breve) video tutorial dimostra come si usa un modulo (che non mi ricordo più il nome - ecco perchè odio i video) per 'spingere' l'utente da un nodo contenitore ad uno contenuto, ovviamente fornendo i rifierimenti in automatico. E' per una galleria d'immagini (pensiero originale) ma nella pagina Gallery c'è già il bottone 'Add Image' - che è un altro nodo di tipo diverso. Sostituisci Gallery/Artist/Album e Image/Album/Brano e credo che potrebbe essere utile per te (se non l'hai già fatto).
La cosa che mi piaceva di questo modello è che puoi spostare un immagine da una galleria ad un altro (o entrambi) - molto più potente dei banali esempi in circolo, ed anche nei libri...
Ma momento - forse non ti serve scrivere codice dopo tutto?

Più imparo, più dubito.

Non ci ho pensato a fondo, ma… per il problema di Bohz non bastava combinare nodereference e nodereferrer?

@pinolo: si. ed infatti avevo iniziato così. ma ci sono alcuni vantaggi di usare backreference in particolare il fatto che non c'è differenza tra tipoA->tipoB e tipoB->tipoA (sono entrambi nodereference) ed un po più di flessibilità in views; e poi mi piace l'idea della tabella di simmetria nodi che implementa backreference (anche se ha un paio di serious bugs).
poi, anche con nodereferrer quando creo un tipoA che ha riferimenti a tipoB e tipoC, li riferimenti B->C e C->B non vengono creati...quindi il mio stupido* modulo lo avrei dovuto fare lo stesso (o no?);
*) dico "stupido" perchè i nomi dei campi sono hardcoded; ho avuto difficoltà ad astrarre la cosa e a implementare un'interfaccia di controllo lato admin... :(