Sviluppare un'estensione in Contao - Seconda parte

08/01/2011 22:15

Questa è la traduzione del tutorial Create a custom Contao module.


Per errori nella traduzione o incomprensioni della guida, contattatemi nel forum dove mi trovate con il nickname paplo.

DCA

In questa parte della guida, vi mostrerò come creare la parte più importante del nostro modulo - i Data Container Array. A colpo d'occhio, è un array di configurazione della tabella, che dice a Contao come realizzare il modulo backend.

Proprio come i file di configurazione, i DCA vengono caricati quando Contao viene inizializzato. Questo consente di sovrascrivere le impostazioni predefinite di altri moduli. Come sapete dalla prima parte della guida, i moduli vengono caricati in ordine alfabetico. Così, se si desidera aggiungere un nuovo campo al modulo News, non è necessario modificare alcun file del modulo esistente.

Struttura del file

Il file DCA deve trovarsi nella cartella /cd_collection/DCA/ e avere lo stesso nome della tabella definita nella configurazione del modulo:
// Back end module
array_insert($GLOBALS['BE_MOD']['content'], 3, array
(
  'cd_collection' => array
  (
    'tables' => array('tl_cds_category', 'tl_cds'),
    'icon'   => 'system/modules/cd_collection/html/icon.gif'
  )
));

Creiamo due file, che ci serviranno in seguito, chiamati tl_cds_category.php e tl_cds.php nella cartella DCA.

All'interno del DCA

L'array DCA ha solitamente questa struttura:

<?php

$GLOBALS['TL_DCA']['tl_table'] = array
(

  'config' => array
  (
    // dca config settings go here
  ),

  'list' => array
  (
    // all settings that are applied to records listing
    // we can define here: sorting, panel layout (filter, search, limit fields), label format, global operations, operations on each record
  ),

  'palettes' => array
  (
    // palettes settings
  ),

  'fields' => array
  (
    // fields that are visible in back end form
  )
);

?>


Come potete vedere si tratta di una grande matrice nidificata. Nella prima parte, la chiave 'config', sono presenti le impostazioni di base come il tipo di contenitore dei dati oppure le tabelle (padre/figlio). La chiave 'list' dell'array è di solito divisa in quattro sezioni: sorting, label, global_operations, operations. Ognuna di loro è a sua volta un'array. Successivamente si trovano le palettes, la chiave 'palettes', - una palette definisce l'ordine di visualizzazione dei campi del modulo, ma permette anche di raggrupparli in sezioni (disponibile dalla versione 2.7.0). Infine, è presente l'elenco dei campi, la chiave 'fields', che contiene le informazioni sul tipo dei campi e le regole per la validazione.

Tutte le opzioni di configurazione sono disponibili sul sito ufficiale.

Questo è tutto sulla teoria, è l'ora di sporcarsi le mani!

Configurazione del DCA per la tabella tl_cds_category

Apriamo tl_cds_category.php e aggiungiamo il seguente codice:
<?php

