Passed
Push — develop ( ef53f3...80bc53 )
by BENARD
08:34
created

TopicUserLastVisitRepository::isTopicRead()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProjetNormandie\ForumBundle\Repository;
6
7
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
8
use Doctrine\ORM\NonUniqueResultException;
9
use Doctrine\ORM\NoResultException;
10
use Doctrine\Persistence\ManagerRegistry;
11
use ProjetNormandie\ForumBundle\Entity\Forum;
12
use ProjetNormandie\ForumBundle\Entity\Topic;
13
use ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit;
14
15
class TopicUserLastVisitRepository extends ServiceEntityRepository
16
{
17
    public function __construct(ManagerRegistry $registry)
18
    {
19
        parent::__construct($registry, TopicUserLastVisit::class);
20
    }
21
22
    /**
23
     * Trouve ou crée une visite pour un utilisateur et un topic
24
     */
25
    public function findOrCreateVisit($user, Topic $topic): TopicUserLastVisit
26
    {
27
        $visit = $this->findOneBy(['user' => $user, 'topic' => $topic]);
28
29
        if (!$visit) {
30
            $visit = new TopicUserLastVisit();
31
            $visit->setUser($user);
32
            $visit->setTopic($topic);
33
            // La date est automatiquement définie dans le constructeur
34
35
            $this->_em->persist($visit);
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
36
        }
37
38
        return $visit;
39
    }
40
41
    /**
42
     * Met à jour la date de dernière visite pour un topic
43
     */
44
    public function updateLastVisit($user, Topic $topic, ?\DateTime $visitDate = null): void
45
    {
46
        $visit = $this->findOrCreateVisit($user, $topic);
47
48
        if ($visitDate) {
49
            $visit->setLastVisitedAt($visitDate);
50
        } else {
51
            $visit->updateLastVisit();
52
        }
53
54
        $this->_em->flush();
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
55
    }
56
57
    /**
58
     * Vérifie si un topic est lu par un utilisateur
59
     */
60
    public function isTopicRead($user, Topic $topic): bool
61
    {
62
        $visit = $this->findOneBy(['user' => $user, 'topic' => $topic]);
63
64
        if (!$visit) {
65
            return false; // Jamais visité = non lu
66
        }
67
68
        return $visit->isTopicRead();
69
    }
70
71
    /**
72
     * Compte le nombre de topics non lus dans un forum
73
     */
74
    public function countUnreadTopicsInForum($user, Forum $forum): int
75
    {
76
        // Topics visités mais avec nouveaux messages
77
        $visitedUnreadQuery = $this->createQueryBuilder('tuv')
78
            ->select('COUNT(t.id)')
79
            ->join('tuv.topic', 't')
80
            ->join('t.lastMessage', 'lm')
81
            ->where('t.forum = :forum')
82
            ->andWhere('tuv.user = :user')
83
            ->andWhere('lm.createdAt > tuv.lastVisitedAt')
84
            ->setParameter('forum', $forum)
85
            ->setParameter('user', $user);
86
87
        // Topics jamais visités avec des messages
88
        $neverVisitedQuery = $this->_em->createQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
89
            ->select('COUNT(t.id)')
90
            ->from('ProjetNormandie\ForumBundle\Entity\Topic', 't')
91
            ->where('t.forum = :forum')
92
            ->andWhere('t.lastMessage IS NOT NULL')
93
            ->andWhere('t.id NOT IN (
94
                SELECT IDENTITY(tuv2.topic) 
95
                FROM ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit tuv2 
96
                WHERE tuv2.user = :user
97
            )')
98
            ->setParameter('forum', $forum)
99
            ->setParameter('user', $user);
100
101
        try {
102
            $visitedUnread = (int) $visitedUnreadQuery->getQuery()->getSingleScalarResult();
103
            $neverVisited = (int) $neverVisitedQuery->getQuery()->getSingleScalarResult();
104
105
            return $visitedUnread + $neverVisited;
106
        } catch (NoResultException | NonUniqueResultException) {
107
            return 0;
108
        }
109
    }
110
111
    /**
112
     * Marque tous les topics comme lus pour un utilisateur
113
     */
114
    public function markAllAsRead($user): void
115
    {
116
        $now = new \DateTime();
117
118
        // Mettre à jour les visites existantes
119
        $query = $this->_em->createQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
120
            ->update('ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit', 'tuv')
121
            ->set('tuv.lastVisitedAt', ':now')
122
            ->where('tuv.user = :user')
123
            ->setParameter('now', $now)
124
            ->setParameter('user', $user);
125
126
        $query->getQuery()->execute();
127
128
        // Créer des visites pour les topics jamais visités qui ont des messages
129
        $topicsWithoutVisit = $this->_em->createQueryBuilder()
130
            ->select('t')
131
            ->from('ProjetNormandie\ForumBundle\Entity\Topic', 't')
132
            ->where('t.id NOT IN (
133
                SELECT IDENTITY(tuv.topic) 
134
                FROM ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit tuv 
135
                WHERE tuv.user = :user
136
            )')
137
            ->andWhere('t.lastMessage IS NOT NULL')
138
            ->setParameter('user', $user)
139
            ->getQuery()
140
            ->getResult();
141
142
        foreach ($topicsWithoutVisit as $topic) {
143
            $visit = new TopicUserLastVisit();
144
            $visit->setUser($user);
145
            $visit->setTopic($topic);
146
            $visit->setLastVisitedAt($now);
147
            $this->_em->persist($visit);
148
        }
149
150
        $this->_em->flush();
151
    }
152
153
    /**
154
     * Marque tous les topics d'un forum comme lus
155
     */
156
    public function markForumTopicsAsRead($user, Forum $forum): void
157
    {
158
        $now = new \DateTime();
159
160
        // Mettre à jour les visites existantes pour ce forum
161
        $query = $this->_em->createQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
162
            ->update('ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit', 'tuv')
163
            ->set('tuv.lastVisitedAt', ':now')
164
            ->where('tuv.user = :user')
165
            ->andWhere('tuv.topic IN (
166
                SELECT t.id FROM ProjetNormandie\ForumBundle\Entity\Topic t 
167
                WHERE t.forum = :forum
168
            )')
169
            ->setParameter('now', $now)
170
            ->setParameter('user', $user)
171
            ->setParameter('forum', $forum);
172
173
        $query->getQuery()->execute();
174
175
        // Créer des visites pour les topics de ce forum jamais visités
176
        $topicsWithoutVisit = $this->_em->createQueryBuilder()
177
            ->select('t')
178
            ->from('ProjetNormandie\ForumBundle\Entity\Topic', 't')
179
            ->where('t.forum = :forum')
180
            ->andWhere('t.lastMessage IS NOT NULL')
181
            ->andWhere('t.id NOT IN (
182
                SELECT IDENTITY(tuv.topic) 
183
                FROM ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit tuv 
184
                WHERE tuv.user = :user
185
            )')
186
            ->setParameter('forum', $forum)
187
            ->setParameter('user', $user)
188
            ->getQuery()
189
            ->getResult();
190
191
        foreach ($topicsWithoutVisit as $topic) {
192
            $visit = new TopicUserLastVisit();
193
            $visit->setUser($user);
194
            $visit->setTopic($topic);
195
            $visit->setLastVisitedAt($now);
196
            $this->_em->persist($visit);
197
        }
198
199
        $this->_em->flush();
200
    }
201
202
    /**
203
     * Marque un topic spécifique comme lu
204
     */
205
    public function markTopicAsRead($user, Topic $topic): void
206
    {
207
        $this->updateLastVisit($user, $topic);
208
    }
209
210
    /**
211
     * Récupère tous les topics non lus pour un utilisateur dans un forum
212
     */
213
    public function getUnreadTopicsInForum($user, Forum $forum): array
214
    {
215
        // Topics visités mais avec nouveaux messages
216
        $visitedUnread = $this->createQueryBuilder('tuv')
217
            ->select('t')
218
            ->join('tuv.topic', 't')
219
            ->join('t.lastMessage', 'lm')
220
            ->where('t.forum = :forum')
221
            ->andWhere('tuv.user = :user')
222
            ->andWhere('lm.createdAt > tuv.lastVisitedAt')
223
            ->setParameter('forum', $forum)
224
            ->setParameter('user', $user)
225
            ->getQuery()
226
            ->getResult();
227
228
        // Topics jamais visités avec des messages
229
        $neverVisited = $this->_em->createQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The property _em does not exist on ProjetNormandie\ForumBun...UserLastVisitRepository. Did you maybe forget to declare it?
Loading history...
230
            ->select('t')
231
            ->from('ProjetNormandie\ForumBundle\Entity\Topic', 't')
232
            ->where('t.forum = :forum')
233
            ->andWhere('t.lastMessage IS NOT NULL')
234
            ->andWhere('t.id NOT IN (
235
                SELECT IDENTITY(tuv.topic) 
236
                FROM ProjetNormandie\ForumBundle\Entity\TopicUserLastVisit tuv 
237
                WHERE tuv.user = :user
238
            )')
239
            ->setParameter('forum', $forum)
240
            ->setParameter('user', $user)
241
            ->getQuery()
242
            ->getResult();
243
244
        return array_merge($visitedUnread, $neverVisited);
245
    }
246
}
247