diff --git a/files/helpers/comments.py b/files/helpers/comments.py index afd622f5c..42139a90e 100644 --- a/files/helpers/comments.py +++ b/files/helpers/comments.py @@ -8,10 +8,17 @@ def update_stateful_counters(comment, delta): When a comment changes publish status, we need to update all affected stateful comment counters (e.g. author comment count, post comment count) """ + update_post_comment_count(comment, delta) + update_author_comment_count(comment, delta) + update_ancestor_descendant_counts(comment, delta) + +def update_post_comment_count(comment, delta): author = comment.author comment.post.comment_count += delta g.db.add(comment.post) +def update_author_comment_count(comment, delta): + author = comment.author comment.author.comment_count = g.db.query(Comment).filter( Comment.author_id == comment.author_id, Comment.parent_submission != None, @@ -20,6 +27,14 @@ def update_stateful_counters(comment, delta): ).count() g.db.add(comment.author) +def update_ancestor_descendant_counts(comment, delta): + parent = comment.parent_comment_writable + if parent is None: + return + parent.descendant_count += delta + g.db.add(parent) + update_ancestor_descendant_counts(parent, delta) + def comment_on_publish(comment:Comment): """ Run when comment becomes visible: immediately for non-filtered comments, diff --git a/files/tests/test_child_comment_counts.py b/files/tests/test_child_comment_counts.py index 77c128118..dda8fb123 100644 --- a/files/tests/test_child_comment_counts.py +++ b/files/tests/test_child_comment_counts.py @@ -3,7 +3,7 @@ from . import fixture_submissions from . import fixture_comments from . import util from files.__main__ import db_session -from files.classes import Submission +from files.classes import Submission, Comment import json @@ -84,3 +84,49 @@ def test_submission_comment_count(accounts, submissions, comments): }) assert 0 == post.comment_count + +@util.no_rate_limit +def test_comment_descendant_count(accounts, submissions, comments): + """ + Here is a contentious top-level comment + You're wrong, this isn't contentious + no u + Good poast + """ + db = db_session() + alice_client, alice = accounts.client_and_user_for_account('Alice') + + post = submissions.submission_for_client(alice_client, { + 'title': 'Discussion', + 'body': 'Discuss stuff', + }) + post_id = post.id + + root = comments.comment_for_client(alice_client, post.id, { + 'body': 'Here is a contentious top-level comment', + }) + + assert 0 == db.query(Comment).filter_by(id=root.id).first().descendant_count + + reply1 = comments.comment_for_client(alice_client, post.id, { + 'body': 'You\'re wrong, this isn\'t contentious', + 'parent_fullname': f't3_{root.id}', + 'parent_level': root.level, + }) + + rereply1 = comments.comment_for_client(alice_client, post.id, { + 'body': 'no u', + 'parent_fullname': f't3_{reply1.id}', + 'parent_level': reply1.level, + }) + + reply2 = comments.comment_for_client(alice_client, post.id, { + 'body': 'Good poast', + 'parent_fullname': f't3_{root.id}', + 'parent_level': root.level, + }) + + assert 3 == db.query(Comment).filter_by(id=root.id).first().descendant_count + assert 1 == db.query(Comment).filter_by(id=reply1.id).first().descendant_count + assert 0 == db.query(Comment).filter_by(id=reply2.id).first().descendant_count + assert 0 == db.query(Comment).filter_by(id=rereply1.id).first().descendant_count