Ascoltastorie

ascoltastorie100 (1)Durante la mia lunga assenza da questo blog, una delle cose che ho realizzato è il sito Ascoltastorie, dedicato a chi ama ascoltare di cultura, scienza, storia, musica, letteratura mentre si è in viaggio.

Il sito è una raccolta di file mp3 liberamente ascoltabili su internet in lingua italiana, offerti dalle principali radio nazionali (Rai, Radio 24) ed estere in italiano (RSI), ma anche da università, associazioni e singoli. Il vantaggio di questo sito è che titoli e descrizioni sono cercabili e quindi è facile trovare rapidamente una o più “storie” relative ad un argomento. Inoltre i file sono scaricabili con un click, permettendo quindi di goderne anche quando non si dispone di una connessione. Il sito è foraggiato giornalmente da una trentina di canali RSS e quindi tutti i giorni si possono trovare novità. Ad oggi ci sono circa 7500 storie, con una durata media di mezz’ora l’una.

Il sito è ottimizzato per la consultazione da smartphone, permette di commentare le storie via Facebook e di condividerle via Google+, Twitter e FB.

L’ho realizzato con Drupal 7.

 

Drupal: propagazione automatica di dati in una gerarchia

Con Drupal si possono creare vere e proprie applicazioni web based orientate alla gestione di dati, molto spesso senza scrivere un rigo di codice. Gli appunti che seguono nascono da esperimenti svolti da me, debitamente astratti per facilitarne il riuso in progetti differenti.

Data una struttura gerarchica di nodi, ognuno dotato di un dato numerico, vogliamo sommare ai livelli superiori i dati dei livelli inferiori. Ecco due possibili esempi di applicazione di questo esperimento:

gerarchia  dato da propagare 
Italia – Regioni – Provincie – Comuni numero abitanti
Casa madre – Distributore sub nazionale – Distributore regionale – Filiale locale fatturato

Vediamo come predisporre la gerarchia e, soprattutto, come istruire Drupal perché, aggiornando un valore in un nodo, questo valore si propaghi automaticamente verso l’alto.

CREAZIONE E NAVIGAZIONE GERARCHIA

Creiamo in Drupal un nuovo tipo di contenuto (es. “Filiale”) dotato di almeno due campi:

  • un campo “fatturato” di tipo decimale, che conterrà il valore del fatturato
  • un campo “superiore” di tipo entity reference che punterà alla Filiale gerarchicamente superiore

e poi creiamo tutti i nodi Filiale che ci servono, es. “Italia”, “Nord Est” (con superiore = “Italia”), “Veneto” (con superiore = “Nord Est”) ecc. Con ciò la gerarchia è pronta. Per facilitarne la navigazione suggerisco di creare, col modulo “EVA”, una vista richiamata nella visualizzazione dei nodi di tipo Filiale e che elenchi per quella Filiale tutte le sue subfiliali e i fatturati corrispondenti. L’effetto sarà il seguente:

NORD EST
Filiale superiore: Italia
Fatturato: 350.000
FILIALE
FATTURATO
Veneto
100.000
Trentino Alto Adige
200.000
Friuli Venezia Giulia
50.000

Cliccando su “Filiale superiore” si risale la gerarchia fino al nodo privo di nodo superiore (nell’esempio, il nodo “Italia”) che dovrà avere come valore del fatturato la somma dei fatturati sottostanti. Cliccando su una delle Filiali elencate, si scende di un livello nella gerarchia, spezzando il fatturato in cifre sempre più piccole e locali, operando quindi una sorta di “drill down” di analisi del fatturato. Ciò naturalmente ha senso solo se qualcosa “magicamente” tiene allineati i dati dal basso verso l’alto. Vediamo cosa.

PROPAGAZIONE DEI DATI DAL BASSO VERSO L’ALTO

In Drupal ci sono diversi modi per automatizzare la valorizzazione di un campo (es. Computed Field) o la sua sola rappresentazione (es. Views Aggregation Plus) ma volendo assicurarsi che in ogni momento i valori siano allineati ho preferito utilizzare le Rules. La soluzione consiste quindi nel scrivere una Rule che,  quando si modifica un nodo N di tipo Filiale (es. “Milano”):

  1. Identifichi il nodo S superiore al nodo N (es. “Lombardia”)
  2. Identifichi tutti i figli F del nodo S (es. “Milano”, “Bergamo”, “Brescia” ecc.)
  3. Sommi i fatturati dei figli F e scriva la somma nel fatturato del nodo S
  4. Risalga la gerarchia ripartendo dal passo 1, stavolta avendo come N il nodo S