$GLOBALS['TL_DCA']['tl_cds_category'] = array
(

  // Config
  'config' => array
  (
    'dataContainer'               => 'Table',
    'ctable'                      => array('tl_dcs'),
    'switchToEdit'                => true
 ),
//...

Come contenitore dei dati abbiamo scelto la tabella del database tl_cds_category.

La chiave 'ctable' definisce la tabella o le tabelle che sono figlie di tl_cds_category. Nella prima parte della guida, abbiamo affermato che tl_cds è figlia di tl_cds_category.

La chiave 'SwitchToEdit', se impostata a true, attiva il pulsante "salva e modifica" quando si aggiunge un nuovo record:



Tuttavia, questo pulsante è disponibile solo quando la modalità di ordinamento è la 4.

La chiave 'list' del DCA

La chiave 'list' è utilizzata per la pagina iniziale del nostro modulo. Il suo scopo è di creare l'interfaccia utente e di fornire l'elenco dei record. Si compone di quattro array che vedremo tra un attimo. Nel frattempo vi consiglio di aprire la guida dello sviluppatore per capire meglio di cosa sto parlando.

L'array sorting (ordinamento)

Il primo array è chiamato 'sorting'. Come evidenzia il nome, viene utilizzato per definire la visualizzazione dei record. Inserisci nel file il codice riportato di seguito:
  // List
  'list' => array
  (
    'sorting' => array
    (
      'mode'                    => 1,
      'fields'                  => array('title'),
      'flag'                    => 1,
      'panelLayout'             => search,limit'
    ),
//...

Se 'mode' è impostato a 1 stabilisce che i record siano ordinati in base ad un campo fisso, che è definito nella riga successiva. Nel nostro codice abbiamo scelto di ordinare in base al titolo della categoria. La chiave 'flag' dice come deve essere ordinato; 1 significa 'ordina per la lettera iniziale in modo ascendete' - in altre parole, in ordine alfabetico. Alla fine dell'array definiamo l'intestazione della tabella, che prevede un modulo di ricerca, un filtro e un menu per limitare il numero di record.

L'array label (etichetta)

L'array 'label' è anch'esso figlio della chiave 'list' ed è usato per definire il formato dell'etichetta dei record. E' possibile utilizzare una sintassi simile alla funziona php sprintf(). Esempio: sprintf(format, fields)

Incolla il seguente codice:

    'label' => array
    (
      'fields'                  => array('title'),
      'format'                  => '%s'
    ),
//...

Spero che questo codice sia chiaro. Semplicemente dico che intendo utilizzare il campo 'title' della tabella e visualizzarlo nel formato della riga sottostante.

L'array global_operations (operazioni globali)

... Sono le funzioni che possono essere applicate a più record contemporaneamente. Un esempio perfetto è la funzione di modifica multipla, che implementeremo nel nostro modulo:

    'global_operations' => array
    (
      'all' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['MSC']['all'],
        'href'                => 'act=select',
        'class'               => 'header_edit_all',
        'attributes'          => 'onclick="Backend.getScrollOffset();"'
      )
    ),
//...

L'array operations (operazioni)

Questo array contiene tutte le operazioni che si possono eseguire su ogni record. Aggiungi questo codice:
    'operations' => array
    (
      'edit' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds_category']['edit'],
        'href'                => 'table=tl_cds',
        'icon'                => 'edit.gif',
      ),
      'copy' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds_category']['copy'],
        'href'                => 'act=copy',
        'icon'                => 'copy.gif',
      ),
      'delete' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds_category']['delete'],
        'href'                => 'act=delete',
        'icon'                => 'delete.gif',
        'attributes'          => 'onclick="if (!confirm(\'' . $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\')) return false; Backend.getScrollOffset();"',
      ),
      'show' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds_category']['show'],
        'href'                => 'act=show',
        'icon'                => 'show.gif'
      )
    )
  ), // end of list array
//...

Credo che il codice si spieghi da sé. Abbiamo aggiunto quattro funzioni base che ritroveremo in quasi tutti i moduli di Contao.

Si noti che l'array 'edit' come valore della chiave 'href' accetta altri valori oltre al nome della tabella, e questo perchè noi usiamo 2 tabelle nel modulo. Così, quando si fa click sul tasto 'modifica', andremo alla lista dei record della tabella tl_cds!




L'array palettes

L'array 'palettes' definisce come deve essere presentato il form del modulo. Dalla versione 2.7 è possibile raggruppare i campi in sezioni, per migliorare l'usabilità.
  // Palettes
  'palettes' => array
  (
    'default'                     => '{title_legend},title,description'
  ),
//...

Come si può intuire, la palette principale è visualizzata per default.

La palette è una stringa con i nomi dei campi, che sono concatenati o con un punto e virgola (;) o con una virgola (,). La virgola è utilizzata solo per separare i nomi dei campi, il punto e virgola, invece, indica l'inizio di un insieme di campi ('fieldset').

Le legende (quei gruppi di campi espandibili e chiudibili) devono essere sempre racchiusi tra parentesi - esattamente come {title_legend}. Vedere l'immagine per capire meglio:

L'array fields (campi)

Gli array sovrastanti possono essere copiati ed incollati (con alcune piccole modifiche) in uno qualsiasi dei nostri moduli, ma i campi devono essere sempre univoci per ogni modulo e devono essere creati manualmente. Inserite il codice seguente:
  // Fields
  'fields' => array
  (
    'title' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds_category']['title'],
      'inputType'               => 'text',
      'search'                  => true,
      'eval'                    => array('mandatory'=>true, 'maxlength'=>64)
    ),
    'description' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds_category']['description'],
      'inputType'               => 'textarea',
      'eval'                    => array('rte' => 'tinyFlash')
    )
  )
); // end of $GLOBALS['TL_DCA']['tl_cds_category'] array

?>
Secondo la tabella del nostro modulo, abbiamo bisogno di due campi: titolo e descrizione. Ora una piccola spiegazione per ciascuno di essi.

