page.py 4.2 KB

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