Partendo dal nodo modificato, questa Rule aggiorna i fatturati delle filiali sovrastanti (“Lombardia” – “Nord Est” – “Italia”) fino ad arrivare al nodo apicale, dove si ferma perché non esiste il nodo S. Ovviamente questo metodo presuppone che i nodi intermedi non fatturino e che sia vietato alterare a mano i fatturati di questi nodi (la protezione del campo fatturato per questi nodi può essere realizzata in molti modi, che non affrontiamo qui).

Come si realizza una Rule di questo genere?

Purtroppo la scrittura di una Rule in Drupal non è sempre una passeggiata: le AVVERTENZE che seguono cercano di offrire un aiuto a superare ostacoli altrimenti di difficile comprensione.

Anzitutto ho scritto un “Component” di tipo “Rules” (che non è la stessa cosa che scrivere una “Rule” e già qui si capisce che muoversi nell’ambiente non è del tutto agevole….): in pratica questo tipo di Rule è una routine, con parametri di ingresso e uscita. Questa Component “CalcolaFatturato” prende come input un nodo N (il nodo di cui aggiornare il fatturato, calcolato come somma dei suoi figli) e restituisce il nodo superiore S, se esiste. Vediamo i dettagli:

  1. inizializza una variabile HaFigli= 0 (serve per sapere alla fine se il nodo N ha figli oppure no e, in caso positivo, assegnargli come fatturato la somma dei fatturati dei figli; serve per evitare di piallare il fatturato dei nodi “terminali” della gerarchia)
  2. inizializza una variabile FatturatoFigli=0
  3. esegue un ciclo sui figli F del nodo N; nel ciclo, legge il fatturato di ogni figlio F e lo somma a FatturatoFigli; mette HaFigli=1
  4. al termine del ciclo, se HaFigli=1 scrive nel campo fatturato di N il valore FatturatoFigli
  5. esamina il campo “superiore” del nodo N e ne carica il valore nel parametro di uscita S

AVVERTENZA per il passo 3: la soluzione più semplice per realizzare questo ciclo è installare il modulo “Views Rules”, che aggiunge alle Rules il ciclo di tipo “Views Loop”, che permette di fare dei cicli sui nodi risultanti da una View, in questo caso la medesima View che abbiamo visto più sopra elencare i nodi figli di una filiale

AVVERTENZA ai passi 3 e 5: perché sia possibile accedere ad un campo di un nodo, è necessario anteporre alla lettura o scrittura del campo la verifica della sua esistenza mediante una apposita condizione del tipo “Se l’entità ha il campo…”; se non si esegue questa verifica, il campo NON sarà disponibile nell’editor della Rules.  Questo è un limite delle Rules che mi ha fatto perder tempo finché non l’ho capito. Per accedere ai campi del nodo N basta quindi mettere nella sezione “condizioni” del Component le due condizioni  “L’entità N ha il campo fatturato?” e “L’entità N ha il campo superiore?”.

Il problema sorge al passo 3, dove si vuole accede al campo fatturato di diversi nodi F, non controllabili dalla sezione “condizioni” del Component in quanto sono via via forniti dalla view. La soluzione che ho trovato è eseguire il passo 3 richiamando un altro Component che, ricevuto in input il nodo F, al suo interno abbia la condizione “L’entità F ha il campo fatturato?”, acceda a quel campo e ne restituisca il valore come output. Scritto questo Component “LeggiFatturato”, il passo 3 diventa il seguente:

3. esegue un ciclo (view loop) su figli F del nodo N: nel ciclo, esegue il Component LeggiFatturato su F e somma in FatturatoFigli il valore restituito da LeggiFatturato

Scritta la Component “CalcolaFatturato” (e la sua ancella “LeggiFatturato”), completiamo l’opera scrivendo la Rule vera e propria, che a questo punto è abbastanza semplice:

Rule attivata quando viene modificato un nodo N di tipo Filiale

  1. Salva il nodo N (il motivo lo spiego dopo)
  2. Inizializza una variabile C di tipo nodo e la mette uguale a N
  3. Esegue un ciclo di tipo WHILE finché C non è nullo (per realizzare questo tipo di ciclo occorre installare il modulo “Conditional Rules”; probabilmente si può farne a meno realizzando un “loop” standard ma sono pigro e ho preferito questa soluzione più leggibile)
  4. nel ciclo, esegue il Component “CalcolaFatturato” applicato al nodo C
  5. sempre nel ciclo, assegna a C il valore S restituito da CalcolaFatturato (queto passaggio permette di risalire la gerarchia)

AVVERTENZA sul passo 1: la Rule viene attivata appena si clicca “Salva” sul nodo N, ma i nuovi valori di N (tra cui il fatturato) non vengono realmente scritti nel database fintanto che la Rule non è terminata. All’interno della Rule i valori sono giusti, ma fuori di essa no. Perciò il Component “CalcolaFatturato” lanciato dalla Rule vede ancora il vecchio valore di fatturato di N, sbagliando di conseguenza il calcolo dei fatturati dei nodi sovrastanti. Per evitare questo errore, è necessario nella Rule principale forzare il salvataggio immediato di N nel database, per essere sicuri che CalcolaFatturato veda il valore aggiornato.

Al di là del caso specifico, un bell’esercizio per capire tante cose del nostro CMS preferito.

Come modificare periodicamente gruppi di oggetti in Drupal

Più che come CMS, utilizzo Drupal come ambiente in cui sviluppare applicazioni web senza scrivere un rigo di codice (ed il fatto di riuscire ad usarlo senza scrivere codice è diventata una specie di sfida a me stesso).

Chi conosce Drupal sa che ciò è reso possibile da tre fattori principali:

  • La disponibilità di migliaia di moduli già pronti che aggiungono le più svariate funzionalità alla piattaforma
  • La possibilità di definire  nuovi tipi di oggetti (Entity) e di aggregarli in viste logiche (Views),  senza utilizzare comandi SQL
  • La possibilità di eseguire catene di azioni sugli oggetti all’occorrenza di certi eventi (Rules)

Il terzo punto è quello forse più potente ma anche quello da me finora meno esplorato, soprattutto da quando sono definitivamente passato alla versione 7 di Drupal che, proprio sulle Rules, differisce parecchio dalla precedente versione.

Grazie a DrupalizeMe, ho appena imparato (e quindi nella logica di questo sito, subito condivido) come utilizzare le Rules per controllare periodicamente e modificare insiemi di oggetti.  Un caso reale che ho risolto è chiudere automaticamente tutte le riunioni il giorno dopo la data di loro convocazione.  Dopo aver installato il modulo VBO, se non già presente, ecco come si fa:

  1. Creo un View che seleziona gli oggetti su cui intendo intervenire (nell’esempio, tutti gli oggetti di tipo Riunione con data di convocazione anteriore di 2 giorni rispetto alla data corrente ed il cui campo stato non sia già a “chiuso”). In questa View non creo una pagina o un blocco, tanto non verrà mai mostrata ed aggiungo il campo “Bulk Operation”, senza specificare quale sia l’azione da eseguire sugli oggetti selezionati.
  2. Creo un Component di Rule di tipo “Action Set” (Insieme di Azioni, nella versione italiana di Drupal), senza parametri di input
  3. Nel Component, aggiungo come prima azione “Load a list of entity objects from a VBO View” specificando come parametro la View creata al punto 1. Questa azione mette a disposizione delle azioni successive l’elenco degli oggetti da modificare, selezionati dalla View.
  4. Sempre nel Component, aggiungo come seconda azione un “Loop” e specifico come variabile del loop quella messa a disposizione dall’azione del passo 3. Questa azione serve per ripetere le azioni successive su tutti gli oggetti selezionati dalla View.
  5. Dentro il loop così creato, aggiungo le azioni che voglio eseguire sui singoli oggetti. Nel mio esempio, avevo creato una Component che, preso un nodo in input, mette il campo “Stato” a “Chiusa”.
  6. Fuori dal loop, aggiungo una azione “Pianifica la valutazione del componente”,   come componente da eseguire scelgo il Component stesso in cui è inserita, cioè il Component che ho creato al passo 2 e come temporizzazione metto “+1 day” cioè tra un giorno. In pratica, significa che il Component pianifica la riesecuzione di se stesso dopo un giorno dall’ultima esecuzione. Salvo il Component.
  7. Dall’elenco dei Component, clicco su “Esegui” a fianco del Component appena creato: in questo modo avvio il ciclo di esecuzioni del Component, che proseguirà senza interruzioni ogni giorno.  Sotto “Pianificazioni”  viene aggiunta una riga che informa quando avverrà la prossima esecuzione del Component.