Le chiavi 'label' e 'inputType' sono evidenti. Il valore della chiave 'label' corrisponde alla matrice delle traduzioni che creeremo nella prossima parte della guida. Se la chiave 'search' è impostata a true, il campo 'title' è a disposizione per la ricerca attraverso l'intestazione della tabella.

L'array 'eval' imposta le informazioni del campo nel dettaglio del record. È possibile ad esempio creare campi obbligatori, aggiungere un calendario per un campo di tipo data o utilizzare il rich text editor per una textarea.

Abbiamo impostato il campo 'title' come obbligatorio e abbiamo deciso che la sua lunghezza massima sia di 64 caratteri, come il campo del database. Il campo 'description' è una textarea con un rich text editor.

Configurazione del DCA per la tabella tl_cds

Ok, ora è il momento di creare l'array contenitore dei dati per la tabella tl_cds. Essa avrà una configurazione leggermente diversa, in quanto è tl_cds è figlia di tl_cds_category. Si noti che Contao non è in grado di visualizzare in modo predefinito i record figli, così dobbiamo utilizzare child_record_callback.
Apriamo il file cd_collection/DCA/tl_cds.php e mettiamo il seguente codice:
<?php

$GLOBALS['TL_DCA']['tl_cds'] = array
  (

  // Config
  'config' => array
  (
    'dataContainer'               => 'Table',
    'ptable'                      => 'tl_cds_category',
  ),
//...
Il codice sopra è molto semplice. Si sceglie la tabella del database come nostro contenitore dei dati, e tl_cds_category come tabella padre.

La chiave 'list' del DCA

L'array sorting (ordinamento)

Scriviamo questo codice:
  // List
  'list' => array
  (
  'sorting' => array
    (
      'mode'                    => 4,
      'headerFields'            => array('title', 'description'),
      'panelLayout'             => 'search,limit',
      'child_record_callback'   => array('tl_cds', 'listCds')
    ),
//...

La modalità di ordinamento è impostato su 4 - visualizza i record figli di un record padre. Tuttavia, come ho già detto, Contao non è in grado di elencare i figli. Quindi, abbiamo bisogno di creare una nuova funzione e assegnarla a child_record_callback. Il primo parametro dell'array è il nome della classe, mentre il secondo è il nome della funzione. Normalmente le funzioni sono posizionate alla fine del file.

L'array headerFields definisce i campi della tabella padre che stanno per essere elencati nel modulo del figlio:



Si può vedere che "My collection of rock cds." non è alla stessa altezza di "description:". Questo succede quando si visualizza un campo che è stato creato da un editor html. Per impostazione predefinita, viene incorporato il testo con i tag <p>. Contao applica a tutti i tag p del backend un margine in fondo di 12 pixel.

Gli array global_operations (operazioni globali) e operations (operazioni)

Le operazioni globali sono le stesse di tl_cds_category. Le operazioni locali hanno una sola piccola differenza - nell'array 'edit', la chiave 'href' prende come valore 'act=edit' e non 'table = tl_cds'.
    'global_operations' => array
    (
      'all' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['MSC']['all'],
        'href'                => 'act=select',
        'class'               => 'header_edit_all',
        'attributes'          => 'onclick="Backend.getScrollOffset();"'
      )
    ),
    'operations' => array
    (
      'edit' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds']['edit'],
        'href'                => 'act=edit',
        'icon'                => 'edit.gif'
      ),
      'copy' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds']['copy'],
        'href'                => 'act=copy',
        'icon'                => 'copy.gif'
      ),
      'delete' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds']['delete'],
        'href'                => 'act=delete',
        'icon'                => 'delete.gif',
        'attributes'          => 'onclick="if (!confirm(\'' . $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\')) return false; Backend.getScrollOffset();"'
      ),
      'show' => array
      (
        'label'               => &$GLOBALS['TL_LANG']['tl_cds']['show'],
        'href'                => 'act=show',
        'icon'                => 'show.gif'
      )
    )
  ), // end of list array
//...

L'array palettes


Ora bisogna organizzare i campi e raggrupparli in sezioni. Inserisci questo codice dopo l'array 'list':
  // Palettes
  'palettes' => array
  (
    'default'                     => '{title_legend},title,artist;{image_legend},image;{comment_legend:hide},comment'
  ),
