__init__.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. """
  2. Posting process implementation
  3. """
  4. from importlib import import_module
  5. from django.utils import timezone
  6. from misago.conf import settings
  7. from misago.core import forms
  8. START = 0
  9. REPLY = 1
  10. EDIT = 2
  11. class PostingInterrupt(Exception):
  12. def __init__(self, message):
  13. if not message:
  14. raise ValueError("You have to provide PostingInterrupt message.")
  15. self.message = message
  16. class EditorFormset(object):
  17. def __init__(self, **kwargs):
  18. self.errors = []
  19. self._forms_list = []
  20. self._forms_dict = {}
  21. is_private = kwargs['forum'].special_role == "private_threads"
  22. kwargs['is_private'] = is_private
  23. self.kwargs = kwargs
  24. self.__dict__.update(kwargs)
  25. self.datetime = timezone.now()
  26. self.middlewares = []
  27. self._load_middlewares()
  28. @property
  29. def start_form(self):
  30. return self.mode == START
  31. @property
  32. def reply_form(self):
  33. return self.mode == REPLY
  34. @property
  35. def edit_form(self):
  36. return self.mode == EDIT
  37. def _load_middlewares(self):
  38. kwargs = self.kwargs.copy()
  39. kwargs.update({
  40. 'datetime': self.datetime,
  41. 'parsing_result': {},
  42. })
  43. for middleware in settings.MISAGO_POSTING_MIDDLEWARES:
  44. module_name = '.'.join(middleware.split('.')[:-1])
  45. class_name = middleware.split('.')[-1]
  46. middleware_module = import_module(module_name)
  47. middleware_class = getattr(middleware_module, class_name)
  48. try:
  49. middleware_obj = middleware_class(prefix=middleware, **kwargs)
  50. if middleware_obj.use_this_middleware():
  51. self.middlewares.append((middleware, middleware_obj))
  52. except PostingInterrupt:
  53. raise ValueError("Posting process can only be "
  54. "interrupted during pre_save phase")
  55. def get_forms_list(self):
  56. """return list of forms belonging to formset"""
  57. if not self._forms_list:
  58. self._build_forms_cache()
  59. return self._forms_list
  60. def get_forms_dict(self):
  61. """return list of forms belonging to formset"""
  62. if not self._forms_dict:
  63. self._build_forms_cache()
  64. return self._forms_dict
  65. def _build_forms_cache(self):
  66. try:
  67. for middleware, obj in self.middlewares:
  68. form = obj.make_form()
  69. if form:
  70. self._forms_dict[middleware] = form
  71. self._forms_list.append(form)
  72. except PostingInterrupt:
  73. raise ValueError("Posting process can only be "
  74. "interrupted during pre_save phase")
  75. def get_main_forms(self):
  76. """return list of main forms"""
  77. main_forms = []
  78. for form in self.get_forms_list():
  79. try:
  80. if form.is_main and form.legend:
  81. main_forms.append(form)
  82. except AttributeError:
  83. pass
  84. return main_forms
  85. def get_supporting_forms(self):
  86. """return list of supporting forms"""
  87. supporting_forms = {}
  88. for form in self.get_forms_list():
  89. try:
  90. if form.is_supporting:
  91. supporting_forms.setdefault(form.location, []).append(form)
  92. except AttributeError:
  93. pass
  94. return supporting_forms
  95. def is_valid(self):
  96. """validate all forms"""
  97. all_forms_valid = True
  98. for form in self.get_forms_list():
  99. if not form.is_valid():
  100. all_forms_valid = False
  101. for error in form.non_field_errors():
  102. self.errors.append(unicode(error))
  103. return all_forms_valid
  104. def save(self):
  105. """change state"""
  106. forms_dict = self.get_forms_dict()
  107. try:
  108. for middleware, obj in self.middlewares:
  109. obj.pre_save(forms_dict.get(middleware))
  110. except PostingInterrupt as e:
  111. raise ValueError("Posting process can only be interrupted "
  112. "from within interrupt_posting method")
  113. for middleware, obj in self.middlewares:
  114. obj.interrupt_posting(forms_dict.get(middleware))
  115. try:
  116. for middleware, obj in self.middlewares:
  117. obj.save(forms_dict.get(middleware))
  118. for middleware, obj in self.middlewares:
  119. obj.post_save(forms_dict.get(middleware))
  120. except PostingInterrupt as e:
  121. raise ValueError("Posting process can only be interrupted "
  122. "from within interrupt_posting method")
  123. def update(self):
  124. """handle POST that shouldn't result in state change"""
  125. forms_dict = self.get_forms_dict()
  126. for middleware, obj in self.middlewares:
  127. obj.pre_save(forms_dict.get(middleware))
  128. class PostingMiddleware(object):
  129. """
  130. Abstract middleware classes
  131. """
  132. def __init__(self, **kwargs):
  133. self.kwargs = kwargs
  134. self.__dict__.update(kwargs)
  135. def use_this_middleware(self):
  136. return True
  137. def make_form(self):
  138. pass
  139. def pre_save(self, form):
  140. pass
  141. def interrupt_posting(self, form):
  142. pass
  143. def save(self, form):
  144. pass
  145. def post_save(self, form):
  146. pass