Upload
vucong
View
227
Download
0
Embed Size (px)
Citation preview
2/7/2013
1
LE NOVITÀ DI JOOMLA!™ 2.5
Sistema ACL (Access Control List, dalla 1.6)
Livelli di categorie definite dall’utente
JForm e JTableNested e JDatabaseQuery
PHP ≥ 5.2 e MySQL ≥ 5.0.4, più altri DB
Formato .ini per i file di linguaggio
One-click update
Miglioramenti alla struttura MVC
Miglioramenti al sistema di ricerca
2/7/2013
2
RIFERIMENTI
http://developer.joomla.org
http://docs.joomla.org/Developers
2/7/2013
3
L’ECOSISTEMA JOOMLA!™
Browser richiede URL
•XHTML generato
•Fogli di stile CSS
•AJAX per i contenuti dinamici
Web server gestisce richiesta
•Tipicamente Apache o Microsoft IIS
•Linguaggio di programmazione PHP
Contenuti dinamici su database
•MySQL come base di dati relazionale
COME ESTENDERE JOOMLA!™
•Hook per intercettare flusso standard
•"Side" content
•Contenuto centrale della pagina
•Modifica visualizzazione contenuti
•Evitare modifiche dirette al codice
•Bassa manutenibilità
Code hack Layout
overrides
Plugin e moduli
Components
2/7/2013
4
Nuovo articolo
Validazione standard
Plugin: metodo
onBeforeSave
Salvataggio su database
Plugin: metodo
onAfterSave Fine
Permettono di intercettare il flusso standard del codice
Sistema ad eventi e trigger
Esempio
• Esaminare ogni nuovo articolo ed assegnare appropriati metadati (keyword)
ESTENDERE JOOMLA!™ CON I PLUGIN INTERNAZIONALIZZAZIONE
Testi dell'interfaccia disaccoppiati dal codice e inseriti in file speciali .ini
• Approccio consigliato per sviluppatori di terze parti
Esempio
• in administrator/templates/bluestork/login.php ed altri: echo JText::_( 'COM_LOGIN_JOOMLA_ADMINISTRATOR_LOGIN' );
• la traduzione si trova in administrator/language/en-GB/en-GB.com_login.ini
2/7/2013
5
ESTENDERE JOOMLA!™ CON I TEMPLATE
La generazione dei contenuti è separata dalla loro presentazione
Non ci occuperemo dello sviluppo dei template ma solo della struttura dei folder per gli override e per il posizionamento dei moduli
2/7/2013
6
REQUISITI DI JOOMLA!™
Web Server
• DocumentRoot di Apache (httpd.conf)
• XAMPP per Windows e Mac OS X
Istruzioni aggiornate
• Aggiornati per ogni nuova versione
Permessi
• Sviluppo ≠ Produzione
• Impostare al minimo set di permessi richiesto
SCEGLIERE GLI STRUMENTI DI SVILUPPO
IDE
•Rileva errori di sintassi
•Autocompletamento del codice
•Visualizzazione di metodi e campi
•Comparazione di versioni
•Ricerca e sostituzioni semplificate
•Debugger
•Revision control system
Editor
•Semplicità d'uso
2/7/2013
7
ECLIPSE
Installare PDT e verificarne le caratteristiche
• Syntax highlighting (e perspective con manuale)
• Autocompletamento del codice
• Autocompletamento dei metodi
• Esempio $this-> Ctrl+Space
• Outline
• Ricerca delle classi correlate
ALTRI EDITOR
IDE (a pagamento)
• NetBeans
• ZendStudio http://www.zend.com
• Aptana Studio http://www.aptana.com
• Komodo IDE
Editor di testo
• Notepad++
• Vi, Sed e Awk direttamente su un server Linux
2/7/2013
8
PANORAMICA DELLA STRUTTURA
Frontend vs Backend
•Applicazioni separate che condividono librerie
•La cartella /administrator
Il file index.html
•<!DOCTYPE html><title></title>
•Per nascondere l’elenco dei file nella directory
2/7/2013
9
PANORAMICA DEL FRONTEND
•File temporanei per il riutilizzo (consigliato in produzione) Cache
•Applicazioni a linea di comando (Unità 13) CLI
•Generano il contenuto principale della pagina (iniziano con com_) Components
•Contiene gli asset pubblici, divisi in sottocartelle Images
•Librerie specifiche per la sessione di frontend Includes
•Miniapplicazione separata per l’installazione dell’applicazione Installation
•File specifici ed override di lingua Language
•Librerie esterne (phpmailer, phputf8, simplepie) ed interne (core di Joomla) Libraries
•Eventi registrati se abilitato Logs
•CSS, JavaScript e immagini per alcuni componenti, moduli ed editor Media
•Generano i contenuti laterali (iniziano con mod_) Modules
•Mini attività e modificatori di contenuto Plugins
•Template grafici Templates
•File temporanei Tmp
PANORAMICA DEL BACKEND (/ADMINISTRATOR)
•Contenuti dinamici temporanei Cache
•Componenti amministrativi (iniziano con com_) Components
•helpsites.xml per i collegamenti remoti o locali Help
•Librerie per la gestione delle sessioni amministrative Includes
•Traduzioni dell’area amministrativa Language
•Lista dei file e URL per gli aggiornamenti Manifests
•Contenuti laterali per l’area amministrativa Modules
•Bluestork (default) e Hator (alta accessibilità) Templates
2/7/2013
10
FILE TOP-LEVEL
•Contiene le impostazioni essenziali del sito (database e path) configuration.php
•Abilita mod_rewrite (.htaccess): rimuove index.php e aggiunge controlli htaccess.txt
•Punto di attacco per tutti i contenuti del sito index.php
•Copia di administrator/manifests/files/joomla.xml joomla.xml
•Licenza Joomla (GPLv2) LICENSE.txt
•Informazioni generali su Joomla README.txt
•Istruisce bot ed webcrawler ad ignorare le sottocartelle robots.txt
•Analogo di .htaccess per Microsoft IIS web.config.txt
LA JOOMLA!™ PLATFORM
Struttura di base per il CMS Joomla
File libraries/loader.php
• Classe JLoader
• Funzione jexit(): wrapper per la funzione exit()
• Funzione jimport(): scorciatoia per JLoader::import() per il caricamento dei file in stile Java o C#
Librerie esterne
• phpmailer: per l’invio di email via PHP
• phputf8: gestione avanzata delle stringhe UTF-8
• simplepie: gestione di file XML, come i feed RSS e Atom
2/7/2013
11
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
factory.php classe statica JFactory per il caricamento degli
oggetti
methods.php alcune helper classes per l’interazione con URL e testo
access funzionalità per il controllo degli accessi (ACL)
application funzionalità per le estensioni e per la main application
base classi astratte di basso livello per design pattern e strutture dati
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
cache gestione dei diversi meccanismi di caching
client connessione a server come FTP o LDAP
database connessione diretta alle basi di dati
document costruzione e la modifica delle
risposte al browser
environment interazione con request (GET, POST, COOKIE) e response
2/7/2013
12
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
error gestione degli errori
event gestione degli eventi (listen e azioni)
filesystem interazione con il filesystem
filter validazione e filtering dei valori di input e di output
form costruzione, modifica e processamento dei form web
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
github interazione con il version control system repository
html helper methods per generare HTML, caricare CSS e JavaScript
http interazione con differenti tipi di richieste HTTP
image operazioni sulle immagini
installer installazione ed aggiornamento delle estensioni
language traduzione delle stringhe
2/7/2013
13
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
log implementazione delle funzionalità di log
mail metodi per l’invio di messaggi di posta elettronica
plugin metodi correlati al sistema di plugin
registry interazione con object data (ad
es INI, JSON, XML)
session creazione, modifica e conservazione delle sessioni
PANORAMICA DELLA JOOMLA!™ PLATFORM (/LIBRARIES/JOOMLA)
Libreria Descrizione
string operazioni sulle stringhe
updater supporto all’auto-aggiornamento delle estensioni
user manipolazione ed interazione con gli oggetti utente
utilities classi e metodi non riconducibili ad altri gruppi
2/7/2013
14
PROGRAMMAZIONE WEB VS PROGRAMMAZIONE "CLASSICA"
Gestione dello stato del programma
•Protocollo HTTP stateless
•Gestione delle variabili di sessione
•Contenuti su database
Validazione dei comandi
•Esposizione degli accessi
•Validazione delle richieste (URL + contenuto dei form)
ANATOMIA DI UN CICLO DI ESECUZIONE JOOMLA!™
Caricamento di index.php
Controllo dell'execution environment
Definizione delle posizioni dei file
Caricamento del framework
Avviamento o continuazione della sessione
Routing dell'URL
Esecuzione del componente
Renderizzazione della pagina
Output della pagina
2/7/2013
15
ESECUZIONE (A)
index.php
• Punto di aggancio predefinito
• Riscrittura degli URL se mod_rewrite abilitato
Controllo dell'execution environment
• define('_JEXEC', 1);
Definizione delle costanti
• includes/defines.php
• Override possibile in /defines.php
ESECUZIONE (B)
Caricamento di includes/framework.php
• Carica la JFactory e il JLoader
• Verifica l'esistenza di configuration.php
Avvia o continua la sessione
• $app = JFactory::getApplication('site');
• JSite estende JApplication e recupera la sessione
• $app->initialise();
• Definisce la lingua e l'editor per l'utente
2/7/2013
16
Routing dell'URL
($app->route();) • Classe che traduce tra
URL e array di comandi
• parse(): da JURI ad
array; build(): inversa
JSite route()
•public function route() {
•parent::route();
•$Itemid = JRequest::getInt('Itemid');
•$this->authorise($Itemid);
• }
JApplication route()
•public function route() {
•$uri = clone JURI::getInstance();
•$router = $this->getRouter();
•$result = $router->parse($uri);
•JRequest::set($result, 'get', false);
•JPluginHelper::importPlugin('system');
•$this->triggerEvent('onAfterRoute');
• }
ESECUZIONE (C) ESECUZIONE (D) – COMPONENTE $APP->DISPATCH() DI JSITE IN INDEX.PHP
Ottiene il componente dalla JRequest
Crea un $document = JFactory::getDocument()
• Contenuti da inviare al browser
• Non è costruito sequenzialmente
• Supporta diversi tipi: html, feed
Carica il componente
• $contents = JComponentHelper::renderComponent($component);
Carica questa parte nel documento
• $document->setBuffer($contents, 'component');
2/7/2013
17
ESECUZIONE (E) – METODO RENDERCOMPONENT()
libraries/joomla/application/component/helper.php
Carica il template e la lingua
Salva il nome in $app->scope (utile per i plugin)
Valida il nome, verifica i path, verifica se abilitato
Esegue il componente!
$contents = self::executeComponent($path);
Metodo statico della classe
•Verifica se generare una toolbar
•return $contents;
protected static function executeComponent($path)
• ob_start();
• require_once $path;
• $contents = ob_get_contents();
• ob_end_clean();
• return $contents();
Attiva l'output buffering
Carica il componente • Tutto è delegato al
componente
• Può seguire qualunque
workflow (non solo MVC)
Salva l'output e pulisce
il buffer
ESECUZIONE (F) – EXECUTECOMPONENT()
2/7/2013
18
ESECUZIONE (G) – RENDERING $APP->RENDER()
Carica il documento (tipo JDocumentHTML, da libraries/joomla/document/html/html.php)
Carica i dati utente
$document->parse($params);
• Carica il template e ne fa il parsing
• return $this->_fetchTemplate($params)->_parseTemplate();
Rendering della response
• JResponse::setBody($document->render($caching, $params));
ESECUZIONE (H) – JDOCUMENTHTML _PARSETEMPLATE()
Prepara un array associativo in $this->_template_tags (oggetto $document)
Contiene
• type: tipo del tag, tra head, modules, messages, debug e component
• name: nome dell'elemento specificato in jdoc:include
• attribs: attributi specifici del tag
2/7/2013
19
ESECUZIONE (I) – RENDERING DEL TEMPLATE
$data = $this->_renderTemplate();
Cicla su tutti i tag
• Il componente è già disponibile in $contents
• I moduli vengono eseguiti ed aggiunti solo se assegnati ad una posizione esistente nel template
render() della parent class JDocument
• Imposta la data ed il content type
ESECUZIONE (J) – OUTPUT DELLA PAGINA
echo $app; chiama il metodo __toString() di JApplication (parenti di JSite)
• $compress = $this->getCfg('gzip', false);
• return JResponse::toString($compress);
• Inserisce il corpo della pagina in $data
• Controlla se comprimere la pagina
• Controlla il caching ed imposta l'header di conseguenza
• Invia l'header
• Invia $data contenente l'intera pagina
2/7/2013
20
Carica index.php
Definisce posizione file
Carica Joomla Framework
Crea o carica sessione
Route URL
Esegue componente
Renderizza pagina
Invia pagina al browser
Durante tutto il processo vengono sollevati trigger per eventuali plugin
I metodi di alto livello sono relativamente pochi
Suddivisione in numerosi sotto task per compiti specifici
RIASSUNTO DEL WORKFLOW NAMING CONVENTIONS
Semplificano la comprensione del sistema
• com_miocomponente/miocomponente.php
Oggetti globali
• Oggetti disponibili in qualunque punto dell'esecuzione
• Design pattern "singleton" e "factory"
• JFactory::getApplication restituisce la JApplication esistente o la crea alla prima esecuzione
2/7/2013
21
GLI OGGETTI GLOBALI DI JOOMLA!™
Oggetto Descrizione Codice
JApplication, JSite e JApplication
Oggetto applicazione e sue declinazioni
$app = JFactory::getApplication();
JRegistry Valori di configuration.php
$config = JFactory::getConfig();
JSession Sessione corrente $session = JFactory::getSession();
JLanguage Contenuti linguistici $language = JFactory::getLanguage();
GLI OGGETTI GLOBALI DI JOOMLA!™
Oggetto Descrizione Codice
JDocument, JDocumentHTML, JDocumentFEED,
JDocumentJSON
Documento corrente
$document = JFactory::getDocument();
JUser Utente corrente $user =
JFactory::getUser();
JAccess Accessi correnti (per il controllo dei permessi)
$access = JFactory::getACL();
JDatabase Per l'esecuzione delle query
$dbo = JFactory::getDbo();
2/7/2013
22
GLI OGGETTI GLOBALI DI JOOMLA!™
Oggetto Descrizione Codice
JMail Per l'invio delle mail
$mail = JFactory::getMailer();
JXMLElement Elemento XML $xml = JFactory::getXML($pathToXml);
JEditor Editor $editor = JFactory::getEditor();
JURI URI $uri = JFactory::getUri();
JDate Date/time (non singleton)
$date = JFactory::getDate();
2/7/2013
23
CONCETTI BASE SUI TEMPLATE
Disaccoppiamento della business logic dalla presentation
Consente modifiche sostanziali al rendering degli elementi via override
css
•Fogli di stile (CSS)
fonts
•Set di caratteri particolari
html
•modules.php: "module chrome", ovvero wrapper per il markup HTML dei moduli
•com_contact e com_content per gli override
images
•Assett grafici
javascript
•Effetti specifici del template
language
•Traduzioni delle stringhe stampate
component.php
•Template per la stampa o l'invio email
error.php
•Template per le pagine di errore (URL invalidi)
favicon.ico
•Icona nella barra degli URL
index.php
•Template principale
•Posiziona i moduli, i componenti ed i messaggi
template_preview.png e _thumbnail.png
•Anteprime del template
templateDetails.xml
•Metadati del template: file, folder e parametri
FOLDER E FILE DEI TEMPLATE (BEEZ_20)
2/7/2013
24
INDEX.PHP DI UN TEMPLATE (ATOMIC)
Istanza $app = JFactory::getApplication()
Tipo di documento <!DOCTYPE html...
HTML tag head meta e title personalizzabili <jdoc:include type="head" />
Contenuto centrale
• <jdoc:include type="component" />
Contenuti laterali
• <jdoc:include type="modules" name="atomic-search"
style="none" />
• name: posizionamento dei moduli
• style: "Module Chrome" (decorazione dei moduli)
PARAMETRI DI TEMPLATE
Extensions > Template Manager > Beez2
Definiti in templates/beez_20/templateDetails.xml
• Ogni <fieldset> è uno "slider"
• Ogni <field> è un parametro definito da attributi
2/7/2013
25
ATTRIBUTI DI UN ELEMENTO <FIELD>
Attributo Descrizione
name Nome per identificare il parametro ed il suo valore
class Classe CSS per la visualizzazione; ad es. la class validate-numeric attiva codice JavaScript per "validare" l'input numerico
type Tipo di dato. Per convenzione se type=text la classe è JFormFieldText dal file libraries/joomla/form/fields/text.php Per il tipo list si aggiungono elementi <option> per descrivere le
opzioni possibili
default Valore predefinito visualizzato nel form
label Etichetta, normalmente traducibile da language/en-GB/en-GB.tpl_beez_20.ini (nell'esempio)
description Descrizione del campo, tradotta come sopra
filter Filtro da applicare, chiama il metodo clean() di JFilterInput da libraries/joomla/filter/filterinput.php con il tipo specificato
SALVATAGGIO PARAMETRI
I fields di tipo "params" (parametri) sono salvati in forma JSON
• Funzioni PHP json_encode e json_decode
I parametri di template sono nella tabella #__templates_styles nella colonna params
2/7/2013
26
DECORATORI DI MODULO (MODULE CHROME)
Definito da <jdoc:include type="modules" ... style="container" />
Cerca funzione modChrome_container in
• Standard templates/system/html/modules.php
• Custom templates/atomic/html/modules.php
FUNZIONE DECORATOR
function modChrome_container ( $module, &$params, &$attribs )
• $module contiene il modulo; $module->content l'HTML da visualizzare
• $params è un JRegistry con i parametri
• $attribs è un array dei valori di jdoc:include
2/7/2013
27
COPIARE UN TEMPLATE
Per lavorare su una versione custom
Copiare la cartella in una nuova
Modificare templateDetails.xml
Rinominare i file di linguaggio
Discover e install
• Extension Manager > Discover
• Funzionalità per installare estensioni copiate localmente
Effettuare le personalizzazioni
TEMPLATE LAYOUT OVERRIDE (MODULO LATEST ARTICLES)
Content > Article Manager > Latest News
Contiene la macro {loadmodule articles_latest,Latest News}
Extensions > Module Manager > Latest News
Trovare il layout originale
• modules/mod_articles_latest/tmpl/default.php
Creare l'override
• templates/<nome>/html/mod_articles_latest/
2/7/2013
28
LAYOUT OVERRIDE I
<h1>Il mio primo override</h1>
<ul class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php foreach ($list as $item) : ?>
• <li><a href="<?php echo $item->link; ?>">
• <?php echo $item->title; ?></a></li>
• <?php var_dump($item); ?>
• <?php echo substr($item->introtext, 0, 50) . '...'; ?>
<?php endforeach; ?>
</ul>
LAYOUT OVERRIDE I: DESCRIZIONE
Inserimento di HTML statico
Controllo delle disponibilità dell'oggetto $item con var_dump
Inserimento dei primi 50 caratteri del testo introduttivo
• Contiene l'articolo fino al primo "Read More" (se esistente)
2/7/2013
29
LAYOUT OVERRIDE II
<ul class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php foreach ($list as $item) : ?>
• <li><a href="<?php echo $item->link; ?>">
• <?php echo $item->title; ?></a></li>
• <p>
• <?php echo substr(strip_tags($item->introtext), 0, 50) . '...'; ?>
• </p>
<?php endforeach; ?>
</ul>
LAYOUT OVERRIDE II: DESCRIZIONE
Elimina i tag HTML presenti nell'articolo
• <img> o <div> causano eventuali problemi di visualizzazione
Funzione-in-funzione substr(strip_tags(...))
Aggiunta tag <p> per racchiudere la stringa
2/7/2013
30
LAYOUT OVERRIDE III
<?php JLoader::register('JHtmlString', JPATH_LIBRARIES . '/joomla/html/html/string.php'); ?>
<ul class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php foreach ($list as $item) : ?>
• <li><a href="<?php echo $item->link; ?>">
• <?php echo $item->title; ?></a></li>
• <p>
• <?php echo JHtmlString::truncate(strip_tags($item->introtext), 53); ?>
• </p>
<?php endforeach; ?>
</ul>
Step operativi 1. Includere la libreria
con JLoader::register • Nome della classe
• Posizione del file
2. Usare la funzione JHtmlString::truncate() • Stringa da tagliare
• Numero di caratteri, comprensivo di '...'
Obiettivo: troncare il testo alla fine di parola
Uso delle funzioni di Joomla
• http://developer.joomla.org/code.html > API
• http://api.joomla.org HTML > Classes > JHtmlString
LAYOUT OVERRIDE III: DESCRIZIONE
2/7/2013
31
LAYOUT OVERRIDE IV
<ul class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php foreach ($list as $item) : ?>
• <li><a href="<?php echo $item->link; ?>">
• <?php echo $item->title; ?></a></li>
• <p>
• <?php echo JHtml::_('string.truncate', strip_tags($item->introtext), 53); ?>
• </p>
<?php endforeach; ?>
</ul>
LAYOUT OVERRIDE IV: DESCRIZIONE
Semplificazione del codice: JHtml::_()
• Argomento string.truncate
• Segmento classe, diventa JHtmlString
• Segmento funzione
• Altri arogmenti passati alla funzione risultante
• La classe è caricata automaticamente
2/7/2013
32
TEMPLATE LAYOUT OVERRIDE (COMPONENTE USER REGISTRATION)
Obiettivo: aggiungere un disclaimer alla procedura di registrazione utente
Originale in components/com_users/views/registration/tmpl
• default.php contiene il form di registrazione
• complete.php la pagina di registrazione completata
Copiare in templates/<nome>/html/com_users/registration
Verificare in Home > Create an Account
Limitazioni • Testo hardcoded • La spunta non è richiesta per
procedere • Il dato non viene salvato
<fieldset> • <legend>Termini di
servizio</legend> • <p><input type="checkbox" />
Consento al trattamento... </p>
</fieldset>
<button type="submit" class="validate"> <?php echo JText::_('JREGISTER'); ?> </button>
LAYOUT OVERRIDE IN AZIONE
2/7/2013
33
Copia "hard-
coded" al template
Layout flessibili
• Diversi da default.php
Rinominare default.php
in <mionome>.php
Selezionare il layout in Advanced Options
• In Module Manager
• Nei Settings globali
LAYOUT ALTERNATIVI CREAZIONE DI UN NUOVO DECORATOR
Creare una nuova funzione modChrome nel modules.php del template
Usare il nuovo stile in una dichiarazione <jdoc:include> per una
specifica posizione
Assegnare un modulo a quella posizione
Raffinare la configurazione con attributi dinamici
2/7/2013
34
1. CREARE LA FUNZIONE MODCHROME
Copiare la funzione modChrome_table da templates/system/html/modules.php in templates/<nome>/html/modules.php
Rinominare in modChrome_<nome>FramedTable
• Nome del template inserito come "namespacing" per evitare
collisioni
Aggiungere un border="5" al tag <table>
2. USARE LO STILE IN UN <JDOC:INCLUDE>
Modificare templates/<nome>/index.php
Aggiungere la posizione 7A sotto la 7
• <jdoc:include type="modules" name="position-7A" style="<nome>FramedTable" />
2/7/2013
35
3. ASSEGNARE UN MODULO ALLA NUOVA POSIZIONE
Module Manager
• Selezionare la posizione a mano
• Per averlo in lista dovremmo modificare templateDetails.xml
• Menu Assignment > On All Pages
4. RAFFINARE LA CONFIGURAZIONE CON GLI ATTRIBUTI
Modificare border="<?php echo $attribs['border'] ?>" nella modChrome
Aggiungere border="2" nel <jdoc:include>
Verificare errore (Notice) se border non specificato nel <jdoc:include>
• Global Configuration > Server > Error Reporting > Maximum
Modificare border="<?php echo (isset($attribs['border'])) ? (int) $attribs['border'] : '0'; ?>"
2/7/2013
36
COS'È UN PLUGIN
Un semplice programma PHP che viene eseguito in uno o più punti predefiniti del
ciclo di esecuzione di Joomla
•L'esecuzione di un plugin è scatenata da un evento
•Plugin semplici (salvare un dato in un database) o complessi (convertire tutti gli URL in un formato diverso)
2/7/2013
37
COME FUNZIONANO I PLUGIN
Inclusione nello script
•JPluginHelper::importPlugin()
•Nessun codice viene eseguito in questo momento
Trigger di un evento
•$dispatcher->trigger()
•Ogni evento ha un nome (ad es. onBeforeInitialize o onContentBeforeSave)
Esecuzione dei metodi
•La procedura cerca tra i plugin abilitati e caricati dei metodi che si riferiscono al nome dell'evento
NAMING CONVENTIONS
Folder plugins/<plugin type>/<plugin name>
•Codice in <plugin name>.php
•Metadati in <plugin name>.xml
Nome della classe
•"plg" + <plugin type> + <plugin file name>
2/7/2013
38
TIPOLOGIE DI PLUGIN
•onUserAuthenticate al tentativo di login di un utente Authentication
•onInit, onDisplay e onCheckAnswer per validare l'input dell'utente Captcha
•Eventi sollevati alla visualizzazione o modifica di contenuti Content
•Implementati come plugin, esulano dalla trattazione Editors
•Pulsanti per attività sull'editor, evento onDisplay Editors-XTD
•Eventi sollevati per installazione/modifica di Estensioni Extension
•onContentSearchAreas (aree di ricerca) e onContentSearch (esegue) Search
•Indicizzano i contenuti Smart Search (Finder)
•Eventi sollevati nel ciclo di esecuzione (onAfterInitialise) System
•Eventi sollevati alla modifica dei profili o al login/logout User
PANORAMICA DEI CORE PLUGIN – SYSTEM: SEF (SEARC-ENGINE-FRIENDLY URL)
JPluginHelper::importPlugin('system'); carica
$this->triggerEvent('onAfterRender'); esegue
• $dispatcher = JDispatcher::getInstance();
• return $dispatcher->trigger($event, $args); chiama il metodo $event per tutti i plugin di tipo system
2/7/2013
39
defined('_JEXEC') or die;
class plgSystemSef extends JPlugin {
• /** • * Converting the site URL to
fit to the HTTP request • */ • public function
onAfterRender() { • ...
Legge documento HTML
Controlla se è sul frontend e l'opzione globale è attiva
• if ($app->getName() != 'site' || $app->getCfg('sef') == '0'
Converte i collegamenti
Rende gli URL assoluti
PLUGIN SEF IN ESECUZIONE PANORAMICA DEI CORE PLUGIN – AUTHENTICATION: JOOMLA
Valida username e password in authenticate() di JAuthentication
• $plugins = JPluginHelper::getPlugin('authentication');
• foreach ($plugins as plugin) {
• $plugin->onUserAuthenticate($credentials, $options, $response);
• }
2/7/2013
40
AUTENTICAZIONE JOOMLA IN ESECUZIONE – PARTE 1
•$credentials contiene username e password
•&$response (by reference) contiene la risposta
function onUserAuthenticate($credentials,
$options, &$response)
• Indica il plugin usato per validare l'utente $response->type = 'Joomla';
•Non consente password vuote e restituisce un errore if (empty($credentials['password'])) ...
• Istanzia una query sul database $db = JFactory::getDbo();
$query = $db->getQuery(true);
•Seleziona i campi dalla tabella
•Usa il prefisso #__ sostituito con quello reale $query->select('id, password');
$query->from('#__users');
•Definisce la condizione
•Valida il campo inserito con $db->Quote $query->where('username=' . $db->Quote($credentials['username']));
AUTENTICAZIONE JOOMLA IN ESECUZIONE – PARTE 2
•Prepara la query ed esegue $db->setQuery($query);
$result = $db->loadObject();
•Se la query non restituisce un valore, utente non esistente
•$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER); if ($result)
•Password composta da <hash>:<salt>
$parts = explode(':', $result->password);
$crypt = $parts[0];
$salt = @$parts[1];
•Esegue la funzione di hashing one-way (md5) sulla password inviata $credentials['password'] con il $salt
$testcrypt = JUserHelper::getCryptedPassword(...);
•Carica profilo utente JUser::getInstance($result->id); o password errata
•restituisce $response passata by reference
if ($crypt == $testcrypt)
2/7/2013
41
PANORAMICA DEI CORE PLUGIN – CONTENT: JOOMLA (PLGCONTENTJOOMLA)
onContentAfterSave
• invia mail di notifica
onContentBeforeDelete
• impedisce di eliminare categorie con item referenziati
• Chiamato dalla delete() di JModelAdmin $result = $dispatcher->trigger($this->event_before_delete, array($context, $table));
"INTEGRITÀ REFERENZIALE" DELLE CATEGORIE IN ESECUZIONE
•Opera solo sulle categorie if ($context !=
'com_categories.category')
•Abilitato nelle opzioni JRegistry
•Parametri definiti nel file XML correlato if(!$this->params-
>def('check_categories', 1)
•Ricava l'estensione
•Plugin lavora solo su estensioni core $extension =
JRequest::getString('extension');
•Conta elementi in tabella (=estensione) $count = $this-
>_countItemsInCategory($table, $data->get('id'));
• Impedisce l'eliminazione della categoria
•Esistono elementi correlati if ($count > 0)
• Impedisce l'eliminazione di una categoria padre (non foglia) if (!$data->isLeaf())
2/7/2013
42
"INTEGRITÀ REFERENZIALE" DELLE CATEGORIE - FAQ
Codice nel plugin = flessibilità
• Può essere disabilitato
• Disabilitabile selettivamente
• Può essere rimpiazzato o esteso
• Modello di sviluppo per altri
Codice hardcoded nelle categorie
• Nessuna operazione attiva
• Restituisce solo un booleano
CREARE UN PLUGIN: DEFINIZIONE E PRIMI CONTROLLI
onBeforeCompileHead
• Prima del rendering degli header HTML
In fetchHead() di JDocumentRendererHtml
• Obiettivo: aggiungere un elemento <meta>
• <meta name="revised" content="Joomlahost, 17/01/2013" />
• Verificare il contenuto di $document prima del trigger
Inserire var_dump($document->getHeadData());
Array associativo di meta tag
2/7/2013
43
CREARE UN PLUGIN: CODE FLOW
Leggere parametri
•meta tag custom
Leggere header esistenti
Modificare header
•Aggiungere elemento
Restituire header
modificati
•setHeaderData()
CREARE UN PLUGIN: STEP OPERATIVI
Creare folder plugins/system/mymeta
Copiare da plugins/system/p3p e rinominare
Modificare mymeta.xml
Codice in mymeta.php
Installare plugin: Extensions Manager » Discover » Install
Inserire valore parametro
Verificare funzionamento
2/7/2013
44
CREARE UN PLUGIN: MYMETA.XML
<fields name="params">
<fieldset name="basic">
<field name="revised" type="text" description="Contenuto del metatag revised" label="Revised content" default="" size="50" />
</fieldset>
</fields>
CREARE UN PLUGIN: MYMETA.PHP
<?php
defined('_JEXEC') or die;
jimport('joomla.plugin.plugin');
class plgSystemMeta extends JPlugin {
function onBeforeCompileHead() {
if ($this->params->get('revised')) {
$document = JFactory::getDocument();
$headData = $document->getHeadData();
$headData['metaTags']['standard']['revised'] = $this->params->get('revised');
$document->setHeadData($headData);
}
}
}
2/7/2013
45
CREARE UN PACKAGE DEL PLUGIN
.zip o .tar.gz dell'intera struttura (senza la trailing directory)
• cd <directory del plugin>
• zip –r plg-<plugin type>-<plugin name>.zip *
• tar cfvz plg-<plugin type>-<plugin name>.tar.gz *
PLUGIN BEST PRACTICES
Ordine di esecuzione in Plugin Manager
•Tipicamente l'ordine non è importante
Usare la naming convention
Eventi differenti hanno signature differenti
•Folder tests/plugins
•http://docs.joomla.org /Plugin/Events
Cercare l'evento migliore
•Non aggiungerne altri
2/7/2013
46
COS'È UN MODULO, AFFINITÀ E DIFFERENZE DA UN COMPOENTE
Piccolo, semplice e "leggero" frammento di
contenuto
• Informazioni e strumenti laterali al componente principale
•Spesso dipende da un componente (ad es gli articoli popolari)
•Spesso aiuta la navigazione dell'utente (menu e form di ricerca)
Non dipende dall'URL: integrato nel workflow built-
in
•Tutti i moduli che sono assegnati (a) al menu item (b) ad una posizione visualizzata nel template
2/7/2013
47
Visualizza gli ultimi n
utenti registrati
Parametri • Limitare utenti visualizzati
• Visualizzare link al profilo
• Visualizzare informazioni
di contatto
Nome del file Descrizione
tmp1/default.php Layout del
modulo (stampa
output su browser)
helper.php Metodi per la
raccolta dei dati
mod_users_latest.php Entry point di
esecuzione
mod_users_latest.xml Metadati per
installazione e
parametri
(formato XML)
PANORAMICA DI UN MODULO CORE – LATEST USERS
PANORAMICA "LATEST USERS" – METADATI
Tipo dell'estensione: modulo
Elenco dei file e delle cartelle
File per la localizzazione linguistica
Copiati nel folder core
•Descrizione dei parametri di configurazione in <fieldset>
3 "basic" e 5 "advanced"
2/7/2013
48
Carica la classe helper
•require_once dirname(__FILE__).'/helper.php';
Chiama metodi helper (per ottenere dati)
•$name = moduserslatestHelper::getUsers($params);
Include file di layout (renderizza i contenuti)
•require JModuleHelper::getLayoutPath('mod_users_latest', $params->get('layout', 'default'));
Dov'è definita la variabile $params?
•Modulo incluso da renderModule() di JModuleHelper
•$params = new JRegistry;
•$params->loadJSON($module->params);
•[...]
•$content = '';
•ob_start();
•require $path; //il codice è inserito ed eseguito as-is, ereditando lo scope
•$module->content = ob_get_contents().$content;
PANORAMICA "LATEST USERS" – CODICE PRINCIPALE (MOD_USERS_LATEST.PHP)
PANORAMICA "LATEST USERS" – RENDERING DEL CONTENUTO
•Classe custom per fine-tuning di CSS $moduleclass_sfx =
htmlspecialchars($params->get('moduleclass_sfx'));
•Eredita lo scope e le variabili (attenzione alle modifiche accidentali)
require JModuleHelper::getLayoutPath(
•Se layout di default modules/mod_users_latest/tmp1/default.php
'mod_users_latest',
•Layout alternativi per i moduli (selezionabili in Module Manager)
$params->get('layout', 'default')
•Il codice è incluso "as-is", ereditando lo scope dallo script chiamante
);
2/7/2013
49
PANORAMICA "LATEST USERS" – CLASSE DI APPOGGIO (HELPER)
•Metodo statico (di classe, non di oggetto) static function getUsers($params)
{
•Query costruita ad oggetti da JDatabaseQuery (platform agnostic)
$query->select('a.id, ...');
$query->order('a.registerDate DESC');
•Definizione tabella (prefix agnostic)
•Selezione per gruppi con $query->leftJoin(...) $query->from('#__users AS a');
•Carica query come stringa: __toString() di JDatabaseQuery
•Condizione LIMIT come shownumber
$db->setQuery($query, 0, $params->get('shownumber'));
•Esegue la query
•Restituisce array di oggetti
$result = $db->loadObjectList();
return (array) $result;
PANORAMICA "LATEST USERS" – LAYOUT PREDEFINITO (TMP1/DEFAULT.PHP)
•Sintassi alternativa PHP per il mixing con HTML <?php if (!empty($names)) : ?>
•Per aggiungere una classe occorre prependere uno spazio
<ul class="latestusers<?php echo $moduleclass_sfx ?>" >
•$names = moduserslatestHelper::getUsers($params); in mod_users_latest.php
<?php foreach ($names as $name) : ?>
•Visualizzazione utenti come lista <li>
<?php echo $name->username; ?> </li>
•Chiusura dei tag PHP e HTML <?php endforeach; ?>
</ul> <?php endif; ?>
2/7/2013
50
SVILUPPO DI UN NUOVO MODULO
Visualizza articoli per autore
•Lista di articoli scritti dallo stesso autore
•Parametri per
•Quanti articoli mostrare
• In che ordine
Lista file mod_<tag>_articles_author
• language/en-GB/
•en-GB.<name>.ini
•en-GB.<name>.sys.ini
• tmpl
•default.php
•helper.php
•<name>.php
•<name>.xml
NUOVO MODULO – METADATI XML
<extension type="module" version="2.5.0" client="site" method="upgrade">
• Modulo area pubblica
<description>MOD_<TAG>_ARTICLES_AUTHOR_DESCRIPTION</description>
• Traduzione dal file .sys.ini
2/7/2013
51
NUOVO MODULO – METADATI XML – PARAMETRI: FIELDSET "BASIC"
<field name="count" type="text" default="5" label="..." description="..."></field>
• Campo tipo testo per il numero di articoli visualizzati, validazione debole
• Macro definite nel linguaggio
<field name="article_ordering" type="list" validate="options" default="a.title"....> <option value="a.title">...</option>
• Campo a scelta multipla, validazione forte tra le opzioni
• Macro lunghe (includono nome modulo) per evitare collisioni
NUOVO MODULO – METADATI XML – PARAMETRI: FIELDSET "ADVANCED"
Copiare mod_articles_archive.xml o altri moduli di front page
• Layout: nome del layout alternativo opzionale
• Module Class Suffix: suffisso classe CSS
• Caching: abilitare la cache
• Cache Time: numero di secondi in cache
• Cachemode: valore di tipo "hidden"; nascosto solo a livello UI =
scarsa validazione
2/7/2013
52
NUOVO MODULO – FILE PRINCIPALE
•JLoader::register('mod<Tag>ArticlesAuthorHelper', dirname(__FILE__).'/helper.php');
•Analogo a require_once ma con autoloading, ovvero jimport(...)
Caricare classe helper
•$list = mod<Tag>ArticlesAuthorHelper::getList($params); Carica articoli
•if (isset($list[0]))
•Analogo a count($list) ma più veloce Se esistono articoli
•$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx')); Carica suffisso CSS
•require JModuleHelper::getLayoutPath('mod_<tag>_articles_author', $params->get('layout', 'default'));
Include il rendering
NUOVO MODULO – CLASSE DI APPOGGIO (I)
•JLoader::register('ContentHelperRoute', JPATH_SITE.'/components/com_content/helpers/route.php');
Registra metodo di appoggio esterno
•Non si istanziano oggetti di questa classe
•abstract class mod<Tag>ArticlesAuthorHelper { Dichiara classe astratta
•public static function getList(&$params) { Dichiara funzione statica
•Per evitare log di livello NOTICE
•$items = array(); Inizializza variabile
•$option = JRequest::getCmd('option'); $view = JRequest::getCmd('view');
•if ($option == 'com_content' && $view == 'article') {
Visualizza articoli correlati solo se in pagina articolo
2/7/2013
53
NUOVO MODULO – CLASSE DI APPOGGIO (II)
•$db = JFactory::getDbo(); $app = JFactory::getApplication(); $user = JFactory::getUser(); Inizializza oggetti usati
•$id = JRequest::getInt('id'); Recupera id articolo
•$levels = implode(',', $user->getAuthorisedViewLevels()); Recupera i permessi
utente
•$date = JFactory::getDate();
•$now = $date->toSql(); $nullDate = $db->getNullDate(); Date di pubblicazione
•$query = $db->getQuery(true);
•$query->select('id, created_by, created_by_alias'); $query->from('#__content');
Recupera autore articolo
•$query->where('id = ' (int) $id);
•$db->setQuery($query); $currentArticle = $db->loadObject(); Conoscendo id articolo
(METODI COMUNI PER RESTITUIRE RISULTATI DI QUERY)
loadObject()
•Restituisce la prima riga della query come oggetto, ogni colonna è un campo
• Utile quando l'output è una singola tupla
loadObjectList()
• Restituisce un array di tutte le righe come oggetti
loadResult()
• Restituisce la prima colonna della prima riga
• Altri metodi in JDatabase (libraries/joomla/database/database.php)
2/7/2013
54
Pulizia query
Tutti i campi articolo e alcuni di categoria
Per eventuali layout override
Alias per overlap dei nomi
•Join delle tabelle
•Pubblicato
•Permessi per accedere
•Date di pubblicazione
In OR, default è AND
•Controllo sull'autore (per esercizio)
$q->clear();
$q->select('a.*');
$q->select('c.access AS cat_access, c.published AS cat_state, c.alias AS cat_alias');
$q->from('#__content AS a');
$q->leftJoin('#__categories AS c ON c.id = a.catid');
$q->where('a.state = 1');
$q->where('c.published = 1');
$q->where('a.access IN ('.$levels.')');
$q->where('c.access IN ('.$levels.')');
$q->where('(a.publish_up = '.$db->Quote($nullDate).' OR a.publish_up <= '.$db->Quote($now).')');
$q->where('(a.publish_down = '.$db->Quote($nullDate).' OR a.publish_down >= '.$db->Quote($now).')');
NUOVO MODULO – CLASSE DI APPOGGIO (III)
Escludere l'articolo corrente
Ricerca per lingua (specifica o generica = *)
Ordinamento e limiti secondo parametri
Creazione dei link per ogni item
"slug": id:alias (es. 23:mio-articolo)
ContentHelperRoute::getArticleRoute crea il link ottimizzato
JRoute::_() lo rende SEF
$q->where('a.id !=' . (int) $currentArticle->id);
if ($app->getLanguageFilter()) {
//Determina la lingua corretta se abilitata
}
$q->order( /*Ordinamento in base a parametri */)
$db->setQuery($q, 0, $params->get('count', 5));
$items = $db->loadObjectList();
$item->link = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug));
NUOVO MODULO – CLASSE DI APPOGGIO (IV)
2/7/2013
55
NUOVO MODULO – LAYOUT DEFAULT.PHP
•Classe di stile aggiuntiva
•<ul class="<tag><?php echo $moduleclass_sfx; ?>"> Lista non numerata
•<?php foreach ($list as $item) : ?> Ciclo su tutti gli
elementi
•<li><a href="<?php echo $item->link; ?>"> <?php echo $item->title ?></a></li>
Visualizza link e titolo
•<?php endforeach; ?> Fine del ciclo
•$list = mod<Tag>ArticlesAuthorHelper::getList($params);
•Variabile ancora in scope dopo il "require" Fine della lista
NUOVO MODULO – FILE DI LINGUAGGIO
Formato MACRO="Traduzione"
File .sys.ini: usato in Extension Manager o Module Manager
File .ini: usato in tutta l'estensione
2/7/2013
56
VALIDAZIONE DEI PARAMETRI IN JFORM – CONTROLLO DEI VALORI NELL'HELPER
<field name="count" type="text"> consente di inserire qualunque valore via form
Validato successivamente nell'helper
• $count = ( $count <= 0 || $count > 10 ) ? 5 : $count;
Svantaggi
• Non viene segnalato all'utente che il valore è errato
• Il valore errato viene comunque salvato
VALIDAZIONE DEI PARAMETRI IN JFORM – TIPO DI DATO
<field name="count" type="integer" first="1" last="10" step="1">
Svantaggi
• Range limitato all'utente (variabile con step)
• Non impedisce all'hacker di forzare un valore con Firebug
2/7/2013
57
VALIDAZIONE DEI PARAMETRI IN JFORM – FILTRO DI TIPO IN JFORM
<field name="count" type="text" filter="integer">
Sicuro (validato prima dell'inserimento, non può essere manipolato dal browser)
I filtri standard sono in JFilterInput e JForm
• integer, float, double, boolean
• word, cmd, base64, string, html, array, path, username
• rules, unset, raw, int_array, safehtml, server_utc, user_utc (novità in JForm)
VALIDAZIONE DEI PARAMETRI IN JFORM – REGOLA CUSTOM JFORMRULE
Aggiunta del path delle regole
• <fieldset name="basic" addrulepath="modules/ilmiomodulo">
Funzione di validazione (cerca un file .php con lo stesso nome)
• <field name="count" type="text" filter="integer" validate="countinteger">
2/7/2013
58
JFORM REGOLA CUSTOM – PRIMA SCREMATURA
• jimport('joomla.form.formrule'); Importa libreria
standard
•class JFormRuleCountInteger extends JFormRule { Definizione classe
•public function test ( & $element, $value, $group = null, & $input = null, & $form = null) {
Funzione di validazione test()
•return ((int) $value > 0 && (int) $value <= 30); Operatore di validazione
•} Chiusura funzione
•} Chiusura classe
JFORM REGOLA CUSTOM - PERFEZIONAMENTI
R E N D E R E P A R A M E T R I C I I L I M I T I H A R D C O D E D
Specificare
parametri nel
<field>
Richiamarli nel
metodo con
$element-
>getAttribute()
M E S S A G G I D I E R R O R E I N V A L I D A Z I O N E
if ( $result === false) {
$result = new JException(
JText::sprintf(MACRO MESSAGGIO DI ERRORE)
)
}
return $result;
2/7/2013
59
HANDS ON REGOLE DI VALIDAZIONE
Leggere ed analizzare la validazione delle opzioni implementata da validate=options
libraries/joomla/form/rules/options.php
PACKAGING DEL MODULO
Aggiornare i metadati XML con l'elenco di tutti i file
Creare un archivio (.zip e/o .tar.gz) con tutti i file contenuti nella directory modules/ilmiomodulo
Per convenzione mod_<tag>_<nome modulo>_1.0.0.zip
2/7/2013
60
RIASSUMENDO
Il modulo si integra nell'installazione di Joomla
Supporta il multilingua
Supporta layout alternativi e template layout
Consente all'utente di controllare il comportamento con alcuni parametri
Il codice è protetto da eventuali attacchi (SQL injection)
Può essere installato/disinstallato
Ulteriori consigli
• Non restituire errori: un modulo non è il contenuto principale del sito! Piuttosto loggare ed avvisare l'utente a posteriori
• Mantenere snelli e veloci i moduli (sono solo una piccola parte del contenuto della pagina)
2/7/2013
61
2 elementi costitutivi
Menu di navigazione
Contenuti visualizzati
2 aree di lavoro
Frontend e backend
CRUD Create Read Update Delete
I componenti sono unici
Sono l'elemento fondante di un sito Joomla
Gestiscono i contenuti ed i menu
Gestiscono il setup nel backend
Gestiscono tutti i task CRUD
Sono usati (oltre che per visualizzare) per gestire i form ed i metodi POST
COS'È UN COMPONENTE MVC DESIGN PATTERN
2/7/2013
62
STRUTTURA DI UN COMPONENTE BACKEND (WEBLINKS) (A)
MVC File Descrizione
Controllers /weblink.php Controller per un singolo weblink
Controllers /weblinks.php Controller per le liste
Helpers /weblinks.php Funzioni di aiuto in C e V
Models /fields/ordering.php
JFormField custom per l'ordinamento
Models /forms/weblink.xml XML JForm per aggiungere/modificare
Models /weblink.php Model per un singolo weblink
Models /weblinks.php Model per le liste
STRUTTURA DI UN COMPONENTE BACKEND (WEBLINKS) (B)
SQL /install.mysql.utf8.sql
SQL /uninstall.mysql.utf8.sql
Tables /weblink.php
Views /weblink/tmpl/edit_metadata.php Layout predefinito per i metadati
Views /weblink/tmpl/edit_params.php Layout predefinito per le opzioni
Views /weblink/tmpl/edit.php Layout per modificare un weblink
Views /view.html.php HTML output per un singolo weblink
2/7/2013
63
STRUTTURA DI UN COMPONENTE BACKEND (WEBLINKS) (C)
MVC File Descrizione
Views /weblinks/tmpl/default.php Layout predefinito per il Manager
Views /weblinks/view.html.php HTML output per il Manager
access.xml config.xml weblinks.xml
Metadati per ACL, configurazioni ed installazione
[Controller] controller.php Classe controller primaria
[Controller] weblinks.php Entry point del componente
STRUTTURA DI WEBLINKS – INSTALLAZIONE
Lista delle tabelle da creare/droppare in installazione/disinstallazione
Per le estensioni core installation/sql/mysql/joomla.sql contiene le
stesse indicazioni
Molte estensioni core possono comunque essere disinstallate
2/7/2013
64
STRUTTURA DI WEBLINKS – MENU DI BACKEND I menu in backend sono gestiti in modo diverso da quelli del
frontend
Definiti in weblinks.xml ed inseriti nella tabella #__menus in
installazione
STRUTTURA DI WEBLINKS – OPZIONI DEL COMPONENTE (PARAMETRI) Più complesse di quelle di moduli e plugin
Opzioni globali (icona Options nella toolbar)
• Gestite dal componente com_config
• Definite da config.xml e access.xml
2/7/2013
65
STRUTTURA DI WEBLINKS – CLASSI DI APPOGGIO I metodi di appoggio non rientrano nell'organizzazione Model-
View-Controller
Possono essere usate in diversi punti (tipicamente View e
Controller)
• addSubmenu() aggiunge i sottomenu in Weblinks Manager
(gestiti separatamente da weblinks.xml)
• getActions() determina le azioni consentite e mostrate in toolbar
• Ciò non protegge da hacking che modifica la PHP $_REQUEST
direttamente: occorre sempre validare i permessi nel controller prima di eseguire qualunque task!
STRUTTURA DI WEBLINKS – ENTRY POINT
administrator/com_weblinks/weblinks.php
• Controllo permessi per l'action core.manage
• jimport ('joomla.application.component.controller');
• $controller = JController::getInstance('Weblinks');
• $controller->execute(JRequest::getCmd('task'));
• $controller->redirect();
2/7/2013
66
IL CONTROLLER IN AZIONE – ESEMPIO 1
Utente seleziona menu Componenti > Weblinks
URL administrator
/index.php?option=com_weblinks
Task - (predefinito display)
Controller WeblinksController (controller.php)
Controller
method
display()
Controller
redirect
-
IL CONTROLLER IN AZIONE – ESEMPIO 2A
Utente clicca su un elemento per modificarlo: verifica dei permessi
URL administrator/index.php?option=com_weblinks&task=weblink.edit&id=7
Task weblink.edit (split controller.task)
Controller WeblinksControllerWeblink (controllers/weblink.php)
Controller method
JControllerForm->edit() (metodo della classe padre, non esiste nel controller: verifica permessi e salva id in sessione)
Controller redirect
index.php?option=com_weblinks&view=weblink&layout=edit&id=7 (reale form di modifica del contenuto)
2/7/2013
67
IL CONTROLLER IN AZIONE – ESEMPIO 2B
Utente clicca su un elemento per modificarlo: modifica del contenuto
URL administrator/index.php?option=com_weblinks&view=weblink&layout=edit&id=7
Task - (predefinito display)
Controller WeblinksController (controller.php)
Controller method
WeblinksController->display() La view ed il layout sono definiti per la modifica L'id specificato viene verificato contro quello in
sessione per prevenire hijacking
Controller redirect
-
IL CONTROLLER IN AZIONE – ESEMPIO 3 Utente clicca su Salva&Chiudi nel form di modifica
URL administrator/index.php?option=com_weblinks&layout=edit&id
=7
Task weblink.save (non in URL ma in
onclick="javascript:Joomla.submitbutton('weblink.save')")
Controller WeblinksControllerWeblink (controllers/weblink.php)
Controller
method
JControllerForm->save()
L'id specificato viene verificato contro quello in sessione per
prevenire hijacking
I permessi vengono verificati
I dati vengono validati via ->validate() del modello
I dati vengono salvati via ->save() del modello
Controller
redirect
index.php?option=com_weblinks&view=weblinks (può differire
a seconda di Salva&Nuovo o Salva)
2/7/2013
68
IL CONTROLLER IN AZIONE – ESEMPIO 4A Utente cestina alcuni weblinks
URL administrator/index.php?option=com_weblinks&view=weblinks
Task weblink.trash (da javascript onclick)
Controller WeblinksControllerWeblinks (controllers/weblinks.php)
Controller method
JControllerAdmin->publish() Il task trash viene mappato in publish dall'array $taskmap • Nel costruttore di JController – parent di JControllerAdmin – vengono
prima registrati i metodi pubblici ispezionati via reflection (checkin, display, publish, reorder, saveorder)
• Nel costruttore viene registrato il default come display
($this->registerDefaultTask) • Nel costruttore vengono mappate le alternative
($this->registerTask('trash', 'publish') e altri)
Controller redirect
administrator/index.php?option=com_weblinks&view=weblinks
IL CONTROLLER IN AZIONE – ESEMPIO 4B
Dal controller al model
• Siamo nel metodo publish() di WeblinksControllerWeblinks, implementato nel parent JControllerAdmin
• Verifiche sul token utente
• $this->getTask() settato dalla execute($task) di JController per decidere il valore da modificare
• $this->getModel() è l'unico metodo implementato realmente in WeblinksControllerWeblinks
• public function getModel ( $name = 'Weblink', $prefix =
'WeblinksModel', ...) {
• $model = parent::getModel($name, $prefix, ...);
2/7/2013
69
IL CONTROLLER IN AZIONE – ESEMPIO 4C
Dopo aver ottenuto il model corretto (WeblinksModelWeblink) in JControllerAdmin
$model->publish($cid, $value) effettua la modifica
Il controller imposta il messaggio da restituire
Il controller imposta il redirect
• $this->setRedirect( JRoute:: ...)
RIASSUNTO DI METODI, TASK E CLASSI NEI CONTROLLER DI WEBLINKS WeblinksController (controller.php)
• Contiene solo display(): è l'unico metodo che visualizza qualcosa a schermo
WeblinksControllerWeblinks < JControllerAdmin < JController gestisce le schermate "plurali"
• Implementa solo getModel()
WeblinksControllerWeblink < JControllerForm < JController gestisce le schermate "singolari"
• Implementa due metodi privati
• Mappa apply, save2new e save2copy a save
2/7/2013
70
Entry point del componente MVC
Decidere il controller per il task
Eseguire il task dal controller
Eseguire, se necessario, un redirect
Regole di inferimento del nome del controller (componente + parte del task)
Se il task è diverso da display • Svolge operazioni • Reindirizza ad un display
I task sono mappati su metodi del controller
• Realmente implementati • Definiti con registerTask()
WORKFLOW DEL CONTROLLER IL MODEL IN AZIONE "SINGOLARE" O "PLURALE"
A seconda del controller
Esplicito "cast" a singolare nel caso del controller plurale, altrimenti automatico in getModel() di JControllerForm
2/7/2013
71
Controller Model
add() controlla permessi e redirige a edit
-
edit() verifica permessi + lock e redirige
getTable() checkout() getError()
cancel() redirige al manager checkin()
publish() checkin() delete()
reorder() save() saveorder()
chiamate corrispondenti in WeblinksModelWeblink < JModelAdmin < JModelForm <
Jmodel
IL METODO PUBLISH() – PRIMA PARTE
Dal controller if (!$model->publish(...)) raise warning
Nel model function publish(&$pks, $value = 1) //$pks chiamato by reference
• $dispatcher = JDispatcher::getInstance(); // per i trigger di eventi
• $user = JFactory::getUser();
• $table = $this->getTable();
• $pks = (array) $pks; // modifica array o singolo item
• JPluginHelper::importPlugin('content'); //trigger plugin di tipo content onContentChangeState
2/7/2013
72
IL METODO PUBLISH() – SECONDA PARTE
foreach ($pks as $i => $pk)
• $table->reset(); // reset colonne a valori default
• if ($table->load($pk)) // carica l'item
• if (!$this->canEditState($table)) // verifica permesso
• unset($pks[$i]) // l'item viene rimosso dalla lista, restituita (by reference) al controller, che invierà il messaggio corretto sul numero di item effettivamente modificati
• raiseWarning su permessi e return false
IL METODO PUBLISH() – TERZA PARTE
Verifica del permesso di modifica protected function canEditState($record) // metodo protetto
• $user = JFactory::getUser();
• if (!empty($record->catid)) // i weblinks hanno sempre una categoria
• return $user->authorise( 'core.edit.state', 'com_weblinks.category.' . (int) $record->catid); // permessi definiti nell'access.xml
• else
• return parent::canEditState($record);
2/7/2013
73
IL METODO PUBLISH() – QUARTA PARTE
if ( !$table->publish(...) ) // Questo statement chiama la funzione di $table che opera realmente sul db
• $this->setError($table->getError());
$result = $dispatcher->trigger(...) // trigger per i plugin onContentChangeState
• if (in_array(false, $result, true))
• $this->setError($table->getError()); // lo sviluppo di plugin customizzati può intervenire sul workflow della pubblicazione
(ed altri)
$this->cleanCache(); // pulisce la cache in modo da visualizzare informazioni aggiornate
IL METODO SAVE() DI JMODELFORM
$form = $model->getForm($data, false);
• // ottiene un'istanza di oggetto JForm
$validData = $model->validate($form, $data);
• I dati vengono validati secondo il metodo definito in JModelForm
• $data = $form->filter($data); // i dati vengono filtrati per eliminare dati non corretti – nessuna notifica
• $return = $form->validate($data); // i dati vengono validati in
base al contesto – tipicamente notifica all'utente per reinserire dati corretti (una data in un campo data, etc.)
2/7/2013
74
GENERICO COMPORTAMENTO DEI METODI DEL MODEL
Azioni preliminari
del controller
Chiama il model
•Metodo del model con lo stesso nome
Riceve messaggio
•Fallimento o successo
Restituisce true o false
APPROFONDIMENTO SULL'ACCESSO AL DB
L'accesso al db dal model avviene attraverso la classe table (WeblinksTableWeblink)
• load(): ereditata da JTable, carica una riga ed associa le colonne del db ai rispettivi campi dell'istanza di JTable
• bind(): ha come input un array associativo o oggetto e carica ciascun elemento in un campo di JTable; gestisce anche da serializzare (JSON, ad es.)
• check(): controlla dati non validi o senza senso; non implementato dal parent JTable
• store(): aggiorna dati esistenti ed il modified_by, oppure crea nuovi dati e il created_by; verifica duplicati di categoria ed alias
2/7/2013
75
LE VIEW ED IL METODO DISPLAY()
Una view viene mostrata quando non ci sono task o quando il task è display
WeblinksController (controller.php) implementa il metodo
display() di 2 viste
• Vista Weblinks (default): lista dei links
• Vista Weblink: per aggiungere/modificare un singolo elemento
2/7/2013
76
LA VISTA WEBLINKS
public function display(...)
• // vista e layout predefiniti, campo id vuoto
• // controlla se si trova in una vista "weblink" con layout "edit"
• parent::display();
• return $this; // method chaining (verificare con l'entry point del modulo, rende possibile $oggetto->metodo1()->metodo2())
IL METODO DISPLAY() DI JCONTROLLER
Definisce un $document di tipo JDocumentHTML
Definisce la vista "weblinks", il layout "default" e la view class "WeblinksViewWeblinks"
Ottiene il $model "WeblinksModelWeblink"
Ottiene la $conf da JFactory::getConfig()
Verifica che la pagina sia in cache ed eventualmente la carica
Altrimenti esegue il metodo display() della vista (in views/weblinks/view.html.php)
2/7/2013
77
IL METODO DISPLAY() DI WEBLINKS VIEW WEBLINKS
$this->state = $this->get('State') e analoghi
• Ottiene il model e cerca un metodo getState()
• Spesso ereditati da JModel e JModelList
// Check for errors
$this->addToolbar();
• Aggiunge icone New, Edit, Publish, ... gestite da mod_toolbar
(renderizzato più tardi nel ciclo)
parent::display($tpl);
• Chiama JView (libraries/joomla/application/component/view.php)
IL METODO DISPLAY() DI JVIEW
$result = $this->loadTemplate($tpl);
• Il template viene incluso in questo metodo con include $this->_template;
• Template predefinito in views/weblinks/tmpl/default.php
• Ad esempio con template Hathor, invece di Bluestork, override in administrator/templates/hathor/html/com_weblinks/weblinks/default.php
if (JError::isError($result)) return $result;
echo $result;
• Output inviato all'output buffer avviato con ob_start()
2/7/2013
78
IL LAYOUT PREDEFINITO: LE SEZIONI VISUALIZZATE A SCHERMO
Filtro titoli Filtri di
selezione a tendina
Box per il check-all
Titoli colonne ordinabili
Elementi Weblink effettivi
Controlli paginazione
LAYOUT: PREPARAZIONE
Include il path administrator/com_weblinks/helpers/html
• Per classi e metodi JHtml specifici richiamabili con JHtml::_(...)
• Creare una classe JHtml<Componente> nella cartella, richiamato con JHtml::_('componente.metodo', 'argomenti')
Imposta variabili usate successivamente
• Il template è nello scope di WeblinksViewWeblinks, $this si riferisce a questa
Apre il form con action=URL corrente e method=POST
2/7/2013
79
LAYOUT SEZIONE A: FILTRO TITOLI
Analizzare il contenuto di <div class="filter-search fltflt">...</div>
LAYOUT SEZIONE B: LE SELECT LIST DI FILTRAGGIO
Inserisce 4 filtri per stato di pubblicazione, categoria, accesso e linguaggio
Usa JHtml::_('select.options') che chiama il metodo JHtmlSelect::options() con 5 argomenti
• Array di valori, proveniente dal risultato di JHtmlGrid::publishedOptions()
• Nome della variabile, settato a "value"
• Nome dell'opzione, settato a "text"
• Valore selezionato, proveniente da $this->state->get('filter_state')
• Booleano se tradurre i testi e le label
Verificare l'output HTML risultante
Le altre select list sono costruite in modo analogo
2/7/2013
80
LAYOUT SEZIONE C: LA CASELLA CHECK-ALL
<input type="checkbox" name="checkall-toggle" value="" onclick="Joomla.checkAll(this)" />
Chiama media/system/js/core.js
Loop su tutte le check box e seleziona/deseleziona
LAYOUT SEZIONE D: COLONNE ORDINABILI
Esempio di ordinamento del titolo, effettuato con JHtml::_('grid.sort', ...
• Titolo: "JGLOBAL_TITLE"
• Campo di ordinamento: "a.title" nella tabella #__weblinks
• Direzione di ordinamento: $listDirn (impostato nella fase preliminare)
• Ordinamento selezionato: $listOrder (come sopra)
Le altre colonne in modo analogo
2/7/2013
81
LAYOUT SEZIONE E: TABELLA DEGLI ITEM
Inserita tra tag <tbody>, un elemento per riga <tr>, un campo per colonna <td>
• Select box generata da JHtmlGrid::id()
• Per esercizio analizzare la cella del titolo
• Codice per visualizzare l'icona di checkin/checkout
• Aggiunge l'URL cliccabile solo se si hanno i permessi
• I testi sono inseriti con ->escape() per prevenire codice malizioso
• Per esercizio analizzare la cella di ordinamento
LAYOUT SEZIONE F: CONTROLLI DI PAGINAZIONE
<tfoot>... $this->pagination->getListFooter();
L'oggetto pagination proviene dal metodo getPagination() del model
• A sua volta è un'istanza di JPagination (non approfondita in questa sede)
La maggior parte del codice presentato in questa vista è riutilizzabile/riutilizzato in gran parte di altre estensioni
2/7/2013
82
IL METODO DISPLAY() DI WEBLINKSVIEWWEBLINK
Classe usata per aggiunta o modifica di un singolo item (views/weblink/view.html.php)
$this->state chiama $model->getState() come nella vista
precedente
$this->item chiama ->getItem() di JModelAdmin
• Carica l'item se esistente e crea oggetto JRegistry per i parametri
$this->form chiama ->getForm() di JForm
IL WORKFLOW DI GETFORM()
WeblinksModelWeblink getForm()
JModelForm loadForm()
WeblinkModelWeblink loadFormData()
JModelForm loadForm()
JModelForm preprocessForm()
JModelForm loadForm()
JForm bind()
2/7/2013
83
WEBLINKSMODELWEBLINK GETFORM()
$form = $this->loadForm(...)
• Parametri: $name, $source ed array di opzioni
JMODELFORM LOADFORM()
$form = JForm::getInstance(...) • In blocco try/catch per sollevare eccezioni • Controlla che $data sia una stringa contenente l'XML o un file XML:
in questo caso $data = 'weblink' • Caricato con loadFile() di JForm dal file
models/forms/weblinks.xml
$data = $this->loadFormData() • Carica i dati dalla sessione (ad es. per un form parzialmente
completato , con getUserState()) o dai valori di un item esistente o di default per un item nuovo (con getItem)
$this->preprocessForm($form, $data) • Trigger evento onContentPrepareForm per i plugin che possono
modificare sia $form che $data
$form->bind($data) • Match ed associazione tra i form fields ed i dati
2/7/2013
84
RENDERIZZAZIONE DEL JFORM (IN VIEWS/WEBLINK/TMPL/EDIT.PHP)
Tipicamente ogni campo nella forma
• $this->form->getLabel() per stampare la label
• $this->form->getInput() fa il rendering dell'elemento del form opportuno
L'area laterale è costruita da
• JHtml::_('sliders.start', ...) e JHtml::_('sliders.panel' ...)
L'area dei parametri è renderizzata da
• $this->loadTemplate('params') chiama ./edit_params.php
• Qua viene usato un ciclo foreach su tutto il fieldset nested presente nell'XML: questa tecnica viene usata per presentare i parametri di moduli, plugin, template e linguaggi
2/7/2013
85
IL COMPONENTE WEBLINKS DI FRONTEND
Focus solo sulle similitudini e differenze dal backend
Simile struttura di cartelle e pattern MVC
• No dati di installazione (solo nel backend)
• No gestore table (solo nel backend)
STRUTTURA DEL FRONTEND MVC File Descrizione
Controllers/ /weblink.php Controller per la schermata singola entry
Helpers/ /{category,icon,route}.php Funzioni di appoggio
Models/ *.php Model
Models/ /forms/weblink.xml JForm XML
Views/ /categories/view.html.php Vista per menu categorie
Views/ /categories/tmpl/* Layout per menu categorie; XML per opzioni menu
Views/ /category/view.{html,feed}.php Vista per singola categoria
Views/ /category/tmpl/* Layout per singola categoria; XML per opzioni menu
Views/ /form/view.html.php Vista per creare menu item
Views/ /form/tmpl/* Layout per il form; XML per opzioni menu
router.php Router del componente
[Controller] controller.php Predefinito per task display
[Controller] weblinks.php Entry point del componente
2/7/2013
86
STRUTTURA GENERALE
Entry point identico a quello del backend
• JController::getInstance('Weblinks')->execute( JRequest::getCmd('task'))->redirect();
3 viste, ciascuna estende JView, ha layout caricati da loadTemplate(), ed ha model
• Categorie: visualizza tutte le categorie
• Categoria: visualizza i weblink in una categoria
• Hanno solo funzione display, sono gestite da
WeblinksController (controller.php)
• Form: visualizza il form per inviare un weblink
• Gestita da WeblinksControllerWeblink, task add/edit/save
PECULIARITÀ DEL COMPONENTE WEBLINKS
Il model per il form WeblinksModelForm eredita WeblinksModelWeblink di backend (per usare il metodo save())
La WeblinksModelWeblink di frontend serve a gestire i task prima di redirigere un elemento weblink alla sua destinazione remota (non ha un template/layout proprio)
• Il controller lancia il task go()
• Il model di frontend verifica i permessi, la pubblicazione ed incrementa l'hit counter
2/7/2013
87
UNA DIFFERENZA IMPORTANTE TRA BACKEND E FRONTEND: I MENU ITEM
In backend i menu sono predefiniti ed immodificabili
administrator/components/com_weblinks/weblinks.xml
• In frontend i menu sono modificabili tra 3 tipi
Lista categorie: views/categories/tmpl/default.xml
Lista link in categoria: views/category/tmpl/default.xml
Invia un link: views/form/tmpl/edit.xml
I MENU ITEM IN FRONTEND: VIEWS/CATEGORY/TMPL/DEFAULT.XML
Field "id" nella lista "request"
• Inserito nell'URL come <name> = <value> (id=5) e disponibile nella $_REQUEST
I field nella lista "params"
• Salvati in #__menus come gli altri, ma serializzati da JRegistry in JSON
I field standard (Link type options, Page display options, Metadata options)
• administrator/components/com_menus/models/forms/item_component.xml
• Validi per quasi tutti i tipi di menu item (eccetto External URL, Menu item alias e Text separator)
2/7/2013
88
IL ROUTING DI FRONTEND
Router: classe che traduce URL in array di comandi (parse()) e viceversa (build())
Ragioni del SEF URL
• In admin non interessano nè motori di ricerca nè leggibilità
• Inizialmente motori non abili a parsare query string ma solo URL statici
• Ora fanno l'indexing anche di URL con query string
• Più che SEF possiamo parlare di "human-friendly"
Obiettivo: una stessa pagina
raggiungibile da catene di link diversi
Soluzione: fornire lo stesso URL da
qualunque posizione
Nella definizione del
router di Weblinks, una
vista di singola
categoria è preferibile
ad una vista generica
In altre parole, un link più
specifico ha sempre la
precedenza
IL METODO "BEST FIT"
2/7/2013
89
LA VISTA "NEWS FEED" DEL FRONTEND
Peculiare del frontend, genera contenuti per i news reader
Metodo _prepareDocument() chiamato da display() di views/category/view.html.php
• Genera link con format=feed e type=rss/atom
Vista generata da JDocumentHTMLFeed
• Chiama views/category/view.feed.php
• Genera dei JFeedItem e li aggiunge al JDocumentFeed via addItem()
2/7/2013
90
SOMMARIO
Concetti di base dei RDBMS
• Focus su MySQL, ma concetti generali applicabili a tutti gli engine
Query SQL
Istanza di JDatabaseQuery per costruire le query in Joomla
Database
•Joomla configuration.php
Table
•Collezione di record
Row (tuple)
•Un set di dati
Column (field, attribute)
•Un dato specifico
L'idea di base dei RDBMS:
consentire accesso ed
interazione ai dati dal
punto di vista logico
(con un linguaggio
specifico – SQL)
indipendentemente
dalla loro archiviazione
fisica
PANORAMICA SUI DATABASE
2/7/2013
91
TIPOLOGIE DI STATEMENT
D D L ( D A T A D E F I N I T I O N )
I dati sono strutturati, devono essere definiti in anticipo
• Creazione delle tabelle
• Definizione dei tipi di
dati nelle colonne
• Gestione dei permessi
di accesso
D M L ( D A T A M A N I P U L A T I O N )
Comandi per l'interrogazione del DB e la manipolazione dei dati
• SELECT
• INSERT / REPLACE
• UPDATE
• DELETE
STATEMENT DDL
Tipicamente solo negli script di installazione
• La struttura dei dati deve essere definita prima di essere usata
Specifici per il motore
• Sintassi simile ma non identica
Installazione del core
• installation/sql/mysql/joomla.sql
2/7/2013
92
CREATE TABLE
CREATE TABLE <tabella> ( <lista di colonne>, <lista di indici> ) <character set>
• <tabella>: #__banner_clients
• Carattere ` per racchiudere parole riservate (circa 200 in MySQL)
• <colonna>: <nome> <tipo> <attributi>
• `id` INTEGER NOT NULL AUTO_INCREMENT
• <indice>: INDEX <idx_nome> ( <colonne> )
• INDEX `idx_own_prefix` ( `own_prefix`)
• <character set>: DEFAULT CHARSET=utf8
INDICI E CHIAVI
C H I A V I
Chiave primaria identifica univocamente un record nella tabella
Usata per riferimenti su tabelle esterne (foreign key)
Singolo dato definito da • NOT NULL • AUTO_INCREMENT
Chiave definita da • PRIMARY KEY (`id`)
I N D I C I
Letture + veloci, scritture + lente
Importanti per grandi tabelle
Utili sugli elementi per cui si selezione, raggruppa o odina
Con UNIQUE utili per evitare set di dati duplicati
Per convenzione idx_<nome>
2/7/2013
93
TIPI DI DATI
• Intero signed o unsigned, n indica solo le cifre in display INT/INTEGER(n)
•0-255, per riferimenti a liste limitate, cast a (int) facilitato TINYINT
•Testo di lunghezza max definita (2^16 / 3 char) VARCHAR(n)
•Testo di lunghezza fissa, raramente usato CHAR(n)
•YYYY-MM-DD HH:MM:SS DATETIME
•Testo max 2^16 caratteri, per keyword e JSON TEXT
•Testo max ~16MB, per articoli e descrizioni MEDIUMTEXT
•Valore decimale di n cifre e p precisione DECIMAL(n,p)
•23 e 53 cifre significative FLOAT e DOUBLE
ATTRIBUTI DELLE COLONNE
NOT NULL
•True, false e null sono 3 valori diversi
AUTO_INCREMENT
• Insieme a INTEGER, definisce un campo che si autoincrementa
DEFAULT
•Definisce un valore predefinito se non specificato
•Utile insieme a NOT NULL
UNSIGNED
• INTEGER o TINYINT solo positivi
2/7/2013
94
ALTER E DROP TABLE
ALTER TABLE <table>
• CHANGE <colonna> <colonna> <tipo> <attributi>
• Non cancella dati esistenti finchè sono contenibili nel nuovo tipo
• ADD COLUMN <colonna> <tipo> <attributi> BEFORE/AFTER <colonna>
DROP TABLE <tabella>
• Cancella la tabella (compreso il suo schema) e tutti i dati
STATEMENT DML
Strumenti di interrogazione e manipolazione dei dati
• SELECT
• UNION
• UPDATE
• INSERT
• DELETE
2/7/2013
95
QUERY DI SELEZIONE (SELECT)
SELECT <lista colonne e espressioni>
FROM <tabella primaria>
JOIN <lista di condizioni di join con altre tabelle>
WHERE <condizioni di selezione>
GROUP BY <raggruppamento>
HAVING <condizioni di selezione sul raggruppamento>
ORDER BY <condizioni di ordinamento>
LIMIT <offset e conteggio record>;
SELECT QUERY NEL DETTAGLIO
•SELECT a.* FROM jos_content AS a
•Alias per semplificare la scrittura Lista delle colonne
•FROM jos_content AS a Tabella primaria
•INNER JOIN jos_categories AS c ON a.catid = c.id
•Differenza tra INNER e LEFT Unione di dati
•WHERE a.state = 1 AND c.title = 'Plugins'
•Condizioni con AND/OR e NOT, LIKE per le stringhe Condizione di selezione
•ORDER BY a.created_by_alias ASC Ordinamento
•LIMIT 5,10 (= 10 record a partire dal quinto) Limitazioni
•Raggruppamento su un attributo; sono selezionabili solo campi raggruppati o espressioni calcolate: MIN(), MAX(), AVG(), SUM(), COUNT() e COUNT(DISTINCT) Aggregati
2/7/2013
96
•UPDATE jos_content UPDATE
<tabella>
•SET created_by_alias = 'Myself', created = '2013-01-01 12:00:00'
SET <lista colonne=valori>
•WHERE created_by_alias = 'Joomla'
WHERE <condizioni>;
•DELETE FROM jos_content_frontpage
DELETE FROM <tabella>
•WHERE contend_id = 35 WHERE
<condizioni>;
• INSERT INTO jos_content_frontpage
INSERT INTO <tabella>
• (content_id, ordering)
•Lista delle colonne con valori, le altre avranno default)
(<colonne>, ...)
•VALUES (8,2), (35,4);
•Più righe contemporaneamente
•Usa NULL per colonne AUTO_INCREMENT
VALUES (<valori>,
...);
QUERY DI AGGIORNAMENTO, INSERIMENTO E CANCELLAZIONE
Entity – Relationship
Minimizzazione delle
informazioni
Esempio basato su DB
per una scuola • Studenti
• Insegnanti
• Classi
3 tipologie di tabelle • Reference: rappresentano
le informazioni statiche di un'entità
• Mapping: per la
mappatura n-m
• History: per la
conservazione dei dati
(log, storici acquisti)
DISEGNO DELLA STRUTTURA DELLE TABELLE (SCHEMA)
2/7/2013
97
REFERENCE E MAPPING TABLE
R E F E R E N C E
Studenti: informazioni statiche (nome, indirizzo, età, ...)
Insegnanti: informazioni statiche
Classi: nome, descrizione, dipartimento, date
Dipartimenti: nome e descrizione
Ciascuna riga di ogni tabella rappresenta un'entità concreta
M A P P I N G
Per le relazioni molti a molti
• Ad esempio ogni studente partecipa a più classi; ogni classe ha più studenti • student_class_map con
student_id e class_id
• Esercizi: selezionare gli studenti di una classe e le classi di uno studente
HISTORY TABLE
Dati "dinamici", riguardano eventi o transazioni
Ad esempio storico delle classi completate da uno studente
• student_class_history (history_id, student_id, class_id, semester, date_completed, class_grade, comments)
2/7/2013
98
LAVORARE CON IL DATABASE IN JOOMLA!™
JTable gestisce la maggior parte dei task di insert, update e delete
• Non quelli per le tabelle di mapping
JDatabaseQuery crea lo statement SQL
• JDatabaseQueryMySQLi implementa il driver specifico
• $query = JFactory::getDbo()->getQuery(true)
• NO $query = new JDatabaseQuery()
JDatabase lo esegue e restituisce i risultati
SQL JDatabaseQuery
Lista di colonne select()
FROM from()
INNER JOIN innerJoin()
LEFT JOIN leftJoin()
WHERE where()
ORDER BY order()
GROUP BY group()
LIMIT Implementato in JDatabase
setQuery($query, $start,
$offset)
La costruzione può
essere fatta in qualunque ordine
__toString() riordina
lo statement SQL
Method chaining • $query->select()-
>from()
COSTRUIRE SELECT CON JDATABASEQUERY
2/7/2013
99
PROTEZIONE DELLE QUERY
Tutte le variabili provenienti da sorgenti esterne devono essere controllate
Cast di valori interi: (int) $catid
Escape dei caratteri speciali via quoting del testo: $db->quote() dell'oggetto
JDatabase
COSTRUIRE INSERT CON JDATABASEQUERY
Alternativa con set()
Ogni valore inserito singolarmente
$q->set('chiave= ' . $valore)
Alternativa con columns() e values()
Valori inseriti in gruppo
Lista delle colonne $q->columns( 'colonne,...' )
Lista dei valori $q->values( 'valori,...')
2/7/2013
100
COSTRUIRE UPDATE E DELETE CON JDATABASEQUERY
Metodi analoghi a quelli precedenti
UPDATE
• update()->set()->where()
DELETE
• delete()->from()->where()
ESECUZIONE DELLE QUERY DI MANIPOLAZIONE Modificano il DB ma non restituiscono dati
• Passare la query all'oggetto DB con setQuery()
• Eseguire la query con query()
• Verificare errori ed eventualmente processarli
• $db->getErrorNum() e $db->getErrorMsg() hanno informazioni sul'errore su database
Esempio
• $db->setQuery($query);
• if ($db->query()) {
• return true;
• else
• $this->setError(JText::_('MACRO_ERRORE')); return false;
2/7/2013
101
ESECUZIONE DELLE QUERY DI INTERROGAZIONE Restituiscono dati ma non modificano il DB
• Passare la query all'oggetto DB con setQuery()
• Usare uno dei metodi di caricamento dei dati
• Verificare errori ed eventualmente processarli
Esempio
• $db->setQuery($query, $limitstart, $limit);
• $data = $db->loadObjects();
• if ($db->getErrorNum()) {
• $this->setError(JText::_('MACRO_ERRORE')); return false;
• else
• return $data;
JDatabase Return Descrizione
loadObject() Oggetto Prima riga
loadObjectList() Array di oggetti Tutte le righe
loadResult() Mixed Prima colonna della prima riga
loadColumn() Array Array di una colonna
loadAssoc() Array associativo
Prima riga
loadAssocList() Array di array associativi
Tutte le righe
loadRow() Array con indici Prima riga come array
loadRowList() Array di array Tutte le righe
Esempio 1 • $dbo->loadObjectList(); • foreach ($d as $row) • $title = $row->get('title'); • $id = $row->get('id'); • ...
Esempio 2 • $dbo->loadAssocList(); • foreac ($d as $row) • $title = $row['title']; • $id = $row['id'];
RESTITUIRE I DATI DI UNA QUERY DI INTERROGAZIONE
2/7/2013
102
STRUTTURA DEI FILE
PHP è un linguaggio interpretato
• Il codice sorgente viene letto ad ogni esecuzione
Tipicamente estensione .php
• Il codice è racchiuso tra tag <?php ... ?>
• Tag di chiusura omesso in file solo php
PHP ed HTML nello stesso file possibile
• Soprattutto nei template
Gli spazi (spazi, tabulazioni, ritorni carrello) sono ignorati,
aumentano leggibilità
2/7/2013
103
Carattere Utilizzo
/* */ // Commenti lunghi e inline
; Terminatore di ogni statement
{ } Blocchi di codice
( ) Metodi di funzione; condizioni logiche; valori di array; espressioni; cast
$ Prefisso di ogni variabile
-> Chiamata di metodo di oggetto
:: Chiamata di metodo statico
[ ] Valori di array
=> Key/value in array associativi
' e " Delimitatori di stringa
Carattere Utilizzo
, Separatore di argomenti
. Concatenatore di stringa
= Operatore di assegnazione
= > < e simili Operatori logici
! || e && Connettivi logici
? : Operatore ternario
\ Carattere di escape
+ - * / Operatori matematici
& Nella signature di un metodo indica che il parametro sarà passato by-reference
CARATTERI IMPORTANTI OPERATORI DI FREQUENTE UTILIZZO
Dichiarazione di variabili ed operazioni
• $a = 'valore'; $a .= 'suffisso';
• $x = 1; $x += 1;
Operatore di cast per forzare il tipo
• $c = (string) $b; $c = (int) $d;
Operatori logici per la verifica delle condizioni
• ($a == $b) oppure ($a === $b)
• Equivalenza vs Identità
• ($a == $b && $c != $d)
• Lazy evaluation e differenze tra && e and
2/7/2013
104
STATEMENT CONDIZIONALI
if: codice classico
• if ( condizione ) {
• // esegui se condizione è true
• } else {
• // esegui se condizione è false
• }
Varianti di if
• Condizione con assegnamento
• if ( $link = $db -> loadResult() )
• Esegue metodo, assegna alla variabile, valuta che non sia null
• Sostituzione con operatore ternario
• $a = ( $b == $c ) ? $d : $e
switch: codice classico
• switch ($a) {
• case 'abc':
• // esegui se $a=='abc'
• break;
• default:
• // esegui se nessuno dei precedenti
• break;
• }
STATEMENT DI CICLO
foreach ( $array as $key => $value ) { ... }
• $key non obbligatorio
for ( $i = 0; $i < $max; $i++ ) { ... }
while ( $a != $b ) { ... }
• continue; // Salta il resto dell'iterazione per questo ciclo: da evitare
2/7/2013
105
SINTASSI ALTERNATIVA
Utile in caso di codice mixed con HTML
<?php if ( $a == $b ) : ?>
• codice misto PHP + HTML
• <p>This is a <?php echo 'test'; ?></p>
<?php endif; ?>
<?php foreach ( $groups as $group ) : ?>
• <p><?php echo $group; ?></p>
<?php endforeach; ?>
VARIABILI
Scalare
• Prefisso $var
• Case sensitive
• Non dichiarare ma inizializzare
• Scope del blocco in cui sono usate
• Un file incluso equivale al file stesso
• Costanti con define()
Array
• $simple = array( 'valore1', 'valore2');
• echo $simple[0];
• $assoc = array( 'name' => 'Me', 'age' => 12);
• echo $assoc['age'];
Stringa
• Variabile contenente caratteri
• Funzioni builtin di PHP oppure metodi statici di JString (libraries/ joomla/utilities/ string.php)
2/7/2013
106
FUNZIONI E METODI
function <nome> ( <argomenti> ) {
• // codice della funzione
Linguaggio procedurale: funzioni
OOP: classi, istanze di classe e metodi
Scope degli argomenti: locale alla funzione, anche se dovessero avere lo stesso nome
• Per passare i valori by reference, aggiungere & nella signature
• NON si può fare call-time pass-by-reference
FILE ED INCLUSIONE
T I P I D I F I L E C O M U N I
Dichiarazioni di classi
•class <nome> { <campi>; <metodi>; }
•Codice eseguito solo quando chiamato (oggetti istanziati o metodi statici)
Dichiarazioni di funzioni
•Non possono essere inclusi con jimport
•Esempi templates/system/html/modules.php o components/com_content/router.php
Script semplici
•Esempio index.php
•Eseguiti immediatamente
I N C L U S I O N E D I F I L E
include • Errore se contiene classe o funzione
già dichiarata
include_once
require • Come include ma il file deve
esistere
require_once
JLoader::register() • Metodo consigliato per le classi
jimport() • Shortcut se classe e nome seguono
la convenzione
2/7/2013
107
CONCETTI BASE DI PROGRAMMAZIONE AD OGGETTI
Classe
• Definisce un tipo di entità
• Possiede attributi e metodi
• Ha un metodo __construct() per definire la creazione di un oggetto
Oggetto
• Istanziazione concreta di una classe
• JFactory::get<Name>(): per gli oggetti globali (singleton)
• ::getInstance(<params): per oggetti che implementano il metodo (es. JTable::getInstance('Client', 'BannersTable'))
• new <Class>(): oggetti con istanze multiple, passa gli argomenti al costruttore
EREDITARIETÀ ED OVERRIDING
class JDocumentHTML extends JDocument
• Una classe più specifica eredita le proprietà da una classe più generica
Method overriding
• La classe figlia può ridefinire i metodi implementati dalla classe padre (con stessa signature)
• Chiama il metodo padre con parent::<metodo>
• Modificatori di metodo
• Public: può essere usato da tutti
• Protected: usato da se stessa o sottoclassi
• Private: usato da se stessa
2/7/2013
108
METODI STATICI, $THIS, SELF E PARENT
Metodo statico: di classe, non di oggetto
• Definizione: public static function <funzione>(...)
• Chiamata: <classe>::<funzione>(...)
$this si riferisce all'oggetto corrente
• $model = $this->getModel();
self chiama un componente statico della stessa classe
• $identities = self::getGroupsByUser($userId);
• return self::$_buffer;
parent chiama metodo o campo di una classe padre
• parent::display();
DEBUGGING SEMPLICE
Visualizzare le variabili definite
• var_dump(get_defined_vars()); die;
Visualizzare lo stack trace
• var_dump(debug_backtrace()); die;
2/7/2013
109
TECNICHE COMUNI NEL CODICE DI JOOMLA!™
Connettivo logico || invece di if
• Statement A || statement B
• Esegue B solo se A restituisce false (lazy evaluation)
Concatenazione di metodi (method chaining)
• if (!JFactory::getUser()->authorise('core.admin'))
PHP "magic" methods
• __construct() e __call()
Espressioni regolari
• (bool) preg_match(<needle>, <haystack>);
• (string) preg_replace(<needle>, <subst>, <haystack>);
SCONTO HOSTING JOOMLA!™
Per i partecipanti al corso Joomlahost.it regala un coupon di sconto del valore di 20€ valido per l’acquisto di un cloud hosting Joomla! SMALL
Codice coupon : CORSOROMA3256
Visita www.joomlahost.it e acquista il tuo hosting completamente dedicato a Joomla!™