sabre-io / Baikal

Baïkal is a Calendar+Contacts server
https://sabre.io/baikal/
GNU General Public License v3.0
2.53k stars 290 forks source link

creating all day event VALUE=DATE issue #1289

Closed gstlouisgit closed 2 months ago

gstlouisgit commented 2 months ago

I am trying to create an all day event. An example here https://datatracker.ietf.org/doc/html/rfc4791#section-7.8

I should be using this string for dtstart and dtend property VALUE=DATE:

When I try this with values below I get server error Sabre\DAV\Exception\UnsupportedMediaType: Validation error in iCalendar: The supplied value (VALUE=DATE:20240827) is not a correct DATE-TIME

Am I doing this wrong? Can you create all day events with vobject?

This systems runs Baïkal 0.9.5

        /*  BAIKAL VOBJECT   */
        $vcalendar = new VObject\Component\VCalendar([
            'VEVENT' => [
                'SUMMARY' => $model['put']['summary'],  
                'PRODID' => OWNER,
                'DTSTART' => 'VALUE=DATE:20240827',
                'DTEND' => 'VALUE=DATE:20240828',
                'DESCRIPTION' => ( isset( $model['put']['description'] ) ? $model['put']['description'] : '' ),
                'RRULE' => ( isset( $model['put']['rrule'] ) ? $model['put']['rrule'] : '' ),
                'VALARM' => [
                    'ACTION' => 'DISPLAY',
                    'TRIGGER' => '-PT' . $model['put']['alarm'] . 'M',
                ]
            ]
        ]);

var_dump($vcalendar->serialize());exit;

gstlouisgit commented 2 months ago

I finally found the flag you can use for creating the event as an all day event instead of date-time. There is no documentation for this in bikal, however the baikal examples that come with the lib package does show how to do this with anniversary vevents.

events by default are VALUE=DATE-TIME in ex. DTSTART;VALUE=DATE-TIME:19970901T130000Z In order to flag an all day it needs DTSTART;VALUE=DATE:20240830

Once vobject, baikal needs $vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE'; which switches it over to DTSTART;VALUE=DATE

IF not you will see an error in the logs about date-time

Here is my example that also show if you put emtpy string in rrule it just get ignored once serialized. Hope it helps someone

        $vcalendar = new VObject\Component\VCalendar([
            'VEVENT' => [
                'SUMMARY' => $model['put']['summary'],  
                'PRODID' => OWNER,
                //'DTSTART' => new \DateTime( $model['put']['start'] ), 
                //'DTEND' => new \DateTime( $model['put']['end'] ),
                'DTSTART' => $model['put']['start'],
                'DTEND' => $model['put']['end'],
                'DESCRIPTION' => ( isset( $model['put']['description'] ) ? $model['put']['description'] : '' ),
                'RRULE' => ( isset( $model['put']['rrule'] ) ? $model['put']['rrule'] : '' ),
                'VALARM' => [
                    'ACTION' => 'DISPLAY',
                    //'DESCRIPTION' => 'alert for event "with nested alarm"',
                    'TRIGGER' => '-PT' . $model['put']['alarm'] . 'M',
                    //  ex. TRIGGER;VALUE=DURATION:-PT2H 2 hours
                    //  ex. TRIGGER;VALUE=DURATION:-P2D 2 days
                    //TRIGGER;VALUE=DATE-TIME:19970317T133000Z, /* to set a precise time */
                ]
            ]
        ]);

        /*
        *   BAIKAL needs a flag for allday events
        *
        *   https://www.rfc-editor.org/rfc/rfc5545#section-3.3.5
        *   in order to create all day event dtstart and dtend needs DTSTART;VALUE=DATE:
        *   baikal needs a flag with $vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
        *
        *   This needs to be setup as string for date_parse() to accept it
            *   ensure your call calling this put() function $model['put']['start'] & $model['put']['end'] are strings using ex.
            *   
            *   $start = new DateTime( explode('Z', explode('DTSTART:', $_SESSION['admin']['createinvoice']['rrule'])[1] )[0] );
            *   $start->format('Ymd H:i:s')
            *
            *

        *   we can check the dates with date_parse( $start ); and ['hour'] will be false
        *   
        */
        if( !date_parse( $model['put']['start'] )['hour'] ){

            $vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
            $vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';

        }// if( !date_parse( $model['put']['start'] )['hours'] )

        $construct['object'] = $vcalendar->serialize();