bgneal@147: """
bgneal@147: This module contains misc. utility functions for forum management.
bgneal@147: """
bgneal@228: import logging
bgneal@228: 
bgneal@147: from forums.models import Post, Topic, Forum, ForumLastVisit, TopicLastVisit
bgneal@147: 
bgneal@147: 
bgneal@147: def delete_user_posts(user):
bgneal@147:     """
bgneal@147:     This function deletes all the posts for a given user.
bgneal@147:     It also cleans up any last visit database records for the user.
bgneal@147:     This function adjusts the last post foreign keys before deleting
bgneal@147:     the posts to avoid the cascading delete behavior.
bgneal@147:     """
bgneal@147:     posts = Post.objects.filter(user=user).select_related()
bgneal@147: 
bgneal@285:     # delete attachments
bgneal@285:     for post in posts:
bgneal@285:         post.attachments.clear()
bgneal@285: 
bgneal@147:     # build a set of topics and forums affected by the post deletions
bgneal@147: 
bgneal@147:     topics = set(post.topic for post in posts)
bgneal@147:     forums = set(topic.forum for topic in topics)
bgneal@147: 
bgneal@147:     post_ids = [post.pk for post in posts]
bgneal@147:     pending_delete = []
bgneal@147: 
bgneal@147:     for topic in topics:
bgneal@147:         if topic.last_post.pk in post_ids:
bgneal@147:             topic_posts = Post.objects.filter(topic=topic).exclude(
bgneal@147:                     pk__in=post_ids)
bgneal@147:             topic.post_count = topic_posts.count()
bgneal@147:             if topic.post_count > 0:
bgneal@147:                 topic.last_post = topic_posts.latest()
bgneal@147:                 topic.update_date = topic.last_post.creation_date
bgneal@147:                 topic.save()
bgneal@147:             else:
bgneal@147:                 # Topic should be deleted, it has no posts;
bgneal@147:                 # We can't delete it now as it could cascade and take out a 
bgneal@147:                 # forum. Remember it for later deletion.
bgneal@147:                 pending_delete.append(topic)
bgneal@147: 
bgneal@147:     for forum in forums:
bgneal@147:         if forum.last_post.pk in post_ids:
bgneal@147:             forum_posts = Post.objects.filter(topic__forum=forum).exclude(
bgneal@147:                     pk__in=post_ids)
bgneal@147:             forum.post_count = forum_posts.count()
bgneal@147:             if forum.post_count > 0:
bgneal@147:                 forum.last_post = forum_posts.latest()
bgneal@147:             else:
bgneal@147:                 forum.last_post = None
bgneal@147:             forum.save()
bgneal@348: 
bgneal@147:     # Delete pending topics now because forums have just adjusted their
bgneal@147:     # foreign keys into Post
bgneal@147:     if pending_delete:
bgneal@147:         topic_ids = [topic.pk for topic in pending_delete]
bgneal@147:         Topic.objects.filter(pk__in=topic_ids).delete()
bgneal@147: 
bgneal@147:         # Topics have been deleted, re-compute topic counts for forums
bgneal@147:         for forum in forums:
bgneal@147:             forum.topic_count = Topic.objects.filter(forum=forum).count()
bgneal@147:             forum.save()
bgneal@348: 
bgneal@147:     # All foreign keys are accounted for, we can now delete the posts in bulk.
bgneal@147:     # Since some posts in our original queryset may have been deleted already,
bgneal@147:     # run a new query (although it may be ok)
bgneal@147:     Post.objects.filter(pk__in=post_ids).delete()
bgneal@147: 
bgneal@147:     # delete all the last visit records for this user
bgneal@147:     TopicLastVisit.objects.filter(user=user).delete()
bgneal@147:     ForumLastVisit.objects.filter(user=user).delete()
bgneal@147: 
bgneal@228: 
bgneal@228: def create_topic(forum_slug, user, topic_name, post_body, ip='', sticky=False,
bgneal@228:         locked=False):
bgneal@228:     """Programmatically create a topic & first post in a given forum.
bgneal@228: 
bgneal@228:     This function creates a new topic in the forum that has the slug
bgneal@228:     specified by the 'forum_slug' argument. Other arguments are as follows:
bgneal@228:     'user' - create the topic and post with this user as the owner
bgneal@228:     'topic_name' - topic name (title)
bgneal@228:     'post_body' - topic post body (as markup, not HTML)
bgneal@228:     'ip' - IP address for the post (as a string)
bgneal@228:     'sticky' - if True, the post will be stickied
bgneal@228:     'locked' - if True, the post will be locked
bgneal@228: 
bgneal@228:     """
bgneal@228:     try:
bgneal@228:         forum = Forum.objects.get(slug=forum_slug)
bgneal@228:     except Forum.DoesNotExist:
bgneal@316:         logging.error('could not create_topic for forum_slug=%s', forum_slug)
bgneal@228:         raise
bgneal@228: 
bgneal@228:     topic = Topic(forum=forum,
bgneal@228:             name=topic_name,
bgneal@228:             user=user,
bgneal@228:             sticky=sticky,
bgneal@228:             locked=locked)
bgneal@228:     topic.save()
bgneal@228: 
bgneal@228:     post = Post(topic=topic,
bgneal@228:             user=user,
bgneal@228:             body=post_body,
bgneal@228:             user_ip=ip)
bgneal@228:     post.save()
bgneal@390: 
bgneal@390: 
bgneal@390: def auto_favorite(post):
bgneal@390:     """
bgneal@390:     Given a newly created post, perform an auto-favorite action if the post
bgneal@390:     creator has that option set in their profile.
bgneal@390: 
bgneal@390:     """
bgneal@390:     profile = post.user.get_profile()
bgneal@390:     if profile.auto_favorite:
bgneal@390:         post.topic.bookmarkers.add(post.user)
bgneal@390: 
bgneal@390: 
bgneal@390: def auto_subscribe(post):
bgneal@390:     """
bgneal@390:     Given a newly created post, perform an auto-subscribe action if the post
bgneal@390:     creator has that option set in their profile.
bgneal@390: 
bgneal@390:     """
bgneal@390:     profile = post.user.get_profile()
bgneal@390:     if profile.auto_subscribe:
bgneal@390:         post.topic.subscribers.add(post.user)