id = $id; $pr = PressRelease::withoutGlobalScopes()->findOrFail($id); $this->portal = $pr->portal->value; $this->language = $pr->language; $this->companyId = $pr->company_id; $this->categoryId = $pr->category_id; $this->title = $pr->title; $this->text = $pr->text; $this->keywords = $pr->keywords ?? ''; $this->backlinkUrl = $pr->backlink_url ?? ''; $this->noExport = $pr->no_export; $this->currentStatus = $pr->status->value; $this->targetStatus = $this->currentStatus; } public function updatedCompanySearch(): void { $this->resetErrorBag('companyId'); } public function save(): void { $this->validate([ 'portal' => ['required', Rule::in(array_map(fn (Portal $p) => $p->value, Portal::cases()))], 'language' => ['required', Rule::in(['de', 'en'])], 'companyId' => ['required', 'integer', Rule::exists('companies', 'id')], 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], 'title' => ['required', 'string', 'min:5', 'max:255'], 'text' => ['required', 'string', 'min:50'], 'keywords' => ['nullable', 'string', 'max:255'], 'backlinkUrl' => ['nullable', 'url', 'max:255'], ]); $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); if ($pr->title !== $this->title || $pr->portal !== $this->portal || $pr->language !== $this->language) { $slug = $pr->generateUniqueSlug($this->title, [ 'portal' => $this->portal, 'language' => $this->language, ]); } else { $slug = $pr->slug; } $cleanText = app(PressReleaseHtmlSanitizer::class)->clean($this->text); $pr->update([ 'portal' => $this->portal, 'language' => $this->language, 'company_id' => (int) $this->companyId, 'category_id' => (int) $this->categoryId, 'title' => $this->title, 'slug' => $slug, 'text' => $cleanText, 'keywords' => $this->keywords ?: null, 'backlink_url' => $this->backlinkUrl ?: null, 'no_export' => $this->noExport, ]); session()->flash('success', __('Pressemitteilung gespeichert.')); } public function submitForReview(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); try { app(PressReleaseService::class)->submitForReview($pr); } catch (BlacklistViolationException $e) { $this->currentStatus = PressReleaseStatus::Rejected->value; session()->flash('error', __('Automatisch abgelehnt: unzulässiges Wort ":word".', ['word' => $e->word])); return; } $this->currentStatus = PressReleaseStatus::Review->value; session()->flash('success', __('Zur Prüfung eingereicht.')); } public function publish(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); try { app(PressReleaseService::class)->publish($pr); } catch (BlacklistViolationException $e) { $this->currentStatus = PressReleaseStatus::Rejected->value; session()->flash('error', __('Automatisch abgelehnt: unzulässiges Wort ":word".', ['word' => $e->word])); return; } $this->currentStatus = PressReleaseStatus::Published->value; session()->flash('success', __('Pressemitteilung veröffentlicht. Autor wurde benachrichtigt.')); } public function reject(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); app(PressReleaseService::class)->reject($pr); $this->currentStatus = PressReleaseStatus::Rejected->value; session()->flash('success', __('Pressemitteilung abgelehnt. Autor wurde benachrichtigt.')); } public function backToDraft(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); app(PressReleaseService::class)->backToDraft($pr); $this->currentStatus = PressReleaseStatus::Draft->value; session()->flash('success', __('Zurück auf Entwurf gesetzt.')); } public function archive(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); app(PressReleaseService::class)->archive($pr); $this->currentStatus = PressReleaseStatus::Archived->value; $this->targetStatus = $this->currentStatus; session()->flash('success', __('Pressemitteilung archiviert.')); } public function changeStatus(): void { $this->validate([ 'targetStatus' => ['required', Rule::in(array_map(fn (PressReleaseStatus $status) => $status->value, PressReleaseStatus::cases()))], ]); if ($this->targetStatus === $this->currentStatus) { $this->addError('targetStatus', __('Bitte wähle einen anderen Status aus.')); return; } $status = PressReleaseStatus::from($this->targetStatus); $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); app(PressReleaseService::class)->changeStatusFromAdmin($pr, $status); $this->currentStatus = $status->value; $this->targetStatus = $status->value; session()->flash('success', __('Status wurde auf ":status" geändert.', ['status' => $status->label()])); Flux::modal('confirm-status-change')->close(); } public function deletePressRelease(): void { $pr = PressRelease::withoutGlobalScopes()->findOrFail($this->id); $wasPublished = $pr->status === PressReleaseStatus::Published; app(PressReleaseService::class)->deleteFromAdmin($pr); session()->flash('success', $wasPublished ? __('Pressemitteilung wurde archiviert und der Inhalt durch den voreingestellten Ersatztext ersetzt.') : __('Pressemitteilung wurde gelöscht.')); $this->redirect(route('admin.press-releases.index'), navigate: true); } public function with(): array { $term = trim($this->companySearch); $companies = Company::withoutGlobalScopes() ->when(filled($term), function ($q) use ($term): void { if ($this->supportsFullTextSearch($term)) { $q->whereFullText(['name', 'email', 'slug'], $term); return; } $q->where('name', 'like', '%'.$term.'%')->orWhere('slug', 'like', '%'.$term.'%'); }) ->when(blank($term) && $this->companyId, fn ($q) => $q->whereIn('id', [(int) $this->companyId])) ->when(blank($term) && ! $this->companyId, fn ($q) => $q->whereRaw('0 = 1')) ->orderBy('name') ->limit(50) ->get(['id', 'name']); $statusEnum = PressReleaseStatus::tryFrom($this->currentStatus); return [ 'companies' => $companies, 'categories' => $this->categoryOptions(), 'portalOptions' => array_filter(Portal::cases(), fn (Portal $p) => $p !== Portal::Both), 'statusOptions' => PressReleaseStatus::cases(), 'statusEnum' => $statusEnum, 'targetStatusEnum' => PressReleaseStatus::tryFrom($this->targetStatus), 'statusColor' => match ($this->currentStatus) { 'published' => 'green', 'review' => 'yellow', 'rejected' => 'red', 'archived' => 'blue', default => 'zinc', }, ]; } private function categoryOptions(): Collection { return app(AdminPerformanceCache::class)->remember(AdminPerformanceCache::ActiveCategoryOptions, AdminPerformanceCache::OptionsTtl, fn () => Category::query() ->with('translations') ->where('is_active', true) ->orderBy('id') ->get()); } private function supportsFullTextSearch(string $term): bool { return mb_strlen($term) >= 3 && in_array(DB::connection()->getDriverName(), ['mysql', 'pgsql'], true); } }; ?>
{{ __('Inhalt, Metadaten und Status der PM aktualisieren. Änderungen werden sofort wirksam.') }}