page.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 "
  23. "resolve. Sections left: %s" % self._unsorted_list
  24. )
  25. raise ValueError(message)
  26. for index, section in enumerate(self._unsorted_list):
  27. if section['after']:
  28. section_added = self._insert_section(section, after=section['after'])
  29. elif section['before']:
  30. section_added = self._insert_section(section, before=section['before'])
  31. else:
  32. section_added = self._insert_section(section)
  33. if section_added:
  34. del self._unsorted_list[index]
  35. break
  36. def _insert_section(self, inserted_section, after=None, before=None):
  37. if after:
  38. new_sorted_list = []
  39. for section in self._sorted_list:
  40. new_sorted_list.append(section)
  41. if section['link'] == after:
  42. new_sorted_list.append(inserted_section)
  43. self._sorted_list = new_sorted_list
  44. return True
  45. else:
  46. return False
  47. elif before:
  48. new_sorted_list = []
  49. for section in self._sorted_list:
  50. if section['link'] == before:
  51. new_sorted_list.append(inserted_section)
  52. new_sorted_list.append(section)
  53. self._sorted_list = new_sorted_list
  54. return True
  55. else:
  56. new_sorted_list.append(section)
  57. else:
  58. return False
  59. else:
  60. self._sorted_list.append(inserted_section)
  61. return True
  62. def add_section(
  63. self, link, after=None, before=None, visible_if=None, get_metadata=None, **kwargs
  64. ):
  65. if self._finalized:
  66. message = ("%s page was initialized already and no longer " "accepts new sections")
  67. raise RuntimeError(message % self.name)
  68. if after and before:
  69. raise ValueError("after and before arguments are exclusive")
  70. kwargs.update({
  71. 'link': link,
  72. 'after': after,
  73. 'before': before,
  74. 'visible_if': visible_if,
  75. 'get_metadata': get_metadata,
  76. })
  77. self._unsorted_list.append(kwargs)
  78. def _active_link_name(self, request):
  79. namespace = request.resolver_match.namespace
  80. url_name = request.resolver_match.url_name
  81. if namespace:
  82. active_link = '%s:%s' % (namespace, url_name)
  83. else:
  84. active_link = url_name
  85. return active_link
  86. def get_sections(self, request, *args):
  87. self.assert_is_finalized()
  88. active_link = self._active_link_name(request)
  89. visible_sections = []
  90. for section_definition in self._sorted_list:
  91. section = section_definition.copy()
  92. is_visible = True
  93. if section['visible_if']:
  94. is_visible = section['visible_if'](request, *args)
  95. if is_visible:
  96. if section['get_metadata']:
  97. section['metadata'] = section['get_metadata'](request, *args)
  98. section['is_active'] = active_link.startswith(section['link'])
  99. visible_sections.append(section)
  100. return visible_sections
  101. def get_default_link(self):
  102. self.assert_is_finalized()
  103. return self._sorted_list[0]['link']