Browse Source

fix #830: Synchronize category after thread is deleted from it via moderation action.

Rafał Pitoń 8 years ago
parent
commit
4302f4e1be

+ 9 - 2
misago/categories/management/commands/synchronizecategories.py

@@ -1,3 +1,5 @@
+import time
+
 from django.core.management.base import BaseCommand
 
 from misago.categories.models import Category
@@ -13,7 +15,9 @@ class Command(BaseCommand):
         message = 'Synchronizing %s categories...\n'
         self.stdout.write(message % categories_to_sync)
 
-        message = '\n\nSynchronized %s categories'
+        message = '\n\nSynchronized %s categories in %s'
+
+        start_time = time.time()
 
         synchronized_count = 0
         show_progress(self, synchronized_count, categories_to_sync)
@@ -24,4 +28,7 @@ class Command(BaseCommand):
             synchronized_count += 1
             show_progress(self, synchronized_count, categories_to_sync)
 
-        self.stdout.write(message % synchronized_count)
+        end_time = time.time() - start_time
+        total_time = time.strftime('%H:%M:%S', time.gmtime(end_time))
+
+        self.stdout.write(message % (synchronized_count, total_time))

+ 1 - 1
misago/categories/tests/test_synchronizecategories.py

@@ -29,4 +29,4 @@ class SynchronizeCategoriesTests(TestCase):
         self.assertEqual(category.posts, 60)
 
         command_output = out.getvalue().splitlines()[-1].strip()
-        self.assertEqual(command_output, 'Synchronized 3 categories')
+        self.assertTrue(command_output.startswith('Synchronized 3 categories in'))

+ 14 - 0
misago/threads/moderation/threads.py

@@ -142,6 +142,11 @@ def unhide_thread(request, thread):
         thread.is_hidden = False
 
         record_event(request, thread, 'unhid')
+
+        if thread.pk == thread.category.last_thread_id:
+            thread.category.synchronize()
+            thread.category.save()
+
         return True
     else:
         return False
@@ -167,6 +172,11 @@ def hide_thread(request, thread):
         thread.is_hidden = True
 
         record_event(request, thread, 'hid')
+
+        if thread.pk == thread.category.last_thread_id:
+            thread.category.synchronize()
+            thread.category.save()
+
         return True
     else:
         return False
@@ -175,4 +185,8 @@ def hide_thread(request, thread):
 @atomic
 def delete_thread(request, thread):
     thread.delete()
+
+    thread.category.synchronize()
+    thread.category.save()
+
     return True

+ 30 - 0
misago/threads/tests/test_threads_api.py

@@ -245,6 +245,12 @@ class ThreadsReadApiTests(ThreadsApiTestCase):
 
 
 class ThreadDeleteApiTests(ThreadsApiTestCase):
+    def setUp(self):
+        super(ThreadDeleteApiTests, self).setUp()
+
+        self.last_thread = testutils.post_thread(category=self.category)
+        self.api_link = self.last_thread.get_api_url()
+
     def test_delete_thread_no_permission(self):
         """DELETE to API link with no permission to delete fails"""
         self.override_acl({'can_hide_threads': 1})
@@ -262,12 +268,36 @@ class ThreadDeleteApiTests(ThreadsApiTestCase):
         response = self.client.delete(self.api_link)
         self.assertEqual(response.status_code, 403)
 
+        response_json = response.json()
+        self.assertEqual(
+            response_json['detail'], "You don't have permission to delete this thread."
+        )
+
     def test_delete_thread(self):
         """DELETE to API link with permission deletes thread"""
         self.override_acl({'can_hide_threads': 2})
 
+        category = Category.objects.get(slug='first-category')
+        self.assertEqual(category.last_thread_id, self.last_thread.pk)
+
         response = self.client.delete(self.api_link)
         self.assertEqual(response.status_code, 200)
 
         with self.assertRaises(Thread.DoesNotExist):
+            Thread.objects.get(pk=self.last_thread.pk)
+
+        # category was synchronised after deletion
+        category = Category.objects.get(slug='first-category')
+        self.assertEqual(category.last_thread_id, self.thread.pk)
+
+        # test that last thread's deletion triggers category sync
+        self.override_acl({'can_hide_threads': 2})
+
+        response = self.client.delete(self.thread.get_api_url())
+        self.assertEqual(response.status_code, 200)
+
+        with self.assertRaises(Thread.DoesNotExist):
             Thread.objects.get(pk=self.thread.pk)
+
+        category = Category.objects.get(slug='first-category')
+        self.assertIsNone(category.last_thread_id)