core/source/sources/ics_feed.php
2025-09-21 13:27:37 +02:00

214 lines
3.6 KiB
PHP

<?php
namespace davina\sources;
require_once(DIR_LOGIC . '/helpers/string.php');
require_once(DIR_LOGIC . '/helpers/cache.php');
require_once(DIR_LOGIC . '/helpers/pit.php');
require_once(DIR_LOGIC . '/helpers/ics.php');
require_once(DIR_LOGIC . '/base.php');
require_once(DIR_LOGIC . '/model.php');
/**
*/
class class_source_ics_feed
implements interface_source
{
/**
*/
private string $url_template;
/**
*/
private ?int $lifetime;
/**
*/
private bool $combine;
/**
*/
public function __construct(
string $url_template,
?int $lifetime,
bool $combine
)
{
$this->url_template = $url_template;
$this->lifetime = $lifetime;
$this->combine = $combine;
$this->cache_file = \davina\helpers\call\convey(
new \davina\helpers\cache\class_cache_file('data'),
[
fn($x) => new \davina\helpers\cache\class_cache_encoded(
$x,
fn($value) => \json_encode($value),
fn($value_encoded) => \json_decode($value_encoded, true)
),
]
);
$this->cache_memory = \davina\helpers\call\convey(
(new \davina\helpers\cache\class_cache_memory()),
[
]
);
}
/**
*/
private function url(
$parameters
) : string
{
return \davina\helpers\string_\coin(
$this->url_template,
$parameters
);
}
/**
*/
private function vcalendar_to_calendar(
\davina\helpers\ics\struct_vcalendar $vcalendar
) : \davina\model\struct_calendar
{
return (
new \davina\model\struct_calendar(
\array_map(
fn($vevent) => (new \davina\model\struct_event(
// id
$vevent->uid,
// title
(
$this->combine
?
\sprintf(
'%s%s',
$vevent->summary,
\implode(
'',
\array_map(
fn($category) => \sprintf(' (%s)', $category),
$vevent->categories
)
)
)
:
$vevent->summary
),
// begin
\davina\helpers\ics\datetime_to_unix_timestamp($vevent->dtstart->value),
// end
(
($vevent->dtend === null)
?
null
:
\davina\helpers\ics\datetime_to_unix_timestamp($vevent->dtend->value)
),
// location
$vevent->location,
// description
$vevent->description,
// 'tags
(
$this->combine
?
['all']
:
$vevent->categories
)
)),
$vcalendar->events
)
)
);
}
/**
*/
private function retrieve(
string $url
)
{
$client = new \Sabre\HTTP\Client();
$request = new \Sabre\HTTP\Request(
'GET',
$url,
[],
null
);
$response = $client->send($request);
$status_code = $response->getStatus();
switch ($status_code)
{
case 200:
{
$ics = $response->getBody();
$vcalendar = \davina\helpers\ics\vcalendar_decode($ics);
$calendar = $this->vcalendar_to_calendar($vcalendar);
$calendar_raw = \davina\model\calendar_to_raw($calendar);
return $calendar_raw;
break;
}
default:
{
throw (
new \Exception(
\sprintf(
'unhandled response status code: %u',
$status_code
)
)
);
break;
}
}
}
/**
* [implementation]
*/
public function read(
array $parameters
) : \davina\model\struct_calendar
{
$url = $this->url(\davina\get_parameters());
$key = $url;
$f1 = fn() => $this->retrieve(
$url
);
$f2 = fn() => \davina\helpers\cache\get(
$this->cache_file,
$key,
$f1,
[
'ttl' => $this->lifetime,
]
);
$f3 = fn() => \davina\helpers\cache\get(
$this->cache_memory,
$key,
$f2,
[
'ttl' => null,
]
);
return \davina\model\calendar_from_raw(
($f3)()
);
}
}
?>