diff --git a/frappe/__init__.py b/frappe/__init__.py
index f055f4d940..f9ef3bb4f9 100644
--- a/frappe/__init__.py
+++ b/frappe/__init__.py
@@ -160,7 +160,7 @@ def get_traceback():
def errprint(msg):
from utils import cstr
- if not request:
+ if not request or (not "cmd" in local.form_dict):
print cstr(msg)
error_log.append(cstr(msg))
diff --git a/frappe/patches.txt b/frappe/patches.txt
index 5d82a4a7b5..1bdeddb05d 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -51,3 +51,4 @@ execute:frappe.db.sql("""update `tabPrint Format` set print_format_type='Client'
frappe.patches.v4_1.file_manager_fix
frappe.patches.v4_2.print_with_letterhead
execute:frappe.delete_doc("DocType", "Control Panel", force=1)
+execute:frappe.delete_doc("DocType", "Website Route", force=1)
diff --git a/frappe/templates/includes/breadcrumbs.html b/frappe/templates/includes/breadcrumbs.html
index f33ab80905..01e1162ac6 100644
--- a/frappe/templates/includes/breadcrumbs.html
+++ b/frappe/templates/includes/breadcrumbs.html
@@ -1,3 +1,4 @@
+{% set parents = doc.get_parents() if doc else [] %}
{% if parents|length > 0 %}
{% for parent in parents %}
diff --git a/frappe/templates/includes/sidebar.html b/frappe/templates/includes/sidebar.html
index 219f3a9f0f..d83e99d6cc 100644
--- a/frappe/templates/includes/sidebar.html
+++ b/frappe/templates/includes/sidebar.html
@@ -1,18 +1,10 @@
+{% set children = doc.get_children() if doc else (get_children() if get_children else []) %}
{% if children -%}
{%- for child in children -%}
{%- endfor -%}
diff --git a/frappe/templates/pages/blog.py b/frappe/templates/pages/blog.py
index a9001bd554..d9accf0198 100644
--- a/frappe/templates/pages/blog.py
+++ b/frappe/templates/pages/blog.py
@@ -7,3 +7,8 @@ import frappe
page_title = "Blog"
def get_context(context):
return frappe.get_doc("Blog Settings", "Blog Settings").as_dict()
+
+def get_children():
+ return frappe.db.sql("""select concat("blog/", page_name) as name,
+ title from `tabBlog Category`
+ where ifnull(published, 0) = 1 order by title asc""", as_dict=1)
diff --git a/frappe/website/context.py b/frappe/website/context.py
index 1c623f26d4..8a2030a523 100644
--- a/frappe/website/context.py
+++ b/frappe/website/context.py
@@ -5,7 +5,6 @@ from __future__ import unicode_literals
import frappe
# frequently used imports (used by other modules)
-from frappe.website.permissions import get_access
from frappe.website.doctype.website_settings.website_settings import get_website_settings
from frappe.website.template import render_blocks
@@ -30,7 +29,7 @@ def get_context(path):
context = get_sitemap_options(path)
# permission may be required for rendering
- context["access"] = get_access(context.pathname)
+ context["access"] = frappe._dict({"public_read":1, "public_write":1})
context = build_context(context)
add_data_path(context)
@@ -39,7 +38,7 @@ def get_context(path):
frappe.cache().set_value(cache_key, context)
else:
- context["access"] = get_access(context.pathname)
+ context["access"] = frappe._dict({"public_read":1, "public_write":1})
add_data_path(context)
context.update(context.data or {})
@@ -52,18 +51,19 @@ def build_context(sitemap_options):
context.update(get_website_settings())
# provide doc
- if context.doctype and context.docname:
- doc = frappe.get_doc(context.doctype, context.docname)
- context.doc = doc
- context.update(doc.as_dict())
+ if context.doc:
+ context.update(context.doc.as_dict())
if hasattr(context.doc, "get_context"):
context.update(context.doc.get_context(context) or {})
elif context.controller:
module = frappe.get_module(context.controller)
- if module and hasattr(module, "get_context"):
- context.update(module.get_context(context) or {})
+ if module:
+ if hasattr(module, "get_context"):
+ context.update(module.get_context(context) or {})
+ if hasattr(module, "get_children"):
+ context.get_children = module.get_children
add_metatags(context)
diff --git a/frappe/website/doctype/blog_category/blog_category.json b/frappe/website/doctype/blog_category/blog_category.json
index 01ccf1318d..34be7993dc 100644
--- a/frappe/website/doctype/blog_category/blog_category.json
+++ b/frappe/website/doctype/blog_category/blog_category.json
@@ -1,80 +1,80 @@
{
- "allow_import": 1,
- "autoname": "field:category_name",
- "creation": "2013-03-08 09:41:11",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Master",
+ "allow_import": 1,
+ "autoname": "field:category_name",
+ "creation": "2013-03-08 09:41:11",
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Master",
"fields": [
{
- "fieldname": "category_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Category Name",
- "permlevel": 0,
+ "fieldname": "category_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Category Name",
+ "permlevel": 0,
"reqd": 1
- },
+ },
{
- "fieldname": "title",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Title",
- "permlevel": 0,
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Title",
+ "permlevel": 0,
"reqd": 1
- },
+ },
{
- "fieldname": "published",
- "fieldtype": "Check",
- "in_list_view": 1,
- "label": "Published",
+ "fieldname": "published",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Published",
"permlevel": 0
- },
+ },
{
- "default": "blog",
- "fieldname": "parent_website_route",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Parent Website Route",
- "options": "Website Route",
- "permlevel": 0,
+ "default": "blog",
+ "fieldname": "parent_website_route",
+ "fieldtype": "Read Only",
+ "in_list_view": 1,
+ "label": "Parent Website Route",
+ "options": "",
+ "permlevel": 0,
"reqd": 1
- },
+ },
{
- "fieldname": "page_name",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Page Name",
+ "fieldname": "page_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Page Name",
"permlevel": 0
}
- ],
- "icon": "icon-tag",
- "idx": 1,
- "modified": "2014-05-27 06:33:22.629900",
- "modified_by": "Administrator",
- "module": "Website",
- "name": "Blog Category",
- "owner": "Administrator",
+ ],
+ "icon": "icon-tag",
+ "idx": 1,
+ "modified": "2014-08-18 06:07:54.923616",
+ "modified_by": "Administrator",
+ "module": "Website",
+ "name": "Blog Category",
+ "owner": "Administrator",
"permissions": [
{
- "create": 1,
- "delete": 1,
- "email": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Website Manager",
- "set_user_permissions": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Website Manager",
+ "set_user_permissions": 1,
"write": 1
- },
+ },
{
- "apply_user_permissions": 1,
- "delete": 0,
- "email": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
+ "apply_user_permissions": 1,
+ "delete": 0,
+ "email": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
"role": "Blogger"
}
]
-}
+}
\ No newline at end of file
diff --git a/frappe/website/doctype/blog_category/blog_category.py b/frappe/website/doctype/blog_category/blog_category.py
index 9ba2fed1f3..ff6a85a017 100644
--- a/frappe/website/doctype/blog_category/blog_category.py
+++ b/frappe/website/doctype/blog_category/blog_category.py
@@ -5,22 +5,23 @@ from __future__ import unicode_literals
import frappe
from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import clear_cache
-
-template = "templates/generators/blog_category.html"
-no_cache = True
+from frappe.templates.pages.blog import get_children
class BlogCategory(WebsiteGenerator):
+ page_title_field = "title"
+ template = "templates/generators/blog_category.html"
+ no_cache = True
def autoname(self):
# to override autoname of WebsiteGenerator
self.name = self.category_name
- def get_page_title(self):
- return self.title or self.name
-
def on_update(self):
WebsiteGenerator.on_update(self)
clear_cache()
- def get_parent_website_route(self):
- parent_website_sitemap = super(BlogCategory, self).get_parent_website_route()
- return parent_website_sitemap or "blog"
+ def get_children(self):
+ return get_children()
+
+ def validate(self):
+ self.parent_website_route = "blog"
+ super(BlogCategory, self).validate()
diff --git a/frappe/website/doctype/blog_post/blog_post.json b/frappe/website/doctype/blog_post/blog_post.json
index 52fc0caef8..1cf57db928 100644
--- a/frappe/website/doctype/blog_post/blog_post.json
+++ b/frappe/website/doctype/blog_post/blog_post.json
@@ -50,10 +50,10 @@
},
{
"fieldname": "parent_website_route",
- "fieldtype": "Link",
+ "fieldtype": "Read Only",
"hidden": 1,
"label": "Parent Website Route",
- "options": "Website Route",
+ "options": "",
"permlevel": 0,
"read_only": 1
},
@@ -98,7 +98,7 @@
"icon": "icon-quote-left",
"idx": 1,
"max_attachments": 5,
- "modified": "2014-08-05 04:54:26.723053",
+ "modified": "2014-08-18 07:08:56.343029",
"modified_by": "Administrator",
"module": "Website",
"name": "Blog Post",
diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py
index 80aa84386f..0f05f3a0be 100644
--- a/frappe/website/doctype/blog_post/blog_post.py
+++ b/frappe/website/doctype/blog_post/blog_post.py
@@ -9,15 +9,14 @@ from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import clear_cache
from frappe.utils import today, cint, global_date_format, get_fullname
from frappe.website.utils import find_first_image, get_comment_list
-
-order_by = "published_on desc"
-condition_field = "published"
-template = "templates/generators/blog_post.html"
+from frappe.templates.pages.blog import get_children
class BlogPost(WebsiteGenerator):
+ condition_field = "published"
+ template = "templates/generators/blog_post.html"
save_versions = True
- def get_page_title(self):
- return self.title
+ order_by = "published_on desc"
+ parent_website_route_field = "blog_category"
def validate(self):
super(BlogPost, self).validate()
@@ -32,12 +31,6 @@ class BlogPost(WebsiteGenerator):
if self.published and not self.published_on:
self.published_on = today()
- # make sure route for category exists
- self.parent_website_route = self.get_category_route()
- if not self.parent_website_route:
- frappe.get_doc("Blog Category", self.blog_category).save(ignore_permissions=True)
- self.parent_website_route = self.get_category_route()
-
# update posts
frappe.db.sql("""update tabBlogger set posts=(select count(*) from `tabBlog Post`
where ifnull(blogger,'')=tabBlogger.name)
@@ -81,6 +74,9 @@ class BlogPost(WebsiteGenerator):
return context
+ def get_children(self):
+ return get_children()
+
def clear_blog_cache():
for blog in frappe.db.sql_list("""select page_name from
`tabBlog Post` where ifnull(published,0)=1"""):
@@ -97,18 +93,18 @@ def get_blog_list(start=0, by=None, category=None):
condition += " and t1.blog_category='%s'" % category.replace("'", "\'")
query = """\
select
- t1.title, t1.name, t3.name as page_name, t1.published_on as creation,
+ t1.title, t1.name,
+ concat(t1.parent_website_route, "/", t1.page_name) as page_name,
+ t1.published_on as creation,
day(t1.published_on) as day, monthname(t1.published_on) as month,
year(t1.published_on) as year,
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, `tabWebsite Route` t3
+ from `tabBlog Post` t1, `tabBlogger` t2
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}
diff --git a/frappe/website/doctype/web_page/web_page.json b/frappe/website/doctype/web_page/web_page.json
index 5822eee4dd..ac2b88d7be 100644
--- a/frappe/website/doctype/web_page/web_page.json
+++ b/frappe/website/doctype/web_page/web_page.json
@@ -30,8 +30,16 @@
"read_only": 0
},
{
- "fieldname": "parent_website_route",
+ "fieldname": "parent_web_page",
"fieldtype": "Link",
+ "label": "Parent Web Page",
+ "options": "Web Page",
+ "permlevel": 0
+ },
+ {
+ "fieldname": "parent_website_route",
+ "fieldtype": "Read Only",
+ "hidden": 1,
"label": "Parent Website Page",
"options": "Website Route",
"permlevel": 0
@@ -157,7 +165,7 @@
"icon": "icon-file-alt",
"idx": 1,
"max_attachments": 20,
- "modified": "2014-08-05 04:54:49.018407",
+ "modified": "2014-08-18 08:10:03.220821",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Page",
diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py
index ffdca2cb2a..a196675693 100644
--- a/frappe/website/doctype/web_page/web_page.py
+++ b/frappe/website/doctype/web_page/web_page.py
@@ -8,11 +8,11 @@ from frappe.website.website_generator import WebsiteGenerator
from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
from frappe.website.utils import find_first_image, get_comment_list
-template = "templates/generators/web_page.html"
-condition_field = "published"
class WebPage(WebsiteGenerator):
save_versions = True
+ template = "templates/generators/web_page.html"
+ condition_field = "published"
def get_context(self, context):
# if static page, get static content
if context.slideshow:
diff --git a/frappe/website/doctype/website_group/website_group.py b/frappe/website/doctype/website_group/website_group.py
index f5a4fb6aab..4f9cc84c2d 100644
--- a/frappe/website/doctype/website_group/website_group.py
+++ b/frappe/website/doctype/website_group/website_group.py
@@ -7,13 +7,10 @@ from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import can_cache
from frappe.templates.website_group.forum import get_post_list_html
-no_cache = True
-template = "templates/generators/website_group.html"
-
class WebsiteGroup(WebsiteGenerator):
- def get_page_title(self):
- return self.group_title
-
+ page_title_field = "name"
+ no_cache = True
+ template = "templates/generators/website_group.html"
def on_update(self):
WebsiteGenerator.on_update(self)
clear_cache(website_group=self.name)
diff --git a/frappe/website/render.py b/frappe/website/render.py
index 2ecc5ca1c8..395e836db1 100644
--- a/frappe/website/render.py
+++ b/frappe/website/render.py
@@ -8,8 +8,9 @@ import mimetypes, json
from werkzeug.wrappers import Response
from frappe.website.context import get_context
-from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache
+from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache, delete_page_cache
from frappe.website.permissions import clear_permissions
+from frappe.website.sitemap import clear_sitemap
class PageNotFoundError(Exception): pass
@@ -165,22 +166,11 @@ def clear_cache(path=None):
if path:
delete_page_cache(path)
- for p in frappe.db.sql_list('''select name from
- `tabWebsite Route` where name like "{0}/%"'''.format(path.replace('"', '\"'))):
- delete_page_cache(p)
else:
- for p in frappe.db.sql_list("""select name from `tabWebsite Route`"""):
- if p is not None:
- delete_page_cache(p)
-
+ clear_sitemap()
frappe.clear_cache("Guest")
clear_permissions()
for method in frappe.get_hooks("website_clear_cache"):
frappe.get_attr(method)(path)
-def delete_page_cache(path):
- cache = frappe.cache()
- cache.delete_value("page:" + path)
- cache.delete_value("page_context:" + path)
- cache.delete_value("sitemap_options:" + path)
diff --git a/frappe/website/sitemap.py b/frappe/website/sitemap.py
index 80f2102b7c..9b6ea17725 100644
--- a/frappe/website/sitemap.py
+++ b/frappe/website/sitemap.py
@@ -2,9 +2,10 @@
# MIT License. See license.txt
from __future__ import unicode_literals
-import frappe
+import frappe, os
-from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache
+from frappe.website.utils import can_cache, delete_page_cache
+from frappe.model.document import get_controller
def get_sitemap_options(path):
sitemap_options = None
@@ -18,11 +19,12 @@ def get_sitemap_options(path):
if can_cache(sitemap_options.no_cache):
frappe.cache().set_value(cache_key, sitemap_options)
- return frappe._dict(sitemap_options)
+ return sitemap_options
def build_sitemap_options(path):
- sitemap_options = frappe._dict(frappe.get_doc("Website Route", path).as_dict())
- home_page = get_home_page()
+ sitemap_options = resolve_route(path)
+ if not sitemap_options:
+ raise frappe.DoesNotExistError
if sitemap_options.controller:
module = frappe.get_module(sitemap_options.controller)
@@ -35,20 +37,7 @@ def build_sitemap_options(path):
sitemap_options.doctype = sitemap_options.ref_doctype
sitemap_options.title = sitemap_options.page_title
- sitemap_options.pathname = sitemap_options.name
-
- # establish hierarchy
- sitemap_options.parents = frappe.db.sql("""select name, page_title from
- `tabWebsite Route`
- 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:
- sitemap_options.children = get_route_children(sitemap_options.pathname, home_page)
-
- if not sitemap_options.children and sitemap_options.parent_website_route \
- and sitemap_options.parent_website_route!=home_page:
- sitemap_options.children = get_route_children(sitemap_options.parent_website_route, home_page)
+ sitemap_options.pathname = path
# determine templates to be used
if not sitemap_options.base_template_path:
@@ -57,43 +46,102 @@ def build_sitemap_options(path):
return sitemap_options
-def get_route_children(pathname, home_page=None):
- if not home_page:
- home_page = get_home_page()
-
- if pathname==home_page or not pathname:
- children = frappe.db.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:
- children = frappe.db.sql("""select * from `tabWebsite Route`
- where ifnull(parent_website_route,'')=%s
- and public_read=1
- order by idx, page_title asc""", pathname, as_dict=True)
-
- if children:
- # if children are from generator and sort order is specified, then get that condition
- module = frappe.get_module(children[0].controller)
- if hasattr(module, "order_by"):
- children = frappe.db.sql("""select t1.* from
- `tabWebsite Route` t1, `tab{ref_doctype}` t2
- where ifnull(t1.parent_website_route,'')=%s
- and t1.public_read=1
- and t1.docname = t2.name
- order by {order_by}""".format(
- ref_doctype = children[0].ref_doctype,
- order_by = module.order_by),
- pathname, as_dict=True)
-
- children = [frappe.get_doc("Website Route", pathname)] + children
-
- return children
-
-def get_next(route):
- siblings = get_route_children(frappe.db.get_value("Website Route",
- route, "parent_website_route"))
- for i, r in enumerate(siblings):
- if i < len(siblings) - 1:
- if route==r.name:
- return siblings[i+1]
+def resolve_route(path):
+ route = get_page_route(path)
+ if route:
+ return route
+
+ return get_generator_route(path)
+
+def get_page_route(path):
+ found = filter(lambda p: p.page_name==path, get_pages())
+ return found[0] if found else None
+
+def get_generator_route(path):
+ def get_route(doctype, condition_field, order_by):
+ condition = []
+ if condition_field:
+ condition.append("ifnull({0}, 0)=1".format(condition_field))
+ meta = frappe.get_meta(doctype)
+
+ if meta.get_field("parent_website_route"):
+ condition.append("""concat(ifnull(parent_website_route, ""),
+ if(ifnull(parent_website_route, "")="", "", "/"), page_name) = %s""")
+ else:
+ condition.append("page_name = %s")
+
+ g = frappe.db.sql("""select name from `tab{0}` where {1}
+ order by {2}""".format(doctype, " and ".join(condition), order_by), path)
+
+ if g:
+ return frappe.get_doc(doctype, g[0][0]).get_website_route()
+
+ return process_generators(get_route)
+
+def clear_sitemap():
+ for p in get_pages():
+ delete_page_cache(p.name)
+
+ def clear_generators(doctype, condition_field, order_by):
+ meta = frappe.get_meta(doctype)
+ query = "select page_name from `tab{0}`"
+ if meta.get_field("parent_website_route"):
+ query = """select concat(ifnull(parent_website_route, ""),
+ if(ifnull(parent_website_route, "")="", "", "/"), page_name) from `tab{0}`"""
+ for route in frappe.db.sql_list(query.format(doctype)):
+ if route:
+ delete_page_cache(route)
+
+ process_generators(clear_generators)
+
+def process_generators(func):
+ for app in frappe.get_installed_apps():
+ for doctype in frappe.get_hooks("website_generators", app_name = app):
+ order_by = "name asc"
+ condition_field = None
+ controller = get_controller(doctype)
+
+ if hasattr(controller, "condition_field"):
+ condition_field = controller.condition_field
+ if hasattr(controller, "order_by"):
+ order_by = controller.order_by
+
+ val = func(doctype, condition_field, order_by)
+ if val:
+ return val
+
+def get_pages():
+ pages = frappe.cache().get_value("_website_pages")
+ if not pages:
+ pages = []
+ for app in frappe.get_installed_apps():
+ app_path = frappe.get_app_path(app)
+ path = os.path.join(app_path, "templates", "pages")
+ if os.path.exists(path):
+ for fname in os.listdir(path):
+ fname = frappe.utils.cstr(fname)
+ page_name, extn = fname.rsplit(".", 1)
+ if extn in ("html", "xml", "js", "css"):
+ route_page_name = page_name if extn=="html" else fname
+
+ # add website route
+ route = frappe._dict()
+ route.page_or_generator = "Page"
+ route.template = os.path.relpath(os.path.join(path, fname), app_path)
+ route.name = route.page_name = route_page_name
+ route.public_read = 1
+ controller_path = os.path.join(path, page_name + ".py")
+
+ if os.path.exists(controller_path):
+ controller = app + "." + os.path.relpath(controller_path,
+ app_path).replace(os.path.sep, ".")[:-3]
+ route.controller = controller
+ try:
+ route.page_title = frappe.get_attr(controller + "." + "page_title")
+ except AttributeError:
+ pass
+
+ pages.append(route)
+
+ frappe.cache().set_value("_website_pages", pages)
+ return pages
diff --git a/frappe/website/statics.py b/frappe/website/statics.py
index 0bb8779afe..e6127cfa4d 100644
--- a/frappe/website/statics.py
+++ b/frappe/website/statics.py
@@ -115,7 +115,7 @@ class sync(object):
else:
# Route does not exist, new page
page = self.get_web_page_for_insert(route, fpath, page_name,
- priority, parent_website_route)
+ priority, parent_web_page)
self.to_insert.append(page)
self.synced.append(route)
@@ -149,7 +149,7 @@ class sync(object):
"idx": priority,
"page_name": page_name,
"published": 1,
- "parent_website_route": parent_website_route
+ "parent_web_page": parent_web_page
})
page.fpath = fpath
diff --git a/frappe/website/sync.py b/frappe/website/sync.py
index 7ce728931d..1412994e4a 100644
--- a/frappe/website/sync.py
+++ b/frappe/website/sync.py
@@ -11,126 +11,98 @@ import statics, render
all_routes = None
def sync(app=None, verbose=False):
- global all_routes
- if app:
- apps = [app]
- else:
- apps = frappe.get_installed_apps()
-
render.clear_cache()
- all_routes = frappe.db.sql_list("select name from `tabWebsite Route`")
-
- # pages
- pages = []
- for app in apps:
- pages += get_sync_pages(app)
- sync_pages(pages)
-
- # sync statics (make generators)
- statics_sync = statics.sync(verbose=verbose)
- statics_sync.start()
-
- # generators
- generators = []
- for app in apps:
- generators += get_sync_generators(app)
- sync_generators(generators)
-
- # delete remaining routes
- for r in all_routes:
- frappe.delete_doc("Website Route", r, force=True)
-
-def sync_pages(routes):
- global all_routes
- l = len(routes)
- if l:
- for i, r in enumerate(routes):
- r.autoname()
- if frappe.db.exists("Website Route", r.name):
- route = frappe.get_doc("Website Route", r.name)
- for key in ("page_title", "controller", "template"):
- route.set(key, r.get(key))
- route.save(ignore_permissions=True)
- else:
- r.insert(ignore_permissions=True)
-
- if r.name in all_routes:
- all_routes.remove(r.name)
- update_progress_bar("Updating Pages", i, l)
-
- print ""
-
-def sync_generators(generators):
- global all_routes
- l = len(generators)
- if l:
- frappe.flags.in_sync_website = True
- for i, g in enumerate(generators):
- doc = frappe.get_doc(g[0], g[1])
- doc.update_sitemap()
- route = doc.get_route()
- if route in all_routes:
- all_routes.remove(route)
- update_progress_bar("Updating Generators", i, l)
- sys.stdout.flush()
-
- frappe.flags.in_sync_website = False
- rebuild_tree("Website Route", "parent_website_route")
-
- # HACK! update public_read, public_write
- for name in frappe.db.sql_list("""select name from `tabWebsite Route` where ifnull(parent_website_route, '')!=''
- order by lft"""):
- route = frappe.get_doc("Website Route", name)
- route.make_private_if_parent_is_private()
- route.db_update()
-
- print ""
-
-def get_sync_pages(app):
- app_path = frappe.get_app_path(app)
- pages = []
-
- path = os.path.join(app_path, "templates", "pages")
- if os.path.exists(path):
- for fname in os.listdir(path):
- fname = frappe.utils.cstr(fname)
- page_name, extn = fname.rsplit(".", 1)
- if extn in ("html", "xml", "js", "css"):
- route_page_name = page_name if extn=="html" else fname
-
- # add website route
- route = frappe.new_doc("Website Route")
- route.page_or_generator = "Page"
- route.template = os.path.relpath(os.path.join(path, fname), app_path)
- route.page_name = route_page_name
- route.public_read = 1
- controller_path = os.path.join(path, page_name + ".py")
-
- if os.path.exists(controller_path):
- controller = app + "." + os.path.relpath(controller_path,
- app_path).replace(os.path.sep, ".")[:-3]
- route.controller = controller
- try:
- route.page_title = frappe.get_attr(controller + "." + "page_title")
- except AttributeError:
- pass
-
- pages.append(route)
-
- return pages
-
-def get_sync_generators(app):
- generators = []
- for doctype in frappe.get_hooks("website_generators", app_name = app):
- condition, order_by = "", "name asc"
- module = load_doctype_module(doctype)
- if hasattr(module, "condition_field"):
- condition = " where ifnull({0}, 0)=1 ".format(module.condition_field)
- if hasattr(module, "order_by"):
- order_by = module.order_by
- for name in frappe.db.sql_list("select name from `tab{0}` {1} order by {2}".format(doctype,
- condition, order_by)):
- generators.append((doctype, name))
-
- return generators
+# def sync_pages(routes):
+# global all_routes
+# l = len(routes)
+# if l:
+# for i, r in enumerate(routes):
+# r.autoname()
+# if frappe.db.exists("Website Route", r.name):
+# route = frappe.get_doc("Website Route", r.name)
+# for key in ("page_title", "controller", "template"):
+# route.set(key, r.get(key))
+# route.save(ignore_permissions=True)
+# else:
+# r.insert(ignore_permissions=True)
+#
+# if r.name in all_routes:
+# all_routes.remove(r.name)
+# update_progress_bar("Updating Pages", i, l)
+#
+# print ""
+#
+# def sync_generators(generators):
+# global all_routes
+# l = len(generators)
+# if l:
+# frappe.flags.in_sync_website = True
+# for i, g in enumerate(generators):
+# doc = frappe.get_doc(g[0], g[1])
+# doc.update_sitemap()
+# route = doc.get_route()
+# if route in all_routes:
+# all_routes.remove(route)
+# update_progress_bar("Updating Generators", i, l)
+# sys.stdout.flush()
+#
+# frappe.flags.in_sync_website = False
+# rebuild_tree("Website Route", "parent_website_route")
+#
+# # HACK! update public_read, public_write
+# for name in frappe.db.sql_list("""select name from `tabWebsite Route` where ifnull(parent_website_route, '')!=''
+# order by lft"""):
+# route = frappe.get_doc("Website Route", name)
+# route.make_private_if_parent_is_private()
+# route.db_update()
+#
+# print ""
+#
+# def get_sync_pages(app):
+# app_path = frappe.get_app_path(app)
+# pages = []
+#
+# path = os.path.join(app_path, "templates", "pages")
+# if os.path.exists(path):
+# for fname in os.listdir(path):
+# fname = frappe.utils.cstr(fname)
+# page_name, extn = fname.rsplit(".", 1)
+# if extn in ("html", "xml", "js", "css"):
+# route_page_name = page_name if extn=="html" else fname
+#
+# # add website route
+# route = frappe.new_doc("Website Route")
+# route.page_or_generator = "Page"
+# route.template = os.path.relpath(os.path.join(path, fname), app_path)
+# route.page_name = route_page_name
+# route.public_read = 1
+# controller_path = os.path.join(path, page_name + ".py")
+#
+# if os.path.exists(controller_path):
+# controller = app + "." + os.path.relpath(controller_path,
+# app_path).replace(os.path.sep, ".")[:-3]
+# route.controller = controller
+# try:
+# route.page_title = frappe.get_attr(controller + "." + "page_title")
+# except AttributeError:
+# pass
+#
+# pages.append(route)
+#
+# return pages
+#
+# def get_sync_generators(app):
+# generators = []
+# for doctype in frappe.get_hooks("website_generators", app_name = app):
+# condition, order_by = "", "name asc"
+# module = load_doctype_module(doctype)
+# if hasattr(module, "condition_field"):
+# condition = " where ifnull({0}, 0)=1 ".format(module.condition_field)
+# if hasattr(module, "order_by"):
+# order_by = module.order_by
+# for name in frappe.db.sql_list("select name from `tab{0}` {1} order by {2}".format(doctype,
+# condition, order_by)):
+# generators.append((doctype, name))
+#
+# return generators
diff --git a/frappe/website/template.py b/frappe/website/template.py
index 2e1ac78f8e..da51af4c6d 100644
--- a/frappe/website/template.py
+++ b/frappe/website/template.py
@@ -10,8 +10,6 @@ from jinja2.utils import concat
from jinja2 import meta
import re
-from sitemap import get_next
-
def render_blocks(context):
"""returns a dict of block name and its rendered content"""
@@ -66,7 +64,7 @@ def render_blocks(context):
out["content"] = out["content"].replace("{index}", html)
if "{next}" in out.get("content", ""):
- next_item = get_next(context["pathname"])
+ next_item = context.get_next()
if next_item:
if next_item.name[0]!="/": next_item.name = "/" + next_item.name
html = '''
diff --git a/frappe/website/utils.py b/frappe/website/utils.py
index 8542eaa471..c2270c9389 100644
--- a/frappe/website/utils.py
+++ b/frappe/website/utils.py
@@ -4,6 +4,14 @@
from __future__ import unicode_literals
import frappe, re
+def delete_page_cache(path):
+ if not path:
+ path = ""
+ cache = frappe.cache()
+ cache.delete_value("page:" + path)
+ cache.delete_value("page_context:" + path)
+ cache.delete_value("sitemap_options:" + path)
+
def scrub_relative_urls(html):
"""prepend a slash before a relative url"""
html = re.sub("""(src|href)[^\w'"]*['"](?!http|ftp|/|#|%|{)([^'" >]+)['"]""", '\g<1> = "/\g<2>"', html)
diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py
index 0b49812fdb..cfcc1fd734 100644
--- a/frappe/website/website_generator.py
+++ b/frappe/website/website_generator.py
@@ -5,13 +5,14 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.model.naming import append_number_if_name_exists
-from frappe.website.utils import cleanup_page_name
+from frappe.website.utils import cleanup_page_name, get_home_page
+from frappe.website.render import clear_cache
from frappe.utils import now
-from frappe.modules import get_module_name, load_doctype_module
-
-from frappe.website.doctype.website_route.website_route import remove_sitemap
+from frappe.modules import get_module_name
+from frappe.website.sitemap import get_page_route
class WebsiteGenerator(Document):
+ page_title_field = "name"
def autoname(self):
self.name = self.get_page_name()
append_number_if_name_exists(self)
@@ -19,100 +20,95 @@ class WebsiteGenerator(Document):
def onload(self):
self.get("__onload").website_route = self.get_route()
- def get_parent_website_route(self):
- return self.get("parent_website_route", "")
-
def validate(self):
- if self.is_condition_field_enabled() and self.meta.get_field("page_name") and not self.page_name:
+ self.set_parent_website_route()
+ if self.website_published() and self.meta.get_field("page_name") and not self.page_name:
self.page_name = self.get_page_name()
+ self.update_routes_of_descendants()
def on_update(self):
- self.update_sitemap()
+ clear_cache(self.get_route())
if getattr(self, "save_versions", False):
frappe.add_version(self)
- def get_route(self):
- parent = self.get_parent_website_route()
- return ((parent + "/") if parent else "") + self.get_page_name()
+ def get_route(self, doc = None):
+ if not self.website_published():
+ return None
+
+ self.get_page_name()
+ return make_route(self)
+
+ def get_page_name(self):
+ return self.get_or_make_page_name()
+
+ def get_or_make_page_name(self):
+ page_name = self.get("page_name")
+ if not page_name:
+ page_name = cleanup_page_name(self.get(self.page_title_field))
+ if self.is_new():
+ self.set("page_name", page_name)
- def get_route_docname(self, name=None):
- return frappe.db.get_value("Website Route",
- {"ref_doctype":self.doctype, "docname": name or self.name})
+ return page_name
+
+ def before_rename(self, oldname, name, merge):
+ self.old_route = self.get_route()
+ clear_cache(self.get_route())
def after_rename(self, olddn, newdn, merge):
- if self.is_condition_field_enabled():
- self.update_route(self.get_route_docname())
+ self.update_routes_of_descendants(self.old_route)
+ clear_cache(self.get_route())
def on_trash(self):
- remove_sitemap(ref_doctype=self.doctype, docname=self.name)
+ clear_cache(self.get_route())
- def is_condition_field_enabled(self):
- self.controller_module = load_doctype_module(self.doctype)
- if hasattr(self.controller_module, "condition_field"):
- return self.get(self.controller_module.condition_field) and True or False
+ def website_published(self):
+ if hasattr(self, "condition_field"):
+ return self.get(self.condition_field) and True or False
else:
return True
- def update_sitemap(self):
- # update route of all descendants
- route_docname = self.get_route_docname()
-
- if not self.is_condition_field_enabled():
- frappe.delete_doc("Website Route", route_docname, ignore_permissions=True)
- return
-
- if route_docname:
- self.update_route(route_docname)
- else:
- self.insert_route()
-
- def update_route(self, route_docname):
- route = frappe.get_doc("Website Route", route_docname)
- if self.get_route() != route_docname:
- route.rename(self.get_page_name(), self.get_parent_website_route())
-
- if self.is_changed(route):
- route.idx = self.idx
- route.page_title = self.get_page_title()
- self.update_permissions(route)
- route.save(ignore_permissions=True)
- else:
- route.clear_cache()
+ def set_parent_website_route(self):
+ if hasattr(self, "parent_website_route_field"):
+ field = self.meta.get_field(self.parent_website_route_field)
+ self.parent_website_route = frappe.get_doc(field.options,
+ self.get(self.parent_website_route_field)).get_route()
- def is_changed(self, route):
- if route.idx != self.idx or route.page_title != self.get_page_title():
- return True
- if self.meta.get_field("public_read"):
- if route.public_read != self.public_read \
- or route.public_write != self.public_write:
- return True
+ def update_routes_of_descendants(self, old_route = None):
+ if not self.is_new():
+ if not old_route:
+ old_route = frappe.get_doc(self.doctype, self.name).get_route()
- return False
+ if old_route != self.get_route():
+ frappe.db.sql("""update `tab{0}` set
+ parent_website_route = replace(parent_website_route, %s, %s)
+ where parent_website_route like %s""".format(self.doctype),
+ (old_route, self.get_route(), old_route + "%"))
- def insert_route(self):
+ def get_website_route(self):
if self.modified:
# for sitemap.xml
lastmod = frappe.utils.get_datetime(self.modified).strftime("%Y-%m-%d")
else:
lastmod = now()
- route = frappe.new_doc("Website Route")
+ route = frappe._dict()
route.update({
+ "doc": self,
"page_or_generator": "Generator",
"ref_doctype":self.doctype,
"idx": self.idx,
"docname": self.name,
"page_name": self.get_page_name(),
"controller": get_module_name(self.doctype, self.meta.module),
- "template": self.controller_module.template,
+ "template": self.template,
"lastmod": lastmod,
- "parent_website_route": self.get_parent_website_route(),
- "page_title": self.get_page_title()
+ "parent_website_route": self.get("parent_website_route", ""),
+ "page_title": self.get(self.page_title_field)
})
self.update_permissions(route)
- route.ignore_links = True
- route.insert(ignore_permissions=True)
+
+ return route
def update_permissions(self, route):
if self.meta.get_field("public_read"):
@@ -121,20 +117,78 @@ class WebsiteGenerator(Document):
else:
route.public_read = 1
- def get_page_name(self):
- return self.get_or_make_page_name()
-
- def get_page_name_field(self):
- return self.page_name_field if hasattr(self, "page_name_field") else "page_name"
+ def get_parents(self):
+ parents = []
+ parent = self
+ while parent:
+ _parent_field = getattr(parent, "parent_website_route_field", None)
+ _parent_val = parent.get(_parent_field) if _parent_field else None
+ if _parent_val:
+ df = parent.meta.get_field(_parent_field)
+ parent_doc = frappe.get_doc(df.options, _parent_val)
+
+ if not parent_doc.website_published():
+ break
+
+ if parent_doc:
+ parent_info = frappe._dict(name = parent_doc.get_route(),
+ title= parent_doc.get(getattr(parent_doc, "page_title_field", "name")))
+ else:
+ parent_info = frappe._dict(name=self.parent_website_route,
+ title=self.parent_website_route.replace("_", " ").title())
+
+ if parent_info.name in [p.name for p in parents]:
+ raise frappe.ValidationError, "Recursion in parent link"
+
+ parents.append(parent_info)
+ parent = parent_doc
+ else:
+ # parent route is a page e.g. "blog"
+ if parent.get("parent_website_route"):
+ page_route = get_page_route(parent.parent_website_route)
+ if page_route:
+ parents.append(frappe._dict(name = page_route.name,
+ title=page_route.page_title))
+ parent = None
+
+ parents.reverse()
+ return parents
+
+ def get_children(self):
+ if self.get_route()==get_home_page():
+ return frappe.db.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)
+
+ if self.meta.get_field("parent_website_route"):
+ children = frappe.db.sql("""select name, page_name,
+ parent_website_route, {title_field} as title from `tab{doctype}`
+ where ifnull(parent_website_route,'')=%s
+ order by {order_by}""".format(
+ doctype = self.doctype,
+ title_field = getattr(self, "page_title_field", "name"),
+ order_by = getattr(self, "order_by", "page_name asc")),
+ self.get_route(), as_dict=True, debug=1)
+
+ for c in children:
+ c.name = make_route(c.name)
+ else:
+ return []
+
+ def get_next(self):
+ if self.meta.get_field("parent_website_route") and self.parent_website_route:
+ route = self.get_route()
+ siblings = frappe.get_doc(self.doctype,
+ self.parent_website_route).get_children()
+ for i, r in enumerate(siblings):
+ if i < len(siblings) - 1:
+ if route==r.name:
+ return siblings[i+1]
+ else:
+ return frappe._dict()
- def get_or_make_page_name(self):
- page_name = self.get(self.get_page_name_field())
- if not page_name:
- page_name = cleanup_page_name(self.get_page_title())
- if self.is_new():
- self.set(self.get_page_name_field(), page_name)
+def make_route(doc):
+ parent = doc.get("parent_website_route", "")
+ return ((parent + "/") if parent else "") + doc.page_name
- return page_name
- def get_page_title(self):
- return self.get("title") or (self.name.replace("-", " ").replace("_", " ").title())