$integration->integration_code, 'name' => $integration->name.' / '.$this->ownerName($owner), 'integration_data' => $integrationData, ]); return $this->associate($owner, $integration->integration_code, $instance); }); } public function associate(Client|WebsiteType $owner, string $code, IntegrationInstance $instance): ClientIntegration|WebsiteTypeIntegration { return DB::transaction(function () use ($owner, $code, $instance): ClientIntegration|WebsiteTypeIntegration { $association = $owner->integrations() ->where('integration_code', $code) ->lockForUpdate() ->first(); $previousInstanceId = $association?->integration_instance_id; $instanceIds = array_values(array_unique(array_filter([ $previousInstanceId, $instance->id, ]))); sort($instanceIds); $instances = IntegrationInstance::query() ->whereKey($instanceIds) ->orderBy('id') ->lockForUpdate() ->get() ->keyBy('id'); $instance = $instances->get($instance->id) ?? IntegrationInstance::query()->findOrFail($instance->id); abort_unless($instance->integration_code === $code, 422, 'The instance belongs to another integration.'); $association = $owner->integrations()->updateOrCreate( ['integration_code' => $code], ['integration_instance_id' => $instance->id], ); if ($previousInstanceId && $previousInstanceId !== $instance->id) { $this->deleteIfUnused($previousInstanceId); } return $association->load('integrationInstance'); }); } public function detach(Client|WebsiteType $owner, string $code): void { DB::transaction(function () use ($owner, $code): void { $association = $owner->integrations() ->where('integration_code', $code) ->lockForUpdate() ->first(); if (! $association) { return; } $instanceId = $association->integration_instance_id; $association->delete(); $this->deleteIfUnused($instanceId); }); } private function deleteIfUnused(int $instanceId): void { $instance = IntegrationInstance::query()->lockForUpdate()->find($instanceId); if ($instance && ! $instance->clientIntegrations()->exists() && ! $instance->websiteTypeIntegrations()->exists()) { $instance->delete(); } } private function ownerName(Client|WebsiteType $owner): string { return $owner instanceof Client ? $owner->name : $owner->nombre; } }