A Composable Date Formatter for Drupal

By mandclu, Mon, 06/21/2021 - 05:39

Something I've enjoyed since starting work on the Smart Date module has been seeing it grow and evolve in ways I wouldn't have expected, in response to the community. I had three specific goals in the beginning: a more "app-like" and intuitive widget, natural language, deduplicated date range output, and more efficient storage of dates and times. Soon after its release, requests started to come in for additional features: calendar integration, repeating events, support for timezones, and more. Many of these have been filed as feature requests in the module's issue queue, but a few have come as questions after presentations I've given about Smart Date.

Last year, one such question asked if it was possible to have "add to calendar" links with Smart Date. It wasn't something I had investigated. I did a little digging, and found that the two popular Drupal modules for adding these links to dates both had external dependencies: one, a third-party service, and another, a JavaScript library. Around the same time I learned that a colleague at Northern had been using a custom module he developed, with no dependencies, and the links rendered as simple HTML.

At first I had planned to add these links through another Smart Date submodule, as I had done with Smart Date's support for repeating dates. But I had also been having conversations with other people in the Drupal community who were also passionate about date and time handling. We've discussed trying to get parts of Smart Date into Drupal core, but also about reducing duplication among Drupal's date-related contributed modules, and about making these modules work together. Did the community need yet another solution for adding calendar links? If I could create a genuinely novel approach, why make something that would only work with Smart Date?

The existing modules that create add to calendar links implemented this as a field formatter, which meant that you had to choose between this functionality, and other date-related display functionality (such as Smart Date's deduplication). It wouldn't be overly difficult to give Smart Date a way to inject these links into its output, but could this be implemented in a way that could be more generic, so it could be used with other modules, and even Drupal core?

A Plugin System for Formatters

If there was a plugin system for formatters, then this functionality for add to calendar links could be added to any formatter that supported this plugin system, and it could be combined with other plugins, allowing a site builder to assemble a set of display capabilities to meet their exact needs.

Creating a custom plugin type in Drupal is reasonably well documented at this point. There's some official documentation and I also found some helpful articles by Udit Rawat, Daniel Sipos, and Aaron Crosman. There's even a Drupal Console command to get you started. One challenge that was starting to become clear was how to give site builder the power to configure these plugins: which plugins should be enabled on any specific date field, in what order should they act on the date display, and how could they provide the specifics on how the plugin should behave?

Drawing Inspiration (and Outright Stealing Code)

Often when I need to develop something new, I try to think about other solutions in the Drupal ecosystem that address a similar set of problems. In recent years I've done quite a bit of work with the popular Search API module, and I started to think about its interface for managing processors on an index: There's a section to specify which processors are enabled, a section to set the order in which they operate, and a section to provide settings for each processor that has its own configuration options.

The beauty of open source is that you can not only draw inspiration from other modules but actually adapt existing code where that's helpful. Search API's implementation is actually more complex than I needed (processors can operate in different stages, and in a different order for each one) and my implementation needed to work nested within the field formatter configuration interface, itself a part of a content type's display configuration, where the Search API processors interface is its own discrete form. Still, being able to examine and adapt a successful approach to similar problems was an immense help. Also, the resulting commonalities should make the resulting interface for managing Date Augmenter plugins feel familiar to Drupal site builders.

Interface for configuring date formatters

The Line Between Complexity and Power

Often in my work on Drual contrib modules, I find myself trying to balance complexity and power: I can foresee ways in which a site builder or other user might want to configure a module to better suit different use cases, but I also don't want its configuration to seem bewilderingly complex. Particularly where such variability might be needed in the specifics of how things will be displayed, I've been trying to leverage twig templates as a way to allow individual sites to customize in any way they need.

In keeping with this strategy, the output of the Add to Calendar Date Augmenter builds the link destination code in its plugins, but a twig template dictates what labels are used, in which order the links appears, and other specifics of the markup generated. Your site's theme can override this template, for example if you wanted to use icons from the Font Awesome Brands library instead of text.

A list of events with add to calendar links
An example set of date listings, with add to calendar links only on the upcoming dates

A Link As Proof-Of-Concept

I recently needed to put together a proof-of-concept of using Drupal to manage events, including registration. I wanted to incorporate the UX simplicity of Smart Date and the drag-and-drop management possible with Fullcalendar View but needed a solution for showing registration. For a robust implementation, purpose-built solutions like Recurring Events or Bookable Calendar can be ideal, but what I needed was simpler, so I decided to write a Date Augmenter plugin to provide a link to a registration webform.

Date listings with registration links added

It was quick to put together, and really drove home for me the power of having a plugin system for modifying date output. I decided to take that initial implementation a little further, so I made it more configurable and you can now try it out as Link Augmenter for Dates. If you find it useful, I'd love to hear how you're using it, and what additions you'd like to see.

The Road Ahead

What's next for these augmenters? First off, I want Add to Calendar augmenter to have full support for recurring dates. Imagine being able to add a whole series of events to your calendar in a single click!

On a related note, I've been trying think broader than the Smart Date ecosystem, and have been having some great conversations with Owen Bush of Recurring Events about making his module and Smart Date work together. Or more accurately, work together better. Since Smart Date's 3.0.0 release, Smart Date has worked with core date fields, which means you can use its formatters and widgets with Instance entities of Recurring Events. And yes, that also means you can use the Date Augmenter plugins we've talked about above.

As the Add to Calendar Augmenter gets support for recurring dates, hopefully we'll support for that in Smart Date, Recurring Events, and others.

I have some other ideas in mind, so stay tuned for more updates as I get to them.



Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.