changelog.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import difflib
  2. from django.core.urlresolvers import reverse
  3. from django.shortcuts import redirect
  4. from django.template import RequestContext
  5. from django.utils.translation import ugettext as _
  6. from misago.acl.exceptions import ACLError403, ACLError404
  7. from misago.apps.errors import error403, error404
  8. from misago.markdown import post_markdown
  9. from misago.messages import Message
  10. from misago.models import Forum, Thread, Post, Change
  11. from misago.utils.datesformats import reldate
  12. from misago.utils.strings import slugify
  13. from misago.apps.threadtype.base import ViewBase
  14. class ChangelogBaseView(ViewBase):
  15. def fetch_target(self):
  16. self.thread = Thread.objects.get(pk=self.kwargs.get('thread'))
  17. self.forum = self.thread.forum
  18. self.request.acl.forums.allow_forum_view(self.forum)
  19. self.proxy = Forum.objects.parents_aware_forum(self.forum)
  20. if self.forum.level:
  21. self.parents = Forum.objects.forum_parents(self.forum.pk, True)
  22. self.check_forum_type()
  23. self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
  24. self.post = Post.objects.select_related('user').get(pk=self.kwargs.get('post'), thread=self.thread.pk)
  25. self.post.thread = self.thread
  26. self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
  27. self.request.acl.threads.allow_changelog_view(self.request.user, self.forum, self.post)
  28. def __call__(self, request, **kwargs):
  29. self.request = request
  30. self.kwargs = kwargs
  31. self.forum = None
  32. self.thread = None
  33. self.post = None
  34. self.parents = []
  35. try:
  36. self._type_available()
  37. self.fetch_target()
  38. self._check_permissions()
  39. if not request.user.is_authenticated():
  40. raise ACLError403(_("Guest, you have to sign-in in order to see posts changelogs."))
  41. except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist, Change.DoesNotExist):
  42. return error404(self.request)
  43. except ACLError403 as e:
  44. return error403(request, e)
  45. except ACLError404 as e:
  46. return error404(request, e)
  47. return self.dispatch(request)
  48. class ChangelogChangesBaseView(ChangelogBaseView):
  49. def dispatch(self, request, **kwargs):
  50. return request.theme.render_to_response('%ss/changelog.html' % self.type_prefix,
  51. self.template_vars({
  52. 'type_prefix': self.type_prefix,
  53. 'forum': self.forum,
  54. 'parents': self.parents,
  55. 'thread': self.thread,
  56. 'post': self.post,
  57. 'edits': self.post.change_set.prefetch_related('user').order_by('-id')
  58. }),
  59. context_instance=RequestContext(request))
  60. class ChangelogDiffBaseView(ChangelogBaseView):
  61. def fetch_target(self):
  62. super(ChangelogDiffBaseView, self).fetch_target()
  63. self.change = self.post.change_set.get(pk=self.kwargs.get('change'))
  64. def dispatch(self, request, **kwargs):
  65. try:
  66. next = self.post.change_set.filter(id__gt=self.change.pk)[:1][0]
  67. except IndexError:
  68. next = None
  69. try:
  70. prev = self.post.change_set.filter(id__lt=self.change.pk).order_by('-id')[:1][0]
  71. except IndexError:
  72. prev = None
  73. self.forum.closed = self.proxy.closed
  74. return request.theme.render_to_response('%ss/changelog_diff.html' % self.type_prefix,
  75. self.template_vars({
  76. 'type_prefix': self.type_prefix,
  77. 'forum': self.forum,
  78. 'parents': self.parents,
  79. 'thread': self.thread,
  80. 'post': self.post,
  81. 'change': self.change,
  82. 'next': next,
  83. 'prev': prev,
  84. 'message': request.messages.get_message('changelog'),
  85. 'l': 1,
  86. 'diff': difflib.ndiff(self.change.post_content.splitlines(), self.post.post.splitlines()),
  87. }),
  88. context_instance=RequestContext(request))
  89. class ChangelogRevertBaseView(ChangelogDiffBaseView):
  90. def fetch_target(self):
  91. super(ChangelogRevertBaseView, self).fetch_target()
  92. self.change = self.post.change_set.get(pk=self.kwargs.get('change'))
  93. self.request.acl.threads.allow_revert(self.proxy, self.thread)
  94. def dispatch(self, request, **kwargs):
  95. if ((not self.change.thread_name_old or self.thread.name == self.change.thread_name_old)
  96. and (self.change.post_content == self.post.post)):
  97. request.messages.set_flash(Message(_("No changes to revert.")), 'error', 'changelog')
  98. return redirect(reverse('%s_changelog_diff' % self.type_prefix, kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'post': self.post.pk, 'change': self.change.pk}))
  99. if self.change.thread_name_old and self.change.thread_name_old != self.thread.name:
  100. self.thread.name = self.change.thread_name_old
  101. self.thread.slug = slugify(self.change.thread_name_old)
  102. self.thread.save(force_update=True)
  103. if self.forum.last_thread_id == self.thread.pk:
  104. self.forum.last_thread_name = self.change.thread_name_old
  105. self.forum.last_thread_slug = slugify(self.change.thread_name_old)
  106. self.forum.save(force_update=True)
  107. if self.change.post_content != self.post.post:
  108. self.post.post = self.change.post_content
  109. md, self.post.post_preparsed = post_markdown(self.change.post_content)
  110. self.post.save(force_update=True)
  111. request.messages.set_flash(Message(_("Post has been reverted to state from %(date)s.") % {'date': reldate(self.change.date).lower()}), 'success', 'threads_%s' % self.post.pk)
  112. return self.redirect_to_post(self.post)