You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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