diff --git a/conf/example.json b/conf/example.json index 0ce304e..3a1d83c 100644 --- a/conf/example.json +++ b/conf/example.json @@ -6,8 +6,12 @@ "source": { "kind": "ics_feed", "data": { - "url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=1&future_months=2" + "url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=1&future_months=2", + "condense": false } + }, + "settings": { + "timezone": "UTC" } } diff --git a/source/conf.php b/source/conf.php index c19a098..4cac9cd 100644 --- a/source/conf.php +++ b/source/conf.php @@ -3,11 +3,47 @@ namespace davigil\conf; +/** + */ +class struct_auth +{ + public string $kind; + public $data; +} + + +/** + */ +class struct_source +{ + public string $kind; + public $data; +} + + +/** + */ +class struct_settings +{ + public string $timezone; +} + + +/** + */ +class struct_root +{ + public struct_auth $auth; + public struct_source $source; + public struct_settings $settings; +} + + /** */ class _state { - public static $data = null; + public static ?struct_root $data = null; } @@ -17,19 +53,43 @@ function load( string $path ) : void { - _state::$data = \json_decode( + $data_raw = \json_decode( \file_get_contents( $path ), true ); + { + $data = new struct_root(); + // auth + { + $auth = new struct_auth(); + $auth->kind = (($data_raw['auth'] ?? [])['kind'] ?? 'none'); + $auth->data = (($data_raw['auth'] ?? [])['data'] ?? null); + $data->auth = $auth; + } + // source + { + $source = new struct_source(); + $source->kind = $data_raw['source']['kind']; + $source->data = ($data_raw['source']['data'] ?? null); + $data->source = $source; + } + // settings + { + $settings = new struct_settings(); + $settings->timezone = (($data_raw['settings'] ?? [])['timezone'] ?? 'UTC'); + $data->settings = $settings; + } + _state::$data = $data; + } } /** */ function get( -) +) : struct_root { return _state::$data; } diff --git a/source/helpers/ics.php b/source/helpers/ics.php index 26927f8..d64a5ac 100644 --- a/source/helpers/ics.php +++ b/source/helpers/ics.php @@ -709,6 +709,24 @@ function vcalendar_encode( ); } */ + + // categories + if ( + ($vevent->categories !== null) + && + (\count($vevent->categories) > 0) + ) + { + \array_push( + $content_lines, + \davigil\helpers\string_\coin( + 'CATEGORIES:{{categories}}', + [ + 'categories' => \implode(',', $vevent->categories), + ] + ) + ); + } } \array_push($content_lines, 'END:VEVENT'); } diff --git a/source/main.php b/source/main.php index 400542d..9b2c006 100644 --- a/source/main.php +++ b/source/main.php @@ -7,6 +7,7 @@ require_once('overwrites/principal_backend.php'); require_once('overwrites/auths/_factory.php'); require_once('overwrites/caldav_backend.php'); require_once('sources/_factory.php'); +require_once('conf.php'); function main( @@ -14,10 +15,14 @@ function main( { \davigil\conf\load('conf.json'); - // \date_default_timezone_set('Europe/Berlin'); - \date_default_timezone_set('UTC'); + \date_default_timezone_set(\davigil\conf\get()->settings->timezone); - $source = \davigil\sources\make(\davigil\conf\get()['source']); + $source = \davigil\sources\make( + [ + 'kind' => \davigil\conf\get()->source->kind, + 'data' => \davigil\conf\get()->source->data, + ] + ); $principal_backend = new \davigil\overwrites\class_principle_backend(); @@ -34,14 +39,17 @@ function main( new \Sabre\DAV\Auth\Plugin( \davigil\overwrites\make_auth_backend( $source, - \davigil\conf\get()['auth'] + [ + 'kind' => \davigil\conf\get()->auth->kind, + 'data' => \davigil\conf\get()->auth->data, + ] ) ) ); /** - * this breaks authentication + * this somehow breaks authentication, but seems to be required for calendar discovery */ - // $server->addPlugin(new \Sabre\DAVACL\Plugin()); + $server->addPlugin(new \Sabre\DAVACL\Plugin()); $server->addPlugin(new \Sabre\CalDAV\Plugin()); $server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); diff --git a/source/overwrites/caldav_backend.php b/source/overwrites/caldav_backend.php index 45f20a4..459772b 100644 --- a/source/overwrites/caldav_backend.php +++ b/source/overwrites/caldav_backend.php @@ -63,9 +63,69 @@ class class_caldav_backend ] ); } + + + /** + * @todo outsource + */ + private function event_to_vevent( + array $event + ) : \davigil\helpers\ics\struct_vevent + { + $vevent = new \davigil\helpers\ics\struct_vevent(); + { + $vevent->uid = $event['id']; + $vevent->dtstamp = \davigil\helpers\ics\datetime_from_unix_timestamp($event['begin']); + $vevent->dtstart = new \davigil\helpers\ics\struct_dt( + '', + \davigil\helpers\ics\datetime_from_unix_timestamp($event['begin']) + ); + $vevent->dtend = ( + ($event['end'] === null) + ? + null + : + new \davigil\helpers\ics\struct_dt( + '', + \davigil\helpers\ics\datetime_from_unix_timestamp($event['end']) + ) + ); + $vevent->summary = $event['title']; + $vevent->location = $event['location']; + $vevent->description = $event['description']; + $vevent->class = \davigil\helpers\ics\enum_class::public_; + $vevent->categories = $event['tags']; + } + return $vevent; + } /** + * @todo outsource + */ + private function events_to_vcalendar( + array $events + ) : \davigil\helpers\ics\struct_vcalendar + { + $vcalendar = new \davigil\helpers\ics\struct_vcalendar(); + { + $vcalendar->version = '2.0'; + /** + * @todo conf + */ + $vcalendar->prodid = 'davigil'; + $vcalendar->method = 'PUBLISH'; + $vcalendar->events = \array_map( + fn($event) => $this->event_to_vevent($event), + $events + ); + } + return $vcalendar; + } + + + /** + * [implementation] */ public function getCalendarsForUser( $principalUri @@ -96,6 +156,7 @@ class class_caldav_backend /** + * [implementation] */ public function createCalendar( $principalUri, @@ -108,6 +169,7 @@ class class_caldav_backend /** + * [implementation] */ public function deleteCalendar( $calendarId @@ -118,6 +180,7 @@ class class_caldav_backend /** + * [implementation] */ public function getCalendarObjects( $calendarId @@ -155,64 +218,7 @@ class class_caldav_backend /** - * @todo outsource - */ - private function event_to_vevent( - array $event - ) : \davigil\helpers\ics\struct_vevent - { - $vevent = new \davigil\helpers\ics\struct_vevent(); - { - $vevent->uid = $event['id']; - $vevent->dtstamp = \davigil\helpers\ics\datetime_from_unix_timestamp($event['begin']); - $vevent->dtstart = new \davigil\helpers\ics\struct_dt( - '', - \davigil\helpers\ics\datetime_from_unix_timestamp($event['begin']) - ); - $vevent->dtend = ( - ($event['end'] === null) - ? - null - : - new \davigil\helpers\ics\struct_dt( - '', - \davigil\helpers\ics\datetime_from_unix_timestamp($event['end']) - ) - ); - $vevent->summary = $event['title']; - $vevent->location = $event['location']; - $vevent->description = $event['description']; - $vevent->class = \davigil\helpers\ics\enum_class::public_; - } - return $vevent; - } - - - /** - * @todo outsource - */ - private function events_to_vcalendar( - array $events - ) : \davigil\helpers\ics\struct_vcalendar - { - $vcalendar = new \davigil\helpers\ics\struct_vcalendar(); - { - $vcalendar->version = '2.0'; - /** - * @todo conf - */ - $vcalendar->prodid = 'davigil'; - $vcalendar->method = 'PUBLISH'; - $vcalendar->events = \array_map( - fn($event) => $this->event_to_vevent($event), - $events - ); - } - return $vcalendar; - } - - - /** + * [implementation] */ public function getCalendarObject( $calendarId, @@ -235,6 +241,7 @@ class class_caldav_backend { $vcalendar = $this->events_to_vcalendar($entries); $ics = \davigil\helpers\ics\vcalendar_encode($vcalendar); +\error_log($ics); return [ 'calendardata' => $ics, 'uri' => $objectUri, @@ -257,6 +264,7 @@ class class_caldav_backend /** + * [implementation] */ public function createCalendarObject( $calendarId, @@ -269,6 +277,7 @@ class class_caldav_backend /** + * [implementation] */ public function updateCalendarObject( $calendarId, @@ -281,6 +290,7 @@ class class_caldav_backend /** + * [implementation] */ public function deleteCalendarObject( $calendarId, diff --git a/source/sources/_factory.php b/source/sources/_factory.php index 42b0aeb..cd7610c 100644 --- a/source/sources/_factory.php +++ b/source/sources/_factory.php @@ -22,7 +22,8 @@ function make( case 'ics_feed': { return (new class_source_ics_feed( - $descriptor['data']['url'] + $descriptor['data']['url'], + ($descriptor['data']['condense'] ?? false) )); } default: diff --git a/source/sources/ics_feed.php b/source/sources/ics_feed.php index 0175389..d3f610b 100644 --- a/source/sources/ics_feed.php +++ b/source/sources/ics_feed.php @@ -19,13 +19,20 @@ class class_source_ics_feed private string $url; + /** + */ + private bool $condense; + + /** */ public function __construct( - string $url + string $url, + bool $condense ) { $this->url = $url; + $this->condense = $condense; $this->cache_file = new \davigil\helpers\cache\class_cache_encoded( new \davigil\helpers\cache\class_cache_file('data'), fn($value) => \json_encode($value), @@ -58,7 +65,23 @@ class class_source_ics_feed $data = \array_map( fn($vevent) => [ 'id' => $vevent->uid, - 'title' => $vevent->summary, + 'title' => ( + $this->condense + ? + \sprintf( + '%s%s', + $vevent->summary, + \implode( + '', + \array_map( + fn($category) => \sprintf(' (%s)', $category), + $vevent->categories + ) + ) + ) + : + $vevent->summary + ), 'begin' => \davigil\helpers\ics\datetime_to_unix_timestamp($vevent->dtstart->value), 'end' => ( ($vevent->dtend === null) @@ -69,7 +92,13 @@ class class_source_ics_feed ), 'location' => $vevent->location, 'description' => $vevent->description, - 'tags' => $vevent->categories, + 'tags' => ( + $this->condense + ? + ['dummy'] + : + $vevent->categories + ), ], $vcalendar->events );