//...
Si noti che il punto e virgola sono usati per separare le sezioni. Inoltre, è presente un elemento :hide che non abbiamo utilizzato prima. Questo valore costringe la sezione a essere chiusa quando si inserisce un nuovo elemento.

L'array fields (campi)

Questa è la parte migliora, la definizione dei campi.

Dobbiamo creare quattro campi: titolo, artista, immagine e commento. Proprio come nel database.
  // Fields
  'fields' => array
  (
    'title' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds']['title'],
      'inputType'               => 'text',
      'search'                  => true,
      'eval'                    => array('mandatory'=>true, 'maxlength'=>64, 'tl_class'=>'w50')
    ),
    'artist' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds']['artist'],
      'inputType'               => 'text',
      'search'                  => true,
      'eval'                    => array('mandatory'=>true, 'maxlength'=>64, 'tl_class'=>'w50')
    ),
    'image' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds']['image'],
      'inputType'               => 'fileTree',
      'eval'                    => array('files'=>true, 'filesOnly'=>true, 'fieldType'=>'radio')
    ),
    'comment' => array
    (
      'label'                   => &$GLOBALS['TL_LANG']['tl_cds']['comment'],
      'inputType'               => 'textarea',
      'eval'                    => array('rte'=>'tinyFlash')
    )
  )
); // end of $GLOBALS['TL_DCA']['tl_cds'] array
//...

Passo per passo:

Titolo - un campo di testo normale, disponibile per la ricerca, con una lunghezza massima di 64 caratteri. L'elemento nuovo per voi è tl_class. Ci sono 5 classi per i campi in Contao che vengono utilizzati per migliorare l'estetica del backend. Tutte le classi si possono trovare in questa pagina.

I campi senza applicare alcuna classe

I campi applicando la classe 'w50'

Artista - questo campo è esattamente uguale al titolo.

Immagine - come tipo di campo abbiamo utilizzato file, che renderà la struttura dei file della cartella tl_files. Inoltre, abbiamo impostato files a true, in questo modo saranno visualizzati sia i file che le cartelle. Tuttavia, abbiamo bisogno di disattivare la selezione di una cartella - ecco perché abbiamo aggiunto 'filesOnly' => true. L'ultimo parametro è il tipo di campo. Potrebbe essere sia un checkbox che un radio, ma dal momento che vogliamo aggiungere una sola copertina cd per album, scegliamo radio.

Commento - Questo è lo stesso campo di tl_cds_category.

Elenco dei record figli

A questo punto, siamo in grado di aggiungere nuovi record al database. Sarebbe bello se si potesse elencarli, così da poterli modificare / visualizzare / cancellare e ricercare.

Alla fine del file tl_cds.php, creiamo una nuova classe che estende Backend e che contiene la funzione listCds:
class tl_cds extends Backend {

  /**
  * List cds of our collection
  * @param array
  * @return string
  */
  public function listCds($arrRow)
  {
    return '<div>
    <img src=" ' . $arrRow['image'] . '  " style="height:100px; width:100px; float:left; margin-right: 1em;" /><p><strong>' . $arrRow['title'] . '</strong> (' . $arrRow['artist'] . ')</p>' . $arrRow['comment']
    . '</div>' . "\n";
  }

}

?>

E' una buona convenzione utilizzare come nome della classe lo stesso nome della tabella. Diamo uno sguardo alla funzione.

Come suo primo e unico parametro accetta un array che contiene i dati recuperati dal database. L'array $arrRow si presenta così:

Array
(
    [id] => 2
    [pid] => 1
    [tstamp] => 1270829730
    [title] => Hellfire Club
    [artist] => Edguy
    [image] => tl_files/Edguy.jpg
    [comment] => <p>In contrast to their previous albums, Hellfire Club owes more to the
sound of Iron Maiden than their biggest influence Helloween, both in
vocals and in music. The first track "Mysteria" opens with the
introduction "Ladies and Gentlemen! Welcome - to the Freak Show!".</p>
)
Array
(
    [id] => 5
    [pid] => 1
    [tstamp] => 1270831831
    [title] => One X
    [artist] => Three Days Grace
    [image] => tl_files/OneX.jpg
    [comment] => <p>One-X is the second album from Three Days Grace, released on June 13,
2006. The album entered the Billboard Top 200 charts at #5 with first
week sales of more than 78,000 and has so far gone to sell over
1,200,000 copies in the US alone.</p>
)

A ogni chiave corrisponde un campo della tabella. Spero che il codice e l'array siano chiari.

Tags

Torna indietro

Aggiungi un commento