2017-03-05 20:22:34 +01:00
|
|
|
# w.c.s. - web application for online forms
|
|
|
|
# Copyright (C) 2005-2013 Entr'ouvert
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2023-11-26 18:06:21 +01:00
|
|
|
import itertools
|
2017-03-05 20:22:34 +01:00
|
|
|
import os
|
2023-11-26 18:06:21 +01:00
|
|
|
import re
|
2017-03-05 20:22:34 +01:00
|
|
|
|
|
|
|
import django.template.loaders.filesystem
|
2023-12-23 10:29:45 +01:00
|
|
|
from quixote import get_publisher, get_request
|
2017-03-05 20:22:34 +01:00
|
|
|
|
2023-11-26 18:06:21 +01:00
|
|
|
from .qommon import _
|
2023-12-23 10:29:45 +01:00
|
|
|
from .qommon.publisher import get_cfg
|
2017-03-05 20:22:34 +01:00
|
|
|
from .qommon.template import get_theme_directory
|
|
|
|
|
2020-01-18 20:33:44 +01:00
|
|
|
|
2017-03-05 20:22:34 +01:00
|
|
|
class TemplateLoader(django.template.loaders.filesystem.Loader):
|
2020-04-01 14:58:08 +02:00
|
|
|
def get_dirs(self):
|
|
|
|
template_dirs = []
|
|
|
|
if get_publisher():
|
2017-03-05 20:22:34 +01:00
|
|
|
# theme set by hobo
|
|
|
|
theme = get_publisher().get_site_option('theme', 'variables')
|
|
|
|
|
|
|
|
# templates from tenant directory
|
|
|
|
if theme:
|
|
|
|
template_dirs.append(os.path.join(get_publisher().app_dir, 'templates', 'variants', theme))
|
2017-08-18 11:08:50 +02:00
|
|
|
template_dirs.append(
|
|
|
|
os.path.join(get_publisher().app_dir, 'theme', 'templates', 'variants', theme)
|
|
|
|
)
|
2017-03-05 20:22:34 +01:00
|
|
|
template_dirs.append(os.path.join(get_publisher().app_dir, 'templates'))
|
2018-07-23 14:59:51 +02:00
|
|
|
template_dirs.append(os.path.join(get_publisher().app_dir, 'theme', 'templates'))
|
2017-03-05 20:22:34 +01:00
|
|
|
|
2022-10-11 17:26:52 +02:00
|
|
|
current_theme = get_cfg('branding', {}).get('theme', get_publisher().default_theme)
|
2017-03-05 20:22:34 +01:00
|
|
|
theme_directory = get_theme_directory(current_theme)
|
|
|
|
if theme_directory:
|
|
|
|
# templates from theme directory
|
|
|
|
theme_directory = os.path.join(theme_directory, 'templates')
|
|
|
|
|
|
|
|
if theme:
|
|
|
|
# template theme set by hobo
|
|
|
|
template_dirs.append(os.path.join(theme_directory, 'variants', theme))
|
|
|
|
|
|
|
|
template_dirs.append(theme_directory)
|
|
|
|
|
2020-04-01 14:58:08 +02:00
|
|
|
return template_dirs
|
2023-11-26 18:06:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
def grep_strings(string, hit_function):
|
|
|
|
from wcs.data_sources import NamedDataSource
|
|
|
|
from wcs.formdef import get_formdefs_of_all_kinds
|
|
|
|
from wcs.mail_templates import MailTemplate
|
|
|
|
from wcs.workflows import Workflow
|
|
|
|
from wcs.wscalls import NamedWsCall
|
|
|
|
|
|
|
|
regex_search = isinstance(string, re.Pattern)
|
|
|
|
|
|
|
|
def check_string(value, source_url, source_name):
|
|
|
|
if isinstance(value, str) and (
|
|
|
|
(regex_search and string.search(value)) or (not regex_search and string in value)
|
|
|
|
):
|
|
|
|
hit_function(source_url, value, source_name=source_name)
|
|
|
|
return True
|
|
|
|
|
|
|
|
for formdef in get_formdefs_of_all_kinds(order_by='id'):
|
|
|
|
url = formdef.get_admin_url()
|
|
|
|
for attr in formdef.TEXT_ATTRIBUTES:
|
|
|
|
if check_string(getattr(formdef, attr, None), source_url=url, source_name=formdef.name):
|
|
|
|
break
|
|
|
|
|
|
|
|
for value in (getattr(formdef, 'workflow_options', None) or {}).values():
|
|
|
|
if check_string(value, source_url=url + 'workflow-variables', source_name=formdef.name):
|
|
|
|
break
|
|
|
|
|
|
|
|
for field in formdef.fields or []:
|
2024-04-14 16:58:39 +02:00
|
|
|
field._formdef = formdef
|
2023-11-26 18:06:21 +01:00
|
|
|
url = formdef.get_field_admin_url(field)
|
2024-04-14 16:58:39 +02:00
|
|
|
source_name = field.get_admin_url_label()
|
2023-11-26 18:06:21 +01:00
|
|
|
for attr in field.get_admin_attributes():
|
|
|
|
if check_string(getattr(field, attr, None), source_url=url, source_name=source_name):
|
|
|
|
break
|
|
|
|
prefill = getattr(field, 'prefill', None)
|
|
|
|
if prefill:
|
|
|
|
if check_string(prefill.get('value', ''), source_url=url, source_name=source_name):
|
|
|
|
continue
|
|
|
|
if check_string(prefill.get('formula', ''), source_url=url, source_name=source_name):
|
|
|
|
continue
|
|
|
|
data_source = getattr(field, 'data_source', None)
|
|
|
|
if data_source and data_source.get('type') in ['json', 'jsonp', 'python']:
|
|
|
|
if check_string(data_source.get('value', ''), source_url=url, source_name=source_name):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if field.key == 'page':
|
|
|
|
for condition in field.get_conditions():
|
|
|
|
if check_string(condition.get('value', ''), source_url=url, source_name=source_name):
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
elif getattr(field, 'condition', None):
|
|
|
|
if check_string(
|
|
|
|
getattr(field, 'condition').get('value', ''), source_url=url, source_name=source_name
|
|
|
|
):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hasattr(formdef, 'options'):
|
|
|
|
url = formdef.get_admin_url() + 'workflow-variables'
|
|
|
|
for option_value in (formdef.options or {}).values():
|
|
|
|
if check_string(option_value, source_url=url, source_name=formdef.name):
|
|
|
|
break
|
|
|
|
|
|
|
|
select_kwargs = {'ignore_errors': True, 'ignore_migration': True, 'order_by': 'id'}
|
|
|
|
for workflow in Workflow.select(**select_kwargs):
|
|
|
|
for action in workflow.get_all_items():
|
|
|
|
url = action.get_admin_url()
|
|
|
|
for parameter in action.get_parameters():
|
|
|
|
if check_string(getattr(action, parameter, None), source_url=url, source_name=workflow.name):
|
|
|
|
break
|
|
|
|
for computed_string in action.get_computed_strings():
|
|
|
|
if check_string(computed_string, source_url=url, source_name=workflow.name):
|
|
|
|
break
|
|
|
|
condition = getattr(action, 'condition', None)
|
|
|
|
if condition:
|
|
|
|
if check_string(condition.get('value', ''), source_url=url, source_name=workflow.name):
|
|
|
|
continue
|
|
|
|
|
|
|
|
for trigger in workflow.get_all_global_action_triggers():
|
|
|
|
url = trigger.get_admin_url()
|
|
|
|
for computed_string in trigger.get_computed_strings():
|
|
|
|
if check_string(computed_string, source_url=url, source_name=workflow.name):
|
|
|
|
break
|
|
|
|
|
|
|
|
for obj in itertools.chain(
|
|
|
|
NamedDataSource.select(**select_kwargs),
|
|
|
|
NamedWsCall.select(**select_kwargs),
|
|
|
|
MailTemplate.select(**select_kwargs),
|
|
|
|
):
|
|
|
|
url = obj.get_admin_url()
|
|
|
|
source_name = obj.name
|
|
|
|
for attr, attr_type in obj.XML_NODES:
|
|
|
|
attr_value = getattr(obj, attr, None)
|
|
|
|
if attr_type == 'str':
|
|
|
|
if check_string(attr_value, source_url=url, source_name=source_name):
|
|
|
|
break
|
|
|
|
elif attr_type == 'str_list':
|
|
|
|
for str_item in attr_value or []:
|
|
|
|
if check_string(str_item, source_url=url, source_name=source_name):
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
break
|
|
|
|
elif isinstance(attr_value, dict):
|
|
|
|
for str_item in attr_value.values():
|
|
|
|
if check_string(str_item, source_url=url, source_name=source_name):
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
break
|
2023-12-23 10:29:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
class record_timings:
|
|
|
|
def __init__(self, name=None, record_if_over=None):
|
|
|
|
self.record_if_over = record_if_over
|
|
|
|
self.name = name
|
|
|
|
|
|
|
|
def __call__(self, func):
|
|
|
|
name = self.name or func.__name__
|
|
|
|
|
|
|
|
def f(*args, **kwargs):
|
|
|
|
request = get_request()
|
|
|
|
timing = request.start_timing(name=name)
|
|
|
|
try:
|
|
|
|
return func(*args, **kwargs)
|
|
|
|
finally:
|
|
|
|
duration = request.stop_timing(timing)
|
|
|
|
if self.record_if_over and duration > self.record_if_over:
|
|
|
|
# timings will be displayed in the traceback part of the error.
|
|
|
|
timings = request.timings # noqa pylint: disable=unused-variable
|
|
|
|
get_publisher().record_error(_('%s is taking too long') % name)
|
|
|
|
|
|
|
|
return f
|