I passi da 1 a 5 contengono la logica di selezione degli oggetti e le azioni da eseguire su di essi. I passi 6 e 7 garantiscono l’esecuzione automatica quotidiana delle azioni descritte ai passi precedenti.

E siccome una figura vale più di 100 parole, ecco lo screenshot del Component che ho creato seguendo questa procedura:

Clicca per ingrandire
Clicca per ingrandire

Drupal 7: gestione note spese

Io amo Drupal perchè, diversamente da quasi tutti gli altri CMS, consente di costruire applicazioni internet “guidate dai dati” strutturati anziché da semplici contenuti “destrutturati” (come articoli e pagine). E (quasi) sempre senza scrivere una riga di codice.

Come esempio, proviamo a costruire la gestione delle Note Spese. Semplificando un po’, una Nota Spese è una entità formata da una intestazione (descrizione, data di presentazione, richiedente, luogo ecc.) e da un numero arbitrario di righe (che chiamerò “Spesa”), ognuna delle quali formata da diversi campi: descrizione, tipologia (es. “vitto”, “alloggio”), valore della spesa, valore del rimborso richiesto ecc.

Questo modello a due livelli (1 intestazione + molte righe) è comune a molti altri casi reali (es. ordini di acquisto, fatture) e quindi è di particolare interesse. Può essere costruito in Drupal (6 o 7) creando due tipi di contenuto (“Nota Spesa” e “Spesa”) legandoli tra loro con una delle seguenti soluzioni:

  • aggiungere al modello”Nota Spese” un campo (di tipo “Node Reference”) che punta a entità di tipo “Spesa” e dichiarare che questo campo può accogliere un numero arbitrario di Spese. Questa soluzione richiede però di inserire prima le singole Spese e poi di collezionarle nel campo della Nota Spese. Questa artificiosità di inserimento può essere parzialmente superata utilizzando moduli appositi (es. “Add and Reference“) che, mentre si modifica una Nota Spese, consentono di creare al volo le Spese e collegarle alla Nota Spese stessa.
  • aggiungere al modello”Spesa” un campo (di tipo “Node Reference”) che punta a entità di tipo “Nota Spese”. Questa soluzione permette un inserimento più intuitivo (prima si inserisce la Nota Spese e poi le singole Spese) ma, ad ogni inserimento di nuova Spesa, bisogna riselezionare la Nota Spese giusta. Questo fastidio può essere ovviato con moduli (es. “URL Fill“) che “precaricano” il campo legame in modo che punti alla Nota Spese voluta.

Entrambe le soluzioni presentano perciò alcuni problemi di usabilità, risolvibili con parecchio sforzo di configurazione. Drupal 7 offre una soluzione molto simile ma più semplice da realizzare, grazie al modulo “field_collection“. Questo modulo (purtroppo non disponibile per Drupal 6) aggiunge un nuovo tipo di campo, “field collection” che a sua volta è formato da diversi campi. Nel nostro esempio, agiungeremo perciò un campo “field collection” di nome “Spesa” al modello Nota Spese come nella soluzione 1; la novità vera è che la creazione e la modifica di un campo field collection (compresi quindi i suoi campi) avviene dentro la medesima maschera in cui si crea / modifica la Nota Spese (cliccare sulle figure per ingrandirle):

Così pure la visualizzazione della Nota Spese mostra anche le Spese, permettendo anche di modificarle al volo senza rimodificare l’intera Nota Spese:

Anche le Viste (“Vews” di Drupal) lavorano bene coi field_collection, mostrando l’intera struttura delle Spese come fosse un singolo campo della Nota Spese:

