ForumUserLastVisitRepository::markAllAsRead()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 37
rs 9.552
cc 2
nc 2
nop 1
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\ForumUserLastVisit;
13
14
class ForumUserLastVisitRepository extends ServiceEntityRepository
15
{
16
    public function __construct(ManagerRegistry $registry)
17
    {
18
        parent::__construct($registry, ForumUserLastVisit::class);
19
    }
20
21
    /**
22
     * Trouve ou crée une visite pour un utilisateur et un forum
23
     */
24
    public function findOrCreateVisit($user, Forum $forum): ForumUserLastVisit
25
    {
26
        $visit = $this->findOneBy(['user' => $user, 'forum' => $forum]);
27
28
        if (!$visit) {
29
            $visit = new ForumUserLastVisit();
30
            $visit->setUser($user);
31
            $visit->setForum($forum);
32
            // La date est automatiquement définie dans le constructeur
33
34
            $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...
35
        }
36
37
        return $visit;
38
    }
39
40
    /**
41
     * Met à jour la date de dernière visite pour un forum
42
     */
43
    public function updateLastVisit($user, Forum $forum, ?\DateTime $visitDate = null): void
44
    {
45
        $visit = $this->findOrCreateVisit($user, $forum);
46
47
        if ($visitDate) {
48
            $visit->setLastVisitedAt($visitDate);
49
        } else {
50
            $visit->updateLastVisit();
51
        }
52
53
        $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...
54
    }
55
56
    /**
57
     * Vérifie si un forum est considéré comme non lu pour un utilisateur
58
     */
59
    public function isForumUnread($user, Forum $forum): bool
60
    {
61
        $visit = $this->findOneBy(['user' => $user, 'forum' => $forum]);
62
63
        if (!$visit) {
64
            return true; // Jamais visité = non lu
65
        }
66
67
        $lastMessage = $forum->getLastMessage();
68
        if (!$lastMessage) {
69
            return false; // Pas de message = pas de nouveau contenu
70
        }
71
72
        return $lastMessage->getCreatedAt() > $visit->getLastVisitedAt();
73
    }
74
75
    /**
76
     * Compte le nombre de sous-forums non lus pour un forum parent
77
     */
78
    public function countUnreadSubForums($user, Forum $parent): int
79
    {
80
        $query = $this->createQueryBuilder('fuv')
81
            ->select('COUNT(f.id)')
82
            ->join('fuv.forum', 'f')
83
            ->join('f.lastMessage', 'lm')
84
            ->where('f.parent = :parent')
85
            ->andWhere('fuv.user = :user')
86
            ->andWhere('lm.createdAt > fuv.lastVisitedAt')
87
            ->setParameter('parent', $parent)
88
            ->setParameter('user', $user);
89
90
        // Ajouter les forums jamais visités
91
        $subQuery = $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...
92
            ->select('COUNT(sf.id)')
93
            ->from('ProjetNormandie\ForumBundle\Entity\Forum', 'sf')
94
            ->join('sf.lastMessage', 'slm')
95
            ->where('sf.parent = :parent')
96
            ->andWhere('sf.id NOT IN (
97
                SELECT IDENTITY(fuv2.forum) 
98
                FROM ProjetNormandie\ForumBundle\Entity\ForumUserLastVisit fuv2 
99
                WHERE fuv2.user = :user
100
            )')
101
            ->setParameter('parent', $parent)
102
            ->setParameter('user', $user);
103
104
        try {
105
            $visitedUnread = (int) $query->getQuery()->getSingleScalarResult();
106
            $neverVisited = (int) $subQuery->getQuery()->getSingleScalarResult();
107
108
            return $visitedUnread + $neverVisited;
109
        } catch (NoResultException | NonUniqueResultException) {
110
            return 0;
111
        }
112
    }
113
114
    /**
115
     * Marque tous les forums comme lus pour un utilisateur
116
     */
117
    public function markAllAsRead($user): void
118
    {
119
        $now = new \DateTime();
120
121
        // Mettre à jour les visites existantes
122
        $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...
123
            ->update('ProjetNormandie\ForumBundle\Entity\ForumUserLastVisit', 'fuv')
124
            ->set('fuv.lastVisitedAt', ':now')
125
            ->where('fuv.user = :user')
126
            ->setParameter('now', $now)
127
            ->setParameter('user', $user);
128
129
        $query->getQuery()->execute();
130
131
        // Créer des visites pour les forums jamais visités qui ont des messages
132
        $forumsWithoutVisit = $this->_em->createQueryBuilder()
133
            ->select('f')
134
            ->from('ProjetNormandie\ForumBundle\Entity\Forum', 'f')
135
            ->where('f.id NOT IN (
136
                SELECT IDENTITY(fuv.forum) 
137
                FROM ProjetNormandie\ForumBundle\Entity\ForumUserLastVisit fuv 
138
                WHERE fuv.user = :user
139
            )')
140
            ->andWhere('f.lastMessage IS NOT NULL')
141
            ->setParameter('user', $user)
142
            ->getQuery()
143
            ->getResult();
144
145
        foreach ($forumsWithoutVisit as $forum) {
146
            $visit = new ForumUserLastVisit();
147
            $visit->setUser($user);
148
            $visit->setForum($forum);
149
            $visit->setLastVisitedAt($now);
150
            $this->_em->persist($visit);
151
        }
152
153
        $this->_em->flush();
154
    }
155
156
    /**
157
     * Marque un forum spécifique comme lu
158
     */
159
    public function markForumAsRead($user, Forum $forum): void
160
    {
161
        $this->updateLastVisit($user, $forum);
162
    }
163
164
    /**
165
     * Récupère tous les forums non lus pour un utilisateur
166
     */
167
    public function getUnreadForums($user): array
168
    {
169
        // Forums visités mais avec nouveaux messages
170
        $visitedUnread = $this->createQueryBuilder('fuv')
171
            ->select('f')
172
            ->join('fuv.forum', 'f')
173
            ->join('f.lastMessage', 'lm')
174
            ->where('fuv.user = :user')
175
            ->andWhere('lm.createdAt > fuv.lastVisitedAt')
176
            ->setParameter('user', $user)
177
            ->getQuery()
178
            ->getResult();
179
180
        // Forums jamais visités avec des messages
181
        $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...
182
            ->select('f')
183
            ->from('ProjetNormandie\ForumBundle\Entity\Forum', 'f')
184
            ->where('f.lastMessage IS NOT NULL')
185
            ->andWhere('f.id NOT IN (
186
                SELECT IDENTITY(fuv.forum) 
187
                FROM ProjetNormandie\ForumBundle\Entity\ForumUserLastVisit fuv 
188
                WHERE fuv.user = :user
189
            )')
190
            ->setParameter('user', $user)
191
            ->getQuery()
192
            ->getResult();
193
194
        return array_merge($visitedUnread, $neverVisited);
195
    }
196
}
197