page.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. class Page(object):
  2. """
  3. Misago page utility
  4. Allows for adding custom views to "sectioned" pages like
  5. User Control Panel, Users List or Threads Lists
  6. """
  7. def __init__(self, name):
  8. self._finalized = False
  9. self.name = name
  10. self._unsorted_list = []
  11. self._sorted_list = []
  12. def assert_is_finalized(self):
  13. if not self._finalized:
  14. self._finalized = True
  15. self._finalize()
  16. def _finalize(self):
  17. iterations = 0
  18. while self._unsorted_list:
  19. iterations += 1
  20. if iterations > 512:
  21. message = (
  22. "%s page hierarchy is invalid or too complex to resolve. Sections left: %s"
  23. )
  24. raise ValueError(message % self._unsorted_list)
  25. for index, section in enumerate(self._unsorted_list):
  26. if section['after']:
  27. section_added = self._insert_section(section, after=section['after'])
  28. elif section['before']:
  29. section_added = self._insert_section(section, before=section['before'])
  30. else:
  31. section_added = self._insert_section(section)
  32. if section_added:
  33. del self._unsorted_list[index]
  34. break
  35. def _insert_section(self, inserted_section, after=None, before=None):
  36. if after:
  37. new_sorted_list = []
  38. for section in self._sorted_list:
  39. new_sorted_list.append(section)
  40. if section['link'] == after:
  41. new_sorted_list.append(inserted_section)
  42. self._sorted_list = new_sorted_list
  43. return True
  44. else:
  45. return False
  46. elif before:
  47. new_sorted_list = []
  48. for section in self._sorted_list:
  49. if section['link'] == before:
  50. new_sorted_list.append(inserted_section)
  51. new_sorted_list.append(section)
  52. self._sorted_list = new_sorted_list
  53. return True
  54. else:
  55. new_sorted_list.append(section)
  56. else:
  57. return False
  58. else:
  59. self._sorted_list.append(inserted_section)
  60. return True
  61. def add_section(
  62. self, link, after=None, before=None, visible_if=None, get_metadata=None, **kwargs
  63. ):
  64. if self._finalized:
  65. message = "%s page was initialized already and no longer accepts new sections"
  66. raise RuntimeError(message % self.name)
  67. if after and before:
  68. raise ValueError("after and before arguments are exclusive")
  69. kwargs.update({
  70. 'link': link,
  71. 'after': after,
  72. 'before': before,
  73. 'visible_if': visible_if,
  74. 'get_metadata': get_metadata,
  75. })
  76. self._unsorted_list.append(kwargs)
  77. def _active_link_name(self, request):
  78. namespace = request.resolver_match.namespace
  79. url_name = request.resolver_match.url_name
  80. if namespace:
  81. active_link = '%s:%s' % (namespace, url_name)
  82. else:
  83. active_link = url_name
  84. return active_link
  85. def get_sections(self, request, *args):
  86. self.assert_is_finalized()
  87. active_link = self._active_link_name(request)
  88. visible_sections = []
  89. for section_definition in self._sorted_list:
  90. section = section_definition.copy()
  91. is_visible = True
  92. if section['visible_if']:
  93. is_visible = section['visible_if'](request, *args)
  94. if is_visible:
  95. if section['get_metadata']:
  96. section['metadata'] = section['get_metadata'](request, *args)
  97. section['is_active'] = active_link.startswith(section['link'])
  98. visible_sections.append(section)
  99. return visible_sections
  100. def get_default_link(self):
  101. self.assert_is_finalized()
  102. return self._sorted_list[0]['link']