The SuluEventBundle has a precise starting point: the first commit was made on 26 March 2021, and the first release, version 1.0.0, followed a day later. The starting point was the examples from the Sulu workshop, as stated in the first README. I didn’t want to have to rewrite the entities from scratch in every project, but rather be able to install them neatly as a bundle once and for all. At the time, the bundle required Sulu 2.2 and PHP 7.1.

Looking back, I’m particularly interested in what came next. In the first three weeks, almost all the integration points were created that a custom component needs in Sulu so that it doesn’t feel like a foreign entity. This post goes through them in order. You can read about how I came to be involved in the project in the first post in the series.

Events and venues as separate content items

From the outset, the bundle consists of two content types: events and venues. Both have a list and a form in the admin panel, and both have their own permissions. Permission checks for venues were added as early as 27 March. As with pages, the role determines who is authorised to manage events.

Content in multiple languages is stored in separate translation tables. This has consequences that only become apparent during development: sorting by title no longer works automatically, because the title is contained within the translation. On 29 March, I therefore added the option to sort by translated properties.

The event form in Sulu Admin, as it looks today. The basic elements have remained the same since 2021: title, URL, start and end times, venue, image and text.

Each event is assigned a URL

An event should have its own address on the website. To achieve this, the bundle uses Sulu’s routing. Since 27 March, the route has been part of the entity: it is derived from the title, appears in the form and can be edited or created there.

SEO and Excerpt: first copied, then into Traits

For pages, the SEO tab and the excerpt are, of course, included. They don’t come with their own content type as standard; I had to integrate both myself. The bundle stores the details in separate tables, each with translations. This means that an event can have its own SEO title and description for each language.

The first version of the SEO code was still contained within two large classes. On 29 March, I split it into interfaces and traits. This didn’t make the code any shorter, but it did make it reusable: I was able to build the excerpt, which followed on 30 and 31 March, using the same pattern. The author and author date also became separate traits.

This pattern later gave rise to the shared bundle SuluSharedTools for my bundles. With Sulu 3, it has been omitted again.

Lean controllers

The controller for events quickly became confusing: Save, Translations, SEO, Excerpt, Route. On 30 March, I introduced model classes for this (EventModel, EventSeoModel, EventExcerptModel), followed on 31 March by the LocationModel. The controller handles the request; the model knows how to save the data.

Author, date and selection fields

A subscriber automatically sets the author and date when saving. The date can be changed in the event settings, effective from 30 March.

For pages, there are selection fields that allow editors to select individual or multiple events. This enables a page to refer specifically to certain events.

Preview, Sitemap and Smart Content

Whilst editing, editors can see how the event will appear on the website. To this end, since 31 March, a preview provider has been supplying the admin with the event in the selected language.

This was followed on 1 April by the sitemap provider. The first version was simple: it included all active events. The SEO option ‘Hide in sitemap’ was already present in the form, but the provider only began to process it later.

The very first README file demonstrates how events can be displayed as a list on a page using Smart Content.

Multilingual, tested and with CI

Unit tests and a Travis configuration were in place on the first day. On 3 April, tests for the traits were added. On 12 April, translations of the website texts followed, and on 14 April, a function was added that copies an event into other languages, with permission checks for each target language.

After that

After that, things quietened down. In September 2022, there were a few minor updates. In January 2023, the first external contribution arrives: the update to Symfony 6 stems from a pull request that I merged in June 2023. The next major update follows in September 2023, introducing a bin, activity log and time control features. That is the subject of the next post.

Previously: How the SuluEventBundle came about.

Repository: manuxi/SuluEventBundle on GitHub