aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/Controllers/GalleryController.php
blob: bc76e21f16ece74aa9e3fa50a4e9aa0e3cdadb97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php

declare(strict_types=1);
// Gallery: public paginated feed with likes, comments, and notifications.

namespace App\Controllers;

use App\Csrf;
use App\Flash;
use App\Mail;
use App\Models\Comment;
use App\Models\Like;
use App\Models\Post;
use App\Models\User;

class GalleryController
{
    private Post $post;
    private Like $like;
    private Comment $comment;
    private const POSTS_PER_PAGE = 5;

    public function __construct()
    {
        $this->post = new Post();
        $this->like = new Like();
        $this->comment = new Comment();
    }

    public function index(): void
    {
        $page = max(1, (int) ($_GET['page'] ?? 1));
        $offset = ($page - 1) * self::POSTS_PER_PAGE;

        $posts = $this->post->findAllPaginated(self::POSTS_PER_PAGE, $offset);
        $totalPosts = $this->post->countAll();
        $totalPages = max(1, (int) ceil($totalPosts / self::POSTS_PER_PAGE));

        $userId = $_SESSION['user_id'] ?? null;

        foreach ($posts as &$post) {
            $post['like_count'] = $this->like->countByPost($post['id']);
            $post['user_liked'] = $userId ? $this->like->hasUserLiked($userId, $post['id']) : false;
            $post['comments'] = $this->comment->findByPostId($post['id']);
        }
        unset($post);

        $content = __DIR__ . '/../Views/gallery/index.php';
        include __DIR__ . '/../Views/layouts/main.php';
    }

    public function like(string $id): void
    {
        if (!isset($_SESSION['user_id'])) {
            header('Location: /login');
            return;
        }

        if (!Csrf::validate($_POST['csrf_token'] ?? '')) {
            Flash::set('error', 'Invalid CSRF token.');
            header('Location: /gallery');
            return;
        }

        $this->like->toggle($_SESSION['user_id'], (int) $id);

        $page = (int) ($_POST['page'] ?? 1);
        header('Location: /gallery?page=' . $page . '#post-' . $id);
    }

    public function comment(string $id): void
    {
        if (!isset($_SESSION['user_id'])) {
            header('Location: /login');
            return;
        }

        if (!Csrf::validate($_POST['csrf_token'] ?? '')) {
            Flash::set('error', 'Invalid CSRF token.');
            header('Location: /gallery');
            return;
        }

        $content = trim($_POST['content'] ?? '');

        if ($content === '') {
            Flash::set('error', 'Comment cannot be empty.');
            $page = (int) ($_POST['page'] ?? 1);
            header('Location: /gallery?page=' . $page . '#post-' . $id);
            return;
        }

        if (\strlen($content) > 500) {
            Flash::set('error', 'Comment is too long (max 500 characters).');
            $page = (int) ($_POST['page'] ?? 1);
            header('Location: /gallery?page=' . $page . '#post-' . $id);
            return;
        }

        $this->comment->create($_SESSION['user_id'], (int) $id, $content);

        // Notify the post owner if they have comment notifications enabled
        $post = $this->post->findById((int) $id);
        if ($post && $post['user_id'] !== $_SESSION['user_id']) {
            $user = new User();
            $owner = $user->findById($post['user_id']);
            if ($owner && $owner['notify_comments']) {
                Mail::sendCommentNotification(
                    $owner['email'],
                    $_SESSION['username'],
                    (int) $id
                );
            }
        }

        $page = (int) ($_POST['page'] ?? 1);
        header('Location: /gallery?page=' . $page . '#post-' . $id);
    }
}