Version 5.1.0
July 19, 2026
Added
- Framework-agnostic recurrence engine (
RecurrenceRule,Occurrence,OccurrenceExpander) with RFC 5545 RRULE expansion, EXDATE exceptions, window overlap handling, and DST-correct wall-clock semantics. - Plugin scaffolding: editions (Lite/Pro), Pest unit suite, ECS, PHPStan, Rector, and CI.
- Per-order ticket capacity validation: a single cart can no longer request more tickets than a capacity-limited ticket has remaining.
Fixed
- All-day events could render on the previous day in the ICS feed and the FullCalendar JSON feed
for timezones east of UTC. All-day occurrences are now emitted as floating calendar dates on the
event's local date (
DisplayInstant). - Adding a ticket that failed to save (e.g. a duplicate SKU) reported "Ticket added" while nothing was persisted. The control panel now surfaces the validation error instead.
- The nightly
owl/maintenance/regeneratecommand aborted entirely if a single event had an invalid recurrence rule, leaving later events' horizons un-rolled. Failures are now logged and skipped, and the command exits non-zero to signal them. craft.owl.upcoming()materialised every occurrence in the window before slicing; the row limit is now applied in SQL.
Changed
- The local DDEV environment is no longer tracked in the repository.