99 lines
3.6 KiB
PHP
99 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Integration\Services;
|
|
|
|
use App\Domains\Client\Models\Client;
|
|
use App\Domains\Integration\Models\ClientIntegration;
|
|
use App\Domains\Integration\Models\Integration;
|
|
use App\Domains\Integration\Models\IntegrationInstance;
|
|
use App\Domains\Integration\Models\WebsiteTypeIntegration;
|
|
use App\Domains\Tenant\Models\WebsiteType;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class IntegrationAssociationService
|
|
{
|
|
public function configure(Client|WebsiteType $owner, Integration $integration, array $integrationData): ClientIntegration|WebsiteTypeIntegration
|
|
{
|
|
return DB::transaction(function () use ($owner, $integration, $integrationData): ClientIntegration|WebsiteTypeIntegration {
|
|
$instance = IntegrationInstance::create([
|
|
'integration_code' => $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;
|
|
}
|
|
}
|