JezK
Edit File: CollaborationService.php
<?php namespace Kirki\App\Services; defined('ABSPATH') || exit; use Kirki\App\Constants\CollaborationConnectionType; use Kirki\App\Constants\CollaborationParent; use Kirki\App\DTO\Collaboration\CreateCollaborationDTO; use Kirki\App\Models\Collaboration; use Kirki\App\Models\CollaborationConnected; use Kirki\Framework\Collections\Collection; use Kirki\Framework\Constants\DateTimeFormats; use function Kirki\Framework\user; class CollaborationService { /** * Save collaboration data. * * @param CreateCollaborationDTO $dto * @param bool $cleanup * * @return Collaboration|false */ public function save_action(CreateCollaborationDTO $dto, bool $cleanup = true) { $all_connected_rows = $this->get_all_connected_rows($cleanup); if ($all_connected_rows->count() <= 1) { return false; } return Collaboration::create([ 'user_id' => user()->get_id(), 'session_id' => $dto->session_id, 'parent' => $dto->parent ?? '', 'parent_id' => $dto->parent_id, 'data' => wp_json_encode($dto->data), 'status' => $dto->status, ]); } /** * Save collaboration batch data. * * @param Collection<CreateCollaborationDTO> $collection * @param bool $cleanup * * @return bool */ public function save_actions(Collection $collection, bool $cleanup = true) { $all_connected_rows = $this->get_all_connected_rows($cleanup); if ($all_connected_rows->count() <= 1) { return false; } $data = $collection->map(function (CreateCollaborationDTO $dto) { return [ 'user_id' => user()->get_id(), 'session_id' => $dto->session_id, 'parent' => $dto->parent ?? '', 'parent_id' => $dto->parent_id, 'data' => wp_json_encode($dto->data), 'status' => $dto->status, ]; })->to_array(); if (empty($data)) { return false; } return Collaboration::insert($data); } /** * Get all connected rows. * first clean disconnected rows then get only recent connected rows. * * @param bool $cleanup if true will clean disconnected rows. * * @return Collection */ public function get_all_connected_rows(bool $cleanup = true) { if ($cleanup) { $this->clean_disconnected_rows(); } return CollaborationConnected::all(); } /** * Clean disconnected rows if inactive less then 20 seconds. * * @return bool */ public function clean_disconnected_rows() { $twenty_seconds_ago = gmdate(DateTimeFormats::DB_DATETIME, time() - 20); // Get all expired connections (session_id + post_id in one query) /** @var Collection $connections */ $connections = CollaborationConnected::where('updated_at', '<=', $twenty_seconds_ago)->get(); if ($connections->is_empty()) { return false; } // Step 1: Broadcast removal for each connection $remove_connections = $connections->map(function (CollaborationConnected $connection) { $data = [ 'type' => CollaborationConnectionType::REMOVE_CONNECTION, 'payload' => [ 'session_id' => $connection->session_id ], ]; return CreateCollaborationDTO::from_array([ 'session_id' => $connection->session_id, 'parent' => CollaborationParent::POST, 'parent_id' => $connection->post_id, 'data' => $data, ])->to_array(); }); if ($remove_connections->not_empty()) { Collaboration::insert($remove_connections->to_array()); } // Step 2: Bulk delete all expired sessions in one query $session_ids = $connections->pluck('session_id')->to_array(); CollaborationConnected::where_in('session_id', $session_ids)->delete(); return true; } }