mooxphp/moox

View on GitHub
packages/sync/src/Jobs/SyncJob.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace Moox\Sync\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Moox\Core\Traits\LogLevel;
use Moox\Sync\Models\Platform;

class SyncJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, LogLevel, Queueable, SerializesModels;

    protected $modelClass;

    protected $modelData;

    protected $eventType;

    protected $sourcePlatform;

    protected $targetPlatform;

    protected $shouldDelete;

    public function __construct($modelClass, $modelData, $eventType, Platform $sourcePlatform, Platform $targetPlatform, bool $shouldDelete)
    {
        $this->modelClass = $modelClass;
        $this->modelData = $modelData;
        $this->eventType = $eventType;
        $this->sourcePlatform = $sourcePlatform;
        $this->targetPlatform = $targetPlatform;
        $this->shouldDelete = $shouldDelete;
    }

    public function handle()
    {
        try {
            if ($this->shouldDelete) {
                $this->deleteModel();
            } else {
                // Existing sync logic
                if ($this->modelClass === Platform::class) {
                    $this->syncPlatform();
                } else {
                    $this->syncModel();
                }
            }
        } catch (\Exception $e) {
            Log::error('Moox Sync: Error syncing model', [
                'model_class' => $this->modelClass,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'source_platform' => $this->sourcePlatform->id,
                'target_platform' => $this->targetPlatform->id,
                'should_delete' => $this->shouldDelete,
            ]);
            throw $e;
        }
    }

    protected function deleteModel()
    {
        $modelId = $this->getModelId();
        $this->logInfo('Moox Sync: Deleting model', [
            'model_class' => $this->modelClass,
            'model_id_field' => $modelId['field'],
            'model_id_value' => $modelId['value'],
        ]);

        DB::table((new $this->modelClass)->getTable())->where($modelId['field'], $modelId['value'])->delete();
    }

    protected function syncPlatform()
    {
        $platform = Platform::updateOrCreate(
            ['name' => $this->modelData['name']],
            $this->modelData
        );

        $this->logDebug('Platform synced successfully', [
            'platform_id' => $platform->id,
            'platform_name' => $platform->name,
        ]);
    }

    protected function syncModel()
    {
        $handlerClass = config("sync.sync_bindings.{$this->modelClass}");

        if ($handlerClass && class_exists($handlerClass)) {
            $handler = new $handlerClass($this->modelClass, $this->modelData, $this->eventType);
            $handler->handle();
        } else {
            $this->defaultSync();
        }
    }

    protected function defaultSync()
    {
        $modelId = $this->getModelId();

        if ($this->eventType === 'deleted') {
            DB::table((new $this->modelClass)->getTable())->where($modelId['field'], $modelId['value'])->delete();
        } else {
            $data = $this->formatDatetimeFields($this->modelData);
            DB::table((new $this->modelClass)->getTable())->updateOrInsert(
                [$modelId['field'] => $modelId['value']],
                $data
            );
        }

        $this->logDebug('Model synced successfully', [
            'model_class' => $this->modelClass,
            'model_id_field' => $modelId['field'],
            'model_id_value' => $modelId['value'],
        ]);
    }

    protected function formatDatetimeFields($data)
    {
        foreach (['created_at', 'updated_at'] as $dateField) {
            if (isset($data[$dateField])) {
                $data[$dateField] = $this->formatDatetime($data[$dateField]);
            }
        }

        return $data;
    }

    protected function formatDatetime($dateString)
    {
        return Carbon::parse($dateString)->format('Y-m-d H:i:s');
    }

    protected function getModelId()
    {
        $localIdentifierFields = config('sync.local_identifier_fields', ['ID', 'uuid', 'ulid', 'id']);

        foreach ($localIdentifierFields as $field) {
            if (isset($this->modelData[$field])) {
                return [
                    'field' => $field,
                    'value' => $this->modelData[$field],
                ];
            }
        }

        Log::error('Moox Sync: No suitable ID field found for model', [
            'model_class' => $this->modelClass,
            'model_data' => $this->modelData,
        ]);

        throw new \Exception('No valid identifier found for the model');
    }
}