Non solo: siccome le singole Spese sono in realtà archiviate in Drupal come entità separate, con un piccolo trucco è possibile richiamarle in una Vista indipendentemente dalla Nota Spese cui si riferiscono; si può così ad esempio costruire una Vista – utile a chi deve autorizzare i rimborsi – che analizza le singole richieste di rimborso per tipologia (es. solo le spese di viaggio):

Naturalmente, per avere una applicazione completa mancano parecchi dettagli, ma la struttura fondamentale c’è tutta ed è realizzabile in un paio d’ore di lavoro, avendo un po’ di dimestichezza con Drupal. Per chi volesse replicare questo esperimento, ho utilizzato Drupal 7 e i moduli aggiuntivi:

La struttura “Nota Spese” è la seguente (si noti il campo “Spesa” definito come “field_collection”, questo è il passaggio fondamentale):

La struttura “Spesa” la si definisce nella nuova sezione  “field_collection”:

La Vista che elenca la Nota Spese è banale: è una Vista che elenca le entità di tipo “Nota Spese” in forma tabellare, dove basta aggiungere alle colonne il campo “Spesa” (indicato dal cursore) per ottenere la visualizzazione completa delle Spese associate alla Nota Spesa:

Meno banale la Vista che elenca le singole Spese: come per la precedente, si parte da una Vista che elenca le Note Spese, cui si aggiunge la “relazione” sul campo Spesa dell’entità Nota Spese (mostrata dal cursore nella figura che segue). Grazie a questa aggiunta, si rendono disponibili per le colonne della Vista tutti i campi delle entità Spesa (che iniziano con “field collection item”):

Per chi vuole giocare con Drupal 7 sul proprio pc consiglio l’applicazione AMPPS che facilita enormemente l’installazione di Drupal (e di altre 200 applicazioni open source a scelta).

Eventi live in un sito Drupal 7

La versione 7 di Drupal è decisamente un grande passo avanti nella storia del mio CMS preferito. Purtroppo, molti dei moduli non sono ancora disponibili per questa versione e quindi spesso occorre arrangiarsi, trovando soluzioni nuove a problemi già risolti nella versione 6.

Uno dei moduli non ancora del tutto portati alla versione 7 è Media, che facilita l’inclusione di video, audio e foto dentro i siti Drupal. In particolare, non è stato portato l’adattatore di Media per Ustream, la piattaforma gratuita di braodcasting audio e video di eventi live. Con Ustream ed un portatile dotato di webcam e connessione internet di buona qualità è possibile riprendere eventi come incontri, convegni, partite e trasmetterle via internet in tempo reale all’interno di siti costruiti con WordPress e Drupal.

Per ovviare a questo problema, è possibile utilizzare il codice di embed fornito da Ustream insieme ad ogni canale attivato. Il codice si presenta in questo modo:

< object classid=”clsid:d27cdb6e-ae6d-11cf-96b8-444553540000″ width=”480″ height=”296″ id=”utv898632″><param name=”flashvars” value=”autoplay=false&amp;brand=embed&amp;cid=8847003&amp;v3=1″/><param name=”allowfullscreen” value=”true”/><param name=”allowscriptaccess” value=”always”/><param name=”movie” value=”http://www.ustream.tv/flash/viewer.swf”/><embed flashvars=”autoplay=false&amp;brand=embed&amp;cid=8847003&amp;v3=1″ width=”480″ height=”296″ allowfullscreen=”true” allowscriptaccess=”always” id=”utv898632″ name=”utv_n_489720″ src=”http://www.ustream.tv/flash/viewer.swf&#8221; type=”application/x-shockwave-flash” /></object><br /><a href=”http://www.ustream.tv/&#8221; style=”padding: 2px 0px 4px; width: 400px; background: #ffffff; display: block; color: #000000; font-weight: normal; font-size: 10px; text-decoration: underline; text-align: center;” target=”_blank”>Broadcasting live with Ustream</a>


Se però ci si limita a incollare questo codice dentro una pagina “full html” di Drupal, non funziona, probabilmente per qualche vincolo sulla sintassi html accettata da Drupal 7. Fortunatamente, ho trovato il modo di risolvere questo inghippo: installato il modulo Wysiwyg e TinyMCE ed attivato sul profilo “full html” il bottone “Media”, ho incollato il codice dentro il tab “Source” swlla finestra “Insert/embed Media”. Questo passaggio riscrive automaticamente il codice in quest’altra forma più semplice:

