NotificationTrackingController::trackOpen()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 11
c 1
b 0
f 1
dl 0
loc 22
rs 9.9
cc 4
nc 8
nop 1
1
<?php
2
3
namespace Usamamuneerchaudhary\Notifier\Http\Controllers;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Http\Response;
7
use Illuminate\Routing\Controller;
8
use Illuminate\Support\Facades\Log;
9
use Usamamuneerchaudhary\Notifier\Services\AnalyticsService;
10
use Usamamuneerchaudhary\Notifier\Services\NotificationRepository;
11
use Usamamuneerchaudhary\Notifier\Services\UrlTrackingService;
12
13
class NotificationTrackingController extends Controller
14
{
15
    public function __construct(
16
        protected AnalyticsService $analyticsService,
17
        protected NotificationRepository $notificationRepository,
18
        protected UrlTrackingService $urlTrackingService
19
    ) {}
20
21
    /**
22
     * Track email open - returns 1x1 transparent pixel
23
     */
24
    public function trackOpen(string $token): Response
25
    {
26
        try {
27
            $notification = $this->notificationRepository->findByToken($token);
28
29
            if (!$notification) {
30
                return $this->transparentPixel();
31
            }
32
33
            if (!$this->analyticsService->isOpenTrackingEnabled()) {
34
                return $this->transparentPixel();
35
            }
36
37
            $this->analyticsService->trackOpen($notification);
38
39
        } catch (\Exception $e) {
40
            Log::error("Failed to track notification open: " . $e->getMessage(), [
41
                'token' => $token,
42
            ]);
43
        }
44
45
        return $this->transparentPixel();
46
    }
47
48
    /**
49
     * Track link click - redirects to original URL
50
     */
51
    public function trackClick(string $token, Request $request)
52
    {
53
        try {
54
            $notification = $this->notificationRepository->findByToken($token);
55
56
            if (!$notification) {
57
                return redirect()->to($request->get('url', '/'));
58
            }
59
60
            if (!$this->analyticsService->isClickTrackingEnabled()) {
61
                return $this->urlTrackingService->safeRedirect($request->get('url', '/'));
62
            }
63
64
            $originalUrl = $request->get('url', '/');
65
66
            if (empty($originalUrl) || $originalUrl === '/') {
67
                return redirect()->to('/');
68
            }
69
70
            $this->analyticsService->trackClick($notification);
71
72
            return $this->urlTrackingService->safeRedirect($originalUrl);
73
74
        } catch (\Exception $e) {
75
            Log::error("Failed to track notification click: " . $e->getMessage(), [
76
                'token' => $token,
77
                'url' => $request->get('url'),
78
            ]);
79
80
            return $this->urlTrackingService->safeRedirect($request->get('url', '/'));
81
        }
82
    }
83
84
    /**
85
     * Return 1x1 transparent PNG pixel
86
     */
87
    protected function transparentPixel(): Response
88
    {
89
        $pixel = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==');
90
91
        return response($pixel, 200)
92
            ->header('Content-Type', 'image/png')
93
            ->header('Cache-Control', 'no-cache, no-store, must-revalidate')
94
            ->header('Pragma', 'no-cache')
95
            ->header('Expires', '0');
96
    }
97
}
98
99