def add_plugin(self, request): """ Plugins can be added to an item or another plugin """ # TODO: Enable number limitations from CMS placeholder configs if 'history' in request.path or 'recover' in request.path: return HttpResponseBadRequest("error") plugin_type = request.POST['plugin_type'] placeholder_id = request.POST.get('placeholder', None) parent_id = request.POST.get('parent_id', None) if placeholder_id: try: placeholder_id = int(placeholder_id) except ValueError: placeholder_id = None if parent_id: try: parent_id = int(parent_id) except ValueError: parent_id = None if placeholder_id: placeholder = get_object_or_404(Placeholder, pk=placeholder_id) item = NewsItem.objects.get(placeholders=placeholder) if not item.has_change_permission(request): raise Http404 plugin = CMSPlugin(language='en', plugin_type=plugin_type, placeholder=placeholder, position=CMSPlugin.objects.filter( placeholder=placeholder).count()) plugin.save() if _REVERSION: make_revision_with_plugins(item, request.user, '%(plugin_name)s plugin added to %(placeholder)s' % { 'plugin_name': unicode(plugin_pool.get_plugin(plugin_type).name), 'placeholder': placeholder.slot}) elif parent_id: parent = CMSPlugin.objects.select_related('placeholder').get( pk=parent_id) item = NewsItem.objects.get(placeholders=parent.placeholder) if not item.has_change_permission(request): raise Http404 plugin = CMSPlugin(language='en', plugin_type=plugin_type, placeholder=parent.placeholder, parent=parent, position=CMSPlugin.objects.filter(parent=parent).count()) plugin.save() if _REVERSION: make_revision_with_plugins(item, request.user, '%(plugin_name)s plugin added to plugin ' '%(plugin)s in %(placeholder)s' % { 'plugin_name': unicode(plugin_pool.get_plugin(plugin_type).name), 'placeholder': parent.placeholder.slot, 'plugin': unicode(parent)}) else: return HttpResponseBadRequest( "Either parent of placeholder is required") return HttpResponse(unicode(plugin.pk), content_type='text/plain')
def clean_plugin_type(self): plugin_type = self.cleaned_data['plugin_type'] try: plugin_pool.get_plugin(plugin_type) except KeyError: message = ugettext("Invalid plugin type '%s'") % plugin_type raise ValidationError(message) return plugin_type
def handle(self, *args, **options): self.stdout.write("") self.stdout.write("_" * 79) self.stdout.write(self.help) self.stdout.write("") all_plugins = CMSPlugin.objects.order_by('plugin_type') plugin_types = list( set(all_plugins.values_list('plugin_type', flat=True))) plugin_types.sort() print("There are %i CMS plugin types..." % len(plugin_types)) uninstalled_count = 0 unsaved_count = 0 plugin_count = 0 for plugin_type in plugin_types: # get all plugins of this type plugins = CMSPlugin.objects.filter(plugin_type=plugin_type) plugin_count += plugins.count() # does this plugin have a model? report unsaved instances try: plugin_pool.get_plugin(name=plugin_type) except KeyError: # catch uninstalled plugins txt = "{txt}: '{plugin_type}'".format( txt=self.style.NOTICE("uninstalled plugin type"), plugin_type=self.style.SQL_FIELD(plugin_type)) print(txt) uninstalled_plugins = CMSPlugin.objects.filter( plugin_type=plugin_type) uninstalled_count += uninstalled_plugins.count() self.print_plugin_info(uninstalled_plugins) else: unsaved_instances = [ p for p in plugins if not p.get_plugin_instance()[0] ] if unsaved_instances: txt = "+ '{plugin_type}' has {count} {txt}:".format( plugin_type=self.style.SQL_FIELD(plugin_type), count=len(unsaved_instances), txt=self.style.NOTICE("unsaved instances")) print(txt) unsaved_count += len(unsaved_instances) self.print_plugin_info(unsaved_instances) self.stdout.write("%i CMS plugins checked" % plugin_count) self.stdout.write("%i uninstalled CMS plugins" % uninstalled_count) self.stdout.write("%i unsaved CMS plugins" % unsaved_count) self.stdout.write("\n --- END ---\n")
def toolbar_plugin_processor(instance, placeholder, rendered_content, original_context): from cms.plugin_pool import plugin_pool original_context.push() child_plugin_classes = [] plugin_class = instance.get_plugin_class() if plugin_class.allow_children: inst, plugin = instance.get_plugin_instance() page = original_context['request'].current_page plugin.cms_plugin_instance = inst children = [plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(placeholder, page)] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct(children, placeholder.slot, placeholder.page, parent=plugin_class) instance.placeholder = placeholder request = original_context['request'] with force_language(request.toolbar.toolbar_language): data = { 'instance': instance, 'rendered_content': rendered_content, 'child_plugin_classes': child_plugin_classes, } # TODO: Remove js_compat once get_action_urls is refactored. data.update(instance.get_action_urls(js_compat=False)) original_context.update(data) plugin_class = instance.get_plugin_class() template = plugin_class.frontend_edit_template output = render_to_string(template, flatten_context(original_context)).strip() original_context.pop() return output
def add_plugin(request): if 'history' in request.path or 'recover' in request.path: return HttpResponse(str("error")) if request.method == "POST": plugin_type = request.POST['plugin_type'] page_id = request.POST.get('page_id', None) parent = None if page_id: page = get_object_or_404(Page, pk=page_id) placeholder = request.POST['placeholder'].lower() language = request.POST['language'] position = CMSPlugin.objects.filter(page=page, language=language, placeholder=placeholder).count() else: parent_id = request.POST['parent_id'] parent = get_object_or_404(CMSPlugin, pk=parent_id) page = parent.page placeholder = parent.placeholder language = parent.language position = None plugin = CMSPlugin(page=page, language=language, plugin_type=plugin_type, position=position, placeholder=placeholder) if parent: plugin.parent = parent plugin.save() if 'reversion' in settings.INSTALLED_APPS: page.save() save_all_plugins(page) revision.user = request.user plugin_name = unicode(plugin_pool.get_plugin(plugin_type).name) revision.comment = _(u"%(plugin_name)s plugin added to %(placeholder)s") % {'plugin_name':plugin_name, 'placeholder':placeholder} return HttpResponse(str(plugin.pk)) raise Http404
def plugin_report(): plugin_report = [] all_plugins = CMSPlugin.objects.order_by("plugin_type") plugin_types = list(set(all_plugins.values_list("plugin_type", flat=True))) plugin_types.sort() # self.stdout.write(plugin+'\n') uninstalled_plugins = [] for plugin_type in plugin_types: plugin = {} plugin["type"] = plugin_type try: # get all plugins of this type plugins = CMSPlugin.objects.filter(plugin_type=plugin_type) plugin["instances"] = plugins # does this plugin have a model? report unsaved instances plugin["model"] = plugin_pool.get_plugin(name=plugin_type).model unsaved_instances = [ p for p in plugins if not p.get_plugin_instance()[0] ] plugin["unsaved_instances"] = unsaved_instances # catch uninstalled plugins except KeyError: uninstalled_plugins.append(plugin_type) plugin["model"] = None plugin["instances"] = plugins plugin["unsaved_instances"] = [] plugin_report.append(plugin) return plugin_report
def has_reached_plugin_limit(placeholder, plugin_type, language, template=None): """ Checks if placeholder has reached it's global plugin limit, if not then it checks if it has reached it's plugin_type limit. """ limits = get_placeholder_conf("limits", placeholder.slot, template) if limits: global_limit = limits.get("global") type_limit = limits.get(plugin_type) # total plugin count count = placeholder.get_plugins(language=language).count() if global_limit and count >= global_limit: raise PluginLimitReached(_("This placeholder already has the maximum number of plugins (%s)." % count)) elif type_limit: # total plugin type count type_count = ( placeholder .get_plugins(language=language) .filter(plugin_type=plugin_type) .count() ) if type_count >= type_limit: plugin_name = force_text(plugin_pool.get_plugin(plugin_type).name) raise PluginLimitReached(_( "This placeholder already has the maximum number (%(limit)s) of allowed %(plugin_name)s plugins.") \ % {'limit': type_limit, 'plugin_name': plugin_name}) return False
def toolbar_plugin_processor(instance, placeholder, rendered_content, original_context): from cms.plugin_pool import plugin_pool original_context.push() child_plugin_classes = [] plugin_class = instance.get_plugin_class() if plugin_class.allow_children: inst, plugin = instance.get_plugin_instance() page = original_context['request'].current_page children = [plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(placeholder, page)] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct(children, placeholder.slot, placeholder.page, parent=plugin_class) instance.placeholder = placeholder request = original_context['request'] with force_language(request.toolbar.toolbar_language): data = { 'instance': instance, 'rendered_content': rendered_content, 'child_plugin_classes': child_plugin_classes, 'edit_url': placeholder.get_edit_url(instance.pk), 'add_url': placeholder.get_add_url(), 'delete_url': placeholder.get_delete_url(instance.pk), 'move_url': placeholder.get_move_url(), } original_context.update(data) output = render_to_string(instance.get_plugin_class().frontend_edit_template, original_context) original_context.pop() return output
def add_plugin(self, request): """ Shows the add plugin form and saves it on POST. Requires the following GET parameters: - placeholder_id - plugin_type - plugin_language - plugin_parent (optional) - plugin_position (optional) """ form = PluginAddValidationForm(request.GET) if not form.is_valid(): # list() is necessary for python 3 compatibility. # errors is s dict mapping fields to a list of errors # for that field. error = list(form.errors.values())[0][0] return HttpResponseBadRequest(force_text(error)) plugin_data = form.cleaned_data placeholder = plugin_data['placeholder_id'] plugin_type = plugin_data['plugin_type'] if not self.has_add_plugin_permission(request, placeholder, plugin_type): message = force_text(_('You do not have permission to add a plugin')) return HttpResponseForbidden(message) parent = plugin_data.get('plugin_parent') if parent: position = parent.cmsplugin_set.count() else: position = CMSPlugin.objects.filter( parent__isnull=True, language=plugin_data['plugin_language'], placeholder=placeholder, ).count() plugin_data['position'] = position plugin_class = plugin_pool.get_plugin(plugin_type) plugin_instance = plugin_class(plugin_class.model, self.admin_site) # Setting attributes on the form class is perfectly fine. # The form class is created by modelform factory every time # this get_form() method is called. plugin_instance._cms_initial_attributes = { 'language': plugin_data['plugin_language'], 'placeholder': plugin_data['placeholder_id'], 'parent': plugin_data.get('plugin_parent', None), 'plugin_type': plugin_data['plugin_type'], 'position': plugin_data['position'], } response = plugin_instance.add_view(request) if request.method == "POST" and plugin_instance.object_successfully_changed: self.post_add_plugin(request, plugin_instance.saved_object) return response
def get_plugin_by_type(self, plugin_type): plugin = plugin_pool.get_plugin(name=plugin_type) model = plugin.model app_label = model._meta.app_label label = "%s.%s" % (app_label, plugin_type) return (label, plugin_type, plugin)
def change_view(self, request, object_id, form_url='', extra_context=None): obj = self.get_object(request, object_id) self.plugin_instance = plugin_pool.get_plugin(obj.plugin_type) extra_context = dict(extra_context or {}, title=format_html(_("Change shared settings of '{}' plugin"), self.plugin_instance.name), icon_fonts=IconFont.objects.all()) return super().change_view(request, object_id, form_url, extra_context=extra_context)
def plugin_report(): plugin_report = [] all_plugins = CMSPlugin.objects.order_by("plugin_type") plugin_types = list(set(all_plugins.values_list("plugin_type", flat=True))) plugin_types.sort() # self.stdout.write(plugin+'\n') uninstalled_plugins = [] for plugin_type in plugin_types: plugin = {} plugin["type"] = plugin_type try: # get all plugins of this type plugins = CMSPlugin.objects.filter(plugin_type=plugin_type) plugin["instances"] = plugins # does this plugin have a model? report unsaved instances plugin["model"] = plugin_pool.get_plugin(name=plugin_type).model unsaved_instances = [p for p in plugins if not p.get_plugin_instance()[0]] plugin["unsaved_instances"] = unsaved_instances # catch uninstalled plugins except KeyError: uninstalled_plugins.append(plugin_type) plugin["model"] = None plugin["instances"] = plugins plugin["unsaved_instances"] = [] plugin_report.append(plugin) return plugin_report
def edit_plugin(self, request, plugin_id): try: plugin_id = int(plugin_id) except ValueError: return HttpResponseNotFound(force_text(_("Plugin not found"))) queryset = CMSPlugin.objects.values_list('plugin_type', flat=True) plugin_type = get_list_or_404(queryset, pk=plugin_id)[0] # CMSPluginBase subclass plugin_class = plugin_pool.get_plugin(plugin_type) # CMSPluginBase subclass instance plugin_instance = plugin_class(plugin_class.model, self.admin_site) # CMSPlugin subclass instance obj = get_object_or_404(plugin_class.model, pk=plugin_id) if not self.has_change_plugin_permission(request, obj): return HttpResponseForbidden( force_text( _("You do not have permission to edit this plugin"))) response = plugin_instance.change_view(request, str(plugin_id)) if request.method == "POST" and plugin_instance.object_successfully_changed: self.post_edit_plugin(request, plugin_instance.saved_object) return response
def plugins_from_data(placeholder, parent, data): for plugin_type, data, children_data in data: try: plugin_class = plugin_pool.get_plugin(plugin_type) except Exception: continue kwargs = dict(data) inlines = kwargs.pop('inlines', []) shared_glossary = kwargs.pop('shared_glossary', None) try: instance = add_plugin(placeholder, plugin_class, language, target=parent, **kwargs) except Exception: continue if isinstance(instance, CascadeElement): instance.plugin_class.add_inline_elements(instance, inlines) instance.plugin_class.add_shared_reference( instance, shared_glossary) # for some unknown reasons add_plugin sets instance.numchild to 0, # but fixing and save()-ing 'instance' executes some filters in an unwanted manner plugins_from_data(placeholder, instance, children_data) if isinstance(instance, Text): # we must convert the old plugin IDs into the new ones, # otherwise links are not displayed id_dict = dict( zip(plugin_tags_to_id_list(instance.body), (t[0] for t in instance.get_children().values_list('id')))) instance.body = replace_plugin_tags(instance.body, id_dict) instance.save()
def _get_plugin_metadata(plugin_name): plugin_class = plugin_pool.get_plugin(plugin_name) plugin_model = plugin_class.model field_name = plugin_class.get_template_field_name() template_name_attr = _get_template_name_attr( plugin_model, field_name) return plugin_model, field_name, template_name_attr
def get_form(self, request, obj=None, **kwargs): """ Creates a temporary form with an identifier and the fields declared as sharables for the corresponding plugin model. Additionally it adds dynamic fields to edit the content inside the model field `glossary`. The layout, validation and media files for these dynamic fields are borrowed from the corresponding plugin. """ self.plugin_instance = plugin_pool.get_plugin(obj.plugin_type) sharable_fields = getattr(self.plugin_instance, 'sharable_fields', []) glossary_fields = [ f for f in self.plugin_instance.glossary_fields if f.name in sharable_fields ] kwargs.update(widgets={'glossary': JSONMultiWidget(glossary_fields)}, labels={'glossary': ''}) try: kwargs.update(form=self.plugin_instance.form) except AttributeError: pass ModelForm = super(SharedGlossaryAdmin, self).get_form(request, obj, **kwargs) if callable(getattr(ModelForm, 'unset_required_for', None)): ModelForm.unset_required_for(sharable_fields) # help_text can not be cleared using an empty string in modelform_factory ModelForm.base_fields['glossary'].help_text = '' for field in glossary_fields: ModelForm.base_fields['glossary'].validators.append( field.run_validators) return ModelForm
def plugins_from_data(placeholder, parent, data): for plugin_type, data, children_data in data: try: plugin_class = plugin_pool.get_plugin(plugin_type) except Exception: continue kwargs = dict(data) inlines = kwargs.pop('inlines', []) shared_glossary = kwargs.pop('shared_glossary', None) try: instance = add_plugin(placeholder, plugin_class, language, target=parent, **kwargs) except Exception: continue if isinstance(instance, CascadeElement): instance.plugin_class.add_inline_elements(instance, inlines) instance.plugin_class.add_shared_reference(instance, shared_glossary) # for some unknown reasons add_plugin sets instance.numchild to 0, # but fixing and save()-ing 'instance' executes some filters in an unwanted manner plugins_from_data(placeholder, instance, children_data) if isinstance(instance, Text): # we must convert the old plugin IDs into the new ones, # otherwise links are not displayed id_dict = dict(zip( plugin_tags_to_id_list(instance.body), (t[0] for t in instance.get_children().values_list('id')) )) instance.body = replace_plugin_tags(instance.body, id_dict) instance.save()
def has_reached_plugin_limit(placeholder, plugin_type, language, template=None): """ Checks if placeholder has reached it's global plugin limit, if not then it checks if it has reached it's plugin_type limit. """ limits = get_placeholder_conf("limits", placeholder.slot, template) if limits: global_limit = limits.get("global") type_limit = limits.get(plugin_type) # total plugin count count = placeholder.get_plugins(language=language).count() if global_limit and count >= global_limit: raise PluginLimitReached( _("This placeholder already has the maximum number of plugins (%s)." % count)) elif type_limit: # total plugin type count type_count = (placeholder.get_plugins(language=language).filter( plugin_type=plugin_type).count()) if type_count >= type_limit: plugin_name = force_text( plugin_pool.get_plugin(plugin_type).name) raise PluginLimitReached(_( "This placeholder already has the maximum number (%(limit)s) of allowed %(plugin_name)s plugins.") \ % {'limit': type_limit, 'plugin_name': plugin_name}) return False
def downcast_plugins(queryset, placeholders=None, select_placeholder=False): plugin_types_map = defaultdict(list) plugin_lookup = {} # make a map of plugin types, needed later for downcasting for plugin in queryset: plugin_types_map[plugin.plugin_type].append(plugin.pk) for plugin_type, pks in plugin_types_map.items(): cls = plugin_pool.get_plugin(plugin_type) # get all the plugins of type cls.model plugin_qs = cls.model.objects.filter(pk__in=pks) if select_placeholder: plugin_qs = plugin_qs.select_related('placeholder') # put them in a map so we can replace the base CMSPlugins with their # downcasted versions for instance in plugin_qs: plugin_lookup[instance.pk] = instance # cache the placeholder if placeholders: for pl in placeholders: if instance.placeholder_id == pl.pk: instance.placeholder = pl if not cls.cache: pl.cache_placeholder = False # make the equivalent list of qs, but with downcasted instances return [plugin_lookup.get(plugin.pk, plugin) for plugin in queryset]
def get_context(self, context, obj): # Prepend frontedit toolbar output if applicable request = context['request'] page = request.current_page child_plugin_classes = [] if isinstance(obj, CMSPlugin): slot = context['slot'] plugin = obj plugin_class = plugin.get_plugin_class() if plugin_class.allow_children: instance, plugin = plugin.get_plugin_instance() childs = [ plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(slot, page) ] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct( childs, slot, page, parent=plugin_class) elif isinstance(obj, PlaceholderModel): placeholder = obj page = placeholder.page if placeholder else None if not page: page = getattr(request, 'current_page', None) if placeholder: slot = placeholder.slot else: slot = None # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct( plugin_pool.get_all_plugins(slot, page), slot, page) return {'plugin_classes': child_plugin_classes}
def get_context(self, context, obj): # Prepend frontedit toolbar output if applicable request = context['request'] page = request.current_page child_plugin_classes = [] if isinstance(obj, CMSPlugin): slot = context['slot'] plugin = obj plugin_class = plugin.get_plugin_class() if plugin_class.allow_children: instance, plugin = plugin.get_plugin_instance() plugin.cms_plugin_instance = instance childs = [plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(slot, page)] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct(childs, slot, page, parent=plugin_class) elif isinstance(obj, PlaceholderModel): placeholder = obj page = placeholder.page if placeholder else None if not page: page = getattr(request, 'current_page', None) if placeholder: slot = placeholder.slot else: slot = None # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct(plugin_pool.get_all_plugins(slot, page), slot, page) return {'plugin_classes': child_plugin_classes}
def add_plugin(self, request): """ Shows the add plugin form and saves it on POST. Requires the following GET parameters: - placeholder_id - plugin_type - plugin_language - plugin_parent (optional) - plugin_position (optional) """ plugin_type = request.GET.get('plugin_type') if not plugin_type: return HttpResponseBadRequest(force_text( _("Invalid request, missing plugin_type parameter") )) try: plugin_class = plugin_pool.get_plugin(plugin_type) except KeyError: return HttpResponseBadRequest(force_text( _("Invalid plugin type '%s'") % plugin_type )) plugin_admin = plugin_class(admin_site=self.admin_site) response = plugin_admin.add_view(request) if request.method == "POST" and plugin_admin.object_successfully_changed: self.post_add_plugin(request, plugin_admin.saved_object) return response
def add_text_plugin(sender, **kwargs): instance = kwargs["instance"] if len(instance.description.get_plugins()) is 0: add_plugin(instance.description, plugin_pool.get_plugin("TextPlugin"), "en", body="<p>Default Text</p>")
def remove_plugin(self, request): if request.method == "POST" and not 'history' in request.path: plugin_id = request.POST['plugin_id'] plugin = get_object_or_404(CMSPlugin, pk=plugin_id) placeholder = plugin.placeholder page = get_item_from_placeholder_if_exists(placeholder) if page and not page.has_change_permission(request): raise Http404 if page and settings.CMS_MODERATOR and page.is_under_moderation(): # delete the draft version of the plugin plugin.delete() # set the page to require approval and save page.moderator_state = NewsItem.MODERATOR_NEED_APPROVEMENT page.save() else: plugin.delete_with_public() plugin_name = unicode(plugin_pool.get_plugin(plugin.plugin_type).name) comment = _(u"%(plugin_name)s plugin at position %(position)s in %(placeholder)s was deleted.") % {'plugin_name':plugin_name, 'position':plugin.position, 'placeholder':plugin.placeholder} if page and 'reversion' in settings.INSTALLED_APPS: make_revision_with_plugins(page) reversion.revision.user = request.user reversion.revision.comment = comment return HttpResponse("%s,%s" % (plugin_id, comment)) raise Http404
def downcast_plugins(queryset, placeholders=None, select_placeholder=False, request=None): plugin_types_map = defaultdict(list) plugin_lookup = {} # make a map of plugin types, needed later for downcasting for plugin in queryset: plugin_types_map[plugin.plugin_type].append(plugin.pk) for plugin_type, pks in plugin_types_map.items(): cls = plugin_pool.get_plugin(plugin_type) # get all the plugins of type cls.model plugin_qs = cls.get_render_queryset().filter(pk__in=pks) if select_placeholder: plugin_qs = plugin_qs.select_related('placeholder') # put them in a map so we can replace the base CMSPlugins with their # downcasted versions for instance in plugin_qs: plugin_lookup[instance.pk] = instance # cache the placeholder if placeholders: for pl in placeholders: if instance.placeholder_id == pl.pk: instance.placeholder = pl if not cls().get_cache_expiration( request, instance, pl) and not cls.cache: pl.cache_placeholder = False # make the equivalent list of qs, but with downcasted instances return [plugin_lookup.get(plugin.pk, plugin) for plugin in queryset]
def _get_plugin_from_id(self, plugin_id): queryset = CMSPlugin.objects.values_list('plugin_type', flat=True) plugin_type = get_list_or_404(queryset, pk=plugin_id)[0] # CMSPluginBase subclass plugin_class = plugin_pool.get_plugin(plugin_type) real_queryset = plugin_class.get_render_queryset().select_related('parent', 'placeholder') return get_object_or_404(real_queryset, pk=plugin_id)
def remove_plugin(self, request): if 'history' in request.path: return HttpResponseBadRequest('Invalid Request') plugin_id = int(request.POST['plugin_id']) plugin = get_object_or_404( CMSPlugin.objects.select_related('placeholder'), pk=plugin_id) item = NewsItem.objects.get(placeholders=plugin.placeholder) if not item.has_change_permission(request): return HttpResponseForbidden( _("You do not have permission to remove a plugin")) plugin.delete() comment = "%(plugin_name)s plugin at position %(position)s in " \ "%(placeholder)s was deleted." % { 'plugin_name': unicode(plugin_pool.get_plugin( plugin.plugin_type).name), 'position': plugin.position, 'placeholder': plugin.placeholder} if _REVERSION: make_revision_with_plugins(item, request.user, comment) return HttpResponse("%s,%s" % (plugin_id, comment), content_type='text/plain')
def plugins_from_data(parent, data): for entry in data: plugin_type = plugin_pool.get_plugin(entry[0]) kwargs = dict(entry[1]) instance = add_plugin(clipboard, plugin_type, language, target=parent, **kwargs) # for some unknown reasons add_plugin sets instance.numchild 0, # but fixing and save()-ing 'instance' executes some filters in an unwanted manner plugins_from_data(instance, entry[2])
def _get_data_glossary(self, option_value): shared_instance = self.choices.queryset.get(pk=option_value) plugin_instance = plugin_pool.get_plugin(shared_instance.plugin_type) # use the saved glossary and filter it by fields marked as sharable glossary = dict((key, value) for key, value in shared_instance.glossary.items() if key in plugin_instance.sharable_fields) self._enrich_link(glossary) return glossary
def change_view(self, request, object_id, form_url='', extra_context=None): obj = self.get_object(request, object_id) self.plugin_instance = plugin_pool.get_plugin(obj.plugin_type) extra_context = dict(extra_context or {}, title=format_html(_("Change shared settings of {} plugin"), self.plugin_instance.name), icon_fonts=IconFont.objects.all()) return super(SharedGlossaryAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)
def save(self, force_insert=False, force_update=False, using=None, update_fields=None): """ Only entries which are declared as sharable, shall be stored in the sharable glossary. """ plugin_instance = plugin_pool.get_plugin(self.plugin_type) glossary = dict((key, value) for key, value in self.glossary.items() if key in plugin_instance.sharable_fields) self.glossary = glossary super(SharedGlossary, self).save(force_insert, force_update, using, update_fields)
def delete_plugin(self, request, plugin_id): plugin = get_object_or_404( CMSPlugin.objects.select_related('placeholder'), pk=plugin_id) if not self.has_delete_plugin_permission(request, plugin): return HttpResponseForbidden( force_text( _("You do not have permission to delete this plugin"))) plugin_cms_class = plugin.get_plugin_class() plugin_class = plugin_cms_class.model opts = plugin_class._meta using = router.db_for_write(plugin_class) app_label = opts.app_label if DJANGO_1_7: deleted_objects, perms_needed, protected = get_deleted_objects( [plugin], opts, request.user, self.admin_site, using) else: deleted_objects, __, perms_needed, protected = get_deleted_objects( [plugin], opts, request.user, self.admin_site, using) if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied( _("You do not have permission to delete this plugin")) obj_display = force_text(plugin) self.log_deletion(request, plugin, obj_display) plugin.delete() self.message_user( request, _('The %(name)s plugin "%(obj)s" was deleted successfully.') % { 'name': force_text(opts.verbose_name), 'obj': force_text(obj_display) }) self.post_delete_plugin(request, plugin) return HttpResponseRedirect( admin_reverse('index', current_app=self.admin_site.name)) plugin_name = force_text( plugin_pool.get_plugin(plugin.plugin_type).name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": plugin_name} else: title = _("Are you sure?") context = { "title": title, "object_name": plugin_name, "object": plugin, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, } return TemplateResponse( request, "admin/cms/page/plugin/delete_confirmation.html", context, current_app=self.admin_site.name)
def edit_plugin(request, plugin_id): if not 'history' in request.path: cms_plugin = get_object_or_404(CMSPlugin, pk=plugin_id) instance, plugin_class = cms_plugin.get_plugin_instance() else: plugin_id = int(plugin_id) from reversion.models import Version version_id = request.path.split("/edit-plugin/")[0].split("/")[-1] version = get_object_or_404(Version, pk=version_id) revs = [related_version.object_version for related_version in version.revision.version_set.all()] for rev in revs: obj = rev.object if obj.__class__ == CMSPlugin and obj.pk == plugin_id: cms_plugin = obj break inst, plugin_class = cms_plugin.get_plugin_instance() instance = None for rev in revs: obj = rev.object if obj.__class__ == inst.__class__ and int(obj.pk) == plugin_id: instance = obj break if request.method == "POST": if instance: form = plugin_class.form(request.POST, request.FILES, instance=instance) else: form = plugin_class.form(request.POST, request.FILES) if form.is_valid(): if 'history' in request.path: return render_to_response('admin/cms/page/plugin_forms_history.html', {'CMS_MEDIA_URL':settings.CMS_MEDIA_URL, 'is_popup':True},RequestContext(request)) inst = form.save(commit=False) inst.pk = cms_plugin.pk inst.page = cms_plugin.page inst.position = cms_plugin.position inst.placeholder = cms_plugin.placeholder inst.language = cms_plugin.language inst.plugin_type = cms_plugin.plugin_type inst.save() inst.page.save() form.save_m2m() if 'reversion' in settings.INSTALLED_APPS: save_all_plugins(inst.page, [inst.pk]) revision.user = request.user plugin_name = unicode(plugin_pool.get_plugin(inst.plugin_type).name) revision.comment = _(u"%(plugin_name)s plugin edited at position %(position)s in %(placeholder)s") % {'plugin_name':plugin_name, 'position':inst.position, 'placeholder':inst.placeholder} return render_to_response('admin/cms/page/plugin_forms_ok.html',{'CMS_MEDIA_URL':settings.CMS_MEDIA_URL, 'plugin':cms_plugin, 'is_popup':True},RequestContext(request)) else: if instance: form = plugin_class.form(instance=instance) else: form = plugin_class.form() if plugin_class.form_template: template = plugin_class.form_template else: template = 'admin/cms/page/plugin_forms.html' return render_to_response(template, {'form':form, 'plugin':cms_plugin, 'instance':instance, 'is_popup':True, 'CMS_MEDIA_URL':settings.CMS_MEDIA_URL}, RequestContext(request))
def has_plugin_permission(user, plugin_type, permission_type): """ Checks that a user has permissions for the plugin-type given to perform the action defined in permission_type permission_type should be 'add', 'change' or 'delete'. """ plugin_class = plugin_pool.get_plugin(plugin_type) plugin_model = plugin_class.model plugin_opts = plugin_model._meta return user.has_perm("%s.%s_%s" % (plugin_opts.app_label, permission_type, plugin_opts.object_name.lower()))
def remove_plugin(self, request): if request.method == "POST": plugin_id = request.POST['plugin_id'] plugin = get_object_or_404(CMSPlugin, pk=plugin_id) placeholder = plugin.placeholder plugin.delete_with_public() plugin_name = unicode(plugin_pool.get_plugin(plugin.plugin_type).name) comment = _(u"%(plugin_name)s plugin at position %(position)s in %(placeholder)s was deleted.") % {'plugin_name':plugin_name, 'position':plugin.position, 'placeholder':plugin.placeholder} return HttpResponse("%s,%s" % (plugin_id, comment)) raise Http404
def has_plugin_permission(user, plugin_type, permission_type): """ Checks that a user has permissions for the plugin-type given to performe the action defined in permission_type permission_type should be 'add', 'change' or 'delete'. """ plugin_class = plugin_pool.get_plugin(plugin_type) plugin_model = plugin_class.model plugin_opts = plugin_model._meta return user.has_perm('%s.%s_%s' % (plugin_opts.app_label, permission_type, plugin_opts.object_name.lower()))
def get_plugin_instance(self, *args, **kwargs): from cms.plugin_pool import plugin_pool plugin = plugin_pool.get_plugin(self.plugin_type)(*args, **kwargs) if plugin.model != CMSPlugin: try: instance = getattr(self, plugin.model.__name__.lower()) except: instance = None else: instance = self return instance, plugin
def plugins_from_data(parent, data): for entry in data: plugin = plugin_pool.get_plugin(entry[0]) kwargs = dict(entry[1]) if parent: kwargs.update(target=parent) instance = add_plugin(clipboard, plugin, language, **kwargs) # for some unknown reasons add_plugin sets instance.numchild 0, # therefore it has to be fixed here instance.numchild = len(entry[2]) instance.save() plugins_from_data(instance, entry[2])
def delete_plugin(self, request, plugin_id): plugin = get_object_or_404( CMSPlugin.objects.select_related('placeholder'), pk=plugin_id) if not self.has_delete_plugin_permission(request, plugin): return HttpResponseForbidden(force_text( _("You do not have permission to delete this plugin"))) plugin_cms_class = plugin.get_plugin_class() plugin_class = plugin_cms_class.model opts = plugin_class._meta using = router.db_for_write(plugin_class) app_label = opts.app_label if DJANGO_1_7: deleted_objects, perms_needed, protected = get_deleted_objects( [plugin], opts, request.user, self.admin_site, using) else: deleted_objects, __, perms_needed, protected = get_deleted_objects( [plugin], opts, request.user, self.admin_site, using) if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied(_("You do not have permission to delete this plugin")) obj_display = force_text(plugin) self.log_deletion(request, plugin, obj_display) plugin.delete() self.message_user(request, _('The %(name)s plugin "%(obj)s" was deleted successfully.') % { 'name': force_text(opts.verbose_name), 'obj': force_text(obj_display)}) self.post_delete_plugin(request, plugin) return HttpResponseRedirect(admin_reverse('index', current_app=self.admin_site.name)) plugin_name = force_text(plugin_pool.get_plugin(plugin.plugin_type).name) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": plugin_name} else: title = _("Are you sure?") context = { "title": title, "object_name": plugin_name, "object": plugin, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, } request.current_app = self.admin_site.name if DJANGO_1_7: return TemplateResponse( request, "admin/cms/page/plugin/delete_confirmation.html", context, current_app=self.admin_site.name ) else: return TemplateResponse( request, "admin/cms/page/plugin/delete_confirmation.html", context )
def has_plugin_permission(user, plugin_type, permission_type): """ Checks that a user has permissions for the plugin-type given to perform the action defined in permission_type permission_type should be 'add', 'change' or 'delete'. """ from cms.plugin_pool import plugin_pool plugin_class = plugin_pool.get_plugin(plugin_type) codename = get_model_permission_codename( plugin_class.model, action=permission_type, ) return user.has_perm(codename)
def get_context(self, context, plugin): # Prepend frontedit toolbar output if applicable request = context['request'] page = request.current_page slot = context['slot'] child_plugin_classes = [] plugin_class = plugin.get_plugin_class() if plugin_class.allow_children: instance, plugin = plugin.get_plugin_instance() childs = [plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(slot, page)] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct(childs, slot, page, parent=plugin_class) return {'plugin_classes': child_plugin_classes}
def downcast_plugins(plugins, placeholders=None, select_placeholder=False, request=None): plugin_types_map = defaultdict(list) plugin_lookup = {} plugin_ids = [] # make a map of plugin types, needed later for downcasting for plugin in plugins: # Keep track of the plugin ids we've received plugin_ids.append(plugin.pk) plugin_types_map[plugin.plugin_type].append(plugin.pk) placeholders = placeholders or [] placeholders_by_id = { placeholder.pk: placeholder for placeholder in placeholders } for plugin_type, pks in plugin_types_map.items(): cls = plugin_pool.get_plugin(plugin_type) # get all the plugins of type cls.model plugin_qs = cls.get_render_queryset().filter(pk__in=pks) if select_placeholder: plugin_qs = plugin_qs.select_related('placeholder') # put them in a map so we can replace the base CMSPlugins with their # downcasted versions for instance in plugin_qs.iterator(): placeholder = placeholders_by_id.get(instance.placeholder_id) if placeholder: instance.placeholder = placeholder if not cls.cache and not cls().get_cache_expiration( request, instance, placeholder): placeholder.cache_placeholder = False plugin_lookup[instance.pk] = instance for plugin in plugins: parent_not_available = (not plugin.parent_id or plugin.parent_id not in plugin_ids) # The plugin either has no parent or needs to have a non-ghost parent valid_parent = (parent_not_available or plugin.parent_id in plugin_lookup) if valid_parent and plugin.pk in plugin_lookup: yield plugin_lookup[plugin.pk]
def remove_plugin(self, request): if request.method != "POST": # only allow POST raise Http404 plugin_id = request.POST['plugin_id'] plugin = get_object_or_404(CMSPlugin, pk=plugin_id) # check the permissions! if not plugin.placeholder.has_delete_permission(request): return HttpResponseForbidden(_("You don't have permission to delete a plugin")) plugin.delete_with_public() plugin_name = unicode(plugin_pool.get_plugin(plugin.plugin_type).name) comment = _(u"%(plugin_name)s plugin at position %(position)s in %(placeholder)s was deleted.") % {'plugin_name':plugin_name, 'position':plugin.position, 'placeholder':plugin.placeholder} return HttpResponse("%s,%s" % (plugin_id, comment))
def remove_plugin(request): if request.method == "POST" and not 'history' in request.path: plugin_id = request.POST['plugin_id'] plugin = get_object_or_404(CMSPlugin, pk=plugin_id) page = plugin.page plugin.delete() if 'reversion' in settings.INSTALLED_APPS: save_all_plugins(page) page.save() revision.user = request.user plugin_name = unicode(plugin_pool.get_plugin(plugin.plugin_type).name) revision.comment = _(u"%(plugin_name)s plugin at position %(position)s in %(placeholder)s was deleted.") % {'plugin_name':plugin_name, 'position':plugin.position, 'placeholder':plugin.placeholder} return HttpResponse(str(plugin_id)) raise Http404
def get_plugin_instance(self, admin=None): from cms.plugin_pool import plugin_pool plugin_class = plugin_pool.get_plugin(self.plugin_type) plugin = plugin_class(plugin_class.model, admin)# needed so we have the same signature as the original ModelAdmin if plugin.model != CMSPlugin and self.__class__ == CMSPlugin: # (if self is actually a subclass, getattr below would break) try: instance = getattr(self, plugin.model.__name__.lower()) # could alternatively be achieved with: # instance = plugin_class.model.objects.get(cmsplugin_ptr=self) except: instance = None else: instance = self return instance, plugin
def get_plugin_instance(self, admin=None): from cms.plugin_pool import plugin_pool plugin_class = plugin_pool.get_plugin(self.plugin_type) plugin = plugin_class(plugin_class.model, admin)# needed so we have the same signature as the original ModelAdmin if plugin.model != self.__class__: # and self.__class__ == CMSPlugin: # (if self is actually a subclass, getattr below would break) try: instance = getattr(self, plugin.model.__name__.lower()) # could alternatively be achieved with: # instance = plugin_class.model.objects.get(cmsplugin_ptr=self) instance._render_meta = self._render_meta except (AttributeError, ObjectDoesNotExist): instance = None else: instance = self return instance, plugin
def test_get_all_plugins_single_page(self): page = create_page('page', 'col_two.html', 'en') placeholder = page.placeholders.get(slot='col_left') conf = { 'col_two': { 'plugins': ['TextPlugin', 'LinkPlugin'], }, 'col_two.html col_left': { 'plugins': ['LinkPlugin'], }, } LinkPlugin = plugin_pool.get_plugin('LinkPlugin') with self.settings(CMS_PLACEHOLDER_CONF=conf): plugins = plugin_pool.get_all_plugins(placeholder, page) self.assertEqual(len(plugins), 1, plugins) self.assertEqual(plugins[0], LinkPlugin)
def get_context(self, context, plugin): # Prepend frontedit toolbar output if applicable request = context['request'] page = request.current_page slot = context['slot'] child_plugin_classes = [] plugin_class = plugin.get_plugin_class() if plugin_class.allow_children: instance, plugin = plugin.get_plugin_instance() childs = [ plugin_pool.get_plugin(cls) for cls in plugin.get_child_classes(slot, page) ] # Builds the list of dictionaries containing module, name and value for the plugin dropdowns child_plugin_classes = get_toolbar_plugin_struct( childs, slot, page, parent=plugin_class) return {'plugin_classes': child_plugin_classes}
def test_get_all_plugins_inherit(self): parent = create_page('parent', 'col_two.html', 'en') page = create_page('page', constants.TEMPLATE_INHERITANCE_MAGIC, 'en', parent=parent) placeholder = page.placeholders.get(slot='col_left') conf = { 'col_two': { 'plugins': ['TextPlugin', 'LinkPlugin'], }, 'col_two.html col_left': { 'plugins': ['LinkPlugin'], }, } LinkPlugin = plugin_pool.get_plugin('LinkPlugin') with self.settings(CMS_PLACEHOLDER_CONF=conf): plugins = plugin_pool.get_all_plugins(placeholder, page) self.assertEqual(len(plugins), 1, plugins) self.assertEqual(plugins[0], LinkPlugin)