<object id="utv304648" data="http://www.ustream.tv/flash/viewer.swf" type="application/x-shockwave-flash" width="480" height="296"><param name="allowfullscreen" value="true"><param name="allowscriptaccess" value="always"><param name="src" value="http://www.ustream.tv/flash/viewer.swf"><param name="flashvars" value="autoplay=false&amp;brand=embed&amp;cid=8847003&amp;v3=1"></object>

Questo secondo codice funziona! E’ perciò possibile includere la trasmissione di eventi live in un sito costruito con Drupal 7 pur di trasformare il codice di embed fornito da Ustream seguendo l’esempio sopra mostrato.

A scuola di Drupal: automatizzare il sito con regole condizionali

Mi appunto qui per esperimenti futuri. Il modulo Rules di Drupal consentono di definire (senza programmare) azioni che vengono eseguite automaticamente dal sito quando accadono eventi quali il logon di un utente, la pubblicazione di un contenuto, una scadenza temporale ecc. Le Rules possono essere anche condizionate dal controllo di valori dei campi (se si è installato il modulo CCK). Si possono definire regole che sono di fatto delle subroutine cui passare parametri prima che vengano eseguite. Grazie ad un altro modulo (VBO) si può dare in pasto ad una regola un insieme di oggetti (o utenti) filtrati da una “vista” Drupal. Rules è quindi un modulo che permette di automatizzare il comportamento di Drupal. Questo video è una ottima introduzione alle Rules:

A scuola di Drupal: proteggere i contenuti per categoria

Drupal è un sistema per costruire siti internet ed intranet dinamici e capaci di svolgere un sacco di funzioni. In Drupal l’informazione è divisa in “nodi”:  un nodo è una notizia, una pagina, un evento, una persona, un libro… Notizia, pagina, evento sono diversi “tipi” di nodi. A loro volta gli utenti sono raggruppati in “ruoli”. E’ possibile configurare Drupal in modo che gli utenti che hanno un certo ruolo vedano i nodi di un certo tipo e non altri tipi (es. i “ragazzi” possono leggere i “libri” ma non possono vedere i “film”). Un limite di Drupal è che non è possibile dire “i ragazzi possono vedere “Nemo” ma non possono vedere “Hannibal the Cannibal”: o vedono tutti i flim o non ne vedono nessuno.

Il modulo TAC_Lite illustrato in questo video supera questo limite di Drupal, permettendo di definire quali ruoli possono vedere quali “categorie” (in Drupal le categorie si possono definire ed assegnare liberamente ai nodi). Grazie a questo modulo quindi basterà: creare le categorie “cartone animato” e “horror”; dichiarare che “i ragazzi possono vedere i cartoni animati ma non gli horror”; assegnare al film “Nemo” la categoria “cartone animato” e al fim “Hannibal” la categoria “Horror” ed il filtro è fatto.

.

Naturalmente lo stesso meccanismo si può usare per realizzare filtri basati su altre caratteristiche dei nodi, ad esempio sullo “stato” dei nodi invece che sul loro contenuto: un utente di ruolo “revisore” potrà vedere i nodi categorizzati come “bozza” mentre un un utente “lettore” potrà vedere solo quelli “approvati” e così via.

Drupal il CMS che preferisco

Ok, non sarà elegante e generoso parlare bene di Drupal mentre sono ospitato da un concorrente con WordPress ma lo faccio lo stesso per tre buoni motivi: (a) Drupal è troppo bello per non parlarne bene e condividerlo con gli altri (b) WordPress è nato ispirandosi a Drupal (c) Drupal e WordPress non sono realmente concorrenti, essendo il primo una piattaforma generale di costruzione di siti internet mentre il secondo è principalmente un gestore di blog.

Per ora mi limito a pubblicare alcuni video introduttivi (ma piuttosto tecnici) su Drupal che ho appena scoperto, anzitutto per non dimenticarmeli e poi perché quando avrò tempo avrei intenzione di parlare un po’ diffusamente di questo spettacolare software open source.

Qui sotto vedete il primo video, per gli altri andate direttamente sul sito LearnByTheDrop