@@ -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 |
@@ -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): | |||
@@ -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)) |
@@ -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) |
@@ -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 |
@@ -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 |
@@ -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) |
@@ -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) |