Summary
The project already depends on sabre/vobject (^4.5) and uses it for ICS import (ICalImportPresenter), but the ICS export path builds calendar output by hand via a raw Smarty template (tpl/Export/ical.tpl) and manual string manipulation in iCalendarReservationView.
Current problems
- Manual RFC 5545 text escaping —
iCalendarReservationView::toRfc5545Text() was added to escape SUMMARY and DESCRIPTION, but LOCATION, ORGANIZER;CN=, and any ExtraIcalLines values are still unescaped.
- No line folding — RFC 5545 §3.1 requires lines longer than 75 octets to be folded with
CRLF + SPACE. The current template does not fold at all, producing invalid output for long titles or descriptions.
- Manual RRULE construction —
CreateRecurRule() hand-builds recurrence rule strings; sabre/vobject has a Recur value type for this.
- Fragile template — The Smarty template emits raw property values with no guarantee of correct encoding, making it easy for future changes to introduce spec violations.
sabre/vobject handles all of the above automatically when properties are set through its object model.
Proposed change
Replace the hand-rolled Smarty template + iCalendarReservationView string escaping with a vobject-based builder that:
- Constructs a
VCALENDAR / VEVENT object model via Sabre\VObject\Component\VCalendar.
- Sets
SUMMARY, DESCRIPTION, LOCATION, ORGANIZER, and other text properties through the vobject API (automatic escaping and line folding).
- Serialises the calendar with
$vcalendar->serialize() instead of rendering the Smarty template.
- Removes
toRfc5545Text() and CreateRecurRule() as they become redundant.
Acceptance criteria
Related Issues
Issue #1336
Assisted-by: Claude:claude-sonnet-4-6
Summary
The project already depends on
sabre/vobject(^4.5) and uses it for ICS import (ICalImportPresenter), but the ICS export path builds calendar output by hand via a raw Smarty template (tpl/Export/ical.tpl) and manual string manipulation iniCalendarReservationView.Current problems
iCalendarReservationView::toRfc5545Text()was added to escapeSUMMARYandDESCRIPTION, butLOCATION,ORGANIZER;CN=, and anyExtraIcalLinesvalues are still unescaped.CRLF + SPACE. The current template does not fold at all, producing invalid output for long titles or descriptions.CreateRecurRule()hand-builds recurrence rule strings; sabre/vobject has aRecurvalue type for this.sabre/vobject handles all of the above automatically when properties are set through its object model.
Proposed change
Replace the hand-rolled Smarty template +
iCalendarReservationViewstring escaping with a vobject-based builder that:VCALENDAR/VEVENTobject model viaSabre\VObject\Component\VCalendar.SUMMARY,DESCRIPTION,LOCATION,ORGANIZER, and other text properties through the vobject API (automatic escaping and line folding).$vcalendar->serialize()instead of rendering the Smarty template.toRfc5545Text()andCreateRecurRule()as they become redundant.Acceptance criteria
iCalendarReservationViewcontinue to pass (or are updated to assert on parsed vobject output).icsfiles are accepted without warnings by at least Google Calendar and ThunderbirdRelated Issues
Issue #1336
Assisted-by: Claude:claude-sonnet-4-6