def add_plugin(self, request): """ POST request should have the following data: - placeholder_id - plugin_type - plugin_language - plugin_parent (optional) """ parent = None plugin_type = request.POST['plugin_type'] placeholder_id = request.POST.get('placeholder_id', None) placeholder = get_object_or_404(Placeholder, pk=placeholder_id) parent_id = request.POST.get('plugin_parent', None) language = request.POST.get('plugin_language') or get_language_from_request(request) if not self.has_add_plugin_permission(request, placeholder, plugin_type): return HttpResponseForbidden(force_unicode(_('You do not have permission to add a plugin'))) try: has_reached_plugin_limit(placeholder, plugin_type, language, template=self.get_placeholder_template(request, placeholder)) except PluginLimitReached as er: return HttpResponseBadRequest(er) # page add-plugin if not parent_id: position = request.POST.get('plugin_order', CMSPlugin.objects.filter(language=language, placeholder=placeholder).count()) # in-plugin add-plugin else: parent = get_object_or_404(CMSPlugin, pk=parent_id) placeholder = parent.placeholder position = request.POST.get('plugin_order', CMSPlugin.objects.filter(language=language, parent=parent).count()) # placeholder (non-page) add-plugin # Sanity check to make sure we're not getting bogus values from JavaScript: if settings.USE_I18N: if not language or not language in [lang[0] for lang in settings.LANGUAGES]: return HttpResponseBadRequest(force_unicode(_("Language must be set to a supported language!"))) if parent and parent.language != language: return HttpResponseBadRequest(force_unicode(_("Parent plugin language must be same as language!"))) else: language = settings.LANGUAGE_CODE plugin = CMSPlugin(language=language, plugin_type=plugin_type, position=position, placeholder=placeholder) if parent: plugin.position = CMSPlugin.objects.filter(parent=parent).count() plugin.parent_id = parent.pk plugin.save() self.post_add_plugin(request, placeholder, plugin) response = { 'url': force_unicode( admin_reverse("%s_%s_edit_plugin" % (self.model._meta.app_label, self.model._meta.model_name), args=[plugin.pk])), 'delete': force_unicode( admin_reverse("%s_%s_delete_plugin" % (self.model._meta.app_label, self.model._meta.model_name), args=[plugin.pk])), 'breadcrumb': plugin.get_breadcrumb(), } return HttpResponse(json.dumps(response), content_type='application/json')
def add_plugin(self, request): """ POST request should have the following data: - placeholder_id - plugin_type - plugin_language - plugin_parent (optional) """ parent = None plugin_type = request.POST['plugin_type'] placeholder_id = request.POST.get('placeholder_id', None) placeholder = get_object_or_404(Placeholder, pk=placeholder_id) parent_id = request.POST.get('plugin_parent', None) language = request.POST.get('plugin_language') or get_language_from_request(request) if not self.has_add_plugin_permission(request, placeholder, plugin_type): return HttpResponseForbidden(force_text(_('You do not have permission to add a plugin'))) try: has_reached_plugin_limit(placeholder, plugin_type, language, template=self.get_placeholder_template(request, placeholder)) except PluginLimitReached as er: return HttpResponseBadRequest(er) # page add-plugin if not parent_id: position = request.POST.get('plugin_order', CMSPlugin.objects.filter(language=language, placeholder=placeholder).count()) # in-plugin add-plugin else: parent = get_object_or_404(CMSPlugin, pk=parent_id) placeholder = parent.placeholder position = request.POST.get('plugin_order', CMSPlugin.objects.filter(language=language, parent=parent).count()) # placeholder (non-page) add-plugin # Sanity check to make sure we're not getting bogus values from JavaScript: if settings.USE_I18N: if not language or not language in [lang[0] for lang in settings.LANGUAGES]: return HttpResponseBadRequest(force_text(_("Language must be set to a supported language!"))) if parent and parent.language != language: return HttpResponseBadRequest(force_text(_("Parent plugin language must be same as language!"))) else: language = settings.LANGUAGE_CODE plugin = CMSPlugin(language=language, plugin_type=plugin_type, position=position, placeholder=placeholder) if parent: plugin.position = CMSPlugin.objects.filter(parent=parent).count() plugin.parent_id = parent.pk plugin.save() self.post_add_plugin(request, placeholder, plugin) response = { 'url': force_text( admin_reverse("%s_%s_edit_plugin" % (self.model._meta.app_label, self.model._meta.model_name), args=[plugin.pk])), 'delete': force_text( admin_reverse("%s_%s_delete_plugin" % (self.model._meta.app_label, self.model._meta.model_name), args=[plugin.pk])), 'breadcrumb': plugin.get_breadcrumb(), } return HttpResponse(json.dumps(response), content_type='application/json')
def move_plugin(self, request): """ POST request with following parameters: -plugin_id -placeholder_id -plugin_language (optional) -plugin_parent (optional) -plugin_order (array, optional) """ plugin = CMSPlugin.objects.get(pk=int(request.POST['plugin_id'])) placeholder = Placeholder.objects.get(pk=request.POST['placeholder_id']) parent_id = request.POST.get('plugin_parent', None) language = request.POST.get('plugin_language', None) source_placeholder = plugin.placeholder if not parent_id: parent_id = None else: parent_id = int(parent_id) if not language and plugin.language: language = plugin.language order = request.POST.getlist("plugin_order[]") if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden(force_text(_("You have no permission to move this plugin"))) if not placeholder == source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) if parent_id: if plugin.parent_id != parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest(force_text('parent must be in the same placeholder')) if parent.language != language: return HttpResponseBadRequest(force_text('parent must be in the same language as plugin_language')) plugin.parent_id = parent.pk plugin.save() plugin = plugin.move(parent, pos='last-child') else: sibling = CMSPlugin.get_last_root_node() plugin.parent_id = None plugin.save() plugin = plugin.move(sibling, pos='right') for child in [plugin] + list(plugin.get_descendants()): child.placeholder = placeholder child.language = language child.save() plugins = reorder_plugins(placeholder, parent_id, language, order) if not plugins: return HttpResponseBadRequest('order parameter did not have all plugins of the same level in it') self.post_move_plugin(request, source_placeholder, placeholder, plugin) json_response = {'reload': requires_reload(PLUGIN_MOVE_ACTION, [plugin])} return HttpResponse(json.dumps(json_response), content_type='application/json')
def clean(self): from cms.utils.plugins import has_reached_plugin_limit data = self.cleaned_data if self.errors: return data language = data['plugin_language'] placeholder = data['placeholder_id'] parent_plugin = data.get('plugin_parent') if language not in get_language_list(): message = ugettext("Language must be set to a supported language!") self.add_error('plugin_language', message) return self.cleaned_data if parent_plugin: if parent_plugin.language != language: message = ugettext("Parent plugin language must be same as language!") self.add_error('plugin_language', message) return self.cleaned_data if parent_plugin.placeholder_id != placeholder.pk: message = ugettext("Parent plugin placeholder must be same as placeholder!") self.add_error('placeholder_id', message) return self.cleaned_data if placeholder.page: template = placeholder.page.get_template() else: template = None try: has_reached_plugin_limit( placeholder, self.plugin_type, language, template=template ) except PluginLimitReached as error: self.add_error(None, force_text(error)) return self.cleaned_data
def clean(self): from cms.utils.plugins import has_reached_plugin_limit data = self.cleaned_data if self.errors: return data language = data['plugin_language'] placeholder = data['placeholder_id'] parent_plugin = data.get('plugin_parent') if language not in get_language_list(): message = ugettext("Language must be set to a supported language!") self.add_error('plugin_language', message) return self.cleaned_data if parent_plugin: if parent_plugin.language != language: message = ugettext( "Parent plugin language must be same as language!") self.add_error('plugin_language', message) return self.cleaned_data if parent_plugin.placeholder_id != placeholder.pk: message = ugettext( "Parent plugin placeholder must be same as placeholder!") self.add_error('placeholder_id', message) return self.cleaned_data if placeholder.page: template = placeholder.page.get_template() else: template = None try: has_reached_plugin_limit(placeholder, data['plugin_type'], language, template=template) except PluginLimitReached as error: self.add_error(None, force_text(error)) return self.cleaned_data
def move_plugin(self, request): """ Performs a move or a "paste" operation (when «move_a_copy» is set) POST request with following parameters: - plugin_id - placeholder_id - plugin_language (optional) - plugin_parent (optional) - plugin_order (array, optional) - move_a_copy (Boolean, optional) (anything supplied here except a case- insensitive "false" is True) NOTE: If move_a_copy is set, the plugin_order should contain an item '__COPY__' with the desired destination of the copied plugin. """ # plugin_id and placeholder_id are required, so, if nothing is supplied, # an ValueError exception will be raised by get_int(). try: plugin_id = get_int(request.POST.get('plugin_id')) except TypeError: raise RuntimeError("'plugin_id' is a required parameter.") plugin = self._get_plugin_from_id(plugin_id) try: placeholder_id = get_int(request.POST.get('placeholder_id')) except TypeError: raise RuntimeError("'placeholder_id' is a required parameter.") except ValueError: raise RuntimeError("'placeholder_id' must be an integer string.") placeholder = Placeholder.objects.get(pk=placeholder_id) # The rest are optional parent_id = get_int(request.POST.get('plugin_parent', ""), None) language = request.POST.get('plugin_language', None) or plugin.language move_a_copy = request.POST.get('move_a_copy') move_a_copy = (move_a_copy and move_a_copy != "0" and move_a_copy.lower() != "false") move_to_clipboard = placeholder == request.toolbar.clipboard source_language = plugin.language source_placeholder = plugin.placeholder order = request.POST.getlist("plugin_order[]") if placeholder != source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) # order should be a list of plugin primary keys # it's important that the plugins being referenced # are all part of the same tree. exclude_from_order_check = ['__COPY__', str(plugin.pk)] ordered_plugin_ids = [int(pk) for pk in order if pk not in exclude_from_order_check] plugins_in_tree_count = ( placeholder .get_plugins(language) .filter(parent=parent_id, pk__in=ordered_plugin_ids) .count() ) if len(ordered_plugin_ids) != plugins_in_tree_count: # order does not match the tree on the db message = _('order parameter references plugins in different trees') return HttpResponseBadRequest(force_text(message)) # True if the plugin is not being moved from the clipboard # to a placeholder or from a placeholder to the clipboard. move_a_plugin = not move_a_copy and not move_to_clipboard if parent_id and plugin.parent_id != parent_id: target_parent = get_object_or_404(CMSPlugin, pk=parent_id) if move_a_plugin and target_parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest(force_text( _('parent must be in the same placeholder'))) if move_a_plugin and target_parent.language != language: return HttpResponseBadRequest(force_text( _('parent must be in the same language as ' 'plugin_language'))) elif parent_id: target_parent = plugin.parent else: target_parent = None new_plugin = None fetch_tree = False if move_a_copy and plugin.plugin_type == "PlaceholderPlugin": new_plugins = self._paste_placeholder( request, plugin=plugin, target_language=language, target_placeholder=placeholder, tree_order=order, ) elif move_a_copy: fetch_tree = True new_plugin = self._paste_plugin( request, plugin=plugin, target_parent=target_parent, target_language=language, target_placeholder=placeholder, tree_order=order, ) elif move_to_clipboard: new_plugin = self._cut_plugin( request, plugin=plugin, target_language=language, target_placeholder=placeholder, ) new_plugins = [new_plugin] else: fetch_tree = True new_plugin = self._move_plugin( request, plugin=plugin, target_parent=target_parent, target_language=language, target_placeholder=placeholder, tree_order=order, ) if new_plugin and fetch_tree: root = (new_plugin.parent or new_plugin) new_plugins = [root] + list(root.get_descendants().order_by('path')) # Mark the target placeholder as dirty placeholder.mark_as_dirty(language) if placeholder != source_placeholder: # Plugin is being moved or copied into a separate placeholder # Mark source placeholder as dirty source_placeholder.mark_as_dirty(source_language) data = get_plugin_tree_as_json(request, new_plugins) return HttpResponse(data, content_type='application/json')
def move_plugin(self, request): """ POST request with following parameters: -plugin_id -placeholder_id -plugin_language (optional) -plugin_parent (optional) -plugin_order (array, optional) """ plugin = CMSPlugin.objects.get(pk=int(request.POST['plugin_id'])) placeholder = Placeholder.objects.get(pk=request.POST['placeholder_id']) parent_id = request.POST.get('plugin_parent', None) language = request.POST.get('plugin_language', None) source_placeholder = plugin.placeholder if not parent_id: parent_id = None else: parent_id = int(parent_id) if not language and plugin.language: language = plugin.language order = request.POST.getlist("plugin_order[]") if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden(force_unicode(_("You have no permission to move this plugin"))) if plugin.parent_id != parent_id: if parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest(force_unicode('parent must be in the same placeholder')) if parent.language != language: return HttpResponseBadRequest(force_unicode('parent must be in the same language as plugin_language')) else: parent = None plugin.move_to(parent, position='last-child') if not placeholder == source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) plugin.save() for child in plugin.get_descendants(include_self=True): child.placeholder = placeholder child.language = language child.save() plugins = CMSPlugin.objects.filter(parent=parent_id, placeholder=placeholder, language=language).order_by('position') x = 0 for level_plugin in plugins: if order: x = 0 found = False for pk in order: if level_plugin.pk == int(pk): level_plugin.position = x level_plugin.save() found = True break x += 1 if not found: return HttpResponseBadRequest('order parameter did not have all plugins of the same level in it') else: level_plugin.position = x level_plugin.save() x += 1 self.post_move_plugin(request, source_placeholder, placeholder, plugin) json_response = {'reload': requires_reload(PLUGIN_MOVE_ACTION, [plugin])} if DJANGO_1_4: return HttpResponse(json.dumps(json_response), mimetype='application/json') else: return HttpResponse(json.dumps(json_response), content_type='application/json')
def move_plugin(self, request): """ Performs a move or a "paste" operation (when «move_a_copy» is set) POST request with following parameters: - plugin_id - placeholder_id - plugin_language (optional) - plugin_parent (optional) - plugin_order (array, optional) - move_a_copy (Boolean, optional) (anything supplied here except a case- insensitive "false" is True) NOTE: If move_a_copy is set, the plugin_order should contain an item '__COPY__' with the desired destination of the copied plugin. """ # plugin_id and placeholder_id are required, so, if nothing is supplied, # an ValueError exception will be raised by get_int(). try: plugin_id = get_int(request.POST.get('plugin_id')) except TypeError: raise RuntimeError("'plugin_id' is a required parameter.") plugin = (CMSPlugin.objects.select_related('placeholder').get( pk=plugin_id)) try: placeholder_id = get_int(request.POST.get('placeholder_id')) except TypeError: raise RuntimeError("'placeholder_id' is a required parameter.") except ValueError: raise RuntimeError("'placeholder_id' must be an integer string.") placeholder = Placeholder.objects.get(pk=placeholder_id) # The rest are optional parent_id = get_int(request.POST.get('plugin_parent', ""), None) language = request.POST.get('plugin_language', None) move_a_copy = request.POST.get('move_a_copy', False) move_a_copy = (move_a_copy and move_a_copy != "0" and move_a_copy.lower() != "false") source_language = plugin.language source_placeholder = plugin.placeholder if not language and plugin.language: language = plugin.language order = request.POST.getlist("plugin_order[]") if placeholder != source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) if move_a_copy: # "paste" if plugin.plugin_type == "PlaceholderPlugin": parent_id = None inst = plugin.get_plugin_instance()[0] plugins = inst.placeholder_ref.get_plugins() else: plugins = [plugin] + list(plugin.get_descendants()) if not self.has_copy_from_clipboard_permission( request, placeholder, plugins): return HttpResponseForbidden( force_text( _("You have no permission to paste this plugin"))) new_plugins = copy_plugins.copy_plugins_to( plugins, placeholder, language, parent_plugin_id=parent_id, ) top_plugins = [] top_parent = new_plugins[0][0].parent_id for new_plugin, old_plugin in new_plugins: if new_plugin.parent_id == top_parent: # NOTE: There is no need to save() the plugins here. new_plugin.position = old_plugin.position top_plugins.append(new_plugin) # Creates a list of string PKs of the top-level plugins ordered by # their position. top_plugins_pks = [ str(p.pk) for p in sorted(top_plugins, key=lambda x: x.position) ] if parent_id: parent = CMSPlugin.objects.get(pk=parent_id) for plugin in top_plugins: plugin.parent = parent plugin.placeholder = placeholder plugin.language = language plugin.save() # If an ordering was supplied, we should replace the item that has # been copied with the new copy if order: if '__COPY__' in order: copy_idx = order.index('__COPY__') del order[copy_idx] order[copy_idx:0] = top_plugins_pks else: order.extend(top_plugins_pks) # Set the plugin variable to point to the newly created plugin. plugin = new_plugins[0][0] else: # Regular move if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden( force_text( _("You have no permission to move this plugin"))) plugin_data = { 'language': language, 'placeholder': placeholder, } if parent_id: if plugin.parent_id != parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest( force_text( _('parent must be in the same placeholder'))) if parent.language != language: return HttpResponseBadRequest( force_text( _('parent must be in the same language as ' 'plugin_language'))) plugin = plugin.update(refresh=True, parent=parent, **plugin_data) plugin = plugin.move(parent, pos='last-child') else: plugin = plugin.update(refresh=True, **plugin_data) else: target = CMSPlugin.get_last_root_node() plugin = plugin.update(refresh=True, parent=None, **plugin_data) plugin = plugin.move(target, pos='right') # Update all children to match the parent's # language and placeholder plugin.get_descendants().update(**plugin_data) if order: # order should be a list of plugin primary keys # it's important that the plugins being referenced # are all part of the same tree. order = [int(pk) for pk in order] plugins_in_tree = CMSPlugin.objects.filter( parent=parent_id, placeholder=placeholder, language=language, pk__in=order, ) if len(order) != plugins_in_tree.count(): # Seems like order does not match the tree on the db message = _( 'order parameter references plugins in different trees') return HttpResponseBadRequest(force_text(message)) # Mark the target placeholder as dirty placeholder.mark_as_dirty(language) if placeholder != source_placeholder: # Plugin is being moved or copied into a separate placeholder # Mark source placeholder as dirty source_placeholder.mark_as_dirty(source_language) reorder_plugins(placeholder, parent_id, language, order) # When this is executed we are in the admin class of the source placeholder # It can be a page or a model with a placeholder field. # Because of this we need to get the admin class instance of the # target placeholder and call post_move_plugin() on it. # By doing this we make sure that both the source and target are # informed of the operation. target_placeholder_admin = self._get_attached_admin(placeholder) if move_a_copy: # "paste" plugins = list(plugin.get_tree()) self.post_copy_plugins(request, source_placeholder, placeholder, plugins) if (target_placeholder_admin and target_placeholder_admin.model != self.model): target_placeholder_admin.post_copy_plugins( request, source_placeholder=source_placeholder, target_placeholder=placeholder, plugins=plugins, ) else: self.post_move_plugin(request, source_placeholder, placeholder, plugin) if (target_placeholder_admin and target_placeholder_admin.model != self.model): target_placeholder_admin.post_move_plugin( request, source_placeholder=source_placeholder, target_placeholder=placeholder, plugin=plugin, ) try: language = request.toolbar.toolbar_language except AttributeError: language = get_language_from_request(request) with force_language(language): plugin_urls = plugin.get_action_urls() json_response = { 'urls': plugin_urls, 'reload': move_a_copy or requires_reload(PLUGIN_MOVE_ACTION, [plugin]) } return HttpResponse(json.dumps(json_response), content_type='application/json')
def move_plugin(self, request): """ POST request with following parameters: -plugin_id -placeholder_id -plugin_language (optional) -plugin_parent (optional) -plugin_order (array, optional) """ plugin = CMSPlugin.objects.get(pk=int(request.POST['plugin_id'])) placeholder = Placeholder.objects.get(pk=request.POST['placeholder_id']) parent_id = request.POST.get('plugin_parent', None) language = request.POST.get('plugin_language', plugin.language) source_placeholder = plugin.placeholder if not parent_id: parent_id = None else: parent_id = int(parent_id) order = request.POST.getlist("plugin_order[]") if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden(force_unicode(_("You have no permission to move this plugin"))) if plugin.parent_id != parent_id: if parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest(force_unicode('parent must be in the same placeholder')) if parent.language != language: return HttpResponseBadRequest(force_unicode('parent must be in the same language as plugin_language')) else: parent = None plugin.move_to(parent, position='last-child') try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) plugin.save() for child in plugin.get_descendants(include_self=True): child.placeholder = placeholder child.language = language child.save() plugins = CMSPlugin.objects.filter(parent=parent_id, placeholder=placeholder, language=language).order_by('position') x = 0 for level_plugin in plugins: if order: x = 0 found = False for pk in order: if level_plugin.pk == int(pk): level_plugin.position = x level_plugin.save() found = True break x += 1 if not found: return HttpResponseBadRequest('order parameter did not have all plugins of the same level in it') else: level_plugin.position = x level_plugin.save() x += 1 self.post_move_plugin(request, source_placeholder, placeholder, plugin) json_response = {'reload': requires_reload(PLUGIN_MOVE_ACTION, [plugin])} return HttpResponse(json.dumps(json_response), content_type='application/json')
def move_plugin(self, request): """ Performs a move or a "paste" operation (when «move_a_copy» is set) POST request with following parameters: - plugin_id - placeholder_id - plugin_language (optional) - plugin_parent (optional) - plugin_order (array, optional) - move_a_copy (Boolean, optional) (anything supplied here except a case- insensitive "false" is True) NOTE: If move_a_copy is set, the plugin_order should contain an item '__COPY__' with the desired destination of the copied plugin. """ # plugin_id and placeholder_id are required, so, if nothing is supplied, # an ValueError exception will be raised by get_int(). try: plugin_id = get_int(request.POST.get('plugin_id')) except TypeError: raise RuntimeError("'plugin_id' is a required parameter.") plugin = CMSPlugin.objects.get(pk=plugin_id) try: placeholder_id = get_int(request.POST.get('placeholder_id')) except TypeError: raise RuntimeError("'placeholder_id' is a required parameter.") except ValueError: raise RuntimeError("'placeholder_id' must be an integer string.") placeholder = Placeholder.objects.get(pk=placeholder_id) # The rest are optional parent_id = get_int(request.POST.get('plugin_parent', ""), None) language = request.POST.get('plugin_language', None) move_a_copy = request.POST.get('move_a_copy', False) move_a_copy = (move_a_copy and move_a_copy != "0" and move_a_copy.lower() != "false") source_placeholder = plugin.placeholder if not language and plugin.language: language = plugin.language order = request.POST.getlist("plugin_order[]") if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden( force_text(_("You have no permission to move this plugin"))) if placeholder != source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) if move_a_copy: # "paste" if plugin.plugin_type == "PlaceholderPlugin": parent_id = None inst = plugin.get_plugin_instance()[0] plugins = inst.placeholder_ref.get_plugins() else: plugins = [plugin] + list(plugin.get_descendants()) new_plugins = copy_plugins.copy_plugins_to( plugins, placeholder, language, parent_plugin_id=parent_id, ) top_plugins = [] top_parent = new_plugins[0][0].parent_id for new_plugin, old_plugin in new_plugins: if new_plugin.parent_id == top_parent: # NOTE: There is no need to save() the plugins here. new_plugin.position = old_plugin.position top_plugins.append(new_plugin) # Creates a list of string PKs of the top-level plugins ordered by # their position. top_plugins_pks = [str(p.pk) for p in sorted( top_plugins, key=lambda x: x.position)] if parent_id: parent = CMSPlugin.objects.get(pk=parent_id) for plugin in top_plugins: plugin.parent = parent plugin.placeholder = placeholder plugin.language = language plugin.save() # If an ordering was supplied, we should replace the item that has # been copied with the new copy if order: if '__COPY__' in order: copy_idx = order.index('__COPY__') del order[copy_idx] order[copy_idx:0] = top_plugins_pks else: order.extend(top_plugins_pks) # Set the plugin variable to point to the newly created plugin. plugin = new_plugins[0][0] else: # Regular move if parent_id: if plugin.parent_id != parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest(force_text( _('parent must be in the same placeholder'))) if parent.language != language: return HttpResponseBadRequest(force_text( _('parent must be in the same language as ' 'plugin_language'))) plugin.parent_id = parent.pk plugin.language = language plugin.save() plugin = plugin.move(parent, pos='last-child') else: sibling = CMSPlugin.get_last_root_node() plugin.parent = plugin.parent_id = None plugin.placeholder = placeholder plugin.save() plugin = plugin.move(sibling, pos='right') plugins = [plugin] + list(plugin.get_descendants()) # Don't neglect the children for child in plugins: child.placeholder = placeholder child.language = language child.save() reorder_plugins(placeholder, parent_id, language, order) # When this is executed we are in the admin class of the source placeholder # It can be a page or a model with a placeholder field. # Because of this we need to get the admin class instance of the # target placeholder and call post_move_plugin() on it. # By doing this we make sure that both the source and target are # informed of the operation. target_placeholder_admin = self._get_attached_admin(placeholder) if move_a_copy: # "paste" self.post_copy_plugins(request, source_placeholder, placeholder, plugins) if (target_placeholder_admin and target_placeholder_admin.model != self.model): target_placeholder_admin.post_copy_plugins( request, source_placeholder=source_placeholder, target_placeholder=placeholder, plugins=plugins, ) else: self.post_move_plugin(request, source_placeholder, placeholder, plugin) if (target_placeholder_admin and target_placeholder_admin.model != self.model): target_placeholder_admin.post_move_plugin( request, source_placeholder=source_placeholder, target_placeholder=placeholder, plugin=plugin, ) try: language = request.toolbar.toolbar_language except AttributeError: language = get_language_from_request(request) with force_language(language): plugin_urls = plugin.get_action_urls() json_response = { 'urls': plugin_urls, 'reload': move_a_copy or requires_reload( PLUGIN_MOVE_ACTION, [plugin]) } return HttpResponse( json.dumps(json_response), content_type='application/json')
def add_module_view(cls, request, module_id): if not request.user.is_staff: raise PermissionDenied module_plugin = get_object_or_404(cls.model, pk=module_id) if request.method == 'GET': form = AddModuleForm(request.GET) else: form = AddModuleForm(request.POST) if not form.is_valid(): return HttpResponseBadRequest('Form received unexpected values') if request.method == 'GET': opts = cls.model._meta context = { 'form': form, 'has_change_permission': True, 'opts': opts, 'root_path': reverse('admin:index'), 'is_popup': True, 'app_label': opts.app_label, 'module': module_plugin, } return render(request, 'djangocms_modules/add_module.html', context) language = form.cleaned_data['target_language'] target_placeholder = form.cleaned_data.get('target_placeholder') if target_placeholder: target_plugin = None else: target_plugin = form.cleaned_data['target_plugin'] target_placeholder = target_plugin.placeholder if not target_placeholder.has_add_plugin_permission( request.user, module_plugin.plugin_type): return HttpResponseForbidden( force_text(_('You do not have permission to add a plugin.'))) pl_admin = target_placeholder._get_attached_admin() if pl_admin: template = pl_admin.get_placeholder_template( request, target_placeholder) else: template = None try: has_reached_plugin_limit( target_placeholder, module_plugin.plugin_type, language=language, template=template, ) except PluginLimitReached as er: return HttpResponseBadRequest(er) tree_order = target_placeholder.get_plugin_tree_order( language=language, parent_id=target_plugin, ) m_admin = module_plugin.placeholder._get_attached_admin() # This is needed only because we of the operation signal requiring # a version of the plugin that's not been committed to the db yet. new_module_plugin = copy.copy(module_plugin) new_module_plugin.pk = None new_module_plugin.placeholder = target_placeholder new_module_plugin.parent = None new_module_plugin.position = len(tree_order) + 1 operation_token = m_admin._send_pre_placeholder_operation( request=request, placeholder=target_placeholder, tree_order=tree_order, operation=operations.ADD_PLUGIN, plugin=new_module_plugin, ) new_plugins = copy_plugins_to_placeholder( plugins=list(module_plugin.get_unbound_plugins()), placeholder=target_placeholder, language=language, root_plugin=target_plugin, ) tree_order.append(new_plugins[0].pk) reorder_plugins( target_placeholder, parent_id=target_plugin, language=language, order=tree_order, ) new_module_plugin = cls.model.objects.get(pk=new_plugins[0].pk) m_admin._send_post_placeholder_operation( request, operation=operations.ADD_PLUGIN, token=operation_token, plugin=new_module_plugin, placeholder=new_module_plugin.placeholder, tree_order=tree_order, ) response = cls().render_close_frame(request, obj=new_module_plugin) if form.cleaned_data.get('disable_future_confirmation'): response.set_cookie(key=cls.confirmation_cookie_name, value=True) return response
def add_plugin(self, request): """ POST request should have the following data: - placeholder_id - plugin_type - plugin_language - plugin_parent (optional) """ plugin_type = request.POST["plugin_type"] placeholder_id = request.POST.get("placeholder_id", None) parent_id = request.POST.get("parent_id", None) if parent_id: warnings.warn( "parent_id is deprecated and will be removed in 3.1, use plugin_parent instead", DeprecationWarning ) if not parent_id: parent_id = request.POST.get("plugin_parent", None) placeholder = get_object_or_404(Placeholder, pk=placeholder_id) if not self.has_add_plugin_permission(request, placeholder, plugin_type): return HttpResponseForbidden(force_unicode(_("You do not have permission to add a plugin"))) parent = None language = request.POST.get("plugin_language") or get_language_from_request(request) try: has_reached_plugin_limit( placeholder, plugin_type, language, template=self.get_placeholder_template(request, placeholder) ) except PluginLimitReached as er: return HttpResponseBadRequest(er) # page add-plugin if not parent_id: position = request.POST.get( "plugin_order", CMSPlugin.objects.filter(language=language, placeholder=placeholder).count() ) # in-plugin add-plugin else: parent = get_object_or_404(CMSPlugin, pk=parent_id) placeholder = parent.placeholder position = request.POST.get( "plugin_order", CMSPlugin.objects.filter(language=language, parent=parent).count() ) # placeholder (non-page) add-plugin # Sanity check to make sure we're not getting bogus values from JavaScript: if settings.USE_I18N: if not language or not language in [lang[0] for lang in settings.LANGUAGES]: return HttpResponseBadRequest(force_unicode(_("Language must be set to a supported language!"))) if parent and parent.language != language: return HttpResponseBadRequest(force_unicode(_("Parent plugin language must be same as language!"))) else: language = settings.LANGUAGE_CODE plugin = CMSPlugin(language=language, plugin_type=plugin_type, position=position, placeholder=placeholder) if parent: plugin.position = CMSPlugin.objects.filter(parent=parent).count() plugin.insert_at(parent, position="last-child", save=False) plugin.save() self.post_add_plugin(request, placeholder, plugin) response = { "url": force_unicode( reverse( "admin:%s_%s_edit_plugin" % (self.model._meta.app_label, self.model._meta.module_name), args=[plugin.pk], ) ), "delete": force_unicode( reverse( "admin:%s_%s_delete_plugin" % (self.model._meta.app_label, self.model._meta.module_name), args=[plugin.pk], ) ), "breadcrumb": plugin.get_breadcrumb(), } return HttpResponse(json.dumps(response), content_type="application/json")
def move_plugin(self, request): """ Performs a move or a "paste" operation (when «move_a_copy» is set) POST request with following parameters: - plugin_id - placeholder_id - plugin_language (optional) - plugin_parent (optional) - plugin_order (array, optional) - move_a_copy (Boolean, optional) (anything supplied here except a case- insensitive "false" is True) NOTE: If move_a_copy is set, the plugin_order should contain an item '__COPY__' with the desired destination of the copied plugin. """ # plugin_id and placeholder_id are required, so, if nothing is supplied, # an ValueError exception will be raised by get_int(). try: plugin_id = get_int(request.POST.get('plugin_id')) except TypeError: raise RuntimeError("'plugin_id' is a required parameter.") plugin = CMSPlugin.objects.get(pk=plugin_id) try: placeholder_id = get_int(request.POST.get('placeholder_id')) except TypeError: raise RuntimeError("'placeholder_id' is a required parameter.") except ValueError: raise RuntimeError("'placeholder_id' must be an integer string.") placeholder = Placeholder.objects.get(pk=placeholder_id) # The rest are optional parent_id = get_int(request.POST.get('plugin_parent', ""), None) language = request.POST.get('plugin_language', None) move_a_copy = request.POST.get('move_a_copy', False) move_a_copy = (move_a_copy and move_a_copy != "0" and move_a_copy.lower() != "false") source_placeholder = plugin.placeholder if not language and plugin.language: language = plugin.language order = request.POST.getlist("plugin_order[]") if not self.has_move_plugin_permission(request, plugin, placeholder): return HttpResponseForbidden( force_text(_("You have no permission to move this plugin"))) if placeholder != source_placeholder: try: template = self.get_placeholder_template(request, placeholder) has_reached_plugin_limit(placeholder, plugin.plugin_type, plugin.language, template=template) except PluginLimitReached as er: return HttpResponseBadRequest(er) if move_a_copy: # "paste" if plugin.plugin_type == "PlaceholderPlugin": inst, _plugin = plugin.get_plugin_instance() source_plugins = inst.placeholder_ref.get_plugins() new_plugins = copy_plugins.copy_plugins_to( source_plugins, placeholder, language) else: source_plugins = [plugin] + list(plugin.get_descendants()) new_plugins = copy_plugins.copy_plugins_to( source_plugins, placeholder, language, parent_id) top_plugins = [] top_parent = new_plugins[0][0].parent_id for new_plugin, old_plugin in new_plugins: if new_plugin.parent_id == top_parent: # NOTE: There is no need to save() the plugins here. new_plugin.position = old_plugin.position top_plugins.append(new_plugin) # Creates a list of string PKs of the top-level plugins ordered by # their position. top_plugins_pks = [ str(p.pk) for p in sorted(top_plugins, key=lambda x: x.position) ] if parent_id: parent = CMSPlugin.objects.get(pk=parent_id) for plugin in top_plugins: plugin.parent = parent plugin.placeholder = placeholder plugin.language = language plugin.save() # If an ordering was supplied, we should replace the item that has # been copied with the new copy if order: if '__COPY__' in order: copy_idx = order.index('__COPY__') del order[copy_idx] order[copy_idx:0] = top_plugins_pks else: order.extend(top_plugins_pks) else: # Regular move if parent_id: if plugin.parent_id != parent_id: parent = CMSPlugin.objects.get(pk=parent_id) if parent.placeholder_id != placeholder.pk: return HttpResponseBadRequest( force_text( _('parent must be in the same placeholder'))) if parent.language != language: return HttpResponseBadRequest( force_text( _('parent must be in the same language as ' 'plugin_language'))) plugin.parent_id = parent.pk plugin.language = language plugin.save() plugin = plugin.move(parent, pos='last-child') else: sibling = CMSPlugin.get_last_root_node() plugin.parent = plugin.parent_id = None plugin.placeholder = placeholder plugin.save() plugin = plugin.move(sibling, pos='right') # Don't neglect the children for child in [plugin] + list(plugin.get_descendants()): child.placeholder = placeholder child.language = language child.save() reorder_plugins(placeholder, parent_id, language, order) self.post_move_plugin(request, source_placeholder, placeholder, plugin) json_response = { 'reload': move_a_copy or requires_reload(PLUGIN_MOVE_ACTION, [plugin]) } return HttpResponse(json.dumps(json_response), content_type='application/json')