refacted webnotes.webutils
This commit is contained in:
parent
e18a974c21
commit
d2fe902b4e
41 changed files with 669 additions and 627 deletions
|
|
@ -588,7 +588,7 @@ def get_jloader():
|
|||
|
||||
def set_filters(jenv):
|
||||
from webnotes.utils import global_date_format
|
||||
from webnotes.webutils import get_hex_shade
|
||||
from webnotes.website.utils import get_hex_shade
|
||||
from markdown2 import markdown
|
||||
from json import dumps
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import webnotes
|
|||
import webnotes.handler
|
||||
import webnotes.auth
|
||||
import webnotes.api
|
||||
import webnotes.webutils
|
||||
import webnotes.website.render
|
||||
from webnotes.utils import get_site_name
|
||||
|
||||
local_manager = LocalManager([webnotes.local])
|
||||
|
|
@ -58,7 +58,7 @@ def application(request):
|
|||
elif webnotes.request.path.startswith("/api/"):
|
||||
webnotes.api.handle()
|
||||
elif webnotes.local.request.method in ('GET', 'HEAD'):
|
||||
webnotes.webutils.render(webnotes.request.path[1:])
|
||||
webnotes.website.render.render(webnotes.request.path[1:])
|
||||
else:
|
||||
raise NotFound
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import webnotes.defaults
|
|||
import webnotes.model.doc
|
||||
import webnotes.widgets.page
|
||||
import json
|
||||
import webnotes.webutils
|
||||
|
||||
def get_bootinfo():
|
||||
"""build and return boot info"""
|
||||
|
|
|
|||
|
|
@ -430,9 +430,9 @@ def clear_cache():
|
|||
|
||||
@cmd
|
||||
def clear_web():
|
||||
import webnotes.webutils
|
||||
import webnotes.website.render
|
||||
webnotes.connect()
|
||||
webnotes.webutils.clear_cache()
|
||||
webnotes.website.render.clear_cache()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import webnotes
|
|||
import json
|
||||
import urllib
|
||||
from email.utils import formataddr
|
||||
from webnotes.webutils import is_signup_enabled
|
||||
from webnotes.website.utils import is_signup_enabled
|
||||
from webnotes.utils import get_url, cstr
|
||||
from webnotes.utils.email_lib.email_body import get_email
|
||||
from webnotes.utils.email_lib.smtp import send
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@
|
|||
</style>
|
||||
{%- endblock %}
|
||||
|
||||
{% block script -%}
|
||||
<script data-html-block="script">
|
||||
{%- if script is defined -%}{{ script }}{%- endif -%}
|
||||
</script>
|
||||
{%- endblock %}
|
||||
{%- endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -80,10 +85,5 @@
|
|||
<div id="wrap-footer">
|
||||
{%- block footer -%}{% include "templates/includes/footer.html" %}{%- endblock -%}
|
||||
</div>
|
||||
{% block script -%}
|
||||
<script data-html-block="script">
|
||||
{%- if script is defined -%}{{ script }}{%- endif -%}
|
||||
</script>
|
||||
{%- endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,7 +5,5 @@
|
|||
{% block header %}<h2>{{ title }}</h2>{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
$(function() {
|
||||
window.category = "{{ docname }}";
|
||||
});
|
||||
window.category = "{{ docname }}";
|
||||
{% endblock %}
|
||||
|
|
@ -46,14 +46,16 @@ def get_blog_list(start=0, by=None, category=None):
|
|||
condition += " and t1.blog_category='%s'" % category.replace("'", "\'")
|
||||
query = """\
|
||||
select
|
||||
t1.title, t1.name, t1.page_name, t1.published_on as creation,
|
||||
t1.title, t1.name, t3.name as page_name, t1.published_on as creation,
|
||||
ifnull(t1.blog_intro, t1.content) as content,
|
||||
t2.full_name, t2.avatar, t1.blogger,
|
||||
(select count(name) from `tabComment` where
|
||||
comment_doctype='Blog Post' and comment_docname=t1.name) as comments
|
||||
from `tabBlog Post` t1, `tabBlogger` t2
|
||||
from `tabBlog Post` t1, `tabBlogger` t2, `tabWebsite Sitemap` t3
|
||||
where ifnull(t1.published,0)=1
|
||||
and t1.blogger = t2.name
|
||||
and t3.docname = t1.name
|
||||
and t3.ref_doctype = "Blog Post"
|
||||
%(condition)s
|
||||
order by published_on desc, name asc
|
||||
limit %(start)s, 20""" % {"start": start, "condition": condition}
|
||||
|
|
@ -63,8 +65,6 @@ def get_blog_list(start=0, by=None, category=None):
|
|||
# strip html tags from content
|
||||
for res in result:
|
||||
res['published'] = global_date_format(res['creation'])
|
||||
if not res['content']:
|
||||
res['content'] = webnotes.webutils.get_html(res['page_name'])
|
||||
res['content'] = res['content'][:140]
|
||||
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
# MIT License. See license.txt
|
||||
|
||||
import webnotes
|
||||
from webnotes.webutils import get_access, can_cache
|
||||
from webnotes.website.permissions import get_access
|
||||
from webnotes.website.render import can_cache
|
||||
from webnotes.templates.website_group.forum import get_post_list_html
|
||||
|
||||
doctype = "Website Group"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ var blog = {
|
|||
b.comment_text = b.comments + ' comments.'
|
||||
}
|
||||
|
||||
b.page_name = encodeURIComponent(b.page_name);
|
||||
b.page_name = $.map(b.page_name.split("/"), function(p)
|
||||
{ return encodeURIComponent(p); }).join("/");
|
||||
|
||||
b.avatar = b.avatar || "";
|
||||
|
||||
$(repl('<div class="row">\
|
||||
|
|
@ -71,7 +73,7 @@ var blog = {
|
|||
|
||||
$(document).ready(function() {
|
||||
// make list of blogs
|
||||
blog.get_list();
|
||||
setTimeout(blog.get_list, 100);
|
||||
|
||||
$("#next-page").click(function() {
|
||||
blog.get_list();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import webnotes
|
||||
import webnotes.utils, markdown2
|
||||
from webnotes.website.render import clear_cache
|
||||
|
||||
from webnotes import _
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ def add_comment(args=None):
|
|||
comment.insert()
|
||||
|
||||
# since comments are embedded in the page, clear the web cache
|
||||
webnotes.webutils.clear_cache(page_name)
|
||||
clear_cache(page_name)
|
||||
|
||||
# notify commentors
|
||||
commentors = [d[0] for d in webnotes.conn.sql("""select comment_by from tabComment where
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||
|
||||
import urllib
|
||||
import webnotes
|
||||
import webnotes.webutils
|
||||
from webnotes.utils import get_request_site_address
|
||||
|
||||
no_cache = 1
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import now_datetime, get_datetime_str
|
||||
from webnotes.webutils import get_access
|
||||
from webnotes.website.permissions import get_access
|
||||
|
||||
@webnotes.whitelist(allow_guest=True)
|
||||
def get_post_list_html(group, view, limit_start=0, limit_length=20):
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import get_fullname
|
||||
from webnotes.webutils import get_access
|
||||
from webnotes.website.permissions import get_access
|
||||
from webnotes.utils.file_manager import save_file
|
||||
from webnotes.templates.generators.website_group import get_pathname
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.webutils import get_access, clear_permissions
|
||||
from webnotes.website.permissions import get_access, clear_permissions
|
||||
from webnotes.templates.generators.website_group import get_pathname
|
||||
from webnotes.utils.email_lib.bulk import send
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ def build_response():
|
|||
|
||||
def print_page():
|
||||
"""print web page"""
|
||||
from webnotes.webutils import render
|
||||
from webnotes.website.render import render
|
||||
render(webnotes.response['page_name'])
|
||||
|
||||
def print_json():
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
Module for website management.
|
||||
|
||||
Contains:
|
||||
|
||||
- DocTypes for Web Page, Blogs
|
||||
- Templates
|
||||
- Settings
|
||||
- Generators for Item, Blog Post, Item Group
|
||||
64
webnotes/website/context.py
Normal file
64
webnotes/website/context.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
# frequently used imports (used by other modules)
|
||||
from webnotes.website.permissions import get_access
|
||||
|
||||
from webnotes.website.doctype.website_settings.website_settings import get_website_settings
|
||||
from webnotes.website.template import render_blocks
|
||||
from webnotes.website.sitemap import get_sitemap_options
|
||||
from webnotes.website.utils import can_cache
|
||||
|
||||
def get_context(path):
|
||||
context = None
|
||||
cache_key = "page_context:{}".format(path)
|
||||
|
||||
# try from memcache
|
||||
if can_cache():
|
||||
context = webnotes.cache().get_value(cache_key)
|
||||
|
||||
if not context:
|
||||
context = get_sitemap_options(path)
|
||||
|
||||
# permission may be required for rendering
|
||||
context["access"] = get_access(context.pathname)
|
||||
|
||||
context = build_context(context)
|
||||
|
||||
if can_cache(context.no_cache):
|
||||
webnotes.cache().set_value(cache_key, context)
|
||||
|
||||
else:
|
||||
context["access"] = get_access(context.pathname)
|
||||
|
||||
context.update(context.data or {})
|
||||
|
||||
# TODO private pages
|
||||
|
||||
return context
|
||||
|
||||
def build_context(sitemap_options):
|
||||
"""get_context method of bean or module is supposed to render content templates and push it into context"""
|
||||
context = webnotes._dict(sitemap_options)
|
||||
context.update(get_website_settings())
|
||||
|
||||
# provide bean
|
||||
if context.doctype and context.docname:
|
||||
context.bean = webnotes.bean(context.doctype, context.docname)
|
||||
|
||||
if context.controller:
|
||||
module = webnotes.get_module(context.controller)
|
||||
if module and hasattr(module, "get_context"):
|
||||
context.update(module.get_context(context) or {})
|
||||
|
||||
if context.get("base_template_path") != context.get("template_path") and not context.get("rendered"):
|
||||
context.data = render_blocks(context)
|
||||
|
||||
# remove bean, as it is not pickle friendly and its purpose is over
|
||||
if context.bean:
|
||||
del context["bean"]
|
||||
|
||||
return context
|
||||
|
|
@ -11,7 +11,7 @@ class DocType:
|
|||
self.doc, self.doclist = d, dl
|
||||
|
||||
def on_update(self):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache("about")
|
||||
|
||||
def get_args():
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.webutils import WebsiteGenerator, cleanup_page_name, clear_cache
|
||||
from webnotes.website.website_generator import WebsiteGenerator
|
||||
from webnotes.website.render import clear_cache
|
||||
|
||||
class DocType(WebsiteGenerator):
|
||||
def __init__(self, d, dl):
|
||||
|
|
@ -18,7 +19,4 @@ class DocType(WebsiteGenerator):
|
|||
|
||||
def on_update(self):
|
||||
WebsiteGenerator.on_update(self)
|
||||
|
||||
from webnotes.webutils import clear_cache
|
||||
clear_cache()
|
||||
|
||||
|
|
@ -4,16 +4,21 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import webnotes
|
||||
from webnotes.webutils import WebsiteGenerator, cleanup_page_name, clear_cache
|
||||
|
||||
from webnotes.website.website_generator import WebsiteGenerator
|
||||
from webnotes.website.render import clear_cache
|
||||
from webnotes import _
|
||||
from webnotes.utils import today
|
||||
|
||||
class DocType(WebsiteGenerator):
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
def autoname(self):
|
||||
self.doc.name = cleanup_page_name(self.doc.title)
|
||||
|
||||
def get_page_title(self):
|
||||
return self.doc.title
|
||||
|
||||
def get_parent_website_sitemap(self):
|
||||
return webnotes.conn.get_value("Website Sitemap", {"ref_doctype": "Blog Category", "docname": self.doc.blog_category})
|
||||
|
||||
def validate(self):
|
||||
if self.doc.blog_intro:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ class DocType:
|
|||
self.doc, self.doclist = d, dl
|
||||
|
||||
def on_update(self):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache("blog")
|
||||
clear_cache("writers")
|
||||
|
|
@ -11,5 +11,5 @@ class DocType:
|
|||
self.doc, self.doclist = d, dl
|
||||
|
||||
def on_update(self):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache("contact")
|
||||
|
|
@ -31,5 +31,5 @@ class DocType:
|
|||
from webnotes.sessions import clear_cache
|
||||
clear_cache('Guest')
|
||||
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.webutils import get_access
|
||||
from webnotes.website.permissions import get_access
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes, os, time
|
||||
from webnotes.webutils import WebsiteGenerator
|
||||
from webnotes.website.website_generator import WebsiteGenerator
|
||||
from webnotes import _
|
||||
from webnotes.utils import cint
|
||||
from markdown2 import markdown
|
||||
|
|
@ -21,7 +21,7 @@ class DocType(WebsiteGenerator):
|
|||
|
||||
# clear all cache if it has toc
|
||||
if self.doclist.get({"parentfield": "toc"}):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
||||
def on_trash(self):
|
||||
|
|
@ -33,7 +33,7 @@ class DocType(WebsiteGenerator):
|
|||
|
||||
# clear all cache if it has toc
|
||||
if self.doclist.get({"parentfield": "toc"}):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
||||
def sync_statics():
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.webutils import WebsiteGenerator
|
||||
from webnotes.website.website_generator import WebsiteGenerator
|
||||
from webnotes.templates.generators.website_group import clear_cache
|
||||
from webnotes.model.doc import make_autoname
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ class DocType:
|
|||
from webnotes.sessions import clear_cache
|
||||
clear_cache('Guest')
|
||||
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
|
@ -4,7 +4,9 @@
|
|||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint
|
||||
from webnotes.utils import get_request_site_address, encode
|
||||
from webnotes.model.controller import DocListController
|
||||
from urllib import quote
|
||||
|
||||
class DocType(DocListController):
|
||||
def validate(self):
|
||||
|
|
@ -43,6 +45,62 @@ class DocType(DocListController):
|
|||
# make js and css
|
||||
# clear web cache (for menus!)
|
||||
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
||||
|
||||
def get_website_settings():
|
||||
hooks = webnotes.get_hooks()
|
||||
|
||||
all_top_items = webnotes.conn.sql("""\
|
||||
select * from `tabTop Bar Item`
|
||||
where parent='Website Settings' and parentfield='top_bar_items'
|
||||
order by idx asc""", as_dict=1)
|
||||
|
||||
top_items = [d for d in all_top_items if not d['parent_label']]
|
||||
|
||||
# attach child items to top bar
|
||||
for d in all_top_items:
|
||||
if d['parent_label']:
|
||||
for t in top_items:
|
||||
if t['label']==d['parent_label']:
|
||||
if not 'child_items' in t:
|
||||
t['child_items'] = []
|
||||
t['child_items'].append(d)
|
||||
break
|
||||
|
||||
context = webnotes._dict({
|
||||
'top_bar_items': top_items,
|
||||
'footer_items': webnotes.conn.sql("""\
|
||||
select * from `tabTop Bar Item`
|
||||
where parent='Website Settings' and parentfield='footer_items'
|
||||
order by idx asc""", as_dict=1),
|
||||
"post_login": [
|
||||
{"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
|
||||
{"label": "Logout", "url": "?cmd=web_logout", "icon": "icon-signout"}
|
||||
]
|
||||
})
|
||||
|
||||
settings = webnotes.doc("Website Settings", "Website Settings")
|
||||
for k in ["banner_html", "brand_html", "copyright", "twitter_share_via",
|
||||
"favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
|
||||
"disable_signup"]:
|
||||
if k in settings.fields:
|
||||
context[k] = settings.fields.get(k)
|
||||
|
||||
if settings.address:
|
||||
context["footer_address"] = settings.address
|
||||
|
||||
for k in ["facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
|
||||
"disable_signup"]:
|
||||
context[k] = int(context.get(k) or 0)
|
||||
|
||||
context.url = quote(str(get_request_site_address(full_address=True)), safe="/:")
|
||||
context.encoded_title = quote(encode(context.title or ""), str(""))
|
||||
|
||||
for update_website_context in hooks.update_website_context or []:
|
||||
webnotes.get_attr(update_website_context)(context)
|
||||
|
||||
context.web_include_js = hooks.web_include_js or []
|
||||
context.web_include_css = hooks.web_include_css or []
|
||||
|
||||
return context
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _
|
||||
|
|
@ -20,12 +18,16 @@ class DocType(DocTypeNestedSet):
|
|||
self.doc.name = self.get_url()
|
||||
|
||||
def get_url(self):
|
||||
parent_website_sitemap = self.get_parent_website_sitemap()
|
||||
url = self.doc.page_name
|
||||
if self.doc.parent_website_sitemap:
|
||||
url = self.doc.parent_website_sitemap + "/" + url
|
||||
if parent_website_sitemap:
|
||||
url = parent_website_sitemap + "/" + url
|
||||
|
||||
return url
|
||||
|
||||
|
||||
def get_parent_website_sitemap(self):
|
||||
return self.doc.parent_website_sitemap
|
||||
|
||||
def validate(self):
|
||||
if self.get_url() != self.doc.name:
|
||||
self.rename()
|
||||
|
|
@ -33,7 +35,7 @@ class DocType(DocTypeNestedSet):
|
|||
self.make_private_if_parent_is_private()
|
||||
|
||||
def rename(self):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
self.old_name = self.doc.name
|
||||
self.doc.name = self.get_url()
|
||||
webnotes.conn.sql("""update `tabWebsite Sitemap` set name=%s where name=%s""",
|
||||
|
|
@ -86,7 +88,7 @@ class DocType(DocTypeNestedSet):
|
|||
self.doc.public_read = self.doc.public_write = 0
|
||||
|
||||
def on_trash(self):
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
# remove website sitemap permissions
|
||||
to_remove = webnotes.conn.sql_list("""select name from `tabWebsite Sitemap Permission`
|
||||
where website_sitemap=%s""", (self.doc.name,))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
|||
import webnotes
|
||||
import webnotes.utils
|
||||
import os
|
||||
|
||||
from webnotes import _
|
||||
from webnotes.website.doctype.website_sitemap.website_sitemap import add_to_sitemap, update_sitemap, cleanup_sitemap
|
||||
from webnotes.utils.nestedset import rebuild_tree
|
||||
|
||||
|
|
@ -95,6 +95,7 @@ def add_website_sitemap_config(page_or_generator, app, path, fname, basepath):
|
|||
wsc.page_name_field = getattr(module, "page_name_field", "page_name")
|
||||
wsc.condition_field = getattr(module, "condition_field", None)
|
||||
wsc.base_template_path = getattr(module, "base_template_path", None)
|
||||
wsc.page_title = getattr(module, "page_title", _(name.title()))
|
||||
|
||||
if webnotes.conn.exists("Website Sitemap Config", wsc.link_name):
|
||||
# found by earlier app, override
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-11-18 15:35:00",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-02-13 15:48:16",
|
||||
"modified": "2014-02-14 12:48:54",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -62,6 +62,12 @@
|
|||
"label": "Link Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "page_title",
|
||||
"fieldtype": "Data",
|
||||
"label": "Page Title"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "base_template_path",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.website.permissions import remove_empty_permissions, clear_permissions
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
|
@ -12,68 +14,3 @@ class DocType:
|
|||
remove_empty_permissions()
|
||||
clear_permissions(self.doc.profile)
|
||||
|
||||
def remove_empty_permissions():
|
||||
permissions_cache_to_be_cleared = webnotes.conn.sql_list("""select distinct profile
|
||||
from `tabWebsite Sitemap Permission`
|
||||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""")
|
||||
|
||||
webnotes.conn.sql("""delete from `tabWebsite Sitemap Permission`
|
||||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""")
|
||||
|
||||
clear_permissions(permissions_cache_to_be_cleared)
|
||||
|
||||
def get_access(sitemap_page, profile=None):
|
||||
profile = profile or webnotes.session.user
|
||||
key = "website_sitemap_permissions:{}".format(profile)
|
||||
|
||||
cache = webnotes.cache()
|
||||
permissions = cache.get_value(key) or {}
|
||||
if not permissions.get(sitemap_page):
|
||||
permissions[sitemap_page] = _get_access(sitemap_page, profile)
|
||||
cache.set_value(key, permissions)
|
||||
|
||||
return permissions.get(sitemap_page)
|
||||
|
||||
def _get_access(sitemap_page, profile):
|
||||
lft, rgt, public_read, public_write = webnotes.conn.get_value("Website Sitemap", sitemap_page,
|
||||
["lft", "rgt", "public_read", "public_write"])
|
||||
|
||||
if not (lft and rgt):
|
||||
raise webnotes.ValidationError("Please rebuild Website Sitemap Tree")
|
||||
|
||||
if profile == "Guest":
|
||||
return { "read": public_read, "write": 0, "admin": 0 }
|
||||
|
||||
read = write = admin = private_read = 0
|
||||
|
||||
if public_write:
|
||||
read = write = 1
|
||||
elif public_read:
|
||||
read = 1
|
||||
|
||||
for perm in webnotes.conn.sql("""select wsp.`read`, wsp.`write`, wsp.`admin`,
|
||||
ws.lft, ws.rgt, ws.name
|
||||
from `tabWebsite Sitemap Permission` wsp, `tabWebsite Sitemap` ws
|
||||
where wsp.profile = %s and wsp.website_sitemap = ws.name
|
||||
order by lft asc""", (profile,), as_dict=True):
|
||||
if perm.lft <= lft and perm.rgt >= rgt:
|
||||
if not (public_read or private_read): private_read = perm.read
|
||||
if not read: read = perm.read
|
||||
if not write: write = perm.write
|
||||
if not admin: admin = perm.admin
|
||||
if write: read = write
|
||||
|
||||
if read and write and admin:
|
||||
break
|
||||
|
||||
return { "read": read, "write": write, "admin": admin, "private_read": private_read }
|
||||
|
||||
def clear_permissions(profiles=None):
|
||||
if isinstance(profiles, basestring):
|
||||
profiles = [profiles]
|
||||
elif profiles is None:
|
||||
profiles = webnotes.conn.sql_list("""select name from `tabProfile`""")
|
||||
|
||||
cache = webnotes.cache()
|
||||
for profile in profiles:
|
||||
cache.delete_value("website_sitemap_permissions:{}".format(profile))
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class DocType:
|
|||
|
||||
def on_update(self):
|
||||
# a slide show can be in use and any change in it should get reflected
|
||||
from webnotes.webutils import clear_cache
|
||||
from webnotes.website.render import clear_cache
|
||||
clear_cache()
|
||||
|
||||
def get_slideshow(bean):
|
||||
|
|
|
|||
72
webnotes/website/permissions.py
Normal file
72
webnotes/website/permissions.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
|
||||
def remove_empty_permissions():
|
||||
permissions_cache_to_be_cleared = webnotes.conn.sql_list("""select distinct profile
|
||||
from `tabWebsite Sitemap Permission`
|
||||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""")
|
||||
|
||||
webnotes.conn.sql("""delete from `tabWebsite Sitemap Permission`
|
||||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""")
|
||||
|
||||
clear_permissions(permissions_cache_to_be_cleared)
|
||||
|
||||
def get_access(sitemap_page, profile=None):
|
||||
profile = profile or webnotes.session.user
|
||||
key = "website_sitemap_permissions:{}".format(profile)
|
||||
|
||||
cache = webnotes.cache()
|
||||
permissions = cache.get_value(key) or {}
|
||||
if not permissions.get(sitemap_page):
|
||||
permissions[sitemap_page] = _get_access(sitemap_page, profile)
|
||||
cache.set_value(key, permissions)
|
||||
|
||||
return permissions.get(sitemap_page)
|
||||
|
||||
def _get_access(sitemap_page, profile):
|
||||
lft, rgt, public_read, public_write = webnotes.conn.get_value("Website Sitemap", sitemap_page,
|
||||
["lft", "rgt", "public_read", "public_write"])
|
||||
|
||||
if not (lft and rgt):
|
||||
raise webnotes.ValidationError("Please rebuild Website Sitemap Tree")
|
||||
|
||||
if profile == "Guest":
|
||||
return { "read": public_read, "write": 0, "admin": 0 }
|
||||
|
||||
read = write = admin = private_read = 0
|
||||
|
||||
if public_write:
|
||||
read = write = 1
|
||||
elif public_read:
|
||||
read = 1
|
||||
|
||||
for perm in webnotes.conn.sql("""select wsp.`read`, wsp.`write`, wsp.`admin`,
|
||||
ws.lft, ws.rgt, ws.name
|
||||
from `tabWebsite Sitemap Permission` wsp, `tabWebsite Sitemap` ws
|
||||
where wsp.profile = %s and wsp.website_sitemap = ws.name
|
||||
order by lft asc""", (profile,), as_dict=True):
|
||||
if perm.lft <= lft and perm.rgt >= rgt:
|
||||
if not (public_read or private_read): private_read = perm.read
|
||||
if not read: read = perm.read
|
||||
if not write: write = perm.write
|
||||
if not admin: admin = perm.admin
|
||||
if write: read = write
|
||||
|
||||
if read and write and admin:
|
||||
break
|
||||
|
||||
return { "read": read, "write": write, "admin": admin, "private_read": private_read }
|
||||
|
||||
def clear_permissions(profiles=None):
|
||||
if isinstance(profiles, basestring):
|
||||
profiles = [profiles]
|
||||
elif profiles is None:
|
||||
profiles = webnotes.conn.sql_list("""select name from `tabProfile`""")
|
||||
|
||||
cache = webnotes.cache()
|
||||
for profile in profiles:
|
||||
cache.delete_value("website_sitemap_permissions:{}".format(profile))
|
||||
128
webnotes/website/render.py
Normal file
128
webnotes/website/render.py
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
import mimetypes, json
|
||||
|
||||
from webnotes.website.context import get_context
|
||||
from webnotes.website.utils import scrub_relative_urls, get_home_page, can_cache
|
||||
|
||||
from webnotes.website.permissions import get_access, clear_permissions
|
||||
|
||||
class PageNotFoundError(Exception): pass
|
||||
|
||||
def render(path):
|
||||
"""render html page"""
|
||||
path = resolve_path(path)
|
||||
|
||||
try:
|
||||
data = render_page(path)
|
||||
except Exception:
|
||||
path = "error"
|
||||
data = render_page(path)
|
||||
|
||||
data = set_content_type(data, path)
|
||||
webnotes._response.data = data
|
||||
webnotes._response.headers[b"Page Name"] = path.encode("utf-8")
|
||||
|
||||
def render_page(path):
|
||||
"""get page html"""
|
||||
cache_key = ("page_context:{}" if is_ajax() else "page:{}").format(path)
|
||||
|
||||
out = None
|
||||
|
||||
# try memcache
|
||||
if can_cache():
|
||||
out = webnotes.cache().get_value(cache_key)
|
||||
if out and is_ajax():
|
||||
out = out.get("data")
|
||||
|
||||
if out:
|
||||
if hasattr(webnotes, "_response"):
|
||||
webnotes._response.headers[b"From Cache"] = True
|
||||
|
||||
return out
|
||||
|
||||
return build(path)
|
||||
|
||||
def build(path):
|
||||
if not webnotes.conn:
|
||||
webnotes.connect()
|
||||
|
||||
build_method = (build_json if is_ajax() else build_page)
|
||||
try:
|
||||
return build_method(path)
|
||||
|
||||
except webnotes.DoesNotExistError:
|
||||
hooks = webnotes.get_hooks()
|
||||
if hooks.website_catch_all:
|
||||
return build_method(hooks.website_catch_all[0])
|
||||
else:
|
||||
return build_method("404")
|
||||
|
||||
def build_json(path):
|
||||
return get_context(path).data
|
||||
|
||||
def build_page(path):
|
||||
context = get_context(path)
|
||||
|
||||
html = webnotes.get_template(context.base_template_path).render(context)
|
||||
html = scrub_relative_urls(html)
|
||||
|
||||
if can_cache(context.no_cache):
|
||||
webnotes.cache().set_value("page:" + path, html)
|
||||
|
||||
return html
|
||||
|
||||
def is_ajax():
|
||||
return webnotes.get_request_header("X-Requested-With")=="XMLHttpRequest"
|
||||
|
||||
def resolve_path(path):
|
||||
if not path:
|
||||
path = "index"
|
||||
|
||||
if path.endswith('.html'):
|
||||
path = path[:-5]
|
||||
|
||||
if path == "index":
|
||||
path = get_home_page()
|
||||
|
||||
return path
|
||||
|
||||
def set_content_type(data, path):
|
||||
if isinstance(data, dict):
|
||||
webnotes._response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
|
||||
data = json.dumps(data)
|
||||
return data
|
||||
|
||||
webnotes._response.headers[b"Content-Type"] = b"text/html; charset: utf-8"
|
||||
|
||||
if "." in path and not path.endswith(".html"):
|
||||
content_type, encoding = mimetypes.guess_type(path)
|
||||
webnotes._response.headers[b"Content-Type"] = content_type.encode("utf-8")
|
||||
|
||||
return data
|
||||
|
||||
def clear_cache(path=None):
|
||||
cache = webnotes.cache()
|
||||
|
||||
if path:
|
||||
delete_page_cache(path)
|
||||
|
||||
else:
|
||||
for p in webnotes.conn.sql_list("""select name from `tabWebsite Sitemap`"""):
|
||||
if p is not None:
|
||||
delete_page_cache(p)
|
||||
|
||||
cache.delete_value("home_page")
|
||||
clear_permissions()
|
||||
|
||||
for method in webnotes.get_hooks("website_clear_cache"):
|
||||
webnotes.get_attr(method)(path)
|
||||
|
||||
def delete_page_cache(path):
|
||||
cache = webnotes.cache()
|
||||
cache.delete_value("page:" + path)
|
||||
cache.delete_value("page_context:" + path)
|
||||
cache.delete_value("sitemap_options:" + path)
|
||||
61
webnotes/website/sitemap.py
Normal file
61
webnotes/website/sitemap.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.website.utils import scrub_relative_urls, get_home_page, can_cache
|
||||
|
||||
def get_sitemap_options(path):
|
||||
sitemap_options = None
|
||||
cache_key = "sitemap_options:{}".format(path)
|
||||
|
||||
if can_cache():
|
||||
sitemap_options = webnotes.cache().get_value(cache_key)
|
||||
|
||||
if not sitemap_options:
|
||||
sitemap_options = build_sitemap_options(path)
|
||||
if can_cache(sitemap_options.no_cache):
|
||||
webnotes.cache().set_value(cache_key, sitemap_options)
|
||||
|
||||
return webnotes._dict(sitemap_options)
|
||||
|
||||
def build_sitemap_options(path):
|
||||
sitemap_options = webnotes.doc("Website Sitemap", path).fields
|
||||
home_page = get_home_page()
|
||||
|
||||
sitemap_config = webnotes.doc("Website Sitemap Config",
|
||||
sitemap_options.get("website_sitemap_config")).fields
|
||||
|
||||
# get sitemap config fields too
|
||||
for fieldname in ("base_template_path", "template_path", "controller", "no_cache", "no_sitemap",
|
||||
"page_name_field", "condition_field"):
|
||||
sitemap_options[fieldname] = sitemap_config.get(fieldname)
|
||||
|
||||
sitemap_options.doctype = sitemap_options.ref_doctype
|
||||
sitemap_options.title = sitemap_options.page_title
|
||||
sitemap_options.pathname = sitemap_options.name
|
||||
|
||||
def set_sidebar_items(pathname):
|
||||
if pathname==home_page or not pathname:
|
||||
sitemap_options.children = webnotes.conn.sql("""select url as name, label as page_title,
|
||||
1 as public_read from `tabTop Bar Item` where parentfield='sidebar_items' order by idx""", as_dict=True)
|
||||
else:
|
||||
sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap`
|
||||
where ifnull(parent_website_sitemap,'')=%s
|
||||
and public_read=1 order by -idx desc, page_title asc""", pathname, as_dict=True)
|
||||
|
||||
# establish hierarchy
|
||||
sitemap_options.parents = webnotes.conn.sql("""select name, page_title from `tabWebsite Sitemap`
|
||||
where lft < %s and rgt > %s order by lft asc""", (sitemap_options.lft, sitemap_options.rgt), as_dict=True)
|
||||
|
||||
if not sitemap_options.no_sidebar:
|
||||
set_sidebar_items(sitemap_options.pathname)
|
||||
if not sitemap_options.children:
|
||||
set_sidebar_items(sitemap_options.parent_website_sitemap)
|
||||
|
||||
# determine templates to be used
|
||||
if not sitemap_options.base_template_path:
|
||||
sitemap_options.base_template_path = "templates/base.html"
|
||||
|
||||
return sitemap_options
|
||||
48
webnotes/website/template.py
Normal file
48
webnotes/website/template.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.website.utils import scrub_relative_urls
|
||||
from jinja2.utils import concat
|
||||
from jinja2 import meta
|
||||
|
||||
def render_blocks(context):
|
||||
"""returns a dict of block name and its rendered content"""
|
||||
|
||||
out = {}
|
||||
|
||||
env = webnotes.get_jenv()
|
||||
|
||||
def _render_blocks(template_path):
|
||||
source = webnotes.local.jloader.get_source(webnotes.local.jenv, template_path)[0]
|
||||
for referenced_template_path in meta.find_referenced_templates(env.parse(source)):
|
||||
if referenced_template_path:
|
||||
_render_blocks(referenced_template_path)
|
||||
|
||||
template = webnotes.get_template(template_path)
|
||||
for block, render in template.blocks.items():
|
||||
out[block] = scrub_relative_urls(concat(render(template.new_context(context))))
|
||||
|
||||
_render_blocks(context["template_path"])
|
||||
|
||||
# default blocks if not found
|
||||
if "title" not in out:
|
||||
out["title"] = context.get("title")
|
||||
|
||||
if "header" not in out:
|
||||
out["header"] = out["title"]
|
||||
|
||||
if not out["header"].startswith("<h"):
|
||||
out["header"] = "<h2>" + out["header"] + "</h2>"
|
||||
|
||||
if "breadcrumbs" not in out:
|
||||
out["breadcrumbs"] = scrub_relative_urls(
|
||||
webnotes.get_template("templates/includes/breadcrumbs.html").render(context))
|
||||
|
||||
if "sidebar" not in out:
|
||||
out["sidebar"] = scrub_relative_urls(
|
||||
webnotes.get_template("templates/includes/sidebar.html").render(context))
|
||||
|
||||
return out
|
||||
67
webnotes/website/utils.py
Normal file
67
webnotes/website/utils.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes, re
|
||||
|
||||
def scrub_relative_urls(html):
|
||||
"""prepend a slash before a relative url"""
|
||||
return re.sub("""(src|href)[^\w'"]*['"](?!http|ftp|/|#)([^'" >]+)['"]""", '\g<1> = "/\g<2>"', html)
|
||||
|
||||
def can_cache(no_cache=False):
|
||||
return not (webnotes.conf.disable_website_cache or no_cache)
|
||||
|
||||
def get_home_page():
|
||||
home_page = webnotes.cache().get_value("home_page", \
|
||||
lambda: (webnotes.get_hooks("home_page") \
|
||||
or [webnotes.conn.get_value("Website Settings", None, "home_page") \
|
||||
or "login"])[0])
|
||||
|
||||
return home_page
|
||||
|
||||
def is_signup_enabled():
|
||||
if getattr(webnotes.local, "is_signup_enabled", None) is None:
|
||||
webnotes.local.is_signup_enabled = True
|
||||
if webnotes.utils.cint(webnotes.conn.get_value("Website Settings",
|
||||
"Website Settings", "disable_signup")):
|
||||
webnotes.local.is_signup_enabled = False
|
||||
|
||||
return webnotes.local.is_signup_enabled
|
||||
|
||||
def cleanup_page_name(title):
|
||||
"""make page name from title"""
|
||||
name = title.lower()
|
||||
name = re.sub('[~!@#$%^&*+()<>,."\'\?]', '', name)
|
||||
name = re.sub('[:/]', '-', name)
|
||||
|
||||
name = '-'.join(name.split())
|
||||
|
||||
# replace repeating hyphens
|
||||
name = re.sub(r"(-)\1+", r"\1", name)
|
||||
|
||||
return name
|
||||
|
||||
def get_hex_shade(color, percent):
|
||||
def p(c):
|
||||
v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
|
||||
if v < 0:
|
||||
v=0
|
||||
if v > 255:
|
||||
v=255
|
||||
h = hex(v)[2:]
|
||||
if len(h) < 2:
|
||||
h = "0" + h
|
||||
return h
|
||||
|
||||
r, g, b = color[0:2], color[2:4], color[4:6]
|
||||
|
||||
avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
|
||||
# switch dark and light shades
|
||||
if avg > 128:
|
||||
percent = -percent
|
||||
|
||||
# stronger diff for darker shades
|
||||
if percent < 25 and avg < 64:
|
||||
percent = percent * 2
|
||||
|
||||
return p(r) + p(g) + p(b)
|
||||
99
webnotes/website/website_generator.py
Normal file
99
webnotes/website/website_generator.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.model.controller import DocListController
|
||||
|
||||
from webnotes.website.doctype.website_sitemap.website_sitemap import add_to_sitemap, update_sitemap, remove_sitemap
|
||||
|
||||
class WebsiteGenerator(DocListController):
|
||||
def autoname(self):
|
||||
from webnotes.website.utils import cleanup_page_name
|
||||
self.doc.name = cleanup_page_name(self.get_page_title())
|
||||
|
||||
def set_page_name(self):
|
||||
"""set page name based on parent page_name and title"""
|
||||
page_name = cleanup_page_name(self.get_page_title())
|
||||
|
||||
if self.doc.is_new():
|
||||
self.doc.fields[self._website_config.page_name_field] = page_name
|
||||
else:
|
||||
webnotes.conn.set(self.doc, self._website_config.page_name_field, page_name)
|
||||
|
||||
def get_parent_website_sitemap(self):
|
||||
return self.doc.parent_website_sitemap
|
||||
|
||||
def setup_generator(self):
|
||||
self._website_config = webnotes.conn.get_values("Website Sitemap Config",
|
||||
{"ref_doctype": self.doc.doctype}, "*")[0]
|
||||
|
||||
def on_update(self):
|
||||
self.update_sitemap()
|
||||
|
||||
def after_rename(self, olddn, newdn, merge):
|
||||
webnotes.conn.sql("""update `tabWebsite Sitemap`
|
||||
set docname=%s where ref_doctype=%s and docname=%s""", (newdn, self.doc.doctype, olddn))
|
||||
|
||||
if merge:
|
||||
self.setup_generator()
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=olddn)
|
||||
|
||||
def on_trash(self):
|
||||
self.setup_generator()
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
|
||||
|
||||
def update_sitemap(self):
|
||||
self.setup_generator()
|
||||
|
||||
if self._website_config.condition_field and \
|
||||
not self.doc.fields.get(self._website_config.condition_field):
|
||||
# condition field failed, remove and return!
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
|
||||
return
|
||||
|
||||
self.add_or_update_sitemap()
|
||||
|
||||
def add_or_update_sitemap(self):
|
||||
page_name = self.get_page_name()
|
||||
|
||||
existing_site_map = webnotes.conn.get_value("Website Sitemap", {"ref_doctype": self.doc.doctype,
|
||||
"docname": self.doc.name})
|
||||
|
||||
opts = webnotes._dict({
|
||||
"page_or_generator": "Generator",
|
||||
"ref_doctype":self.doc.doctype,
|
||||
"docname": self.doc.name,
|
||||
"page_name": page_name,
|
||||
"link_name": self._website_config.name,
|
||||
"lastmod": webnotes.utils.get_datetime(self.doc.modified).strftime("%Y-%m-%d"),
|
||||
"parent_website_sitemap": self.get_parent_website_sitemap(),
|
||||
"page_title": self.get_page_title(),
|
||||
"public_read": 1 if not self._website_config.no_sidebar else 0
|
||||
})
|
||||
|
||||
self.update_permissions(opts)
|
||||
|
||||
if existing_site_map:
|
||||
update_sitemap(existing_site_map, opts)
|
||||
else:
|
||||
add_to_sitemap(opts)
|
||||
|
||||
def update_permissions(self, opts):
|
||||
if self.meta.get_field("public_read"):
|
||||
opts.public_read = self.doc.public_read
|
||||
opts.public_write = self.doc.public_write
|
||||
else:
|
||||
opts.public_read = 1
|
||||
|
||||
def get_page_name(self):
|
||||
if not self._get_page_name():
|
||||
self.set_page_name()
|
||||
|
||||
return self._get_page_name()
|
||||
|
||||
def _get_page_name(self):
|
||||
return self.doc.fields.get(self._website_config.page_name_field)
|
||||
|
||||
def get_page_title(self):
|
||||
return self.doc.title or (self.doc.name.replace("-", " ").replace("_", " ").title())
|
||||
|
|
@ -1,496 +0,0 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
import json, os, time, re
|
||||
from webnotes import _
|
||||
import webnotes.utils
|
||||
from webnotes.utils import get_request_site_address, encode, cint
|
||||
from webnotes.model import default_fields
|
||||
from webnotes.model.controller import DocListController
|
||||
from urllib import quote
|
||||
|
||||
import mimetypes
|
||||
from webnotes.website.doctype.website_sitemap.website_sitemap import add_to_sitemap, update_sitemap, remove_sitemap
|
||||
|
||||
# frequently used imports (used by other modules)
|
||||
from webnotes.website.doctype.website_sitemap_permission.website_sitemap_permission \
|
||||
import get_access, clear_permissions
|
||||
|
||||
class PageNotFoundError(Exception): pass
|
||||
|
||||
def render(path):
|
||||
"""render html page"""
|
||||
path = resolve_path(path)
|
||||
|
||||
try:
|
||||
data = render_page(path)
|
||||
except Exception:
|
||||
path = "error"
|
||||
data = render_page(path)
|
||||
|
||||
data = set_content_type(data, path)
|
||||
webnotes._response.data = data
|
||||
webnotes._response.headers[b"Page Name"] = path.encode("utf-8")
|
||||
|
||||
def render_page(path):
|
||||
"""get page html"""
|
||||
cache_key = ("page_context:{}" if is_ajax() else "page:{}").format(path)
|
||||
|
||||
out = None
|
||||
|
||||
# try memcache
|
||||
if can_cache():
|
||||
out = webnotes.cache().get_value(cache_key)
|
||||
if out and is_ajax():
|
||||
out = out.get("data")
|
||||
|
||||
if out:
|
||||
if hasattr(webnotes, "_response"):
|
||||
webnotes._response.headers[b"From Cache"] = True
|
||||
|
||||
return out
|
||||
|
||||
return build(path)
|
||||
|
||||
def build(path):
|
||||
if not webnotes.conn:
|
||||
webnotes.connect()
|
||||
|
||||
build_method = (build_json if is_ajax() else build_page)
|
||||
try:
|
||||
return build_method(path)
|
||||
|
||||
except webnotes.DoesNotExistError:
|
||||
hooks = webnotes.get_hooks()
|
||||
if hooks.website_catch_all:
|
||||
return build_method(hooks.website_catch_all[0])
|
||||
else:
|
||||
return build_method("404")
|
||||
|
||||
def build_json(path):
|
||||
return get_context(path).data
|
||||
|
||||
def build_page(path):
|
||||
context = get_context(path)
|
||||
|
||||
html = webnotes.get_template(context.base_template_path).render(context)
|
||||
html = scrub_relative_urls(html)
|
||||
|
||||
if can_cache(context.no_cache):
|
||||
webnotes.cache().set_value("page:" + path, html)
|
||||
|
||||
return html
|
||||
|
||||
def get_context(path):
|
||||
context = None
|
||||
cache_key = "page_context:{}".format(path)
|
||||
from pickle import dump
|
||||
from StringIO import StringIO
|
||||
|
||||
# try from memcache
|
||||
if can_cache():
|
||||
context = webnotes.cache().get_value(cache_key)
|
||||
|
||||
if not context:
|
||||
context = get_sitemap_options(path)
|
||||
|
||||
# permission may be required for rendering
|
||||
context["access"] = get_access(context.pathname)
|
||||
|
||||
context = build_context(context)
|
||||
|
||||
if can_cache(context.no_cache):
|
||||
webnotes.cache().set_value(cache_key, context)
|
||||
|
||||
else:
|
||||
context["access"] = get_access(context.pathname)
|
||||
|
||||
context.update(context.data or {})
|
||||
|
||||
# TODO private pages
|
||||
|
||||
return context
|
||||
|
||||
def get_sitemap_options(path):
|
||||
sitemap_options = None
|
||||
cache_key = "sitemap_options:{}".format(path)
|
||||
|
||||
if can_cache():
|
||||
sitemap_options = webnotes.cache().get_value(cache_key)
|
||||
|
||||
if not sitemap_options:
|
||||
sitemap_options = build_sitemap_options(path)
|
||||
if can_cache(sitemap_options.no_cache):
|
||||
webnotes.cache().set_value(cache_key, sitemap_options)
|
||||
|
||||
return webnotes._dict(sitemap_options)
|
||||
|
||||
def build_sitemap_options(path):
|
||||
sitemap_options = webnotes.doc("Website Sitemap", path).fields
|
||||
home_page = get_home_page()
|
||||
|
||||
sitemap_config = webnotes.doc("Website Sitemap Config",
|
||||
sitemap_options.get("website_sitemap_config")).fields
|
||||
|
||||
# get sitemap config fields too
|
||||
for fieldname in ("base_template_path", "template_path", "controller", "no_cache", "no_sitemap",
|
||||
"page_name_field", "condition_field"):
|
||||
sitemap_options[fieldname] = sitemap_config.get(fieldname)
|
||||
|
||||
sitemap_options.doctype = sitemap_options.ref_doctype
|
||||
sitemap_options.title = sitemap_options.page_title
|
||||
sitemap_options.pathname = sitemap_options.name
|
||||
|
||||
def set_sidebar_items(pathname):
|
||||
if pathname==home_page or not pathname:
|
||||
sitemap_options.children = webnotes.conn.sql("""select url as name, label as page_title,
|
||||
1 as public_read from `tabTop Bar Item` where parentfield='sidebar_items' order by idx""", as_dict=True)
|
||||
else:
|
||||
sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap`
|
||||
where ifnull(parent_website_sitemap,'')=%s
|
||||
and public_read=1 order by -idx desc, page_title asc""", pathname, as_dict=True)
|
||||
|
||||
# establish hierarchy
|
||||
sitemap_options.parents = webnotes.conn.sql("""select name, page_title from `tabWebsite Sitemap`
|
||||
where lft < %s and rgt > %s order by lft asc""", (sitemap_options.lft, sitemap_options.rgt), as_dict=True)
|
||||
|
||||
if not sitemap_options.no_sidebar:
|
||||
set_sidebar_items(sitemap_options.pathname)
|
||||
if not sitemap_options.children:
|
||||
set_sidebar_items(sitemap_options.parent_website_sitemap)
|
||||
|
||||
# determine templates to be used
|
||||
if not sitemap_options.base_template_path:
|
||||
sitemap_options.base_template_path = "templates/base.html"
|
||||
|
||||
return sitemap_options
|
||||
|
||||
def build_context(sitemap_options):
|
||||
"""get_context method of bean or module is supposed to render content templates and push it into context"""
|
||||
context = webnotes._dict(sitemap_options)
|
||||
context.update(get_website_settings())
|
||||
|
||||
# provide bean
|
||||
if context.doctype and context.docname:
|
||||
context.bean = webnotes.bean(context.doctype, context.docname)
|
||||
|
||||
if context.controller:
|
||||
module = webnotes.get_module(context.controller)
|
||||
if module and hasattr(module, "get_context"):
|
||||
context.update(module.get_context(context) or {})
|
||||
|
||||
if context.get("base_template_path") != context.get("template_path") and not context.get("rendered"):
|
||||
context.data = render_blocks(context)
|
||||
|
||||
# remove bean, as it is not pickle friendly and its purpose is over
|
||||
if context.bean:
|
||||
del context["bean"]
|
||||
|
||||
return context
|
||||
|
||||
def can_cache(no_cache=False):
|
||||
return not (webnotes.conf.disable_website_cache or no_cache)
|
||||
|
||||
def get_home_page():
|
||||
home_page = webnotes.cache().get_value("home_page", \
|
||||
lambda: (webnotes.get_hooks("home_page") \
|
||||
or [webnotes.conn.get_value("Website Settings", None, "home_page") \
|
||||
or "login"])[0])
|
||||
|
||||
return home_page
|
||||
|
||||
def get_website_settings():
|
||||
# TODO Cache this
|
||||
hooks = webnotes.get_hooks()
|
||||
|
||||
all_top_items = webnotes.conn.sql("""\
|
||||
select * from `tabTop Bar Item`
|
||||
where parent='Website Settings' and parentfield='top_bar_items'
|
||||
order by idx asc""", as_dict=1)
|
||||
|
||||
top_items = [d for d in all_top_items if not d['parent_label']]
|
||||
|
||||
# attach child items to top bar
|
||||
for d in all_top_items:
|
||||
if d['parent_label']:
|
||||
for t in top_items:
|
||||
if t['label']==d['parent_label']:
|
||||
if not 'child_items' in t:
|
||||
t['child_items'] = []
|
||||
t['child_items'].append(d)
|
||||
break
|
||||
|
||||
context = webnotes._dict({
|
||||
'top_bar_items': top_items,
|
||||
'footer_items': webnotes.conn.sql("""\
|
||||
select * from `tabTop Bar Item`
|
||||
where parent='Website Settings' and parentfield='footer_items'
|
||||
order by idx asc""", as_dict=1),
|
||||
"post_login": [
|
||||
{"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
|
||||
{"label": "Logout", "url": "?cmd=web_logout", "icon": "icon-signout"}
|
||||
]
|
||||
})
|
||||
|
||||
settings = webnotes.doc("Website Settings", "Website Settings")
|
||||
for k in ["banner_html", "brand_html", "copyright", "twitter_share_via",
|
||||
"favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
|
||||
"disable_signup"]:
|
||||
if k in settings.fields:
|
||||
context[k] = settings.fields.get(k)
|
||||
|
||||
if settings.address:
|
||||
context["footer_address"] = settings.address
|
||||
|
||||
for k in ["facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
|
||||
"disable_signup"]:
|
||||
context[k] = cint(context.get(k) or 0)
|
||||
|
||||
context.url = quote(str(get_request_site_address(full_address=True)), safe="/:")
|
||||
context.encoded_title = quote(encode(context.title or ""), str(""))
|
||||
|
||||
for update_website_context in hooks.update_website_context or []:
|
||||
webnotes.get_attr(update_website_context)(context)
|
||||
|
||||
context.web_include_js = hooks.web_include_js or []
|
||||
context.web_include_css = hooks.web_include_css or []
|
||||
|
||||
return context
|
||||
|
||||
def is_ajax():
|
||||
return webnotes.get_request_header("X-Requested-With")=="XMLHttpRequest"
|
||||
|
||||
def resolve_path(path):
|
||||
if not path:
|
||||
path = "index"
|
||||
|
||||
if path.endswith('.html'):
|
||||
path = path[:-5]
|
||||
|
||||
if path == "index":
|
||||
path = get_home_page()
|
||||
|
||||
return path
|
||||
|
||||
def set_content_type(data, path):
|
||||
if isinstance(data, dict):
|
||||
webnotes._response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
|
||||
data = json.dumps(data)
|
||||
return data
|
||||
|
||||
webnotes._response.headers[b"Content-Type"] = b"text/html; charset: utf-8"
|
||||
|
||||
if "." in path and not path.endswith(".html"):
|
||||
content_type, encoding = mimetypes.guess_type(path)
|
||||
webnotes._response.headers[b"Content-Type"] = content_type.encode("utf-8")
|
||||
|
||||
return data
|
||||
|
||||
def clear_cache(path=None):
|
||||
cache = webnotes.cache()
|
||||
|
||||
if path:
|
||||
delete_page_cache(path)
|
||||
|
||||
else:
|
||||
for p in webnotes.conn.sql_list("""select name from `tabWebsite Sitemap`"""):
|
||||
if p is not None:
|
||||
delete_page_cache(p)
|
||||
|
||||
cache.delete_value("home_page")
|
||||
clear_permissions()
|
||||
|
||||
for method in webnotes.get_hooks("website_clear_cache"):
|
||||
webnotes.get_attr(method)(path)
|
||||
|
||||
def delete_page_cache(path):
|
||||
cache = webnotes.cache()
|
||||
cache.delete_value("page:" + path)
|
||||
cache.delete_value("page_context:" + path)
|
||||
cache.delete_value("sitemap_options:" + path)
|
||||
|
||||
def is_signup_enabled():
|
||||
if getattr(webnotes.local, "is_signup_enabled", None) is None:
|
||||
webnotes.local.is_signup_enabled = True
|
||||
if webnotes.utils.cint(webnotes.conn.get_value("Website Settings",
|
||||
"Website Settings", "disable_signup")):
|
||||
webnotes.local.is_signup_enabled = False
|
||||
|
||||
return webnotes.local.is_signup_enabled
|
||||
|
||||
def call_website_generator(bean, method, *args, **kwargs):
|
||||
getattr(WebsiteGenerator(bean.doc, bean.doclist), method)(*args, **kwargs)
|
||||
|
||||
class WebsiteGenerator(DocListController):
|
||||
def autoname(self):
|
||||
from webnotes.webutils import cleanup_page_name
|
||||
self.doc.name = cleanup_page_name(self.get_page_title())
|
||||
|
||||
def set_page_name(self):
|
||||
"""set page name based on parent page_name and title"""
|
||||
page_name = cleanup_page_name(self.get_page_title())
|
||||
|
||||
if self.doc.is_new():
|
||||
self.doc.fields[self._website_config.page_name_field] = page_name
|
||||
else:
|
||||
webnotes.conn.set(self.doc, self._website_config.page_name_field, page_name)
|
||||
|
||||
def setup_generator(self):
|
||||
self._website_config = webnotes.conn.get_values("Website Sitemap Config",
|
||||
{"ref_doctype": self.doc.doctype}, "*")[0]
|
||||
|
||||
def on_update(self):
|
||||
self.update_sitemap()
|
||||
|
||||
def after_rename(self, olddn, newdn, merge):
|
||||
webnotes.conn.sql("""update `tabWebsite Sitemap`
|
||||
set docname=%s where ref_doctype=%s and docname=%s""", (newdn, self.doc.doctype, olddn))
|
||||
|
||||
if merge:
|
||||
self.setup_generator()
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=olddn)
|
||||
|
||||
def on_trash(self):
|
||||
self.setup_generator()
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
|
||||
|
||||
def update_sitemap(self):
|
||||
self.setup_generator()
|
||||
|
||||
if self._website_config.condition_field and \
|
||||
not self.doc.fields.get(self._website_config.condition_field):
|
||||
# condition field failed, remove and return!
|
||||
remove_sitemap(ref_doctype=self.doc.doctype, docname=self.doc.name)
|
||||
return
|
||||
|
||||
self.add_or_update_sitemap()
|
||||
|
||||
def add_or_update_sitemap(self):
|
||||
page_name = self.get_page_name()
|
||||
|
||||
existing_site_map = webnotes.conn.get_value("Website Sitemap", {"ref_doctype": self.doc.doctype,
|
||||
"docname": self.doc.name})
|
||||
|
||||
opts = webnotes._dict({
|
||||
"page_or_generator": "Generator",
|
||||
"ref_doctype":self.doc.doctype,
|
||||
"docname": self.doc.name,
|
||||
"page_name": page_name,
|
||||
"link_name": self._website_config.name,
|
||||
"lastmod": webnotes.utils.get_datetime(self.doc.modified).strftime("%Y-%m-%d"),
|
||||
"parent_website_sitemap": self.doc.parent_website_sitemap,
|
||||
"page_title": self.get_page_title(),
|
||||
"public_read": 1 if not self._website_config.no_sidebar else 0
|
||||
})
|
||||
|
||||
self.update_permissions(opts)
|
||||
|
||||
if existing_site_map:
|
||||
update_sitemap(existing_site_map, opts)
|
||||
else:
|
||||
add_to_sitemap(opts)
|
||||
|
||||
def update_permissions(self, opts):
|
||||
if self.meta.get_field("public_read"):
|
||||
opts.public_read = self.doc.public_read
|
||||
opts.public_write = self.doc.public_write
|
||||
else:
|
||||
opts.public_read = 1
|
||||
|
||||
def get_page_name(self):
|
||||
if not self._get_page_name():
|
||||
self.set_page_name()
|
||||
|
||||
return self._get_page_name()
|
||||
|
||||
def _get_page_name(self):
|
||||
return self.doc.fields.get(self._website_config.page_name_field)
|
||||
|
||||
def get_page_title(self):
|
||||
return self.doc.title or (self.doc.name.replace("-", " ").replace("_", " ").title())
|
||||
|
||||
def cleanup_page_name(title):
|
||||
"""make page name from title"""
|
||||
import re
|
||||
name = title.lower()
|
||||
name = re.sub('[~!@#$%^&*+()<>,."\'\?]', '', name)
|
||||
name = re.sub('[:/]', '-', name)
|
||||
|
||||
name = '-'.join(name.split())
|
||||
|
||||
# replace repeating hyphens
|
||||
name = re.sub(r"(-)\1+", r"\1", name)
|
||||
|
||||
return name
|
||||
|
||||
def get_hex_shade(color, percent):
|
||||
def p(c):
|
||||
v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
|
||||
if v < 0:
|
||||
v=0
|
||||
if v > 255:
|
||||
v=255
|
||||
h = hex(v)[2:]
|
||||
if len(h) < 2:
|
||||
h = "0" + h
|
||||
return h
|
||||
|
||||
r, g, b = color[0:2], color[2:4], color[4:6]
|
||||
|
||||
avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
|
||||
# switch dark and light shades
|
||||
if avg > 128:
|
||||
percent = -percent
|
||||
|
||||
# stronger diff for darker shades
|
||||
if percent < 25 and avg < 64:
|
||||
percent = percent * 2
|
||||
|
||||
return p(r) + p(g) + p(b)
|
||||
|
||||
def render_blocks(context):
|
||||
"""returns a dict of block name and its rendered content"""
|
||||
from jinja2.utils import concat
|
||||
from jinja2 import meta
|
||||
|
||||
out = {}
|
||||
|
||||
env = webnotes.get_jenv()
|
||||
|
||||
def _render_blocks(template_path):
|
||||
source = webnotes.local.jloader.get_source(webnotes.local.jenv, template_path)[0]
|
||||
for referenced_template_path in meta.find_referenced_templates(env.parse(source)):
|
||||
if referenced_template_path:
|
||||
_render_blocks(referenced_template_path)
|
||||
|
||||
template = webnotes.get_template(template_path)
|
||||
for block, render in template.blocks.items():
|
||||
out[block] = scrub_relative_urls(concat(render(template.new_context(context))))
|
||||
|
||||
_render_blocks(context["template_path"])
|
||||
|
||||
# default blocks if not found
|
||||
if "title" not in out:
|
||||
out["title"] = context.get("title")
|
||||
|
||||
if "header" not in out:
|
||||
out["header"] = out["title"]
|
||||
|
||||
if not out["header"].startswith("<h"):
|
||||
out["header"] = "<h2>" + out["header"] + "</h2>"
|
||||
|
||||
if "breadcrumbs" not in out:
|
||||
out["breadcrumbs"] = scrub_relative_urls(
|
||||
webnotes.get_template("templates/includes/breadcrumbs.html").render(context))
|
||||
|
||||
if "sidebar" not in out:
|
||||
out["sidebar"] = scrub_relative_urls(
|
||||
webnotes.get_template("templates/includes/sidebar.html").render(context))
|
||||
|
||||
return out
|
||||
|
||||
def scrub_relative_urls(html):
|
||||
"""prepend a slash before a relative url"""
|
||||
return re.sub("""(src|href)[^\w'"]*['"](?!http|ftp|/|#)([^'" >]+)['"]""", '\g<1> = "/\g<2>"', html)
|
||||
Loading…
Add table
Reference in a new issue