PM-Tracking: Ereignis-Log fuer Aufrufe + Shares (press_release_events)
- press_release_events (type view/share, channel, ohne Personenbezug):
Model/Enums/Factory, Cascade-Delete an der PM
- Detailaufruf loggt View-Event zusaetzlich zum Legacy-hits-Zaehler
(bleibt bewusst einfacher Page-Request-Zaehler, User-Vorgabe 10.07.)
- POST press-release/{slug}/share (throttle 30/min, nur archiv-sichtbare
PMs des Portals) loggt Teilen-Klicks je Kanal (LinkedIn/X/E-Mail/Copy)
- Kundenpanel-PM-Seite: neue Kachel Geteilt mit Kanal-Aufschluesselung
- lang: web.detail.views (de/en)
- Tests: Web/PressReleaseTrackingTest (7)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
80a37f8fcd
commit
644f860223
14 changed files with 392 additions and 0 deletions
45
app/Http/Controllers/Web/ReleaseShareTrackingController.php
Normal file
45
app/Http/Controllers/Web/ReleaseShareTrackingController.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use App\Enums\PressReleaseEventType;
|
||||
use App\Enums\PressReleaseShareChannel;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PressRelease;
|
||||
use App\Scopes\PortalScope;
|
||||
use App\Support\WebPortalContext;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
* Nimmt Share-Klicks der öffentlichen PM-Detailseite entgegen und loggt
|
||||
* sie als Ereignis (Kanal: LinkedIn/X/E-Mail/Link kopiert) — ohne
|
||||
* Personenbezug. Nur für im Archiv sichtbare PMs des aufrufenden Portals.
|
||||
*/
|
||||
class ReleaseShareTrackingController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request, string $edition, string $slug): Response
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'channel' => ['required', Rule::enum(PressReleaseShareChannel::class)],
|
||||
]);
|
||||
|
||||
$context = WebPortalContext::fromRequest();
|
||||
|
||||
$release = PressRelease::query()
|
||||
->withoutGlobalScope(PortalScope::class)
|
||||
->forPortalValues($context->portalValues)
|
||||
->forLanguage($context->language)
|
||||
->visibleInArchive()
|
||||
->where('slug', $slug)
|
||||
->firstOrFail();
|
||||
|
||||
$release->events()->create([
|
||||
'type' => PressReleaseEventType::Share,
|
||||
'channel' => $validated['channel'],
|
||||
]);
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue