hierarchy.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. from django.core.urlresolvers import reverse
  2. class Node(object):
  3. def __init__(self, link=None, name=None, icon=None):
  4. self.parent = None
  5. self.link = link
  6. self.name = name
  7. self.icon = icon
  8. self._children = []
  9. self._children_dict = {}
  10. @property
  11. def namespace(self):
  12. try:
  13. return self._resolved_namespace
  14. except AttributeError:
  15. bits = self.link.split(':')
  16. self._resolved_namespace = ':'.join(bits[:-1])
  17. return self._resolved_namespace
  18. def children(self):
  19. return self._children
  20. def children_as_dicts(self):
  21. childrens = []
  22. for children in self._children:
  23. childrens.append(
  24. {
  25. 'link': reverse(children.link),
  26. 'namespace': self.namespace,
  27. 'name': children.name,
  28. 'icon': children.icon,
  29. })
  30. return childrens
  31. def add_node(self, node, after=None, before=None):
  32. if after:
  33. return self.add_node_after(node, after)
  34. elif before:
  35. return self.add_node_before(node, before)
  36. else:
  37. node.parent = self
  38. self._children.append(node)
  39. self._children_dict[node.link] = node
  40. return True
  41. def add_node_after(self, node, after):
  42. success = False
  43. new_children_list = []
  44. for children in self._children:
  45. new_children_list.append(children)
  46. if children.link == after:
  47. new_children_list.append(node)
  48. success = True
  49. if success:
  50. node.parent = self
  51. self._children_dict[node.link] = node
  52. self._children = new_children_list
  53. return success
  54. def add_node_before(self, node, before):
  55. success = False
  56. new_children_list = []
  57. for children in self._children:
  58. if children.link == before:
  59. new_children_list.append(node)
  60. success = True
  61. new_children_list.append(children)
  62. if success:
  63. node.parent = self
  64. self._children_dict[node.link] = node
  65. self._children = new_children_list
  66. return success
  67. def child(self, namespace):
  68. try:
  69. return self._children_dict[namespace]
  70. except KeyError:
  71. raise ValueError(
  72. "Node %s is not a child of node %s" % (namespace, self.name))
  73. def is_root(self):
  74. return False
  75. class AdminHierarchyBuilder(object):
  76. def __init__(self):
  77. self.nodes_record = []
  78. self.nodes_dict = {}
  79. def build_nodes_dict(self):
  80. nodes_dict = {'misago:admin': Node(link='misago:admin:index')}
  81. iterations = 0
  82. while self.nodes_record:
  83. iterations += 1
  84. if iterations > 512:
  85. message = ("Misago Admin hierarchy is invalid or too complex "
  86. "to resolve. Nodes left: %s" % self.nodes_record)
  87. raise ValueError(message)
  88. for index, node in enumerate(self.nodes_record):
  89. if node['parent'] in nodes_dict:
  90. node_obj = Node(link=node['link'],
  91. name=node['name'],
  92. icon=node['icon'])
  93. parent = nodes_dict[node['parent']]
  94. if node['after']:
  95. node_added = parent.add_node(node_obj,
  96. after=node['after'])
  97. elif node['before']:
  98. node_added = parent.add_node(node_obj,
  99. before=node['before'])
  100. else:
  101. node_added = parent.add_node(node_obj)
  102. if node_added:
  103. namespace = node_obj.namespace
  104. if namespace not in nodes_dict:
  105. nodes_dict[namespace] = node_obj
  106. del self.nodes_record[index]
  107. break
  108. return nodes_dict
  109. def add_node(self, parent='misago:admin', after=None, before=None,
  110. namespace=None, link=None, name=None, icon=None):
  111. if self.nodes_dict:
  112. raise ValueError("Misago admin site has already been "
  113. "initialized. You can't add new nodes to it.")
  114. if after and before:
  115. raise ValueError("You cannot use both after and before kwargs.")
  116. self.nodes_record.append(
  117. {
  118. 'parent': parent,
  119. 'namespace': namespace,
  120. 'after': after,
  121. 'before': before,
  122. 'link': link,
  123. 'name': name,
  124. 'icon': icon,
  125. })
  126. def visible_branches(self, request):
  127. if not self.nodes_dict:
  128. self.nodes_dict = self.build_nodes_dict()
  129. branches = []
  130. if request.resolver_match.namespace in self.nodes_dict:
  131. node = self.nodes_dict[request.resolver_match.namespace]
  132. while node:
  133. children = node.children_as_dicts()
  134. if children:
  135. branches.append(children)
  136. node = node.parent
  137. branches.reverse()
  138. # Lowest level branch, active link
  139. for node in branches[0]:
  140. node['is_active'] = node['link'] in request.path
  141. # Other levels branches
  142. for branch in branches[1:]:
  143. for node in branch:
  144. active = node['namespace'] in request.resolver_match.namespace
  145. node['is_active'] = active
  146. # Hack for index link
  147. full_url_name = '%s:%s' % (request.resolver_match.namespace,
  148. request.resolver_match.url_name)
  149. if full_url_name != 'misago:admin:index':
  150. branches[0][0]['is_active'] = False
  151. return branches
  152. site = AdminHierarchyBuilder()