Advertisement
Advertisement

More Related Content

Advertisement

Come portare il profiler di symfony2 in drupal8

  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
  3. INTRODUZIONE
  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
  10. DAL BUNDLE AL MODULO
  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
  13. ANATOMIA DI UN MODULO
  14. WEBPROFILER.INFO.YML name: Web Profiler type: module description: 'Drupal Web Profiler.' package: Development version: 8.x-1.1-beta1 core: 8.x configure: webprofiler.admin_configure
  15. WEBPROFILER.ROUTING.YML webprofiler.toolbar: path: '/profiler/{profile}' defaults: _controller: 'DrupalwebprofilerControllerWebprofilerController::toolbarAction' options: parameters: profile: type: 'webprofiler:token' requirements: _permission: 'view webprofiler toolbar' webprofiler.profiler: path: '/admin/reports/profiler/view/{profile}' defaults: _content: 'DrupalwebprofilerControllerWebprofilerController::profilerAction' _title: 'Webprofiler' options: parameters: profile: type: 'webprofiler:token' requirements: _permission: 'access webprofiler'
  16. WEBPROFILER.SERVICES.YML services: logger.channel.webprofiler: class: DrupalCoreLoggerLoggerChannel factory_method: get factory_service: logger.factory arguments: ['webprofiler'] profiler.file_storage: class: SymfonyComponentHttpKernelProfilerFileProfilerStorage arguments: ['%data_collector.storage%'] tags: - { name: webprofiler_storage, title:'File storage' } profiler.database_storage: class: DrupalwebprofilerProfilerDatabaseProfilerStorage arguments: ['@database'] tags: - { name: webprofiler_storage, title:'Database storage' } profiler.storage_manager: class: DrupalwebprofilerProfilerProfilerStorageManager profiler.storage: class: SymfonyComponentHttpKernelProfilerProfilerStorageInterface factory_class: DrupalwebprofilerProfilerProfilerStorageFactory factory_method: getProfilerStorage arguments: ['@config.factory', '@service_container'] profiler: class: DrupalwebprofilerProfilerProfiler
  17. CARTELLA SRC (PSR/4)
  18. CARTELLA TEMPLATES
  19. 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
  20. 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
  21. 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'
  22. SERVICE CONTAINER Per registrare i vari data_collector ho bisogno di aggiungere un passo di compilazione durante la costruzione del service container
  23. 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());
  24. 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!!
  25. 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')));
  26. 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
  27. 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
  28. 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
  29. 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(), ) ); } }
  30. TWIG {{ template.renderblock('panel', { 'token': profile.token, 'name': name, 'content': content }) }} <div class="summary" style="display:none">{{ summary }}</div> templates/Profiler/webprofiler_panel.html.twig
  31. 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 :-(
  32. TWIG I css e i javascript invece sono rimasti esattamente gli stessi (più o meno)!
  33. 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); }
  34. 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)
  35. 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)
  36. SVILUPPI FUTURI Grafici Analisi statistiche per il monitoraggio automatico delle performance (media, mediana, massimo, minimo, ...) Diff tra profili differenti
  37. 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
  38. SEI UN SYMFONY DEVELOPER? ALLORA GIÀ CONOSCI DRUPAL8 WE ARE HIRING!
  39. GRAZIE Domande? joind.in/12216
  40. DRUPALDAY MILANO 2014 14 novembre conferenza gratuita 15 novembre trainig gratuito e sprint Deadline CFP 12 ottobre
Advertisement