monatsplan - ckalender read fixed, developerpanel - rss feed implemented
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const DEVELOPER_FEED_URL = 'https://git.pelpino.de/NAK-Reinickendorf/intranet.rss';
|
||||
const DEVELOPER_REPO_URL = 'https://git.pelpino.de/NAK-Reinickendorf/intranet';
|
||||
const DEVELOPER_FEED_LIMIT = 7;
|
||||
|
||||
function developer_feed_plain_text(string $value): string
|
||||
{
|
||||
return trim(preg_replace(
|
||||
'/\s+/u',
|
||||
' ',
|
||||
strip_tags(preg_replace('/>\s*</', '> <', html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8')) ?? '')
|
||||
) ?? '');
|
||||
}
|
||||
|
||||
function developer_feed_items(string $url = DEVELOPER_FEED_URL): array
|
||||
{
|
||||
$handle = curl_init($url);
|
||||
if ($handle === false) {
|
||||
throw new RuntimeException('RSS-Feed konnte nicht initialisiert werden.');
|
||||
}
|
||||
|
||||
curl_setopt_array($handle, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ['Accept: application/rss+xml, application/xml;q=0.9'],
|
||||
CURLOPT_USERAGENT => 'NAK-Reinickendorf-Intranet/1.0',
|
||||
CURLOPT_CONNECTTIMEOUT => 2,
|
||||
CURLOPT_TIMEOUT => 4,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_MAXREDIRS => 3,
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
||||
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS,
|
||||
]);
|
||||
|
||||
try {
|
||||
$response = curl_exec($handle);
|
||||
$status = (int) curl_getinfo($handle, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($handle);
|
||||
} finally {
|
||||
curl_close($handle);
|
||||
}
|
||||
|
||||
if ($response === false || $status < 200 || $status >= 300) {
|
||||
throw new RuntimeException($error !== '' ? $error : 'HTTP ' . $status);
|
||||
}
|
||||
|
||||
return developer_parse_feed($response);
|
||||
}
|
||||
|
||||
function developer_parse_feed(string $xml): array
|
||||
{
|
||||
$previous = libxml_use_internal_errors(true);
|
||||
try {
|
||||
$feed = simplexml_load_string($xml, SimpleXMLElement::class, LIBXML_NONET | LIBXML_NOCDATA);
|
||||
} finally {
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($previous);
|
||||
}
|
||||
|
||||
if ($feed === false || !isset($feed->channel->item)) {
|
||||
throw new RuntimeException('Ungültiger RSS-Feed.');
|
||||
}
|
||||
|
||||
$items = [];
|
||||
foreach ($feed->channel->item as $item) {
|
||||
$title = developer_feed_plain_text((string) $item->title);
|
||||
if ($title === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$description = developer_feed_plain_text((string) $item->description);
|
||||
$author = trim((string) $item->children('http://purl.org/dc/elements/1.1/')->creator ?: (string) $item->author);
|
||||
if (preg_match('/\(([^)]+)\)\s*$/u', $author, $match) === 1) {
|
||||
$author = trim($match[1]);
|
||||
} else {
|
||||
$author = trim(preg_replace('/<[^>]+>|\S+@\S+/u', '', $author) ?? '');
|
||||
}
|
||||
$link = trim((string) $item->link);
|
||||
|
||||
$items[] = [
|
||||
'title' => $title,
|
||||
'description' => $description !== $title ? $description : '',
|
||||
'url' => filter_var($link, FILTER_VALIDATE_URL) && str_starts_with($link, DEVELOPER_REPO_URL) ? $link : DEVELOPER_REPO_URL,
|
||||
'author' => $author !== '' ? $author : 'Git',
|
||||
'timestamp' => strtotime((string) $item->pubDate) ?: 0,
|
||||
];
|
||||
}
|
||||
|
||||
usort($items, static fn(array $a, array $b): int => $b['timestamp'] <=> $a['timestamp']);
|
||||
return $items;
|
||||
}
|
||||
|
||||
function developer_feed_groups(array $items, ?DateTimeImmutable $now = null): array
|
||||
{
|
||||
$now ??= new DateTimeImmutable();
|
||||
$today = $now->setTime(0, 0);
|
||||
$week = $today->modify('monday this week');
|
||||
$month = $today->modify('first day of this month');
|
||||
$year = $today->setDate((int) $today->format('Y'), 1, 1);
|
||||
$starts = [
|
||||
'Heute' => $today,
|
||||
'Gestern' => $today->modify('-1 day'),
|
||||
'Diese Woche' => $week,
|
||||
'Letzte Woche' => $week->modify('-1 week'),
|
||||
'Diesen Monat' => $month,
|
||||
'Letzten Monat' => $month->modify('-1 month'),
|
||||
'Dieses Jahr' => $year,
|
||||
'Letztes Jahr' => $year->modify('-1 year'),
|
||||
];
|
||||
|
||||
$groups = [];
|
||||
foreach ($items as $item) {
|
||||
$date = (new DateTimeImmutable('@' . (int) $item['timestamp']))->setTimezone($now->getTimezone());
|
||||
$group = 'Älter';
|
||||
foreach ($starts as $label => $start) {
|
||||
if ($date >= $start) {
|
||||
$group = $label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$groups[$group][] = $item;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
function developer_feed_icon(string $title): string
|
||||
{
|
||||
$title = strtolower($title);
|
||||
|
||||
return match (true) {
|
||||
str_contains($title, 'merge pull'), str_starts_with($title, 'merge ') => 'M7 3a3 3 0 1 0-2 2.83v12.34a3 3 0 1 0 2 0V9h4a4 4 0 0 1 4 4v1.17a3 3 0 1 0 2 0V13a6 6 0 0 0-6-6H7V5.83A3 3 0 0 0 7 3Z',
|
||||
preg_match('/\b(fix|fixed|bugfix|hotfix|repair)\b/u', $title) === 1 => 'M14.7 6.3a5 5 0 0 0-6.47 6.47l-5.94 5.94a1 1 0 0 0 0 1.42l1.58 1.58a1 1 0 0 0 1.42 0l5.94-5.94A5 5 0 0 0 17.7 9.3l-3 3-3-3 3-3Z',
|
||||
preg_match('/\b(remove|removed|delete|deleted|revert)\b/u', $title) === 1 => 'M9 3h6l1 2h4v2H4V5h4l1-2Zm-3 6h12l-1 12H7L6 9Zm3 2v8h2v-8H9Zm4 0v8h2v-8h-2Z',
|
||||
preg_match('/\b(refactor|cleanup|clean up|simplif|optimi[sz])\w*/u', $title) === 1 => 'M7 3a3 3 0 1 0-2 2.83v12.34a3 3 0 1 0 2 0V14h3a5 5 0 0 0 5-5V7.83a3 3 0 1 0-2 0V9a3 3 0 0 1-3 3H7V5.83A3 3 0 0 0 7 3Z',
|
||||
preg_match('/\b(doc|docs|readme|wiki|tutorial)\w*/u', $title) === 1 => 'M4 3h7a2 2 0 0 1 2 2v15a3 3 0 0 0-3-3H4V3Zm16 0h-5v14h5V3Zm0 16h-5a1 1 0 0 0-1 1h6v-1Z',
|
||||
preg_match('/\b(add|added|new|create|created|introduce|introduced|implement|implemented)\b/u', $title) === 1 => 'M11 5h2v6h6v2h-6v6h-2v-6H5v-2h6V5Z',
|
||||
default => 'M12 3a4 4 0 0 0-3.87 3H3v2h5.13a4 4 0 0 0 7.74 0H21V6h-5.13A4 4 0 0 0 12 3Zm0 2a2 2 0 1 1 0 4 2 2 0 0 1 0-4Zm0 10a4 4 0 0 0-3.87 3H3v2h5.13a4 4 0 0 0 7.74 0H21v-2h-5.13A4 4 0 0 0 12 15Zm0 2a2 2 0 1 1 0 4 2 2 0 0 1 0-4Z',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user