Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

11 лет назад
11 лет назад
12 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
12 лет назад
12 лет назад
11 лет назад
11 лет назад
11 лет назад
12 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
12 лет назад
12 лет назад
12 лет назад
12 лет назад
12 лет назад
12 лет назад
12 лет назад
11 лет назад
12 лет назад
12 лет назад
11 лет назад
11 лет назад
11 лет назад
11 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. from webnotes import conf
  5. import webnotes
  6. import json, os, time
  7. from webnotes import _
  8. import webnotes.utils
  9. import mimetypes
  10. class PageNotFoundError(Exception): pass
  11. def render(page_name):
  12. """render html page"""
  13. try:
  14. html = render_page(page_name or "index")
  15. except PageNotFoundError:
  16. html = render_page("404")
  17. except Exception:
  18. html = render_page("error")
  19. webnotes._response.data = html
  20. def render_page(page_name):
  21. """get page html"""
  22. set_content_type(page_name)
  23. if page_name.endswith('.html'):
  24. page_name = page_name[:-5]
  25. html = ''
  26. if not conf.auto_cache_clear:
  27. html = webnotes.cache().get_value("page:" + page_name)
  28. from_cache = True
  29. if not html:
  30. html = build_page(page_name)
  31. from_cache = False
  32. if not html:
  33. raise PageNotFoundError
  34. if page_name=="error":
  35. html = html.replace("%(error)s", webnotes.getTraceback())
  36. elif "text/html" in webnotes._response.headers["Content-Type"]:
  37. comments = "\npage:"+page_name+\
  38. "\nload status: " + (from_cache and "cache" or "fresh")
  39. html += """\n<!-- %s -->""" % webnotes.utils.cstr(comments)
  40. return html
  41. def set_content_type(page_name):
  42. webnotes._response.headers["Content-Type"] = "text/html; charset: utf-8"
  43. if "." in page_name and not page_name.endswith(".html"):
  44. content_type, encoding = mimetypes.guess_type(page_name)
  45. webnotes._response.headers["Content-Type"] = content_type
  46. def build_page(page_name):
  47. if not webnotes.conn:
  48. webnotes.connect()
  49. sitemap_options = webnotes.doc("Website Sitemap", page_name).fields
  50. page_options = webnotes.doc("Website Sitemap Config",
  51. sitemap_options.get("website_sitemap_config")).fields.update(sitemap_options)
  52. if not page_options:
  53. raise PageNotFoundError
  54. else:
  55. page_options["page_name"] = page_name
  56. basepath = webnotes.utils.get_base_path()
  57. no_cache = page_options.get("no_cache")
  58. # if generator, then load bean, pass arguments
  59. if page_options.get("page_or_generator")=="Generator":
  60. doctype = page_options.get("ref_doctype")
  61. obj = webnotes.get_obj(doctype, page_options["docname"], with_children=True)
  62. if hasattr(obj, 'get_context'):
  63. obj.get_context()
  64. context = webnotes._dict(obj.doc.fields)
  65. context["obj"] = obj
  66. else:
  67. # page
  68. context = webnotes._dict({ 'name': page_name })
  69. if page_options.get("controller"):
  70. module = webnotes.get_module(page_options.get("controller"))
  71. if module and hasattr(module, "get_context"):
  72. context.update(module.get_context())
  73. context.update(get_website_settings())
  74. jenv = webnotes.get_jenv()
  75. context["base_template"] = jenv.get_template(webnotes.get_config().get("base_template"))
  76. template_name = page_options['template_path']
  77. html = jenv.get_template(template_name).render(context)
  78. if not no_cache:
  79. webnotes.cache().set_value("page:" + page_name, html)
  80. return html
  81. def build_sitemap():
  82. webnotes.conn.sql("""delete from `tabWebsite Sitemap Config`""")
  83. webnotes.conn.sql("""delete from `tabWebsite Sitemap`""")
  84. webnotes.conn.commit()
  85. build_website_sitemap_config()
  86. for config in webnotes.conn.sql("""select * from `tabWebsite Sitemap Config`""", as_dict=True):
  87. if config.page_or_generator == "Page":
  88. config.page_name = config.link_name
  89. add_to_sitemap(config)
  90. else:
  91. module = webnotes.get_module(config.controller)
  92. condition = ""
  93. if hasattr(module, "condition_field"):
  94. condition = " where ifnull(%s, 0)=1" % module.condition_field
  95. page_name_field = getattr(module, "page_name_field", "page_name")
  96. for name in webnotes.conn.sql_list("""select name from `tab%s` %s""" \
  97. % (module.doctype, condition)):
  98. webnotes.bean(module.doctype, name).run_method("on_update")
  99. def add_to_sitemap(options):
  100. doc = webnotes.doc({"doctype":"Website Sitemap"})
  101. for key in ("page_name", "ref_doctype", "docname", "page_or_generator", "lastmod"):
  102. doc.fields[key] = options.get(key)
  103. doc.name = options.page_name
  104. doc.website_sitemap_config = options.link_name
  105. doc.insert()
  106. webnotes.conn.commit()
  107. def get_home_page():
  108. if not webnotes.conn:
  109. webnotes.connect()
  110. doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page')
  111. if doc_name:
  112. page_name = webnotes.conn.get_value('Web Page', doc_name, 'page_name')
  113. else:
  114. page_name = 'login'
  115. return page_name
  116. def build_website_sitemap_config():
  117. config = {"pages": {}, "generators":{}}
  118. basepath = webnotes.utils.get_base_path()
  119. for path, folders, files in os.walk(basepath, followlinks=True):
  120. if 'locale' in folders:
  121. folders.remove('locale')
  122. # utility - remove pyc files
  123. for f in files:
  124. if f.decode("utf-8").endswith(".pyc"):
  125. os.remove(os.path.join(path, f))
  126. if os.path.basename(path)=="pages" and os.path.basename(os.path.dirname(path))=="templates":
  127. for fname in files:
  128. fname = webnotes.utils.cstr(fname)
  129. if fname.split(".")[-1] in ("html", "xml", "js", "css"):
  130. add_website_sitemap_config("Page", path, fname)
  131. if os.path.basename(path)=="generators" and os.path.basename(os.path.dirname(path))=="templates":
  132. for fname in files:
  133. if fname.endswith(".html"):
  134. add_website_sitemap_config("Generator", path, fname)
  135. webnotes.conn.commit()
  136. def add_website_sitemap_config(page_or_generator, path, fname):
  137. basepath = webnotes.utils.get_base_path()
  138. name = fname
  139. if fname.endswith(".html"):
  140. name = fname[:-5]
  141. template_path = os.path.relpath(os.path.join(path, fname), basepath)
  142. options = webnotes._dict({
  143. "doctype": "Website Sitemap Config",
  144. "page_or_generator": page_or_generator,
  145. "link_name": name,
  146. "template_path": template_path,
  147. "lastmod": time.ctime(os.path.getmtime(template_path))
  148. })
  149. controller_name = fname.split(".")[0].replace("-", "_") + ".py"
  150. controller_path = os.path.join(path, controller_name)
  151. if os.path.exists(controller_path):
  152. options.controller = os.path.relpath(controller_path[:-3], basepath).replace(os.path.sep, ".")
  153. options.controller = ".".join(options.controller.split(".")[1:])
  154. if options.controller:
  155. module = webnotes.get_module(options.controller)
  156. options.no_cache = getattr(module, "no_cache", 0)
  157. options.no_sitemap = options.no_cache or getattr(module, "no_sitemap", 0)
  158. options.ref_doctype = getattr(module, "doctype", None)
  159. webnotes.doc(options).insert()
  160. return options
  161. def get_website_settings():
  162. from webnotes.utils import get_request_site_address, encode, cint
  163. from urllib import quote
  164. all_top_items = webnotes.conn.sql("""\
  165. select * from `tabTop Bar Item`
  166. where parent='Website Settings' and parentfield='top_bar_items'
  167. order by idx asc""", as_dict=1)
  168. top_items = [d for d in all_top_items if not d['parent_label']]
  169. # attach child items to top bar
  170. for d in all_top_items:
  171. if d['parent_label']:
  172. for t in top_items:
  173. if t['label']==d['parent_label']:
  174. if not 'child_items' in t:
  175. t['child_items'] = []
  176. t['child_items'].append(d)
  177. break
  178. context = webnotes._dict({
  179. 'top_bar_items': top_items,
  180. 'footer_items': webnotes.conn.sql("""\
  181. select * from `tabTop Bar Item`
  182. where parent='Website Settings' and parentfield='footer_items'
  183. order by idx asc""", as_dict=1),
  184. "webnotes": webnotes,
  185. "utils": webnotes.utils,
  186. "post_login": [
  187. {"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
  188. {"label": "Logout", "url": "/?cmd=web_logout", "icon": "icon-signout"}
  189. ]
  190. })
  191. settings = webnotes.doc("Website Settings", "Website Settings")
  192. for k in ["banner_html", "brand_html", "copyright", "twitter_share_via",
  193. "favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
  194. "disable_signup"]:
  195. if k in settings.fields:
  196. context[k] = settings.fields.get(k)
  197. if settings.address:
  198. context["footer_address"] = settings.address
  199. for k in ["facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
  200. "disable_signup"]:
  201. context[k] = cint(context.get(k) or 0)
  202. context.url = quote(str(get_request_site_address(full_address=True)), str(""))
  203. context.encoded_title = quote(encode(context.title or ""), str(""))
  204. try:
  205. import startup.webutils
  206. if hasattr(startup.webutils, "get_website_settings"):
  207. startup.webutils.get_website_settings(context)
  208. except:
  209. pass
  210. return context
  211. def clear_cache(page_name=None):
  212. if page_name:
  213. delete_page_cache(page_name)
  214. else:
  215. cache = webnotes.cache()
  216. for p in webnotes.conn.sql_list("""select name from `tabWebsite Sitemap`"""):
  217. if p is not None:
  218. cache.delete_value("page:" + p)
  219. cache.delete_value("page:index")
  220. cache.delete_value("website_sitemap")
  221. cache.delete_value("website_sitemap_config")
  222. def delete_page_cache(page_name):
  223. if page_name:
  224. cache = webnotes.cache()
  225. cache.delete_value("page:" + page_name)
  226. cache.delete_value("website_sitemap")
  227. def get_hex_shade(color, percent):
  228. def p(c):
  229. v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
  230. if v < 0:
  231. v=0
  232. if v > 255:
  233. v=255
  234. h = hex(v)[2:]
  235. if len(h) < 2:
  236. h = "0" + h
  237. return h
  238. r, g, b = color[0:2], color[2:4], color[4:6]
  239. avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
  240. # switch dark and light shades
  241. if avg > 128:
  242. percent = -percent
  243. # stronger diff for darker shades
  244. if percent < 25 and avg < 64:
  245. percent = percent * 2
  246. return p(r) + p(g) + p(b)
  247. def is_signup_enabled():
  248. if getattr(webnotes.local, "is_signup_enabled", None) is None:
  249. webnotes.local.is_signup_enabled = True
  250. if webnotes.utils.cint(webnotes.conn.get_value("Website Settings",
  251. "Website Settings", "disable_signup")):
  252. webnotes.local.is_signup_enabled = False
  253. return webnotes.local.is_signup_enabled
  254. class WebsiteGenerator(object):
  255. def setup_generator(self):
  256. self._website_config = webnotes.conn.get_values("Website Sitemap Config", {"ref_doctype": self.doc.doctype}, "*")[0]
  257. self._website_module = webnotes.get_module(self._website_config.controller)
  258. self._page_name_field = getattr(self._website_module, "page_name_field", "page_name")
  259. self._condition_field = getattr(self._website_module, "condition_field", "")
  260. def on_update(self, page_name=None):
  261. self.setup_generator()
  262. if self._condition_field:
  263. if not self.doc.fields[self._condition_field]:
  264. remove_page(self.doc.fields[self._page_name_field])
  265. return
  266. if not page_name:
  267. new_page_name = cleanup_page_name(self.get_page_title() \
  268. if hasattr(self, "get_page_title") else (self.doc.title or self.doc.name))
  269. self.check_if_page_name_is_unique(new_page_name)
  270. remove_page(self.doc.page_name)
  271. add_generator_to_sitemap(self.doc.doctype, self.doc.name, new_page_name, self.doc.modified,
  272. self._website_config, self._website_module)
  273. if self.doc.fields[self._page_name_field]!=new_page_name:
  274. webnotes.conn.set(self.doc, self._page_name_field, new_page_name)
  275. else:
  276. add_generator_to_sitemap(self.doc.doctype, self.doc.name, page_name, self.doc.modified,
  277. self._website_config, self._website_module)
  278. delete_page_cache(self.doc.page_name)
  279. def check_if_page_name_is_unique(self, new_page_name):
  280. if webnotes.conn.sql("""select name from `tabWebsite Sitemap` where name=%s
  281. and ref_doctype!=%s and docname!=%s""", (new_page_name, self.doc.doctype, self.doc.name)):
  282. webnotes.throw("%s: %s. %s: <b>%s<b>" % (new_page_name, _("Page already exists"),
  283. _("Please change the value"), title))
  284. def on_trash(self):
  285. self.setup_generator()
  286. remove_page(self.doc.fields[self._page_name_field])
  287. def add_generator_to_sitemap(ref_doctype, docname, page_name, modified, config=None, module=None):
  288. if not config:
  289. config = webnotes.conn.get_values("Website Sitemap Config", {"ref_doctype": ref_doctype}, "*")[0]
  290. if not module:
  291. module = webnotes.get_module(config.controller)
  292. page_name_field = getattr(module, "page_name_field", "page_name")
  293. opts = config.copy()
  294. opts["page_name"] = page_name
  295. if page_name_field != "page_name":
  296. opts["page_name_field"] = page_name_field
  297. opts["docname"] = docname
  298. opts["lastmod"] = modified
  299. add_to_sitemap(opts)
  300. def remove_page(page_name):
  301. if page_name:
  302. delete_page_cache(page_name)
  303. webnotes.conn.sql("delete from `tabWebsite Sitemap` where name=%s", page_name)
  304. def cleanup_page_name(title):
  305. """make page name from title"""
  306. import re
  307. name = title.lower()
  308. name = re.sub('[~!@#$%^&*+()<>,."\']', '', name)
  309. name = re.sub('[:/]', '-', name)
  310. name = '-'.join(name.split())
  311. # replace repeating hyphens
  312. name = re.sub(r"(-)\1+", r"\1", name)
  313. return name