25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

227 lines
6.9 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe
  5. from frappe.utils import now
  6. from frappe.model.document import Document
  7. from frappe.model.naming import append_number_if_name_exists
  8. from frappe.website.utils import cleanup_page_name, get_home_page
  9. from frappe.website.render import clear_cache
  10. from frappe.modules import get_module_name
  11. from frappe.website.router import get_page_route
  12. class WebsiteGenerator(Document):
  13. page_title_field = "name"
  14. def autoname(self):
  15. if self.meta.autoname != "hash":
  16. self.name = self.get_page_name()
  17. append_number_if_name_exists(self)
  18. def onload(self):
  19. self.get("__onload").website_route = self.get_route()
  20. def validate(self):
  21. self.set_parent_website_route()
  22. if self.meta.get_field("page_name") and not self.get("__islocal"):
  23. current_route = self.get_route()
  24. current_page_name = self.page_name
  25. self.page_name = self.make_page_name()
  26. # page name changed, rename everything
  27. if current_page_name and current_page_name != self.page_name:
  28. self.update_routes_of_descendants(current_route)
  29. def on_update(self):
  30. clear_cache(self.get_route())
  31. if getattr(self, "save_versions", False):
  32. frappe.add_version(self)
  33. def get_route(self, doc = None):
  34. self.get_page_name()
  35. return make_route(self)
  36. def clear_cache(self):
  37. clear_cache(self.get_route())
  38. def get_page_name(self):
  39. return self.get_or_make_page_name()
  40. def get_or_make_page_name(self):
  41. page_name = self.get("page_name")
  42. if not page_name:
  43. page_name = self.make_page_name()
  44. self.set("page_name", page_name)
  45. return page_name
  46. def make_page_name(self):
  47. return cleanup_page_name(self.get(self.page_title_field))
  48. def before_rename(self, oldname, name, merge):
  49. self._local = self.get_route()
  50. self.clear_cache()
  51. def after_rename(self, olddn, newdn, merge):
  52. if getattr(self, "_local"):
  53. self.update_routes_of_descendants(self._local)
  54. self.clear_cache()
  55. def on_trash(self):
  56. clear_cache(self.get_route())
  57. def website_published(self):
  58. if hasattr(self, "condition_field"):
  59. return self.get(self.condition_field) and True or False
  60. else:
  61. return True
  62. def set_parent_website_route(self):
  63. if hasattr(self, "parent_website_route_field"):
  64. field = self.meta.get_field(self.parent_website_route_field)
  65. parent = self.get(self.parent_website_route_field)
  66. if parent:
  67. parent_doc = frappe.get_doc(field.options, parent)
  68. if parent_doc.website_published():
  69. self.parent_website_route = parent_doc.get_route()
  70. else:
  71. self.parent_website_route = None
  72. def update_routes_of_descendants(self, old_route = None):
  73. if not self.is_new() and self.meta.get_field("parent_website_route"):
  74. if not old_route:
  75. old_route = frappe.get_doc(self.doctype, self.name).get_route()
  76. if old_route and old_route != self.get_route():
  77. # clear cache of old routes
  78. old_routes = frappe.get_all(self.doctype, fields=["parent_website_route", "page_name"],
  79. filters={"parent_website_route": ("like", old_route + "%")})
  80. if old_routes:
  81. for old_route in old_routes:
  82. clear_cache(make_route(old_route))
  83. frappe.db.sql("""update `tab{0}` set
  84. parent_website_route = replace(parent_website_route, %s, %s),
  85. modified = %s
  86. modified_by = %s
  87. where parent_website_route like %s""".format(self.doctype),
  88. (old_route, self.get_route(), now(), frappe.session.user, old_route + "%"))
  89. def get_website_route(self):
  90. route = frappe._dict()
  91. route.update({
  92. "doc": self,
  93. "page_or_generator": "Generator",
  94. "ref_doctype":self.doctype,
  95. "idx": self.idx,
  96. "docname": self.name,
  97. "page_name": self.get_page_name(),
  98. "controller": get_module_name(self.doctype, self.meta.module),
  99. "template": self.template,
  100. "parent_website_route": self.get("parent_website_route", ""),
  101. "page_title": getattr(self, "page_title", None) or self.get(self.page_title_field)
  102. })
  103. self.update_permissions(route)
  104. return route
  105. def update_permissions(self, route):
  106. if self.meta.get_field("public_read"):
  107. route.public_read = self.public_read
  108. route.public_write = self.public_write
  109. else:
  110. route.public_read = 1
  111. def get_parents(self, context):
  112. parents = []
  113. parent = self
  114. while parent:
  115. _parent_field = getattr(parent, "parent_website_route_field", None)
  116. _parent_val = parent.get(_parent_field) if _parent_field else None
  117. if _parent_val:
  118. df = parent.meta.get_field(_parent_field)
  119. parent_doc = frappe.get_doc(df.options, _parent_val)
  120. if not parent_doc.website_published():
  121. break
  122. if parent_doc:
  123. parent_info = frappe._dict(name = parent_doc.get_route(),
  124. title= parent_doc.get(getattr(parent_doc, "page_title_field", "name")))
  125. else:
  126. parent_info = frappe._dict(name=self.parent_website_route,
  127. title=self.parent_website_route.replace("_", " ").title())
  128. if parent_info.name in [p.name for p in parents]:
  129. raise frappe.ValidationError, "Recursion in parent link"
  130. parents.append(parent_info)
  131. parent = parent_doc
  132. else:
  133. # parent route is a page e.g. "blog"
  134. if parent.get("parent_website_route"):
  135. page_route = get_page_route(parent.parent_website_route)
  136. if page_route:
  137. parents.append(frappe._dict(name = page_route.name,
  138. title=page_route.page_title))
  139. parent = None
  140. parents.reverse()
  141. return parents
  142. def get_parent(self):
  143. if hasattr(self, "parent_website_route_field"):
  144. return self.get(self.parent_website_route_field)
  145. def get_children(self):
  146. if self.get_route()==get_home_page():
  147. return frappe.db.sql("""select url as name, label as page_title,
  148. 1 as public_read from `tabTop Bar Item` where parentfield='sidebar_items'
  149. order by idx""", as_dict=True)
  150. if self.meta.get_field("parent_website_route"):
  151. children = self.get_children_of(self.get_route())
  152. if not children and self.parent_website_route:
  153. children = self.get_children_of(self.parent_website_route)
  154. return children
  155. else:
  156. return []
  157. def get_children_of(self, route):
  158. children = frappe.db.sql("""select name, page_name,
  159. parent_website_route, {title_field} as title from `tab{doctype}`
  160. where ifnull(parent_website_route,'')=%s
  161. order by {order_by}""".format(
  162. doctype = self.doctype,
  163. title_field = getattr(self, "page_title_field", "name"),
  164. order_by = getattr(self, "order_by", "idx asc")),
  165. route, as_dict=True)
  166. for c in children:
  167. c.name = make_route(c)
  168. return children
  169. def get_next(self):
  170. if self.meta.get_field("parent_website_route") and self.parent_website_route:
  171. route = self.get_route()
  172. siblings = frappe.get_doc(self.doctype, self.get_parent()).get_children()
  173. for i, r in enumerate(siblings):
  174. if i < len(siblings) - 1:
  175. if route==r.name:
  176. return siblings[i+1]
  177. else:
  178. return frappe._dict()
  179. def make_route(doc):
  180. parent = doc.get("parent_website_route", "")
  181. return ((parent + "/") if parent else "") + doc.page_name