__title__ = 'fobi.utils' __author__ = 'Artur Barseghyan ' __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)