django-fobi/src/fobi/utils.py
Artur Barseghyan f315c9bcc6 initial
2014-10-11 05:54:24 +02:00

376 lines
13 KiB
Python

__title__ = 'fobi.utils'
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__copyright__ = 'Copyright (c) 2014 Artur Barseghyan'
__license__ = 'GPL 2.0/LGPL 2.1'
__all__ = (
'get_allowed_plugin_uids', 'get_user_plugins', 'get_user_plugin_uids',
'sync_plugins', 'get_allowed_form_element_plugin_uids',
'get_user_form_element_plugins', 'get_user_form_element_plugin_uids',
'get_allowed_form_handler_plugin_uids', 'get_user_form_handler_plugins',
'get_user_form_handler_plugin_uids', 'get_user_plugins_grouped',
'get_user_form_element_plugins_grouped',
'get_user_form_handler_plugins_grouped'
)
from six import PY3
from django.core.urlresolvers import reverse
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.forms.widgets import TextInput
from fobi.base import (
form_element_plugin_registry, form_handler_plugin_registry,
ensure_autodiscover, get_registered_form_element_plugin_uids,
get_registered_form_element_plugins, ensure_autodiscover,
get_registered_form_handler_plugin_uids, get_theme,
get_registered_form_handler_plugins,
get_registered_form_element_plugins_grouped,
)
from fobi.models import (
FormElement, FormHandler,
)
from fobi.helpers import update_plugin_data, safe_text
from fobi.settings import RESTRICT_PLUGIN_ACCESS, DEBUG
from fobi.dynamic import assemble_form_class
import logging
logger = logging.getLogger(__name__)
_ = lambda s: s
def sync_plugins():
"""
Syncs the registered plugin list with data in
``fobi.models.FormFieldPluginModel`` and
``fobi.models.FormHandlerPluginModel``.
"""
ensure_autodiscover()
def base_sync_plugins(get_plugin_uids_func, PluginModel):
"""
:param callable get_plugin_uids_func:
:param fobi.models.AbstractPluginModel PluginModel: Subclass of
``fobi.models.AbstractPluginModel``.
"""
# If not in restricted mode, the quit.
# TODO - perform a subclass check
# TODO - perhaps uncomment this after everything works
#if not RESTRICT_PLUGIN_ACCESS:
# return
registered_plugins = set(get_plugin_uids_func())
synced_plugins = set([p.plugin_uid for p in \
PluginModel._default_manager.only('plugin_uid')])
non_synced_plugins = registered_plugins - synced_plugins
if not non_synced_plugins:
return
buf = []
for plugin_uid in non_synced_plugins:
buf.append(PluginModel(plugin_uid=plugin_uid))
PluginModel._default_manager.bulk_create(buf)
base_sync_plugins(get_registered_form_element_plugin_uids, FormElement)
base_sync_plugins(get_registered_form_handler_plugin_uids, FormHandler)
# ****************************************************************************
# ****************************************************************************
# ********************************* Abstract *********************************
# ****************************************************************************
# ****************************************************************************
def get_allowed_plugin_uids(PluginModel, user):
"""
Gets allowed plugins uids for user given.
:param fobi.models.AbstractPluginModel PluginModel: Subclass of
``fobi.models.AbstractPluginModel``.
:param django.contrib.auth.models.User user:
:return list:
"""
try:
queryset_groups = PluginModel._default_manager.filter(
groups__in = user.groups.all()
).distinct()
queryset_users = PluginModel._default_manager.filter(
users = user
).distinct()
queryset = queryset_groups | queryset_users
queryset = queryset.only('plugin_uid')
return [p.plugin_uid for p in queryset]
except Exception as e:
if DEBUG:
logger.debug(e)
return []
def get_user_plugins(get_allowed_plugin_uids_func, \
get_registered_plugins_func, registry, user):
"""
Gets a list of user plugins in a form if tuple (plugin name, plugin
description). If not yet autodiscovered, autodiscovers them.
:param callable get_allowed_plugin_uids_func:
:param callable get_registered_plugins_func:
:param fobi.base.BaseRegistry registry: Subclass of
``fobi.base.BaseRegistry`` instance.
:param django.contrib.auth.models.User user:
:return list:
"""
ensure_autodiscover()
if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False):
return get_registered_plugins_func()
registered_plugins = []
allowed_plugin_uids = get_allowed_plugin_uids_func(user)
for uid, plugin in registry._registry.items():
if uid in allowed_plugin_uids:
if PY3:
plugin_name = force_text(plugin.name, encoding='utf-8')
else:
plugin_name = force_text(
plugin.name, encoding='utf-8'
).encode('utf-8')
registered_plugins.append((uid, plugin_name))
return registered_plugins
def get_user_plugins_grouped(get_allowed_plugin_uids_func, \
get_registered_plugins_grouped_func, registry, \
user, sort_items=True):
"""
Gets user plugins grouped.
:param callable get_allowed_plugin_uids_func:
:param callable get_registered_plugins_grouped_func:
:param fobi.base.BaseRegistry registry: Subclass of
``fobi.base.BaseRegistry`` instance.
:param django.contrib.auth.models.User user:
:param bool sort_items:
:return dict:
"""
ensure_autodiscover()
if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False):
return get_registered_plugins_grouped_func()
registered_plugins = {}
allowed_plugin_uids = get_allowed_plugin_uids_func(user)
for uid, plugin in registry._registry.items():
if uid in allowed_plugin_uids:
if PY3:
plugin_name = force_text(plugin.name, encoding='utf-8')
plugin_group = force_text(plugin.group, encoding='utf-8')
else:
plugin_name = force_text(
plugin.name, encoding='utf-8'
).encode('utf-8')
plugin_group = force_text(
plugin.group, encoding='utf-8'
).encode('utf-8')
if not plugin_group in registered_plugins:
registered_plugins[plugin_group] = []
registered_plugins[plugin_group].append((uid, plugin_name))
if sort_items:
for key, prop in registered_plugins.items():
prop.sort()
return registered_plugins
def get_user_plugin_uids(get_allowed_plugin_uids_func, \
get_registered_plugin_uids_func, registry, user):
"""
Gets a list of user plugin uids as a list . If not yet autodiscovered,
autodiscovers them.
:param callable get_allowed_plugin_uids_func:
:param callable get_registered_plugins_func:
:param fobi.base.BaseRegistry registry: Subclass of
``fobi.base.BaseRegistry`` instance.
:param django.contrib.auth.models.User user:
:return list:
"""
ensure_autodiscover()
if not RESTRICT_PLUGIN_ACCESS or getattr(user, 'is_superuser', False):
return get_registered_plugin_uids_func()
registered_plugins = []
allowed_plugin_uids = get_allowed_plugin_uids_func(user)
for uid, plugin in registry._registry.items():
if uid in allowed_plugin_uids:
registered_plugins.append(uid)
return registered_plugins
# ****************************************************************************
# ****************************************************************************
# **************************** Form field specific ***************************
# ****************************************************************************
# ****************************************************************************
def get_allowed_form_element_plugin_uids(user):
return get_allowed_plugin_uids(FormElement, user)
def get_user_form_element_plugins(user):
return get_user_plugins(
get_allowed_form_element_plugin_uids,
get_registered_form_element_plugins,
form_element_plugin_registry,
user
)
def get_user_form_element_plugins_grouped(user):
return get_user_plugins_grouped(
get_allowed_form_element_plugin_uids,
get_registered_form_element_plugins_grouped,
form_element_plugin_registry,
user
)
def get_user_form_field_plugin_uids(user):
return get_user_plugin_uids(
get_allowed_form_element_plugin_uids,
get_registered_form_element_plugin_uids,
form_element_plugin_registry,
user
)
# ****************************************************************************
# ****************************************************************************
# *************************** Form handler specific **************************
# ****************************************************************************
# ****************************************************************************
def get_allowed_form_handler_plugin_uids(user):
return get_allowed_plugin_uids(FormHandler, user)
def get_user_form_handler_plugins(user):
return get_user_plugins(
get_allowed_form_handler_plugin_uids,
get_registered_form_handler_plugins,
form_handler_plugin_registry,
user
)
def get_user_form_handler_plugins_grouped(user):
return get_user_plugins_grouped(
get_allowed_form_handler_plugin_uids,
get_registered_form_handler_plugins,
form_handler_plugin_registry,
user
)
def get_user_form_handler_plugin_uids(user):
return get_user_plugin_uids(
get_allowed_form_handler_plugin_uids,
get_registered_form_handler_plugin_uids,
form_handler_plugin_registry,
user
)
# ****************************************************************************
# ****************************************************************************
# *************************** Dynamic forms specific *************************
# ****************************************************************************
# ****************************************************************************
def get_assembled_form(form_entry):
"""
Gets assembled form.
:param fobi.models.FormEntry form_entry:
:return django.forms.Form:
"""
# TODO
FormClass = assemble_form_class(form_entry)
form = FormClass()
return form
def append_edit_and_delete_links_to_field(form_element_plugin, \
form_element_entry, origin=None, \
extra={}):
"""
Should return dictionary, which would be used to update default kwargs
of form fields.
The hidden inputs `form-{counter}-position` and `form-{counter}-id` are
for saving the ordering of the elements (`position` field).
:return dict:
"""
theme = get_theme(as_instance=True)
PluginForm = form_element_plugin.get_form()
counter = extra.get('counter')
edit_url = reverse(
'fobi.edit_form_element_entry',
kwargs = {'form_element_entry_id': form_element_entry.pk}
)
edit_option_html = theme.edit_form_entry_edit_option_html().format(
edit_url = edit_url,
edit_text = _("Edit"),
)
help_text_extra = theme.edit_form_entry_help_text_extra().format(
edit_option_html = edit_option_html if PluginForm else '',
delete_url = reverse('fobi.delete_form_element_entry', kwargs={'form_element_entry_id': form_element_entry.pk}),
delete_text = _("Delete"),
form_element_pk = form_element_entry.pk,
form_element_position = form_element_entry.position,
counter = counter
)
try:
help_text = safe_text(form_element_plugin.data.help_text)
except:
help_text = ''
d = {
'help_text': "{0} {1}".format(help_text, help_text_extra),
}
label = safe_text(getattr(form_element_plugin.data, 'label', ''))
d.update({'label': "{0} ({1})".format(label, safe_text(form_element_plugin.name))})
if 'hidden' == form_element_plugin.uid:
d.update({'widget': TextInput(attrs={'class': theme.form_element_html_class})})
return d
def update_plugin_data_for_entries(entries=None, request=None, \
entry_model_cls=None):
"""
Updates the plugin data for all entries of all users. Rules for update
are specified in the plugin itself.
:param iterable entries: If given, is used to iterate through and update
the plugin data. If left empty, all entries will be updated.
:param django.http.HttpRequest request:
:param fobi.models.AbstractPluginEntry entry_model_cls: Sublcass of
the ``fobi.models.AbstractPluginEntry``.
"""
if entries is None and entry_model_cls is not None:
entries = entry_model_cls._default_manager.all()
if not entries:
return None
for entry in entries:
update_plugin_data(entry, request=request)
logger.debug(entries)