Browse Source

Refactored the update_read method in the Topic class.

sh4nks 11 years ago
parent
commit
9bc805b84e
2 changed files with 117 additions and 65 deletions
  1. 1 1
      .travis.yml
  2. 116 64
      flaskbb/forum/models.py

+ 1 - 1
.travis.yml

@@ -1,4 +1,4 @@
-nguage: python
+language: python
 python:
 python:
   - "2.7"
   - "2.7"
 # command to install dependencies
 # command to install dependencies

+ 116 - 64
flaskbb/forum/models.py

@@ -457,19 +457,15 @@ class Topic(db.Model):
         db.session.commit()
         db.session.commit()
         return self
         return self
 
 
-    def update_read(self, user, forum, forumsread=None):
-        """Update the topics read status if the user hasn't read the latest
-        post. Returns True if the tracker has been updated.
-
-        :param user: The user for whom the readstracker should be updated
+    def is_unread(self, user, forumsread):
+        """Returns True if the topic is unread for the user.
 
 
-        :param forum: The forum in which the topic is
+        :param user: The user whom should be checked if he has read the topic.
 
 
-        :param forumsread: The forumsread object. It is used to check if there
-                           is a new post since the forum has been marked as
-                           read
+        :param forumsread: The ForumsRead object is needed because we also
+                           need to check if the topic is below or above the
+                           read_cutoff.
         """
         """
-
         read_cutoff = datetime.utcnow() - timedelta(
         read_cutoff = datetime.utcnow() - timedelta(
             days=current_app.config['TRACKER_LENGTH'])
             days=current_app.config['TRACKER_LENGTH'])
 
 
@@ -477,73 +473,65 @@ class Topic(db.Model):
         # TopicsRead model
         # TopicsRead model
         if not user.is_authenticated() or \
         if not user.is_authenticated() or \
                 read_cutoff > self.last_post.date_created:
                 read_cutoff > self.last_post.date_created:
-            return
-
-        topicread = TopicsRead.query.\
-            filter(TopicsRead.user_id == user.id,
-                   TopicsRead.topic_id == self.id).first()
+            return False
 
 
         # Can be None if the user has never marked the forum as read. If this
         # Can be None if the user has never marked the forum as read. If this
         # condition is false - we need to update the tracker
         # condition is false - we need to update the tracker
         if forumsread and forumsread.cleared is not None and \
         if forumsread and forumsread.cleared is not None and \
                 forumsread.cleared >= self.last_post.date_created:
                 forumsread.cleared >= self.last_post.date_created:
-            return
+            return False
+
+        return True
+
+    def update_read(self, user, forum, forumsread):
+        """Update the topics read status if the user hasn't read the latest
+        post. Returns True if the tracker has been updated.
+
+        :param user: The user for whom the readstracker should be updated.
+
+        :param forum: The forum in which the topic is.
+
+        :param forumsread: The forumsread object. It is used to check if there
+                           is a new post since the forum has been marked as
+                           read.
+        """
+        if not self.is_unread(user, forumsread):
+            return False
+
+        topicsread = TopicsRead.query.\
+            filter(TopicsRead.user_id == user.id,
+                   TopicsRead.topic_id == self.id).first()
+
+        # Because we return True/False if the trackers have been
+        # updated, we need to store the status in a temporary variable
+        updated = False
 
 
         # A new post has been submitted that the user hasn't read.
         # A new post has been submitted that the user hasn't read.
         # Updating...
         # Updating...
-        if topicread and (topicread.last_read < self.last_post.date_created):
-            topicread.last_read = datetime.utcnow()
-            topicread.save()
+        if topicsread and (topicsread.last_read < self.last_post.date_created):
+            topicsread.last_read = datetime.utcnow()
+            topicsread.save()
+            updated = True
 
 
         # The user has not visited the topic before. Inserting him in
         # The user has not visited the topic before. Inserting him in
         # the TopicsRead model.
         # the TopicsRead model.
-        elif not topicread:
-            topicread = TopicsRead()
-            topicread.user_id = user.id
-            topicread.topic_id = self.id
-            topicread.forum_id = self.forum_id
-            topicread.last_read = datetime.utcnow()
-            topicread.save()
-
-        # else: no unread posts
+        elif not topicsread:
+            topicsread = TopicsRead()
+            topicsread.user_id = user.id
+            topicsread.topic_id = self.id
+            topicsread.forum_id = self.forum_id
+            topicsread.last_read = datetime.utcnow()
+            topicsread.save()
+            updated = True
+
+        # No unread posts
+        else:
+            updated = False
 
 
         if forum:
         if forum:
-            # fetch the unread posts in the forum
-            unread_count = Topic.query.\
-                outerjoin(TopicsRead,
-                          db.and_(TopicsRead.topic_id == Topic.id,
-                                  TopicsRead.user_id == user.id)).\
-                outerjoin(ForumsRead,
-                          db.and_(ForumsRead.forum_id == Topic.forum_id,
-                                  ForumsRead.user_id == user.id)).\
-                filter(Topic.forum_id == forum.id,
-                       db.or_(TopicsRead.last_read == None,
-                              TopicsRead.last_read < Topic.last_updated)).\
-                count()
-
-            # No unread topics available - trying to mark the forum as read
-            if unread_count == 0:
-                forumread = ForumsRead.query.\
-                    filter(ForumsRead.user_id == user.id,
-                           ForumsRead.forum_id == forum.id).first()
-
-                # ForumsRead is already up-to-date.
-                if forumread and forumread.last_read > topicread.last_read:
-                    return
-
-                # ForumRead Entry exists - Updating it because a new post
-                # has been submitted that the user hasn't read.
-                elif forumread:
-                    forumread.last_read = datetime.utcnow()
-                    forumread.save()
-
-                # No ForumRead Entry existing - creating one.
-                else:
-                    forumread = ForumsRead()
-                    forumread.user_id = user.id
-                    forumread.forum_id = forum.id
-                    forumread.last_read = datetime.utcnow()
-                    forumread.save()
+            updated = forum.update_read(user, forumsread, topicsread)
+
+        return updated
 
 
 
 
 class Forum(db.Model):
 class Forum(db.Model):
@@ -618,6 +606,70 @@ class Forum(db.Model):
 
 
         db.session.commit()
         db.session.commit()
 
 
+    def is_unread(self, user, forumsread, topicsread):
+        """Returns True if the forum is unread for the specified user.
+
+        :param user: The user who should be checked if he has read the forum.
+
+        :param forumsread: The forumsread object is needed because we are
+                           going to check if the forum is unread.
+
+        :param topicsread: The topicsread object is used in combination
+                           with the forumsread object to check if the
+                           forumsread relation should be updated and
+                           therefore is unread.
+        """
+        # fetch the unread posts in the forum
+        unread_count = Topic.query.\
+            outerjoin(TopicsRead,
+                      db.and_(TopicsRead.topic_id == Topic.id,
+                              TopicsRead.user_id == user.id)).\
+            outerjoin(ForumsRead,
+                      db.and_(ForumsRead.forum_id == Topic.forum_id,
+                              ForumsRead.user_id == user.id)).\
+            filter(Topic.forum_id == self.id,
+                   db.or_(TopicsRead.last_read == None,
+                          TopicsRead.last_read < Topic.last_updated)).\
+            count()
+
+
+        # No unread topics available - trying to mark the forum as read
+        if unread_count == 0:
+            # ForumsRead is already up-to-date.
+            # This condition is used to prevent updating the forumsread
+            # everytime you visit a topic in the forum
+            if forumsread and forumsread.last_read > topicsread.last_read:
+                return False
+
+            # else the forum is unread
+            return True
+
+        # if > 0 unread topics - the forum is unread
+        return True
+
+    def update_read(self, user, forumsread, topicsread):
+        """Updates the ForumsRead status for the user
+
+        :param user: The user whom should be checked if he has read the forum.
+        """
+        if not self.is_unread(user, forumsread, topicsread):
+            return False
+
+        # ForumRead Entry exists - Updating it because a new post
+        # has been submitted that the user hasn't read.
+        if forumsread:
+            forumsread.last_read = datetime.utcnow()
+            forumsread.save()
+            return True
+
+        # No ForumRead Entry existing - creating one.
+        forumsread = ForumsRead()
+        forumsread.user_id = user.id
+        forumsread.forum_id = self.id
+        forumsread.last_read = datetime.utcnow()
+        forumsread.save()
+        return True
+
     def save(self, moderators=None):
     def save(self, moderators=None):
         """Saves a forum"""
         """Saves a forum"""
         if moderators is not None:
         if moderators is not None: