Molti progetti PHP open source hanno adottato Symfony2 come base per la loro prossima versione, tra questi c'è anche il CMS Drupal (http://drupal.org). In questo talk vedremo come scrivere un modulo per Drupal8 in modo da sfruttare il più possibile il suo nuovo motore Symfony2, dall'integrazione con il service container alla gestione degli eventi, dal routing a Twig. Verrà usato come esempio il modulo webprofiler (http://drupal.org/project/webprofiler) per dimostrare come un bundle per Symfony2 possa essere trasformato in un modulo per Drupal8 e integrato facilmente nel sistema.
1. COME PORTARE IL PROFILER DI SYMFONY2 IN DRUPAL8
Luca Lusso
Senior Software Architect and Drupal Expert
llusso@wellnet.it - @lussoluca - drupal.org/u/lussoluca
2. AGENDA
Intoduzione
Dal bundle al modulo
Anatomia di un modulo
Routing
Service container
Eventi
Twig
4. SYMFONY2 ALLA BASE DI DIVERSI PRODOTTI:
phpBB
Laravel
eZ publish
Piwik
Drupal8
...
5. I’m not a Drupal developer, but I do know a lot
about Drupal 8. I know how the event system
works, what a service is, how it relates to a
dependency injection container and how the
deepest and darkest of Drupal’s request-response
workflow looks.
How?
Because I’m a Symfony developer. And if you
want to get a jumpstart on Drupal 8, you should
be to. I’m not saying use Symfony instead of
Drupal - they each solve very different problems.
Use both.
Ryan Weaver - KnpLabs
6. COMPONENTI DI SYMFONY2 IN DRUPAL8
Class loader
Css selector
Debug
Dependency injection
Event dispatcher
HTTP foundation
HTTP kernel
Process
Routing
Serializer
Translation
Validator
Yaml
7. ALTRI COMPONENTI INCLUSI IN DRUPAL8
twig/twig
doctrine/common
doctrine/annotations
guzzlehttp/guzzle
kriswallsmith/assetic
symfony-cmf/routing
easyrdf/easyrdf
phpunit/phpunit
phpunit/phpunit-mock-objects
zendframework/zend-feed
mikey179/vfsStream
stack/builder
egulias/email-validator
8. STATO DEL PROGETTO
8.0.x-beta1
Le API sono stabili anche se qualche dettaglio potrebbe ancora
cambiare
www.drupal.org/project/drupal
9. WARNING
Drupal8 NON è un'applicazione full-stack Symfony, è un
software PHP che si basa su alcune componenti di Symfony per
non reinventare la ruota
Ad esempio non si può prendere un bundle di Symfony e
"installarlo" su un sito Drupal8
11. WEBPROFILER BUNDLE
La toolbar di debug e profiling inclusa nel full-stack Symfony è
contribuita da tre distinte componenti:
Le funzionalità sono fornite da classi nel namespace
SymfonyComponentHttpKernelProfiler nel componente
HttpKernel (data collecting, storage, ...)
L'interfaccia utente (toolbar e pagine di report) sono fornite
dal bundle WebProfilerBundle
Il tutto è configurato dal bundle FrameworkBundle (passi di
compilazione e registrazione dei data_collector)
12. MODULO WEBPROFILER
In Drupal non abbiamo i bundle ma i moduli:
Le funzionalità sono fornite da classi nel namespace
SymfonyComponentHttpKernelProfiler nel componente
HttpKernel ==> big win!!
L'interfaccia utente (toolbar e pagine di report) e la
configurazione (passi di compilazione e registrazione dei
data_collector) sono fornite dal modulo webprofiler
www.drupal.org/project/webprofiler
oppure
github.com/lussoluca/webprofiler
20. FILE SPECIFICI DRUPAL8
webprofiler.module -> codice procedurale (hook), non
obbligatorio
webprofiler.install -> codice eseguito all'installazione e
aggiornamento del modulo (procedurale), non obbligatorio
webprofiler.permissions.yml -> permessi aggiunti dal modulo,
non obbligatorio
webprofiler.links.menu.yml -> voci di menu aggiunte dal
modulo, non obbligatorio
webprofiler.links.task.yml -> task (una sorta di link contestuali)
aggiunti dal modulo, non obbligatorio
webprofiler.libraries.yml -> librerie (insiemi di css e javascript)
aggiunti dal modulo, non obbligatorio
21. ROUTING
Molto simile a Symfony
_content -> ritorna un render array di Drupal, che verrà
traformato in HTML e incluso nel "main content" di una pagina
_controller -> ritorna il contenuto direttamente senza passare
dal livello di theming di Drupal
_form -> si aspetta una classe che implementa
DrupalCoreFormFormInterface (usato nel caso in cui il
"main content" sia una form)
_entity[_view|_list|_form] -> per lavorare sulle entità (il model
in Drupal), ritorna un render array per il dettaglio, la lista o la
form di inserimento/update di un'entità
https://www.drupal.org/node/2092643
22. ROUTING
Gestisce il controllo di accesso alle risorse (_permission, _role,
_access, _entity_access, ...)
Gestisce la conversione dei parametri della url
webprofiler.toolbar:
path: '/profiler/{profile}'
defaults:
_controller: 'DrupalwebprofilerControllerWebprofilerController::toolbarAction'
options:
parameters:
profile:
type: 'webprofiler:token'
requirements:
_permission: 'view webprofiler toolbar'
23. SERVICE CONTAINER
Per registrare i vari data_collector ho bisogno di aggiungere un
passo di compilazione durante la costruzione del service
container
24. SERVICE CONTAINER
Per aggiungere un passo di compilazione in Symfony2 devo fare:
class FrameworkBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ProfilerPass());
25. SERVICE CONTAINER
Per aggiungere un passo di compilazione in Drupal8 devo fare:
class WebprofilerServiceProvider extends ServiceProviderBase {
public function register(ContainerBuilder $container) {
$container->addCompilerPass(new ProfilerPass());
L'implementazione della classe ProfilerPass è la stessa in
entrambi i casi ==> big win!!
26. SERVICE CONTAINER
Per poter profilare e analizzare un sotto-sistema di Drupal quello
che abbiamo fatto è stato sostituire una dato servizio con una
nostra implementazione:
// Replaces the existing cache_factory service to be able to collect the
// requested data.
$container->setDefinition('cache_factory.default',
$container->getDefinition('cache_factory'));
$container->register('cache_factory',
'DrupalwebprofilerCacheCacheFactoryWrapper')
->addArgument(new Reference('cache_factory.default'))
->addArgument(new Reference('webprofiler.cache'))
->addMethodCall('setContainer', array(new Reference('service_container')));
27. EVENTI
webprofiler.WebprofilerEventSubscriber:
class: DrupalwebprofilerEventSubscriberWebprofilerEventSubscriber
arguments: ['@current_user', '@url_generator']
tags:
- { name: event_subscriber }
class WebprofilerEventSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return array(
KernelEvents::RESPONSE => array('onKernelResponse', -128),
);
}
public function onKernelResponse(FilterResponseEvent $event) {
$response = $event->getResponse();
$request = $event->getRequest();
Stesso approccio di Symfony
28. EVENTI
Durante lo sviluppo di Drupal8 si pensava che gli eventi di
Symfony avrebbero rimpiazzato del tutto gli hook di Drupal,
invece molti hook sono stati mantenuti e fanno parte dell'eredità
procedurale delle versioni precedenti del CMS.
Gli hook in effetti sono l'unica cosa che "stona" nella nuova
architettura di Drupal8
Issue #1509164: Use Symfony EventDispatcher for hook system
29. TWIG
Uno degli hook rimasti è quello per definire i template
(hook_theme(), va messo dentro nomemodulo.module)
function webprofiler_theme() {
return array(
'webprofiler_toolbar' => array(
'template' => 'Profiler/webprofiler_toolbar',
'variables' => array('token' => NULL, 'templates' => array(), 'profile' => NULL, 'profiler_),
'webprofiler_panel' => array(
'template' => 'Profiler/webprofiler_panel',
'variables' => array('template' => array(), 'profile' => NULL, 'name' => NULL, 'summary'
),
),
template => file *.html.twig
variables => elenco delle variabili che il template "accetta" in
input
30. TWIG
Tipicamente un controller in Drupal ritorna un render array,
ossia un array associativo PHP che Drupal sa come trasformare
in HTML
public function profilerAction(Profile $profile) {
[...]
'#theme' => 'webprofiler_panel',
'#template' => $template,
'#profile' => $profile,
'#name' => $name,
'#summary' => $collector->getPanelSummary(),
'#content' => $collector->getPanel(),
)
);
}
}
32. TWIG
Il backoffice è stato ristrutturato per adattarsi alle specifiche
sull'interfaccia di Drupal quindi in questo caso non abbiamo
potuto usare i file twig originali :-(
33. TWIG
I css e i javascript invece sono rimasti esattamente gli stessi (più o
meno)!
34. TWIG
Abbiamo esteso twig per aggiungere nuove funzioni, nel nostro
caso ne abbiamo aggiunte 2: url e path
services:
webprofiler.twig_extension:
class: DrupalwebprofilerTwigRoutingExtension
arguments: ['@url_generator']
class WebprofilerServiceProvider extends ServiceProviderBase {
public function alter(ContainerBuilder $container) {
$container->getDefinition('twig')
->addMethodCall('addExtension',
array(new Reference('webprofiler.twig_extension')));
}
class RoutingExtension extends Twig_Extension {
public function getPath($name, $parameters = array(), $options = array()) {
$options['absolute'] = FALSE;
return $this->urlGenerator->generateFromRoute($name, $parameters, $options);
}
35. API SPECIFICHE
Drupal ha una sua versione delle Form API (soprattutto per
ragioni storiche) e non usa l'implementazione di Symfony. La
validazione però è fatta utilizzando il componente Validator di
Symfony (e la libreria egulias/email-validator per la validazione
degli indirizzi email)
Drupal non usa Doctrine per la persistenza dei dati ma
un'implementazione custom bastata su PDO (e ha un Entity
manager specifico)
36. DATA COLLECTORS
Oltre ai data_collector presenti in Symfony ne abbiamo
aggiunti di specifici per Drupal (views, blocchi, cache, ...)
Abbiamo aggiunto anche data_collector che potrebbero essere
riportati in Symfony stesso, ad esempio il collector dei servizi
Abbiamo in programma di arricchire il dati profilati con
informazioni provenienti da un profiler di codice, come XHProf
o uprofiler (in parte è già stato fatto)
37. SVILUPPI FUTURI
Grafici
Analisi statistiche per il monitoraggio automatico delle
performance (media, mediana, massimo, minimo, ...)
Diff tra profili differenti
38. LINKS
(un
Symfony2 meets Drupal 8
Porting Symfony Acme Demo Bundle as a Drupal 8 Module
po' vecchiotto)
Want to be a Drupal 8 Expert? Start with Symfony
Build a Drupal 8 Module
The state of Webprofiler
39. SEI UN SYMFONY DEVELOPER?
ALLORA GIÀ CONOSCI DRUPAL8
WE ARE HIRING!