Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sulu 2.0 - Workshop Symfony Live Berlin 2019

Sulu 2.0 - Workshop Symfony Live Berlin 2019

Thomas Schedler

September 25, 2019

More Decks by Thomas Schedler

Other Decks in Programming


  1. Hey, I’m Thomas – Co-founder & CEO of Sulu GmbH

    – More than 15 years of experience in web technologies & development – PHP, Symfony, React, SQL, Elasticsearch, … – Open source enthusiast – Loves cooking and mountains @chirimoya [email protected] https://github.com/chirimoya
  2. Sulu CMS – Content Management Platform – Full-Stack Symfony –

    Made for businesses – Simple UI – High Performance – 100% Open Source
  3. For business – Built with the needs of business and

    industry in mind – Enterprise features without ridiculous license fees – Supports multi-language, multi-portal and multi-channel – Easy to integrate data from external resources – Perfect for developing any type of business app
  4. For editors – Really simple and very fast user interface

    – Web-based, no installation required – Edit forms that validate content & ensure correct semantics – Live preview content as you type it – Switch between different devices (Smartphone, Tablet or Desktop)
  5. For developers – Full-Stack Symfony environment – Semantic configuration of

    templates – Easy transition from data to HTML – Build applications around content management – Add/Remove functionality with Symfony Bundles
  6. Bicycles Everyone can ride them, many can repair it

    etc.) Cars Many can ride them, some can repair it
 (Drupal, TYPO3 etc.) Supertanker Need highly specialized staff, expensive and very complex
 (Hybris, OpenText, Adobe Experience Manager etc.) Trucks Need a special license, must be configured to your needs (eZ Publish, Pimcore etc.) Where we see us …
  7. When to use Sulu? – Complex brand and corporate presences

    – News- and media platforms – Social and collaborative sites – E-Business projects – Handling external data resources – Speed is a critical success factor
  8. When not to use Sulu? – Sulu is not WordPress

    – We don’t recommend to use Sulu for: – Low budget marketing sites – Simple blogs – Hobby websites – Small business websites
  9. Webspaces – One single content-structure / page tree – The

    structure represents one or more websites – Multiple languages implemented as dimensions – Multiple webspaces support
  10. <!-- config/webspaces/example.xml —> <?xml version="1.0" encoding="utf-8"?> <webspace xmlns="http://schemas.sulu.io/webspace/webspace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.sulu.io/webspace/webspace

    http://schemas.sulu.io/ webspace/webspace-1.1.xsd“> <name>example.com</name> <key>example</key> <localizations> <localization language="en" default=„true"/> <localization language="de"/> </localizations> ... <portals> <portal> <name>example.com</name> <key>example</key> <environments> <environment type="prod"> <urls> <url>{host}/{localization}</url>
  11. Templates & Content Types – The structure of the page

    – How that structure is rendered – Each page template is defined by two files: – an XML file that contains the page structure – a Twig file that contains the HTML code – A page structure consists of properties, each of which has a content type
  12. <!-- config/templates/pages/default.xml --> <?xml version="1.0" ?> <template xmlns="http://schemas.sulu.io/template/template" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.sulu.io/template/template

    http://schemas.sulu.io/ template/template-1.0.xsd"> <key>default</key> <view>pages/default</view> <controller>Sulu\Bundle\WebsiteBundle\Controller\DefaultController::indexAction</controller> <cacheLifetime>604800</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/>
  13. {# templates/pages/default.html.twig #} {% extends "base.html.twig" %} {% block content

    %} <h1>{{ content.title }}</h1> {{ content.article|raw }} {% endblock %}
  14. Media management – Centralised repository for documents, images etc. –

    Independent management of folder hierarchies – Multi-language support for documents – Management of metadata – Asset versioning – Image cropping
  15. <!-- config/webspaces/example.xml —> <?xml version="1.0" encoding="UTF-8"?> <formats xmlns="http://schemas.sulu.io/media/formats" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.sulu.io/media/formats

    http://schemas.sulu.io/media/ formats-1.1.xsd"> <format key="300x"> <meta> <title lang="en">Example Image</title> <title lang="de">Beispielbild</title> </meta> <scale x="300"/> </format> </formats> {# templates/pages/default.html.twig #} {% extends "base.html.twig" %} {% block content %} <img src="{{ image.thumbnails['300x'] }}" alt="{{ image.title }}" title="{{ image.description|default(image.title) }}"> {% endblock %}
  16. Sulu Administration Interface Single-Page Application – Fast and responsive UI

    – Improved user experience – Only data is transmitted back and forth – Caching capabilities – Clean separation – REST API
  17. Sulu Administration Interface Single-Page Application – Don't break the internet

    – Deep linking might be hard – Keep an eye on security (XSS) – On-the-fly extensibility is difficult – back-end developer != front-end developer
  18. Metadata for JavaScript views - List & Form – Determines

    all the available fields for lists and forms – Contains a data-type to know how to represent this field – Contains a title to display above fields – Form can contain more parameters to customize fields
  19. <!-- config/lists/events.xml --> <?xml version="1.0" ?> <list xmlns="http://schemas.sulu.io/list-builder/list"> <key>events</key> <joins

    name="translation"> <join> <entity-name>App\Entity\EventTranslation</entity-name> <field-name>App\Entity\Event.translations</field-name> <condition>App\Entity\EventTranslation.locale = :locale</condition> </join> </joins> ... <properties> <property name="id" visibility="no" translation="sulu_admin.id"> <field-name>id</field-name> <entity-name>App\Entity\Event</entity-name> </property> <property name="title" visibility="always" searchability="yes" translation="sulu_admin.title"> <field-name>title</field-name> <entity-name>App\Entity\EventTranslation</entity-name> <joins ref="translation"/> </property>
  20. <!-- config/form/event_detail.xml --> <?xml version="1.0" ?> <form xmlns="http://schemas.sulu.io/template/template" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.sulu.io/template/template

    http://schemas.sulu.io/template/ form-1.0.xsd" > <key>event_details</key> <properties> <property name="title" type="text_line" mandatory="true" colspan="9"> <meta> <title>sulu_admin.title</title> </meta> </property> <property name="location" type="text_line" colspan="3"> <meta> <title>app.location</title> </meta> </property> <property name="teaser" type="text_area"> <meta> <title>app.teaser</title> </meta>
  21. REST API – The way data is transferred between backend

    and frontend – Identified by a resourceKey to combine list and detail requests – API has to follow a standard – Helper for list representations
  22. // src/Controller/Admin/EventController.php class EventController extends RestController implements ClassResourceInterface { ...

    public function cgetAction(Request $request): Response { $locale = $request->query->get(‚locale'); $listRepresentation = $this->doctrineListRepresentationFactory ->createDoctrineListRepresentation( Event::RESOURCE_KEY, [], ['locale' => $locale] ); return $this->handleView($this->view($listRepresentation)); } public function getAction(int $id, Request $request): Response { $entity = $this->load($id, $request); if (!$entity) { throw new NotFoundHttpException(); }
  23. # config/packages/sulu_admin.yaml sulu_admin: email: "%env(SULU_ADMIN_EMAIL)%" forms: directories: - "%kernel.project_dir%/config/forms" lists:

    directories: - "%kernel.project_dir%/config/lists" resources: events: routes: list: app.get_events detail: app.get_event field_type_options: selection: event_selection: default_type: list_overlay resource_key: events types: list_overlay: adapter: table list_key: events
  24. Sulu Admin Class – Tagged Symfony service to extend the

    admin application of Sulu – Allows configuration of views and navigation items – Introduces security contexts – Add settings to configuration request
  25. // src/Admin/EventAdmin.php class EventAdmin extends Admin { ... public function

    configureViews(ViewCollection $viewCollection): void { $locales = $this->webspaceManager->getAllLocales(); $listToolbarActions = [ new ToolbarAction('sulu_admin.add'), new ToolbarAction('sulu_admin.delete') ]; $listView = $this->viewBuilderFactory ->createListViewBuilder(self::EVENT_LIST_VIEW, '/events/:locale') ->setResourceKey(Event::RESOURCE_KEY) ->setListKey(self::EVENT_LIST_KEY) ->setTitle('app.events') ->addListAdapters(['table']) ->addLocales($locales) ->setDefaultLocale($locales[0]) ->setAddView(static::EVENT_ADD_FORM_VIEW) ->setEditView(static::EVENT_EDIT_FORM_VIEW) ->addToolbarActions($listToolbarActions); $viewCollection->add($listView);
  26. // src/Admin/EventAdmin.php class EventAdmin extends Admin { ... public function

    configureNavigationItems(NavigationItemCollection $navigationItemCollection): void { // Configure a NavigationItem without a Route $module = new NavigationItem('app.events'); $module->setPosition(40); $module->setIcon('fa-calendar'); // Configure a NavigationItem with a Route $events = new NavigationItem('app.events'); $events->setPosition(10); $events->setMainRoute(static::EVENT_LIST_ROUTE); $module->addChild($events); $navigationItemCollection->add($module); } ...
  27. Abstract field types – Almost every entity should have a

    selection for form assignments – Sulu includes an abstract `selection` and `single_selection` field type – This abstract field type can be configured by options such as resourceKey
  28. # config/packages/sulu_admin.yaml sulu_admin: email: "%env(SULU_ADMIN_EMAIL)%" forms: directories: - "%kernel.project_dir%/config/forms" lists:

    directories: - "%kernel.project_dir%/config/lists" resources: events: routes: list: app.get_events detail: app.get_event field_type_options: selection: event_selection: default_type: list_overlay resource_key: events types: list_overlay: adapter: table list_key: events
  29. Registries … FTW! – Lot of registries to hook into

    different places – Includes e.g. separate views, toolbar actions, form fields, … – React and JavaScript knowledge required to write them