seitime-frappe/frappe/website/context.py
Faris Ansari 51ece4a920 feat: Flip sitemap switch
BREAKING CHANGE
A route is added to the sitemap if no_sitemap is not set.
This PR reverses this design. Because sitemap should contain publicly accessible pages and not utility pages.
Also, having lots of utility pages on sitemap does more harm than good.
2019-03-19 15:12:28 +05:30

267 lines
8 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals
import frappe, os, json
from frappe.website.doctype.website_settings.website_settings import get_website_settings
from frappe.website.router import get_page_context
from frappe.model.document import Document
def get_context(path, args=None):
if args and args.source:
context = args
else:
context = get_page_context(path)
if args:
context.update(args)
if hasattr(frappe.local, 'request'):
# for <body data-path=""> (remove leading slash)
# path could be overriden in render.resolve_from_map
context["path"] = frappe.local.request.path.strip('/ ')
else:
context["path"] = path
context.route = context.path
context = build_context(context)
# set using frappe.respond_as_web_page
if hasattr(frappe.local, 'response') and frappe.local.response.get('context'):
context.update(frappe.local.response.context)
return context
def update_controller_context(context, controller):
module = frappe.get_module(controller)
if module:
# get config fields
for prop in ("base_template_path", "template", "no_cache", "sitemap",
"condition_field"):
if hasattr(module, prop):
context[prop] = getattr(module, prop)
if hasattr(module, "get_context"):
try:
ret = module.get_context(context)
if ret:
context.update(ret)
except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect):
raise
except:
if not frappe.flags.in_migrate:
frappe.errprint(frappe.utils.get_traceback())
if hasattr(module, "get_children"):
context.children = module.get_children(context)
def build_context(context):
"""get_context method of doc or module is supposed to render
content templates and push it into context"""
context = frappe._dict(context)
if not "url_prefix" in context:
context.url_prefix = ""
if context.url_prefix and context.url_prefix[-1]!='/':
context.url_prefix += '/'
# for backward compatibility
context.docs_base_url = '/docs'
context.update(get_website_settings())
context.update(frappe.local.conf.get("website_context") or {})
# provide doc
if context.doc:
context.update(context.doc.as_dict())
context.update(context.doc.get_website_properties())
if not context.template:
context.template = context.doc.meta.get_web_template()
if hasattr(context.doc, "get_context"):
ret = context.doc.get_context(context)
if ret:
context.update(ret)
for prop in ("no_cache", "sitemap"):
if not prop in context:
context[prop] = getattr(context.doc, prop, False)
elif context.controller:
# controller based context
update_controller_context(context, context.controller)
# controller context extensions
context_controller_hooks = frappe.get_hooks("extend_website_page_controller_context") or {}
for controller, extension in context_controller_hooks.items():
if isinstance(extension, list):
for ext in extension:
if controller == context.controller:
update_controller_context(context, ext)
else:
update_controller_context(context, extension)
add_metatags(context)
add_sidebar_and_breadcrumbs(context)
# determine templates to be used
if not context.base_template_path:
app_base = frappe.get_hooks("base_template")
context.base_template_path = app_base[0] if app_base else "templates/base.html"
if context.title_prefix and context.title and not context.title.startswith(context.title_prefix):
context.title = '{0} - {1}'.format(context.title_prefix, context.title)
return context
def load_sidebar(context, sidebar_json_path):
with open(sidebar_json_path, 'r') as sidebarfile:
context.sidebar_items = json.loads(sidebarfile.read())
context.show_sidebar = 1
def get_sidebar_json_path(path, look_for=False):
'''
Get _sidebar.json path from directory path
:param path: path of the current diretory
:param look_for: if True, look for _sidebar.json going upwards from given path
:return: _sidebar.json path
'''
if os.path.split(path)[1] == 'www' or path == '/' or not path:
return ''
sidebar_json_path = os.path.join(path, '_sidebar.json')
if os.path.exists(sidebar_json_path):
return sidebar_json_path
else:
if look_for:
return get_sidebar_json_path(os.path.split(path)[0], look_for)
else:
return ''
def add_sidebar_and_breadcrumbs(context):
'''Add sidebar and breadcrumbs to context'''
from frappe.website.router import get_page_info_from_template
if context.show_sidebar:
context.no_cache = 1
add_sidebar_data(context)
else:
if context.basepath:
hooks = frappe.get_hooks('look_for_sidebar_json')
look_for_sidebar_json = hooks[0] if hooks else 0
sidebar_json_path = get_sidebar_json_path(
context.basepath,
look_for_sidebar_json
)
if sidebar_json_path:
load_sidebar(context, sidebar_json_path)
if context.add_breadcrumbs and not context.parents:
if context.basepath:
parent_path = os.path.dirname(context.path).rstrip('/')
page_info = get_page_info_from_template(parent_path)
if page_info:
context.parents = [dict(route=parent_path, title=page_info.title)]
def add_sidebar_data(context):
from frappe.utils.user import get_fullname_and_avatar
import frappe.www.list
if context.show_sidebar and context.website_sidebar:
context.sidebar_items = frappe.get_all('Website Sidebar Item',
filters=dict(parent=context.website_sidebar), fields=['title', 'route', '`group`'],
order_by='idx asc')
if not context.sidebar_items:
sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user)
if sidebar_items == None:
sidebar_items = []
roles = frappe.get_roles()
portal_settings = frappe.get_doc('Portal Settings', 'Portal Settings')
def add_items(sidebar_items, items):
for d in items:
if d.get('enabled') and ((not d.get('role')) or d.get('role') in roles):
sidebar_items.append(d.as_dict() if isinstance(d, Document) else d)
if not portal_settings.hide_standard_menu:
add_items(sidebar_items, portal_settings.get('menu'))
if portal_settings.custom_menu:
add_items(sidebar_items, portal_settings.get('custom_menu'))
items_via_hooks = frappe.get_hooks('portal_menu_items')
if items_via_hooks:
for i in items_via_hooks: i['enabled'] = 1
add_items(sidebar_items, items_via_hooks)
frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items)
context.sidebar_items = sidebar_items
info = get_fullname_and_avatar(frappe.session.user)
context["fullname"] = info.fullname
context["user_image"] = info.avatar
context["user"] = info.name
def add_metatags(context):
tags = context.get("metatags")
if tags:
if not "twitter:card" in tags:
tags["twitter:card"] = "summary_large_image"
if not "og:type" in tags:
tags["og:type"] = "article"
if tags.get("name"):
tags["og:title"] = tags["twitter:title"] = tags["name"]
if tags.get("title"):
tags["og:title"] = tags["twitter:title"] = tags["title"]
if tags.get("description"):
tags["og:description"] = tags["twitter:description"] = tags["description"]
image = tags.get('image', context.image or None)
if image:
tags["og:image"] = tags["twitter:image:src"] = tags["image"] = frappe.utils.get_url(image)
if context.path:
tags['og:url'] = tags['url'] = frappe.utils.get_url(context.path)
if context.published_on:
tags['datePublished'] = context.published_on
if context.author:
tags['author'] = context.author
if context.description:
tags['description'] = context.description
tags['language'] = frappe.local.lang or 'en'
# Get meta tags from Website Route meta
# they can override the defaults set above
route = context.route
if route == '':
# homepage
route = frappe.db.get_single_value('Website Settings', 'home_page')
route_exists = (route
and not route.endswith(('.js', '.css'))
and frappe.db.exists('Website Route Meta', route))
if route_exists:
context.setdefault('metatags', frappe._dict({}))
website_route_meta = frappe.get_doc('Website Route Meta', route)
for meta_tag in website_route_meta.meta_tags:
d = meta_tag.get_meta_dict()
context.metatags.update(d)