info('Synchronizing Todo itmes with CalDAV server'); $todos = $service->getTodos(); $count = 0; foreach ($todos as $todo) { // Only update the fields that are present in CalDAV $data = $todo->attributesToArray(); $data = array_intersect_key($data, array_flip([ 'id', 'etag', 'title', 'description', 'type_id', 'url', 'due_date', 'recurring', 'priority', 'status', 'created_at', 'last_modified', 'parent', 'object', ])); // Parse the title to extract the todoable title and todo title if (isset($data['title'])) { $titleParts = explode('] ', $data['title'], 2); if (count($titleParts) === 2) { $todoableTitle = trim($titleParts[0], '[]'); $todoTitle = $titleParts[1]; // Find the todoable model by title $models = [ 'PipelineItem' => PipelineItem::class, // Add other models here as needed ]; foreach ($models as $modelName => $modelClass) { $todoable = $modelClass::where('title', $todoableTitle)->first(); if ($todoable) { $data['todoable_type'] = 'App\\Models\\' . $modelName; $data['todoable_id'] = $todoable->id; break; } } } } Todo::upsert($data, 'id'); $count++; } // Collect hrefs/URLs returned by the CalDAV server so we can remove local // todos that belong to this calendar but were deleted on the server. $hrefs = array_values(array_filter(array_map(function ($t) { return $t->url ?? null; }, $todos))); // Remove local todos that have a URL in this calendar but weren't returned // by the server (i.e. they were deleted remotely). Scope deletion by // calendar prefix to avoid touching other calendars. $calendarId = $service->getCalendarId(); $username = config('caldav.username') ?? ''; $calendarPrefix = 'calendars/' . $username . '/' . $calendarId; if ($calendarId && $username) { Todo::whereNotNull('url') ->where('url', 'like', '%' . $calendarPrefix . "%") ->whereNotIn('url', $hrefs ?: ['']) ->delete(); } // Remove old todos Todo::where('status', 'COMPLETED') ->where('last_modified', '<', now()->subDays(30)) // TODO: get from settings ->where('due_date', '<', now()->subDays(30)) ->delete(); Log::info("Synced " . count($todos) . " todos."); $this->info("Synced " . count($todos) . " todos."); return 0; } }