pp-planer/app/Services/TranslationService.php
Thorsten Bus bdbf0c65e3 refactor(php): rename SongGroup references throughout controllers/services/tests
Replace all SongGroup/SongArrangementGroup model usages with Label/SongArrangementLabel
after the schema migration to global labels. Updates 12 app files and 11 test files:

- SongService: createDefaultGroups now finds-or-creates global Labels by name
- ArrangementController: validates label_id (labels are global, no song-ownership)
- ProImportService: imports groups as Labels (firstOrCreate by name); does not
  overwrite existing label colors per spec
- ProExportService/SongPdfController/TranslationService/etc: traverse via
  arrangements -> arrangementLabels -> label -> songSlides chain
- All test factories and assertions adapted to label-based schema
2026-05-03 22:55:02 +02:00

90 lines
2.4 KiB
PHP

<?php
namespace App\Services;
use App\Models\Song;
use App\Models\SongSlide;
use Illuminate\Support\Facades\Http;
class TranslationService
{
public function fetchFromUrl(string $url): ?string
{
try {
$response = Http::timeout(10)->get($url);
if ($response->successful()) {
$html = $response->body();
$text = strip_tags($html);
$text = trim($text);
return $text !== '' ? $text : null;
}
} catch (\Exception) {
// Best-effort: Fehler stillschweigend behandeln
}
return null;
}
public function importTranslation(Song $song, string $text): void
{
$translatedLines = explode("\n", $text);
$offset = 0;
$defaultArr = $song->arrangements()
->where('is_default', true)
->with(['arrangementLabels' => fn ($q) => $q->orderBy('order'), 'arrangementLabels.label.songSlides'])
->first();
if ($defaultArr === null) {
$this->markAsTranslated($song);
return;
}
foreach ($defaultArr->arrangementLabels->sortBy('order') as $arrangementLabel) {
$label = $arrangementLabel->label;
if ($label === null) {
continue;
}
foreach ($label->songSlides->sortBy('order') as $slide) {
$originalLineCount = count(explode("\n", $slide->text_content ?? ''));
$chunk = array_slice($translatedLines, $offset, $originalLineCount);
$offset += $originalLineCount;
$slide->update([
'text_content_translated' => implode("\n", $chunk),
]);
}
}
$this->markAsTranslated($song);
}
public function markAsTranslated(Song $song): void
{
$song->update(['has_translation' => true]);
}
public function removeTranslation(Song $song): void
{
$labelIds = $song->arrangements()
->with('arrangementLabels')
->get()
->flatMap(fn ($arr) => $arr->arrangementLabels->pluck('label_id'))
->unique()
->values();
if ($labelIds->isNotEmpty()) {
SongSlide::whereIn('label_id', $labelIds)->update([
'text_content_translated' => null,
]);
}
$song->update(['has_translation' => false]);
}
}