Browse Source

fix #679: actually use queryset passed down in exclude_invisible_threads

Rafał Pitoń 8 years ago
parent
commit
41378ab636

+ 10 - 12
misago/readtracker/categoriestracker.py

@@ -4,7 +4,7 @@ from django.utils import timezone
 from misago.threads.permissions import exclude_invisible_threads
 
 from . import signals
-from .dates import is_date_tracked
+from .dates import get_cutoff_date, is_date_tracked
 from .models import CategoryRead
 
 
@@ -52,7 +52,9 @@ def start_record(user, category):
 
 
 def sync_record(user, category):
-    cutoff_date = user.joined_on
+    cutoff_date = get_cutoff_date()
+    if user.joined_on > cutoff_date:
+        cutoff_date = user.joined_on
 
     try:
         category_record = user.categoryread_set.get(category=category)
@@ -61,17 +63,14 @@ def sync_record(user, category):
     except CategoryRead.DoesNotExist:
         category_record = None
 
-    recorded_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
-    recorded_threads = exclude_invisible_threads(
-        user, [category], recorded_threads)
+    all_threads = category.thread_set.filter(last_post_on__gt=cutoff_date)
+    all_threads_count = exclude_invisible_threads(
+        user, [category], all_threads).count()
 
-    all_threads_count = recorded_threads.count()
-
-    read_threads = user.threadread_set.filter(
+    read_threads_count = user.threadread_set.filter(
         category=category,
-        last_read_on__gt=cutoff_date
-    )
-    read_threads_count = read_threads.filter(
+        thread__in=all_threads,
+        last_read_on__gt=cutoff_date,
         thread__last_post_on__lte=F("last_read_on")
     ).count()
 
@@ -91,7 +90,6 @@ def sync_record(user, category):
             last_read_on = timezone.now()
         else:
             last_read_on = cutoff_date
-
         category_record = user.categoryread_set.create(
             category=category,
             last_read_on=last_read_on

+ 4 - 0
misago/readtracker/dates.py

@@ -4,6 +4,10 @@ from django.conf import settings
 from django.utils import timezone
 
 
+def get_cutoff_date(*dates):
+    return timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
+
+
 def is_date_tracked(date, user, category_read_cutoff=None):
     if date:
         cutoff_date = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)

+ 29 - 7
misago/readtracker/tests/test_readtracker.py

@@ -35,7 +35,7 @@ class CategoriesTrackerTests(ReadTrackerTests):
         self.assertIsNone(self.category.last_post_on)
         self.assertTrue(self.category.is_read)
 
-    def test_anon_category_with_recent_reply_read(self):
+    def test_anon_category_recent_reply_read(self):
         """anon users content is always read"""
         categoriestracker.make_read_aware(self.anon, self.categories)
         self.category.last_post_on = timezone.now()
@@ -54,14 +54,14 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertTrue(self.category.is_read)
 
-    def test_make_read_aware_sets_read_flag_for_category_with_old_thread(self):
+    def test_make_read_aware_sets_read_flag_for_category_old_thread(self):
         """make_read_aware sets read flag on category with old thread"""
         self.category.last_post_on = self.user.joined_on - timedelta(days=1)
 
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertTrue(self.category.is_read)
 
-    def test_make_read_aware_sets_unread_flag_for_category_with_new_thread(self):
+    def test_make_read_aware_sets_unread_flag_for_category_new_thread(self):
         """make_read_aware sets unread flag on category with new thread"""
         self.category.last_post_on = self.user.joined_on + timedelta(days=1)
 
@@ -77,7 +77,7 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertTrue(self.category.is_read)
 
-    def test_sync_record_for_category_with_old_thread_and_reply(self):
+    def test_sync_record_for_category_old_thread_and_reply(self):
         """
         sync_record sets read flag on category with old thread,
         then changes flag to unread when new reply is posted
@@ -96,7 +96,7 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertFalse(self.category.is_read)
 
-    def test_sync_record_for_category_with_new_thread(self):
+    def test_sync_record_for_category_new_thread(self):
         """
         sync_record sets read flag on category with old thread,
         then keeps flag to unread when new reply is posted
@@ -115,7 +115,7 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertFalse(self.category.is_read)
 
-    def test_sync_record_for_category_with_deleted_threads(self):
+    def test_sync_record_for_category_deleted_threads(self):
         """unread category reverts to read after its emptied"""
         self.post_thread(self.user.joined_on + timedelta(days=1))
         self.post_thread(self.user.joined_on + timedelta(days=1))
@@ -133,7 +133,7 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertTrue(self.category.is_read)
 
-    def test_sync_record_for_category_with_many_threads(self):
+    def test_sync_record_for_category_many_threads(self):
         """sync_record sets unread flag on category with many threads"""
         self.post_thread(self.user.joined_on + timedelta(days=1))
         self.post_thread(self.user.joined_on - timedelta(days=1))
@@ -152,6 +152,21 @@ class CategoriesTrackerTests(ReadTrackerTests):
         categoriestracker.make_read_aware(self.user, self.categories)
         self.assertFalse(self.category.is_read)
 
+    def test_sync_record_for_category_threads_behind_cutoff(self):
+        """
+        sync_record sets read flag on category with only thread being behind cutoff
+        """
+        self.post_thread(timezone.now() - timedelta(days=180))
+
+        read_thread = self.post_thread(timezone.now())
+
+        threadstracker.make_read_aware(self.user, read_thread)
+        threadstracker.read_thread(self.user, read_thread, read_thread.last_post)
+
+        category = Category.objects.get(pk=self.category.pk)
+        categoriestracker.make_read_aware(self.user, [category])
+        self.assertTrue(category.is_read)
+
     def test_read_leaf_category(self):
         """read_category reads leaf category for user"""
         categoriestracker.read_category(self.user, self.category)
@@ -281,3 +296,10 @@ class ThreadsTrackerTests(ReadTrackerTests):
         for post in posts[:-1]:
             self.assertTrue(post.is_read)
         self.assertTrue(posts[-1].is_new)
+
+        # last post read will change readstate of categories
+        threadstracker.make_read_aware(self.user, self.thread)
+        threadstracker.read_thread(self.user, self.thread, posts[-1])
+
+        categoriestracker.make_read_aware(self.user, self.categories)
+        self.assertTrue(self.category.is_read)

+ 1 - 1
misago/threads/permissions/threads.py

@@ -902,7 +902,7 @@ def exclude_invisible_threads(user, categories, queryset):
             conditions = condition
 
     if conditions:
-        return Thread.objects.filter(conditions)
+        return queryset.filter(conditions)
     else:
         return Thread.objects.none()