@@ -568,9 +568,10 @@ def clear_all_sessions(): | |||
@cmd | |||
def build_website(verbose=False): | |||
import frappe.website.sync | |||
from frappe.website import render, statics | |||
frappe.connect() | |||
frappe.website.sync.sync(verbose=verbose) | |||
render.clear_cache() | |||
statics.sync(verbose=verbose).start() | |||
frappe.db.commit() | |||
frappe.destroy() | |||
@@ -19,7 +19,7 @@ class Comment(Document): | |||
self.update_comment_in_doc() | |||
def update_comment_in_doc(self): | |||
if self.comment_doctype and self.comment_docname and self.comment: | |||
if self.comment_doctype and self.comment_docname and self.comment and self.comment_type=="Comment": | |||
try: | |||
_comments = self.get_comments_from_parent() | |||
updated = False | |||
@@ -67,9 +67,6 @@ doc_events = { | |||
], | |||
"on_trash": "frappe.core.doctype.notification_count.notification_count.clear_doctype_notifications" | |||
}, | |||
"User Vote": { | |||
"after_insert": "frappe.website.doctype.website_group.website_group.clear_cache_on_doc_event" | |||
}, | |||
"Website Route Permission": { | |||
"on_update": "frappe.website.doctype.website_group.website_group.clear_cache_on_doc_event" | |||
} | |||
@@ -51,4 +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) | |||
frappe.patches.v4_2.refactor_website_routing |
@@ -0,0 +1,6 @@ | |||
import frappe | |||
def execute(): | |||
# clear all static web pages | |||
frappe.delete_doc("DocType", "Website Route", force=1) | |||
frappe.db.sql("drop table `tabWebsite Route`") |
@@ -12,6 +12,7 @@ | |||
"public/js/lib/nprogress.js", | |||
"public/js/frappe/translate.js", | |||
"public/js/frappe/misc/pretty_date.js", | |||
"public/js/lib/moment/moment.min.js", | |||
"website/js/website.js", | |||
"website/js/website_group.js" | |||
], | |||
@@ -263,8 +263,8 @@ _f.Frm.prototype.new_doc = function(doctype, field) { | |||
_f.Frm.prototype.set_read_only = function() { | |||
var perm = []; | |||
$.each(frappe.perm.get_perm(cur_frm.doc.doctype), function(i, permlevel) { | |||
if(permlevel!=null) perm[permlevel] = {read:1}; | |||
$.each(frappe.perm.get_perm(cur_frm.doc.doctype), function(i, p) { | |||
perm[p.permlevel || 0] = {read:1}; | |||
}); | |||
cur_frm.perm = perm; | |||
} | |||
@@ -43,7 +43,8 @@ | |||
{% if child.class %} class="{{ child.class }}" {% endif %}> | |||
{%- if child.url -%} | |||
<a href="{{ child.url }}" {{ child.target or '' }}> | |||
<a href="{{ child.url }}" {{ child.target or '' }} | |||
rel="nofollow"> | |||
{%- if child.icon -%} | |||
<i class="icon-fixed-width {{ child.icon }}"></i> | |||
{%- endif -%} | |||
@@ -1,5 +1,4 @@ | |||
<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"> | |||
@@ -7,7 +7,7 @@ | |||
<div class="row"> | |||
<div class="col-xs-1 text-right" style="padding-right: 0px;"><b>{{ loop.index }}.</b></div> | |||
<div class="col-xs-11"> | |||
<a href="/{{ item.name }}">{{ item.page_title }}</a> | |||
<a href="/{{ item.name }}">{{ item.title }}</a> | |||
</div> | |||
</div> | |||
</li> | |||
@@ -6,7 +6,8 @@ import frappe | |||
page_title = "Blog" | |||
def get_context(context): | |||
return frappe.get_doc("Blog Settings", "Blog Settings").as_dict() | |||
context.update(frappe.get_doc("Blog Settings", "Blog Settings").as_dict()) | |||
context.children = get_children() | |||
def get_children(): | |||
return frappe.db.sql("""select concat("blog/", page_name) as name, | |||
@@ -5,7 +5,8 @@ from __future__ import unicode_literals | |||
import urllib | |||
import frappe | |||
from frappe.utils import get_request_site_address | |||
from frappe.utils import get_request_site_address, get_datetime | |||
from frappe.website.sitemap import get_pages, process_generators | |||
no_cache = 1 | |||
no_sitemap = 1 | |||
@@ -15,14 +16,32 @@ def get_context(context): | |||
"""generate the sitemap XML""" | |||
host = get_request_site_address() | |||
links = [] | |||
for l in frappe.db.sql("""select page_name, lastmod, controller | |||
from `tabWebsite Route`""", | |||
as_dict=True): | |||
module = frappe.get_module(l.controller) if l.controller else None | |||
if not getattr(module, "no_sitemap", False): | |||
for page in get_pages(): | |||
if not page.no_sitemap: | |||
links.append({ | |||
"loc": urllib.basejoin(host, urllib.quote(l.page_name.encode("utf-8"))), | |||
"lastmod": l.lastmod | |||
"loc": urllib.basejoin(host, urllib.quote(page.name.encode("utf-8"))), | |||
"lastmod": "2014-01-01" | |||
}) | |||
def add_links(doctype, condition_field, order_by): | |||
meta = frappe.get_meta(doctype) | |||
page_name = "page_name" | |||
condition = "" | |||
if meta.get_field("parent_website_route"): | |||
page_name = """concat(ifnull(parent_website_route, ""), | |||
if(ifnull(parent_website_route, "")="", "", "/"), page_name)""" | |||
if condition_field: | |||
condition ="where ifnull({0}, 0)=1".format(condition_field) | |||
for route in frappe.db.sql("select {0}, modified from `tab{1}` {2}".format(page_name, | |||
doctype, condition)): | |||
if route[0]: | |||
links.append({ | |||
"loc": urllib.basejoin(host, urllib.quote(route[0].encode("utf-8"))), | |||
"lastmod": get_datetime(route[1]).strftime("%Y-%m-%d") | |||
}) | |||
process_generators(add_links) | |||
return {"links":links} |
@@ -12,9 +12,8 @@ def get_post_list_html(group, view, limit_start=0, limit_length=20): | |||
# verify permission for paging | |||
if frappe.local.form_dict.cmd == "get_post_list_html": | |||
pathname = frappe.db.get_value("Website Route", | |||
{"ref_doctype": "Website Group", "docname": group}) | |||
access = get_access(pathname) | |||
doc = frappe.get_doc("Website Group", group) | |||
access = get_access(doc, doc.get_route()) | |||
if not access.get("read"): | |||
return frappe.PermissionError | |||
@@ -57,7 +56,7 @@ def get_post_list_html(group, view, limit_start=0, limit_length=20): | |||
from `tabPost` p, `tabUser` pr | |||
where p.website_group = %s and pr.name = p.owner and ifnull(p.parent_post, '')='' | |||
{conditions} order by {order_by} limit %s, %s""".format(conditions=conditions, order_by=order_by), | |||
tuple(values), as_dict=True, debug=True) | |||
tuple(values), as_dict=True) | |||
context = { "posts": posts, "limit_start": limit_start, "view": get_views(group_type)[view] } | |||
@@ -7,7 +7,6 @@ from frappe import _ | |||
from frappe.utils import get_fullname | |||
from frappe.website.permissions import get_access | |||
from frappe.utils.file_manager import save_file | |||
from frappe.website.doctype.website_group.website_group import get_pathname | |||
def get_post_context(context): | |||
post = frappe.get_doc("Post", frappe.form_dict.name) | |||
@@ -58,7 +57,8 @@ def clear_post_cache(post=None): | |||
def add_post(group, content, picture, picture_name, title=None, parent_post=None, | |||
assigned_to=None, status=None, event_datetime=None): | |||
access = get_access(get_pathname(group)) | |||
doc = frappe.get_doc("Website Group", group) | |||
access = get_access(doc, doc.get_route()) | |||
if not access.get("write"): | |||
raise frappe.PermissionError | |||
@@ -100,7 +100,8 @@ def save_post(post, content, picture=None, picture_name=None, title=None, | |||
assigned_to=None, status=None, event_datetime=None): | |||
post = frappe.get_doc("Post", post) | |||
access = get_access(get_pathname(post.website_group)) | |||
group = frappe.get_doc("Website Group", post.website_group) | |||
access = get_access(group, group.get_route()) | |||
if not access.get("write"): | |||
raise frappe.PermissionError | |||
@@ -3,14 +3,14 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.permissions import get_access, clear_permissions | |||
from frappe.website.doctype.website_group.website_group import get_pathname | |||
from frappe.website.permissions import get_access | |||
from frappe.utils.email_lib.bulk import send | |||
@frappe.whitelist() | |||
def suggest_user(term, group): | |||
pathname = get_pathname(group) | |||
if not get_access(pathname).get("admin"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
users = frappe.db.sql("""select pr.name, pr.first_name, pr.last_name, | |||
@@ -32,8 +32,9 @@ def suggest_user(term, group): | |||
@frappe.whitelist() | |||
def add_sitemap_permission(group, user): | |||
pathname = get_pathname(group) | |||
if not get_access(pathname).get("admin"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
permission = frappe.get_doc({ | |||
@@ -54,11 +55,13 @@ def add_sitemap_permission(group, user): | |||
@frappe.whitelist() | |||
def update_permission(group, user, perm, value): | |||
pathname = get_pathname(group) | |||
if not get_access(pathname).get("admin"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
permission = frappe.get_doc("Website Route Permission", {"website_route": pathname, "user": user}) | |||
permission = frappe.get_doc("Website Route Permission", | |||
{"website_route": pathname, "user": user, "reference": group}) | |||
permission.set(perm, int(value)) | |||
permission.save(ignore_permissions=True) | |||
@@ -76,7 +79,9 @@ def update_permission(group, user, perm, value): | |||
@frappe.whitelist() | |||
def update_description(group, description): | |||
if not get_access(get_pathname(group)).get("admin"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
group = frappe.get_doc("Website Group", group) | |||
@@ -85,7 +90,9 @@ def update_description(group, description): | |||
@frappe.whitelist() | |||
def add_website_group(group, new_group, public_read, public_write, group_type="Forum"): | |||
if not get_access(get_pathname(group)).get("admin"): | |||
doc = frappe.get_doc("Website Group", group) | |||
pathname = doc.get_route() | |||
if not get_access(doc, pathname).get("admin"): | |||
raise frappe.PermissionError | |||
parent_website_route = frappe.db.get_value("Website Route", | |||
@@ -4,12 +4,11 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
# frequently used imports (used by other modules) | |||
from frappe.website.doctype.website_settings.website_settings import get_website_settings | |||
from frappe.website.template import render_blocks | |||
from frappe.website.sitemap import get_sitemap_options | |||
from frappe.website.utils import can_cache | |||
from frappe.website.permissions import get_access | |||
def get_context(path): | |||
context = None | |||
@@ -29,7 +28,10 @@ def get_context(path): | |||
context = get_sitemap_options(path) | |||
# permission may be required for rendering | |||
context["access"] = frappe._dict({"public_read":1, "public_write":1}) | |||
if context.doc and context.doc.doctype=="Website Group": | |||
context["access"] = get_access(context.doc, context.pathname) | |||
else: | |||
context["access"] = frappe._dict({"public_read":1, "public_write":1}) | |||
context = build_context(context) | |||
add_data_path(context) | |||
@@ -242,7 +242,9 @@ fieldset { | |||
} | |||
.sidebar-item { | |||
margin: 20px auto; | |||
background-color: #f7f7f7; | |||
margin: 0 -15px; | |||
padding: 5px 10px; | |||
color: #999; | |||
font-size: 85%; | |||
} | |||
@@ -72,10 +72,9 @@ class BlogPost(WebsiteGenerator): | |||
context.comment_list = get_comment_list(self.doctype, self.name) | |||
return context | |||
context.children = get_children() | |||
def get_children(self): | |||
return get_children() | |||
return context | |||
def clear_blog_cache(): | |||
for blog in frappe.db.sql_list("""select page_name from | |||
@@ -4,19 +4,21 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.website.permissions import get_access | |||
from frappe.website.doctype.website_group.website_group import clear_cache | |||
from frappe.model.document import Document | |||
class UserVote(Document): | |||
def after_insert(self): | |||
clear_cache(self.ref_name) | |||
def validate(self): | |||
# if new | |||
if self.get("__islocal"): | |||
if frappe.db.get_value("User Vote", {"ref_doctype": self.ref_doctype, | |||
if frappe.db.get_value("User Vote", {"ref_doctype": self.ref_doctype, | |||
"ref_name": self.ref_name, "owner": frappe.session.user}): | |||
raise frappe.DuplicateEntryError | |||
def on_update(self): | |||
self.update_ref_count() | |||
@@ -27,20 +29,19 @@ class UserVote(Document): | |||
count = frappe.db.sql("""select count(*) from `tabUser Vote` where ref_doctype=%s and ref_name=%s""", | |||
(self.ref_doctype, self.ref_name))[0][0] | |||
frappe.db.set_value(self.ref_doctype, self.ref_name, "upvotes", count + cnt) | |||
def on_doctype_update(): | |||
frappe.db.add_index("User Vote", ["ref_doctype", "ref_name"]) | |||
# don't allow guest to give vote | |||
@frappe.whitelist() | |||
def set_vote(ref_doctype, ref_name): | |||
website_group = frappe.db.get_value(ref_doctype, ref_name, "website_group") | |||
pathname = frappe.db.get_value("Website Route", {"ref_doctype": "Website Group", | |||
"docname": website_group}) | |||
if not get_access(pathname).get("read"): | |||
website_group_name = frappe.db.get_value(ref_doctype, ref_name, "website_group") | |||
group = frappe.get_doc("Website Group", website_group_name) | |||
if not get_access(group, group.get_route()).get("read"): | |||
raise frappe.PermissionError | |||
try: | |||
user_vote = frappe.get_doc({ | |||
"doctype": "User Vote", | |||
@@ -19,6 +19,9 @@ $.extend(cur_frm.cscript, { | |||
refresh: function(doc) { | |||
cur_frm.cscript.layout(doc); | |||
cur_frm.set_intro(""); | |||
if(cur_frm.doc.template_path) { | |||
cur_frm.set_read_only(); | |||
} | |||
if (!doc.__islocal && doc.published) { | |||
cur_frm.set_intro(__("Published on website at: {0}", | |||
[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>', doc.__onload)])); | |||
@@ -40,8 +40,8 @@ | |||
"fieldname": "parent_website_route", | |||
"fieldtype": "Read Only", | |||
"hidden": 1, | |||
"label": "Parent Website Page", | |||
"options": "Website Route", | |||
"label": "Parent Website Route", | |||
"options": "", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
@@ -57,6 +57,13 @@ | |||
"label": "Priority", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "template_path", | |||
"fieldtype": "Data", | |||
"label": "Template Path", | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "cb1", | |||
"fieldtype": "Column Break", | |||
@@ -165,7 +172,7 @@ | |||
"icon": "icon-file-alt", | |||
"idx": 1, | |||
"max_attachments": 20, | |||
"modified": "2014-08-18 08:10:03.220821", | |||
"modified": "2014-08-19 02:19:05.426465", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Web Page", | |||
@@ -2,17 +2,25 @@ | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe, re | |||
import frappe, re, os | |||
import requests, requests.exceptions | |||
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 | |||
from markdown2 import markdown | |||
class WebPage(WebsiteGenerator): | |||
save_versions = True | |||
template = "templates/generators/web_page.html" | |||
condition_field = "published" | |||
page_title_field = "title" | |||
parent_website_route_field = "parent_web_page" | |||
def validate(self): | |||
if self.template_path and not getattr(self, "from_website_sync"): | |||
frappe.throw(frappe._("Cannot edit templated page")) | |||
super(WebPage, self).validate() | |||
def get_context(self, context): | |||
# if static page, get static content | |||
if context.slideshow: | |||
@@ -21,16 +29,34 @@ class WebPage(WebsiteGenerator): | |||
if self.enable_comments: | |||
context.comment_list = get_comment_list(self.doctype, self.name) | |||
context.update({ | |||
"style": self.css or "", | |||
"script": self.javascript or "" | |||
}) | |||
if self.template_path: | |||
# load content from template | |||
context.update(get_static_content(self, self.template_path)) | |||
else: | |||
context.update({ | |||
"style": self.css or "", | |||
"script": self.javascript or "" | |||
}) | |||
self.render_dynamic(context) | |||
self.set_metatags(context) | |||
if not context.header: | |||
context.header = self.title | |||
# for sidebar | |||
context.children = self.get_children() | |||
return context | |||
def render_dynamic(self, context): | |||
# dynamic | |||
if "<!-- render-jinja -->" in self.main_section: | |||
context["main_section"] = frappe.render_template(self.main_section, | |||
{"doc": self, "frappe": frappe}) | |||
context["no_cache"] = 1 | |||
def set_metatags(self, context): | |||
context.metatags = { | |||
"name": self.title, | |||
"description": self.description or (self.main_section or "")[:150] | |||
@@ -40,11 +66,34 @@ class WebPage(WebsiteGenerator): | |||
if image: | |||
context.metatags["image"] = image | |||
if not context.header: | |||
context.header = self.title | |||
return context | |||
def get_static_content(doc, template_path): | |||
d = frappe._dict({}) | |||
with open(template_path, "r") as contentfile: | |||
content = unicode(contentfile.read(), 'utf-8') | |||
if template_path.endswith(".md"): | |||
if content: | |||
lines = content.splitlines() | |||
first_line = lines[0].strip() | |||
if first_line.startswith("# "): | |||
d.title = first_line[2:] | |||
content = "\n".join(lines[1:]) | |||
content = markdown(content) | |||
d.main_section = unicode(content.encode("utf-8"), 'utf-8') | |||
if not d.title: | |||
d.title = doc.name.replace("-", " ").replace("_", " ").title() | |||
for extn in ("js", "css"): | |||
fpath = template_path.rsplit(".", 1)[0] + "." + extn | |||
if os.path.exists(fpath): | |||
with open(fpath, "r") as f: | |||
d["css" if extn=="css" else "javascript"] = f.read() | |||
return d | |||
def check_broken_links(): | |||
cnt = 0 | |||
@@ -0,0 +1,7 @@ | |||
[ | |||
{ | |||
"doctype": "Website Group", | |||
"group_name": "_Test Website Group 1", | |||
"group_title": "_Test Website Group 1" | |||
} | |||
] |
@@ -0,0 +1,10 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# See license.txt | |||
import frappe | |||
import unittest | |||
test_records = frappe.get_test_records('Website Group') | |||
class TestWebsiteGroup(unittest.TestCase): | |||
pass |
@@ -0,0 +1,7 @@ | |||
frappe.ui.form.on("Website Group", "refresh", function(frm) { | |||
if (!frm.doc.__islocal) { | |||
cur_frm.set_intro(__("Published on website at: {0}", | |||
[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>', | |||
frm.doc.__onload)])); | |||
} | |||
}) |
@@ -1,5 +1,5 @@ | |||
{ | |||
"creation": "2014-01-29 15:57:42.000000", | |||
"creation": "2014-01-29 15:57:42", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "Master", | |||
@@ -33,13 +33,20 @@ | |||
"permlevel": 0, | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "parent_website_group", | |||
"fieldtype": "Link", | |||
"label": "Parent Website Group", | |||
"options": "Website Group", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"description": "Display in the sidebar of this Website Route node", | |||
"fieldname": "parent_website_route", | |||
"fieldtype": "Link", | |||
"fieldtype": "Read Only", | |||
"in_list_view": 0, | |||
"label": "Parent Website Page", | |||
"options": "Website Route", | |||
"label": "Parent Website Route", | |||
"options": "", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
@@ -98,11 +105,32 @@ | |||
"label": "Replies", | |||
"permlevel": 0, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "lft", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"label": "lft", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "rgt", | |||
"fieldtype": "Int", | |||
"hidden": 1, | |||
"label": "rgt", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "old_parent", | |||
"fieldtype": "Read Only", | |||
"hidden": 1, | |||
"label": "Old Parent", | |||
"permlevel": 0 | |||
} | |||
], | |||
"icon": "icon-group", | |||
"idx": 1, | |||
"modified": "2014-03-04 09:36:30.000000", | |||
"modified": "2014-08-19 14:33:40.664635", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Website Group", | |||
@@ -119,5 +147,7 @@ | |||
"role": "Website Manager", | |||
"write": 1 | |||
} | |||
] | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC" | |||
} |
@@ -6,17 +6,25 @@ import frappe | |||
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 | |||
from frappe.utils.nestedset import NestedSet | |||
class WebsiteGroup(WebsiteGenerator): | |||
page_title_field = "name" | |||
class WebsiteGroup(WebsiteGenerator, NestedSet): | |||
no_cache = True | |||
template = "templates/generators/website_group.html" | |||
parent_website_route_field = "parent_website_group" | |||
page_title_field = "group_title" | |||
def on_update(self): | |||
WebsiteGenerator.on_update(self) | |||
NestedSet.on_update(self) | |||
clear_cache(website_group=self.name) | |||
def on_trash(self): | |||
WebsiteGenerator.on_trash(self) | |||
NestedSet.on_trash(self) | |||
def after_insert(self): | |||
clear_cache(path=self.parent_website_route) | |||
clear_cache(website_group=self.name) | |||
def get_context(self, context): | |||
group, view = guess_group_view(context) | |||
@@ -57,6 +65,8 @@ def get_group_context(group, view, context): | |||
if can_cache(view.get("no_cache")): | |||
frappe.cache().set_value(cache_key, group_context) | |||
group_context.children = context.doc.get_children() | |||
return group_context | |||
def build_group_context(group, view, views, context): | |||
@@ -128,11 +138,9 @@ def has_access(access, view): | |||
else: | |||
return access.get("read") | |||
def clear_cache(path=None, website_group=None): | |||
def clear_cache(website_group=None): | |||
from frappe.templates.website_group.post import clear_post_cache | |||
if path: | |||
website_groups = [frappe.db.get_value("Website Route", path, "docname")] | |||
elif website_group: | |||
if website_group: | |||
website_groups = [website_group] | |||
else: | |||
clear_post_cache() | |||
@@ -148,13 +156,6 @@ def clear_event_cache(): | |||
for group in frappe.db.sql_list("""select name from `tabWebsite Group` where group_type='Event'"""): | |||
clear_cache(website_group=group) | |||
def clear_cache_on_doc_event(doc, method, *args, **kwargs): | |||
clear_cache(path=doc.website_route, website_group=doc.website_group) | |||
def get_pathname(group): | |||
return frappe.db.get_value("Website Route", {"ref_doctype": "Website Group", | |||
"docname": group}) | |||
views = { | |||
"Forum": { | |||
"popular": { | |||
@@ -0,0 +1,6 @@ | |||
[ | |||
{ | |||
"doctype": "Website Route Permission", | |||
"name": "_Test Website Route Permission 1" | |||
} | |||
] |
@@ -0,0 +1,10 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# See license.txt | |||
import frappe | |||
import unittest | |||
test_records = frappe.get_test_records('Website Route Permission') | |||
class TestWebsiteRoutePermission(unittest.TestCase): | |||
pass |
@@ -1,6 +1,6 @@ | |||
{ | |||
"autoname": "WSP.######", | |||
"creation": "2014-01-29 17:56:29.000000", | |||
"creation": "2014-01-29 17:56:29", | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"fields": [ | |||
@@ -44,11 +44,18 @@ | |||
"in_list_view": 1, | |||
"label": "Admin", | |||
"permlevel": 0 | |||
}, | |||
{ | |||
"fieldname": "reference", | |||
"fieldtype": "Link", | |||
"label": "reference", | |||
"options": "Website Group", | |||
"permlevel": 0 | |||
} | |||
], | |||
"icon": "icon-shield", | |||
"idx": 1, | |||
"modified": "2014-02-24 13:17:18.000000", | |||
"modified": "2014-08-19 14:55:07.186713", | |||
"modified_by": "Administrator", | |||
"module": "Website", | |||
"name": "Website Route Permission", | |||
@@ -66,5 +73,7 @@ | |||
"role": "Website Manager", | |||
"write": 1 | |||
} | |||
] | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC" | |||
} |
@@ -4,67 +4,66 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
def remove_empty_permissions(): | |||
permissions_cache_to_be_cleared = frappe.db.sql_list("""select distinct user | |||
permissions_cache_to_be_cleared = frappe.db.sql_list("""select distinct user | |||
from `tabWebsite Route Permission` | |||
where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""") | |||
frappe.db.sql("""delete from `tabWebsite Route 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, user=None): | |||
def get_access(doc, pathname, user=None): | |||
user = user or frappe.session.user | |||
key = "website_route_permissions:{}".format(user) | |||
cache = frappe.cache() | |||
permissions = cache.get_value(key) or {} | |||
if not permissions.get(sitemap_page): | |||
permissions[sitemap_page] = _get_access(sitemap_page, user) | |||
if not permissions.get(doc.name): | |||
permissions[doc.name] = _get_access(doc, pathname, user) | |||
cache.set_value(key, permissions) | |||
return permissions.get(sitemap_page) | |||
def _get_access(sitemap_page, user): | |||
lft, rgt, public_read, public_write, page_or_generator = frappe.db.get_value("Website Route", sitemap_page, | |||
["lft", "rgt", "public_read", "public_write", "page_or_generator"]) | |||
return permissions.get(doc.name) | |||
def _get_access(doc, pathname, user): | |||
read = write = admin = private_read = 0 | |||
if page_or_generator=="Generator": | |||
if not (lft and rgt): | |||
raise frappe.ValidationError("Please rebuild Website Route Tree") | |||
if user == "Guest": | |||
return { "read": public_read, "write": 0, "admin": 0 } | |||
if public_write: | |||
read = write = 1 | |||
elif public_read: | |||
read = 1 | |||
for perm in frappe.db.sql("""select wsp.`read`, wsp.`write`, wsp.`admin`, | |||
ws.lft, ws.rgt, ws.name | |||
from `tabWebsite Route Permission` wsp, `tabWebsite Route` ws | |||
where wsp.user = %s and wsp.website_route = ws.name | |||
order by lft asc""", (user,), 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 | |||
if user == "Guest": | |||
return { "read": doc.public_read, "write": 0, "admin": 0 } | |||
if doc.public_write: | |||
read = write = 1 | |||
elif doc.public_read: | |||
read = 1 | |||
for perm in frappe.db.sql("""select | |||
`tabWebsite Route Permission`.`read`, | |||
`tabWebsite Route Permission`.`write`, | |||
`tabWebsite Route Permission`.`admin`, | |||
`tabWebsite Group`.lft, | |||
`tabWebsite Group`.rgt | |||
from | |||
`tabWebsite Route Permission`, `tabWebsite Group` | |||
where | |||
`tabWebsite Route Permission`.website_route = %s and | |||
`tabWebsite Route Permission`.user = %s and | |||
`tabWebsite Route Permission`.reference = `tabWebsite Group`.name | |||
order by `tabWebsite Group`.lft asc""", (user, pathname), as_dict=True): | |||
if perm.lft <= doc.lft and perm.rgt >= doc.rgt: | |||
if not (doc.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 | |||
else: | |||
read = write = admin = private_read = 1 | |||
return { "read": read, "write": write, "admin": admin, "private_read": private_read } | |||
def clear_permissions(users=None): | |||
@@ -72,7 +71,7 @@ def clear_permissions(users=None): | |||
users = [users] | |||
elif users is None: | |||
users = frappe.db.sql_list("""select name from `tabUser`""") | |||
cache = frappe.cache() | |||
for user in users: | |||
cache.delete_value("website_route_permissions:{}".format(user)) |
@@ -4,8 +4,7 @@ | |||
from __future__ import unicode_literals | |||
import frappe, os, time, sys | |||
from frappe.utils import cint, update_progress_bar | |||
from markdown2 import markdown | |||
from frappe.utils import update_progress_bar | |||
# from frappe.website.sitemap import get_route_children, get_next | |||
def sync_statics(rebuild=False): | |||
@@ -92,164 +91,98 @@ class sync(object): | |||
if not (page_name=="index" and basepath!=self.statics_path): | |||
self.sync_file(fname, os.path.join(basepath, fname), None) | |||
def sync_file(self, fname, fpath, priority): | |||
route = os.path.relpath(fpath, self.statics_path).rsplit(".", 1)[0] | |||
def sync_file(self, fname, template_path, priority): | |||
route = os.path.relpath(template_path, self.statics_path).rsplit(".", 1)[0] | |||
if fname.rsplit(".", 1)[0]=="index" and os.path.dirname(fpath) != self.statics_path: | |||
if fname.rsplit(".", 1)[0]=="index" and \ | |||
os.path.dirname(template_path) != self.statics_path: | |||
route = os.path.dirname(route) | |||
if route in self.synced: | |||
return | |||
parent_website_route = os.path.dirname(route) | |||
page_name = os.path.basename(route) | |||
parent_web_page = os.path.basename(os.path.dirname(route)) | |||
if page_name in self.synced: | |||
return | |||
route_details = frappe.db.get_value("Website Route", route, | |||
["name", "idx", "static_file_timestamp", "docname"], as_dict=True) | |||
title = self.get_title(template_path) | |||
if not frappe.db.exists("Web Page", page_name): | |||
web_page = frappe.new_doc("Web Page") | |||
web_page.page_name = page_name | |||
web_page.parent_web_page = parent_web_page | |||
web_page.template_path = template_path | |||
web_page.title = title | |||
web_page.from_website_sync = True | |||
self.to_insert.append(web_page) | |||
if route_details: | |||
page = self.get_route_details_for_update(route_details, fpath, | |||
priority, parent_website_route) | |||
if page: | |||
self.to_update.append(page) | |||
else: | |||
# Route does not exist, new page | |||
page = self.get_web_page_for_insert(route, fpath, page_name, | |||
priority, parent_web_page) | |||
self.to_insert.append(page) | |||
web_page = frappe.get_doc("Web Page", page_name) | |||
dirty = False | |||
for key in ("parent_web_page", "title", "template_path"): | |||
if web_page.get(key) != locals().get(key): | |||
web_page.set(key, locals().get(key)) | |||
dirty = True | |||
if dirty: | |||
web_page.from_website_sync = True | |||
self.to_update.append(web_page) | |||
self.synced.append(page_name) | |||
def get_title(self, fpath): | |||
title = os.path.basename(fpath).rsplit(".", 1)[0] | |||
if title =="index": | |||
title = os.path.basename(os.path.dirname(fpath)) | |||
title = title.replace("-", " ").replace("_", " ").title() | |||
with open(fpath, "r") as f: | |||
content = unicode(f.read().strip(), "utf-8") | |||
if content.startswith("# "): | |||
title = content.splitlines()[0][2:] | |||
self.synced.append(route) | |||
if "<!-- title:" in content: | |||
title = content.split("<!-- title:", 1)[1].split("-->", 1)[0].strip() | |||
return title | |||
def insert_and_update(self): | |||
if self.to_insert: | |||
l = len(self.to_insert) | |||
for i, page in enumerate(self.to_insert): | |||
if self.verbose: | |||
print "Inserting " + page.route | |||
print "Inserting " + page.page_name | |||
else: | |||
update_progress_bar("Updating Static Pages", i, l) | |||
self.insert_web_page(page) | |||
page.insert() | |||
if not self.verbose: print "" | |||
if self.to_update: | |||
for i, route_details in enumerate(self.to_update): | |||
for i, page in enumerate(self.to_update): | |||
if not self.verbose: | |||
print "Updating " + route_details.name | |||
print "Updating " + page.page_name | |||
else: | |||
sys.stdout.write("\rUpdating statics {0}/{1}".format(i+1, len(self.to_update))) | |||
sys.stdout.flush() | |||
self.update_web_page(route_details) | |||
page.save() | |||
if not self.verbose: print "" | |||
def get_web_page_for_insert(self, route, fpath, page_name, priority, parent_website_route): | |||
page = frappe.get_doc({ | |||
"doctype":"Web Page", | |||
"idx": priority, | |||
"page_name": page_name, | |||
"published": 1, | |||
"parent_web_page": parent_web_page | |||
}) | |||
page.fpath = fpath | |||
page.route = route | |||
page.update(get_static_content(fpath, page_name, route)) | |||
return page | |||
def insert_web_page(self, page): | |||
try: | |||
page.insert() | |||
except frappe.NameError, e: | |||
print e | |||
# page exists, if deleted static, delete it and try again | |||
old_route = frappe.get_doc("Website Route", {"ref_doctype":"Web Page", | |||
"docname": page.name}) | |||
if old_route.static_file_timestamp and \ | |||
not os.path.exists(os.path.join(self.statics_path, old_route.name)): | |||
frappe.delete_doc("Web Page", page.name) | |||
page.insert() # retry | |||
# update timestamp | |||
route_doc = frappe.get_doc("Website Route", {"ref_doctype": "Web Page", | |||
"docname": page.name}) | |||
route_doc.static_file_timestamp = cint(os.path.getmtime(page.fpath)) | |||
route_doc.save() | |||
def get_route_details_for_update(self, route_details, fpath, priority, parent_website_route): | |||
out = None | |||
if not route_details.docname: | |||
print "Ignoring {0} because page found".format(route_details.name) | |||
return | |||
if str(cint(os.path.getmtime(fpath)))!= route_details.static_file_timestamp \ | |||
or (cint(route_details.idx) != cint(priority) and (priority is not None) \ | |||
or self.rebuild): | |||
out = route_details | |||
out.idx = priority | |||
out.fpath = fpath | |||
return out | |||
def update_web_page(self, route_details): | |||
page = frappe.get_doc("Web Page", route_details.docname) | |||
page.update(get_static_content(route_details.fpath, | |||
route_details.docname, route_details.name)) | |||
page.save() | |||
route_doc = frappe.get_doc("Website Route", route_details.name) | |||
route_doc.static_file_timestamp = cint(os.path.getmtime(route_details.fpath)) | |||
route_doc.idx = route_details.idx | |||
route_doc.save() | |||
def cleanup(self): | |||
if self.synced: | |||
# delete static web pages that are not in immediate list | |||
frappe.delete_doc("Web Page", frappe.db.sql_list("""select docname | |||
from `tabWebsite Route` | |||
where ifnull(static_file_timestamp,'')!='' and name not in ({}) | |||
order by (rgt-lft) asc""".format(', '.join(["%s"]*len(self.synced))), | |||
tuple(self.synced))) | |||
frappe.delete_doc("Web Page", frappe.db.sql_list("""select name | |||
from `tabWeb Page` | |||
where ifnull(template_path,'')!='' | |||
and name not in ({})""".format(', '.join(["%s"]*len(self.synced))), | |||
tuple(self.synced)), force=1) | |||
else: | |||
# delete all static web pages | |||
frappe.delete_doc("Web Page", frappe.db.sql_list("""select docname | |||
from `tabWebsite Route` | |||
where ifnull(static_file_timestamp,'')!='' | |||
order by (rgt-lft) asc""")) | |||
def delete_static_web_pages(): | |||
for name in frappe.db.sql_list("""select docname from `tabWebsite Route` | |||
where ifnull(static_file_timestamp,'')!=''"""): | |||
frappe.db.sql("delete from `tabWeb Page` where name=%s", name) | |||
def get_static_content(fpath, docname, route): | |||
d = frappe._dict({}) | |||
with open(fpath, "r") as contentfile: | |||
content = unicode(contentfile.read(), 'utf-8') | |||
if fpath.endswith(".md"): | |||
if content: | |||
lines = content.splitlines() | |||
first_line = lines[0].strip() | |||
if first_line.startswith("# "): | |||
d.title = first_line[2:] | |||
content = "\n".join(lines[1:]) | |||
content = markdown(content) | |||
d.main_section = unicode(content.encode("utf-8"), 'utf-8') | |||
if not d.title: | |||
d.title = docname.replace("-", " ").replace("_", " ").title() | |||
for extn in ("js", "css"): | |||
fpath = fpath.rsplit(".", 1)[0] + "." + extn | |||
if os.path.exists(fpath): | |||
with open(fpath, "r") as f: | |||
d["css" if extn=="css" else "javascript"] = f.read() | |||
d.insert_style = 1 if d.css else 0 | |||
d.insert_code = 1 if d.javascript else 0 | |||
return d | |||
frappe.delete_doc("Web Page", frappe.db.sql_list("""select name | |||
from `tabWeb Page` | |||
where ifnull(template_path,'')!=''"""), force=1) | |||
@@ -1,108 +0,0 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe, os, sys | |||
from frappe.modules import load_doctype_module | |||
from frappe.utils.nestedset import rebuild_tree | |||
from frappe.utils import update_progress_bar | |||
import statics, render | |||
all_routes = None | |||
def sync(app=None, verbose=False): | |||
render.clear_cache() | |||
# 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 |
@@ -70,8 +70,10 @@ class WebsiteGenerator(Document): | |||
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() | |||
parent = self.get(self.parent_website_route_field) | |||
if parent: | |||
self.parent_website_route = frappe.get_doc(field.options, | |||
parent).get_route() | |||
def update_routes_of_descendants(self, old_route = None): | |||
if not self.is_new(): | |||
@@ -85,12 +87,6 @@ class WebsiteGenerator(Document): | |||
(old_route, self.get_route(), old_route + "%")) | |||
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._dict() | |||
route.update({ | |||
"doc": self, | |||
@@ -101,7 +97,6 @@ class WebsiteGenerator(Document): | |||
"page_name": self.get_page_name(), | |||
"controller": get_module_name(self.doctype, self.meta.module), | |||
"template": self.template, | |||
"lastmod": lastmod, | |||
"parent_website_route": self.get("parent_website_route", ""), | |||
"page_title": self.get(self.page_title_field) | |||
}) | |||
@@ -167,11 +162,13 @@ class WebsiteGenerator(Document): | |||
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) | |||
order_by = getattr(self, "order_by", "idx asc")), | |||
self.get_route(), as_dict=True) | |||
for c in children: | |||
c.name = make_route(c.name) | |||
c.name = make_route(c) | |||
return children | |||
else: | |||
return [] | |||