Browse Source

remove website route, wip

version-14
Rushabh Mehta 11 years ago
parent
commit
f6bd8bf192
20 changed files with 464 additions and 393 deletions
  1. +1
    -1
      frappe/__init__.py
  2. +1
    -0
      frappe/patches.txt
  3. +1
    -0
      frappe/templates/includes/breadcrumbs.html
  4. +3
    -11
      frappe/templates/includes/sidebar.html
  5. +5
    -0
      frappe/templates/pages/blog.py
  6. +9
    -9
      frappe/website/context.py
  7. +60
    -60
      frappe/website/doctype/blog_category/blog_category.json
  8. +10
    -9
      frappe/website/doctype/blog_category/blog_category.py
  9. +3
    -3
      frappe/website/doctype/blog_post/blog_post.json
  10. +12
    -16
      frappe/website/doctype/blog_post/blog_post.py
  11. +10
    -2
      frappe/website/doctype/web_page/web_page.json
  12. +2
    -2
      frappe/website/doctype/web_page/web_page.py
  13. +3
    -6
      frappe/website/doctype/website_group/website_group.py
  14. +3
    -13
      frappe/website/render.py
  15. +107
    -59
      frappe/website/sitemap.py
  16. +2
    -2
      frappe/website/statics.py
  17. +93
    -121
      frappe/website/sync.py
  18. +1
    -3
      frappe/website/template.py
  19. +8
    -0
      frappe/website/utils.py
  20. +130
    -76
      frappe/website/website_generator.py

+ 1
- 1
frappe/__init__.py View File

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


+ 1
- 0
frappe/patches.txt View File

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

+ 1
- 0
frappe/templates/includes/breadcrumbs.html View File

@@ -1,3 +1,4 @@
{% set parents = doc.get_parents() if doc else [] %}
<ul class="breadcrumb">
{% if parents|length > 0 %}
{% for parent in parents %}


+ 3
- 11
frappe/templates/includes/sidebar.html View File

@@ -1,18 +1,10 @@
<div class="sidebar-exists"></div>
{% set children = doc.get_children() if doc else (get_children() if get_children else []) %}
{% if children -%}
{%- for child in children -%}
<div class="sidebar-item">
{% set is_parent = parents and child.name == parents[-1].name or (loop.first and child.name==pathname) %}
{% set has_children = (child.lft != None) and (child.rgt - child.lft != 1) and (not loop.first) %}
<i class="{% if has_children %} icon-chevron-right {% endif %} icon-fixed-width"
style="color: #ddd; {% if is_parent %} margin-left: -30px;
{% else %} margin-left: -18px;
{% endif %}"></i>
<a href="{{ child.name }}" class="no-decoration {% if child.name == pathname %}active{% endif %}">
{{ child.page_title or child.name.replace("_", " ").title() }}
{% if not child.public_read %}
(<i class="icon-fixed-width icon-lock"></i>)
{% endif %}
<a href="{{ child.name }}" class="no-decoration {% if pathname.startswith(child.name) %}active{% endif %}">
{{ child.title or child.page_title or child.name.replace("_", " ").title() }}
</a>
</div>
{%- endfor -%}


+ 5
- 0
frappe/templates/pages/blog.py View File

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

+ 9
- 9
frappe/website/context.py View File

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



+ 60
- 60
frappe/website/doctype/blog_category/blog_category.json View File

@@ -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"
}
]
}
}

+ 10
- 9
frappe/website/doctype/blog_category/blog_category.py View File

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

+ 3
- 3
frappe/website/doctype/blog_post/blog_post.json View File

@@ -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",


+ 12
- 16
frappe/website/doctype/blog_post/blog_post.py View File

@@ -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}


+ 10
- 2
frappe/website/doctype/web_page/web_page.json View File

@@ -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",


+ 2
- 2
frappe/website/doctype/web_page/web_page.py View File

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


+ 3
- 6
frappe/website/doctype/website_group/website_group.py View File

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


+ 3
- 13
frappe/website/render.py View File

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

+ 107
- 59
frappe/website/sitemap.py View File

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

+ 2
- 2
frappe/website/statics.py View File

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


+ 93
- 121
frappe/website/sync.py View File

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

+ 1
- 3
frappe/website/template.py View File

@@ -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 = '''<p><br><a href="{name}" class="btn btn-primary">


+ 8
- 0
frappe/website/utils.py View File

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


+ 130
- 76
frappe/website/website_generator.py View File

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

Loading…
Cancel
Save