PIMS/app/Modules/Movies/Services/UpdateMovieService.php

69 lines
2.6 KiB
PHP
Raw Normal View History

2025-12-07 03:49:26 +00:00
<?php
namespace App\Modules\Movies\Services;
use App\Modules\Movies\Models\{Movie, Genre, Actor, Director, Studio, Country, Language};
use App\Modules\Movies\Services\Contracts\UpdateMovieServiceInterface;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\DB;
class UpdateMovieService implements UpdateMovieServiceInterface
{
public function handle(int $id, array $data): Movie
{
/** @var Movie|null $movie */
$movie = Movie::query()->find($id);
if (!$movie) {
throw (new ModelNotFoundException())->setModel(Movie::class, [$id]);
}
return DB::transaction(function () use ($movie, $data) {
// Scalars
$movie->fill(array_intersect_key($data, array_flip([
'title', 'original_title', 'description', 'poster_url', 'backdrop_url', 'rating', 'release_date', 'year', 'runtime',
])));
$movie->save();
// Relations via free-text chips (names)
$this->syncNames($movie, Genre::class, 'genres', $data['genres'] ?? []);
$this->syncNames($movie, Actor::class, 'actors', $data['actors'] ?? []);
$this->syncNames($movie, Director::class, 'directors', $data['directors'] ?? []);
$this->syncNames($movie, Studio::class, 'studios', $data['studios'] ?? []);
$this->syncNames($movie, Country::class, 'countries', $data['countries'] ?? []);
$this->syncNames($movie, Language::class, 'languages', $data['languages'] ?? []);
return $movie->refresh();
});
}
protected function syncNames(Movie $movie, string $modelClass, string $relation, array $names): void
{
if (!is_array($names)) return;
$ids = collect($names)
->filter()
->map(fn($n) => $this->normalizeName((string)$n))
->filter(fn($n) => $n !== '')
->map(function ($normalized) use ($modelClass) {
$existing = $modelClass::query()
->whereRaw('lower(name) = ?', [mb_strtolower($normalized)])
->first();
if ($existing) return $existing->getKey();
$m = new $modelClass();
$m->setAttribute('name', $normalized);
$m->save();
return $m->getKey();
})
->values()
->all();
if (method_exists($movie, $relation)) {
$movie->{$relation}()->sync($ids);
}
}
protected function normalizeName(string $name): string
{
return trim(preg_replace('/\s+/u', ' ', $name) ?? '');
}
}