changelog.py 6.3 KB

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