app/Http/Controllers/DAV/Backend/CalDAV/CalDAVTasks.php (112 lines of code) (raw):
<?php
namespace App\Http\Controllers\DAV\Backend\CalDAV;
use Illuminate\Support\Arr;
use App\Models\Contact\Task;
use App\Services\Task\DestroyTask;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use App\Services\VCalendar\ExportTask;
use App\Services\VCalendar\ImportTask;
use Sabre\CalDAV\Plugin as CalDAVPlugin;
use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
class CalDAVTasks extends AbstractCalDAVBackend
{
/**
* Returns the uri for this backend.
*
* @return string
*/
public function backendUri()
{
return 'tasks';
}
public function getDescription()
{
return parent::getDescription()
+ [
'{DAV:}displayname' => trans('app.dav_tasks'),
'{'.CalDAVPlugin::NS_CALDAV.'}calendar-description' => trans('app.dav_tasks_description', ['name' => Auth::user()->name]),
'{'.CalDAVPlugin::NS_CALDAV.'}calendar-timezone' => Auth::user()->timezone,
'{'.CalDAVPlugin::NS_CALDAV.'}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VTODO']),
'{'.CalDAVPlugin::NS_CALDAV.'}schedule-calendar-transp' => new ScheduleCalendarTransp(ScheduleCalendarTransp::TRANSPARENT),
];
}
/**
* Returns the collection of all tasks.
*
* @return \Illuminate\Support\Collection
*/
public function getObjects()
{
return Auth::user()->account
->tasks()
->get();
}
/**
* Returns the contact for the specific uuid.
*
* @param string $uuid
* @return mixed
*/
public function getObjectUuid($uuid)
{
return Task::where([
'account_id' => Auth::user()->account_id,
'uuid' => $uuid,
])->first();
}
/**
* Extension for Calendar objects.
*
* @var string
*/
public function getExtension()
{
return '.ics';
}
/**
* Datas for this task.
*
* @param mixed $task
* @return array
*/
public function prepareData($task)
{
if ($task instanceof Task) {
try {
$vcal = app(ExportTask::class)
->execute([
'account_id' => Auth::user()->account_id,
'task_id' => $task->id,
]);
$calendardata = $vcal->serialize();
return [
'id' => $task->id,
'uri' => $this->encodeUri($task),
'calendardata' => $calendardata,
'etag' => '"'.md5($calendardata).'"',
'lastmodified' => $task->updated_at->timestamp,
];
} catch (\Exception $e) {
Log::debug(__CLASS__.' prepareData: '.(string) $e);
}
}
return [];
}
/**
* Updates an existing calendarobject, based on it's uri.
*
* The object uri is only the basename, or filename and not a full path.
*
* It is possible return an etag from this function, which will be used in
* the response to this PUT request. Note that the ETag must be surrounded
* by double-quotes.
*
* However, you should only really return this ETag if you don't mangle the
* calendar-data. If the result of a subsequent GET to this object is not
* the exact same as this request body, you should omit the ETag.
*
* @param string $objectUri
* @param string $calendarData
* @return string|null
*/
public function updateOrCreateCalendarObject($objectUri, $calendarData): ?string
{
$task_id = null;
if ($objectUri) {
$task = $this->getObject($objectUri);
if ($task) {
$task_id = $task->id;
}
}
try {
$result = app(ImportTask::class)
->execute([
'account_id' => Auth::user()->account_id,
'task_id' => $task_id,
'entry' => $calendarData,
]);
if (! Arr::has($result, 'error')) {
$task = Task::where('account_id', Auth::user()->account_id)
->find($result['task_id']);
$calendar = $this->prepareData($task);
return $calendar['etag'];
}
} catch (\Exception $e) {
Log::debug(__CLASS__.' updateOrCreateCalendarObject: '.(string) $e);
}
return null;
}
/**
* Deletes an existing calendar object.
*
* The object uri is only the basename, or filename and not a full path.
*
* @param string $objectUri
* @return void
*/
public function deleteCalendarObject($objectUri)
{
$task = $this->getObject($objectUri);
if ($task) {
try {
app(DestroyTask::class)
->execute([
'account_id' => Auth::user()->account_id,
'task_id' => $task->id,
]);
} catch (\Exception $e) {
Log::debug(__CLASS__.' deleteCalendarObject: '.(string) $e);
}
}
}
}