Exemple #1
0
    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')
Exemple #2
0
    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')
Exemple #3
0
    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')
Exemple #4
0
    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
Exemple #5
0
    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')
Exemple #11
0
    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")
Exemple #13
0
    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')