page.py 4.2 KB

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