%PDF- %PDF-
| Direktori : /www/loslex/test/app/Http/Controllers/ |
| Current File : //www/loslex/test/app/Http/Controllers/IcsController.php |
<?php
namespace App\Http\Controllers;
use App\Models\Contest;
use App\Models\User;
use Barryvdh\Debugbar\Facades\Debugbar;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterval;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class IcsController extends Controller
{
protected $host;
public function __construct()
{
$this->host = request()->getHttpHost();
}
// all available contests
public function contests()
{
app('debugbar')->disable();
// DEBUG Cache::forget('icsContests');
$feedData = Cache::remember('icsContests', 3600, function () {
Log::info("Cache MISS", ['key' => 'icsContests']);
$contestlist = Contest::where('date', '>=', Carbon::today())
->where('published', 1)
->orderBy('date')
->with(['contest_level','contest_category','organizer_group','range'])
->get();
$feedArray = $this->getIcsHeader();
foreach ($contestlist as $contest) {
$feedArray = array_merge($feedArray, $this->getIcsContestData($contest));
}
$feedArray = array_merge($feedArray, $this->getIcsFooter());
return implode("\r\n", $feedArray);
});
return response($feedData, Response::HTTP_OK, [
'Content-type' => 'text/calendar; charset=utf-8',
'Content-Disposition' => 'attachment; filename=contests.ics'
]);
}
// contests from specific range
public function range(Range $range)
{
}
// contests where user is registered
public function user(string $token)
{
$user = User::where('personaltoken', $token)->first();
if ($user->count() == 0) {
// return 404?
return;
}
$registrations = Registration::where('user_id', $user->id)->get();
// TODO tady neco chybi?
}
private function getIcsContestData(Contest $contest)
{
$description[] = "Druh závodu: " . __('contest.' . $contest->contest_level?->name) . ", " . __('contest.' . $contest->contest_category?->name);
$description[] = "Pořadatelský tým: {$contest->organizer_group->name}";
$description[] = "Startovné: LEX: {$contest->feelex} Kč; Ostatní: {$contest->feeothers} Kč";
$description[] = "Kapacita závodu: {$contest->capacity} střelců";
$description[] = "Podrobnosti závodu: " . route('contest.show', $contest->id);
$desctext = implode('\n', $description);
$data = array();
$data[] = "BEGIN:VEVENT";
$data[] = "UID:c{$contest->id}@{$this->host}";
$data[] = "SEQUENCE:{$contest->version}";
$data[] = "DTSTAMP:{$contest->date->format("Ymd\\THis")}";
if ($contest->squadShootStyle == "manual") {
$start = CarbonInterval::createFromFormat('H:i', min(array_slice($contest->contestStart, 1, $contest->squads)));
$end = CarbonInterval::createFromFormat('H:i', max(array_slice($contest->contestEnd, 1, $contest->squads)));
} else {
$start = CarbonInterval::createFromFormat('H:i', $contest->presentationStart[0]);
$end = CarbonInterval::createFromFormat('H:i', $contest->contestEnd[0]);
}
$ctDate = new CarbonImmutable($contest->date);
$data[] = "DTSTART;TZID=Europe/Prague:{$ctDate->addMinutes($start->totalMinutes)->format("Ymd\\THis")}";
$data[] = "DTEND;TZID=Europe/Prague:{$ctDate->addMinutes($end->totalMinutes)->format("Ymd\\THis")}";
$data[] = "LAST-MODIFIED;TZID=Europe/Prague:{$contest->updated_at->format("Ymd\\THis")}";
$data[] = "LOCATION:{$contest->range->name}";
$data[] = "GEO:{$contest->range->coords->latitude};{$contest->range->coords->longitude}";
$data[] = $this->wrapLine("SUMMARY:LOS: {$contest->contestname}");
$data[] = $this->wrapLine("DESCRIPTION:{$desctext}");
$data[] = "URL:" . route('contest.show', $contest->id);
$data[] = "ORGANIZER;CN={$contest->organizer_group->name}:mailto:{$contest->organizerEmail}";
$data[] = "CATEGORIES:" . __('contest.' . $contest->contest_level?->name) . "," . __('contest.' . $contest->contest_category?->name);
$data[] = "END:VEVENT";
return $data;
}
private function getIcsHeader()
{
$data = array();
$data[] = "BEGIN:VCALENDAR";
$data[] = "VERSION:2.0";
$data[] = "CALSCALE:GREGORIAN";
$data[] = "PRODID:-//{$this->host}//NONSGML Contests//cs";
$data[] = "NAME:LOS LEX";
$data[] = "X-WR-CALNAME:LOS LEX";
$data[] = "DESCRIPTION;LANGUAGE=cs:Kalendář závodů LOS";
$data[] = "DESCRIPTION;LANGUAGE=en:LOS Contest calendar";
$data[] = "SOURCE;VALUE=URI:" . route('ics.contests');
$data[] = "X-WR-CALDESC:Kalendář závodů LOS";
$data[] = "REFRESH-INTERVAL;VALUE=DURATION:P3H";
$date[] = "COLOR:red";
$data[] = "BEGIN:VTIMEZONE";
$data[] = "TZID:Europe/Prague";
$data[] = "BEGIN:DAYLIGHT";
$data[] = "TZNAME:CEST";
$data[] = "TZOFFSETFROM:+0100";
$data[] = "TZOFFSETTO:+0200";
$data[] = "DTSTART:19700329T020000";
$data[] = "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU";
$data[] = "END:DAYLIGHT";
$data[] = "BEGIN:STANDARD";
$data[] = "TZOFFSETFROM:+0200";
$data[] = "TZOFFSETTO:+0100";
$data[] = "TZNAME:CET";
$data[] = "DTSTART:19701025T030000";
$data[] = "RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU";
$data[] = "END:STANDARD";
$data[] = "END:VTIMEZONE";
return $data;
}
private function getIcsFooter()
{
$data = array();
$data[] = "END:VCALENDAR";
return $data;
}
private function wrapLine(string $text)
{
/* Lines of text SHOULD NOT be longer than 75 octets, excluding the line break. Long content lines SHOULD be split
* into a multiple line representations using a line "folding" technique. That is, a long line can be split between
* any two characters by inserting a CRLF immediately followed by a single linear white-space character (i.e., SPACE or HTAB).
*/
$segments = mb_str_split($text, 70, 'UTF-8');
$result = array_shift($segments);
foreach ($segments as $segment) {
$result .= "\r\n " . $segment;
}
return $result;
}
private function replaceNewlines(string $text)
{
$text = preg_replace("/\n+/", "\\n", $text);
return $text;
}
}