%PDF- %PDF-
Direktori : /www/loslex/demo/app/Http/Controllers/ |
Current File : //www/loslex/demo/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; } }