This commit is contained in:
fenris 2025-09-09 17:43:23 +00:00
parent 6033cea60e
commit 9f455202b3
7 changed files with 202 additions and 72 deletions

View file

@ -6,8 +6,12 @@
"source": { "source": {
"kind": "ics_feed", "kind": "ics_feed",
"data": { "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"
} }
} }

View file

@ -3,11 +3,47 @@
namespace davigil\conf; 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 class _state
{ {
public static $data = null; public static ?struct_root $data = null;
} }
@ -17,19 +53,43 @@ function load(
string $path string $path
) : void ) : void
{ {
_state::$data = \json_decode( $data_raw = \json_decode(
\file_get_contents( \file_get_contents(
$path $path
), ),
true 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( function get(
) ) : struct_root
{ {
return _state::$data; return _state::$data;
} }

View file

@ -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'); \array_push($content_lines, 'END:VEVENT');
} }

View file

@ -7,6 +7,7 @@ require_once('overwrites/principal_backend.php');
require_once('overwrites/auths/_factory.php'); require_once('overwrites/auths/_factory.php');
require_once('overwrites/caldav_backend.php'); require_once('overwrites/caldav_backend.php');
require_once('sources/_factory.php'); require_once('sources/_factory.php');
require_once('conf.php');
function main( function main(
@ -14,10 +15,14 @@ function main(
{ {
\davigil\conf\load('conf.json'); \davigil\conf\load('conf.json');
// \date_default_timezone_set('Europe/Berlin'); \date_default_timezone_set(\davigil\conf\get()->settings->timezone);
\date_default_timezone_set('UTC');
$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(); $principal_backend = new \davigil\overwrites\class_principle_backend();
@ -34,14 +39,17 @@ function main(
new \Sabre\DAV\Auth\Plugin( new \Sabre\DAV\Auth\Plugin(
\davigil\overwrites\make_auth_backend( \davigil\overwrites\make_auth_backend(
$source, $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\Plugin());
$server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); $server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());

View file

@ -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( public function getCalendarsForUser(
$principalUri $principalUri
@ -96,6 +156,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function createCalendar( public function createCalendar(
$principalUri, $principalUri,
@ -108,6 +169,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function deleteCalendar( public function deleteCalendar(
$calendarId $calendarId
@ -118,6 +180,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function getCalendarObjects( public function getCalendarObjects(
$calendarId $calendarId
@ -155,64 +218,7 @@ class class_caldav_backend
/** /**
* @todo outsource * [implementation]
*/
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;
}
/**
*/ */
public function getCalendarObject( public function getCalendarObject(
$calendarId, $calendarId,
@ -235,6 +241,7 @@ class class_caldav_backend
{ {
$vcalendar = $this->events_to_vcalendar($entries); $vcalendar = $this->events_to_vcalendar($entries);
$ics = \davigil\helpers\ics\vcalendar_encode($vcalendar); $ics = \davigil\helpers\ics\vcalendar_encode($vcalendar);
\error_log($ics);
return [ return [
'calendardata' => $ics, 'calendardata' => $ics,
'uri' => $objectUri, 'uri' => $objectUri,
@ -257,6 +264,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function createCalendarObject( public function createCalendarObject(
$calendarId, $calendarId,
@ -269,6 +277,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function updateCalendarObject( public function updateCalendarObject(
$calendarId, $calendarId,
@ -281,6 +290,7 @@ class class_caldav_backend
/** /**
* [implementation]
*/ */
public function deleteCalendarObject( public function deleteCalendarObject(
$calendarId, $calendarId,

View file

@ -22,7 +22,8 @@ function make(
case 'ics_feed': case 'ics_feed':
{ {
return (new class_source_ics_feed( return (new class_source_ics_feed(
$descriptor['data']['url'] $descriptor['data']['url'],
($descriptor['data']['condense'] ?? false)
)); ));
} }
default: default:

View file

@ -19,13 +19,20 @@ class class_source_ics_feed
private string $url; private string $url;
/**
*/
private bool $condense;
/** /**
*/ */
public function __construct( public function __construct(
string $url string $url,
bool $condense
) )
{ {
$this->url = $url; $this->url = $url;
$this->condense = $condense;
$this->cache_file = new \davigil\helpers\cache\class_cache_encoded( $this->cache_file = new \davigil\helpers\cache\class_cache_encoded(
new \davigil\helpers\cache\class_cache_file('data'), new \davigil\helpers\cache\class_cache_file('data'),
fn($value) => \json_encode($value), fn($value) => \json_encode($value),
@ -58,7 +65,23 @@ class class_source_ics_feed
$data = \array_map( $data = \array_map(
fn($vevent) => [ fn($vevent) => [
'id' => $vevent->uid, '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), 'begin' => \davigil\helpers\ics\datetime_to_unix_timestamp($vevent->dtstart->value),
'end' => ( 'end' => (
($vevent->dtend === null) ($vevent->dtend === null)
@ -69,7 +92,13 @@ class class_source_ics_feed
), ),
'location' => $vevent->location, 'location' => $vevent->location,
'description' => $vevent->description, 'description' => $vevent->description,
'tags' => $vevent->categories, 'tags' => (
$this->condense
?
['dummy']
:
$vevent->categories
),
], ],
$vcalendar->events $vcalendar->events
); );