Exemple #1
0
    def test_inherit_plugin_with_empty_plugin(self):
        inheritfrompage = create_page('page to inherit from',
                                      'nav_playground.html',
                                      'en', published=True)

        body = inheritfrompage.placeholders.get(slot="body")
        empty_plugin = CMSPlugin(
            plugin_type='TextPlugin', # create an empty plugin
            placeholder=body,
            position=1,
            language='en',
        )
        empty_plugin.insert_at(None, position='last-child', save=True)
        other_page = create_page('other page', 'nav_playground.html', 'en', published=True)
        inherited_body = other_page.placeholders.get(slot="body")
        inherit_plugin = InheritPagePlaceholder(
            plugin_type='InheritPagePlaceholderPlugin',
            placeholder=inherited_body,
            position=1,
            language='en',
            from_page=inheritfrompage,
            from_language='en'
        )
        inherit_plugin.insert_at(None, position='last-child', save=True)
        add_plugin(inherited_body, "TextPlugin", "en", body="foobar")
        # this should not fail, even if there in an empty plugin
        rendered = inherited_body.render(context=self.get_context(other_page.get_absolute_url()), width=200)
        self.assertIn("foobar", rendered)
Exemple #2
0
    def add_plugin(self, request):
        # only allow POST
        if request.method != "POST":
            raise Http404
        plugin_type = request.POST['plugin_type']
        if not has_plugin_permission(request.user, plugin_type, "add"):
            return HttpResponseForbidden(
                "You don't have permission to add plugins")

        placeholder_id = request.POST.get('placeholder', None)
        position = None
        language = get_language_from_request(request)
        parent = None
        # check if we got a placeholder (id)
        if placeholder_id:
            placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
        else:  # else get the parent_id
            parent_id = request.POST.get('parent_id', None)
            if not parent_id:  # if we get neither a placeholder nor a parent, bail out
                raise Http404
            parent = get_object_or_404(CMSPlugin, pk=parent_id)
            placeholder = parent.placeholder

        # check add permissions on placeholder
        if not placeholder.has_add_permission(request):
            return HttpResponseForbidden(
                _("You don't have permission to add content here."))

        # check the limits defined in CMS_PLACEHOLDER_CONF for this placeholder
        limits = settings.CMS_PLACEHOLDER_CONF.get(placeholder.slot,
                                                   {}).get('limits', None)
        if limits:
            count = placeholder.cmsplugin_set.count()
            global_limit = limits.get("global", None)
            type_limit = limits.get(plugin_type, None)
            # check the global limit first
            if global_limit and count >= global_limit:
                return HttpResponseBadRequest(
                    "This placeholder already has the maximum number of plugins."
                )
            elif type_limit:  # then check the type specific limit
                type_count = CMSPlugin.objects.filter(
                    language=language,
                    placeholder=placeholder,
                    plugin_type=plugin_type).count()
                if type_count >= type_limit:
                    return HttpResponseBadRequest(
                        "This placeholder already has the maximum number (%s) "
                        "of %s plugins." % (type_limit, plugin_type))

        # actually add the plugin
        plugin = CMSPlugin(language=language,
                           plugin_type=plugin_type,
                           position=position,
                           placeholder=placeholder,
                           parent=parent)
        plugin.save()

        # returns it's ID as response
        return HttpResponse(str(plugin.pk))
    def save_body(self, placeholder, desc):
        language = settings.LANGUAGE_CODE
        try:
            plugin = CMSPlugin.objects.get(placeholder=placeholder, position=0, language=language)
            plugin.body = desc
        except CMSPlugin.DoesNotExist:
            plugin = CMSPlugin(language=language, plugin_type="TextPlugin", position=0, placeholder=placeholder)
            plugin.save()

        if plugin:
            text = Text()
            # text.set_base_attr(plugin)
            text.pk = plugin.pk
            text.id = plugin.pk
            text.placeholder = placeholder
            text.position = plugin.position
            text.plugin_type = plugin.plugin_type
            text.tree_id = plugin.tree_id
            text.lft = plugin.lft
            text.rght = plugin.rght
            text.level = plugin.level
            text.cmsplugin_ptr = plugin
            text.publisher_public_id = None
            text.public_id = None
            text.published = False
            text.language = language
            text.body = desc
            text.save()
Exemple #4
0
    def add_plugin(self,
                   user=None,
                   page=None,
                   placeholder=None,
                   language='en',
                   body=''):
        if not placeholder:
            if page:
                placeholder = page.placeholders.get(
                    slot__iexact='Right-Column')
            else:
                placeholder = page.placeholders.get(
                    slot__iexact='Right-Column')

        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=language)
        plugin_base.insert_at(None, position='last-child', commit=False)

        plugin = Text(body=body)
        plugin_base.set_base_attr(plugin)
        plugin.save()
        return plugin.pk
Exemple #5
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)
    
    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
        
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=1, 
        language=language
    )
    plugin_base.insert_at(None, position=position, save=False)
            
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #6
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)
    
    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
        

    max_pos = CMSPlugin.objects.filter(language=language,
        placeholder=placeholder).aggregate(Max('position'))['position__max'] or 0

    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=max_pos + 1,
        language=language
    )
    plugin_base.insert_at(target, position=position, save=False)
            
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
    def save_body(self, placeholder, desc):
        language = settings.LANGUAGE_CODE
        try:
            plugin = CMSPlugin.objects.get(placeholder=placeholder,
                                           position=0,
                                           language=language)
            plugin.body = desc
        except CMSPlugin.DoesNotExist:
            plugin = CMSPlugin(language=language,
                               plugin_type='TextPlugin',
                               position=0,
                               placeholder=placeholder)
            plugin.save()

        if plugin:
            text = Text()
            #text.set_base_attr(plugin)
            text.pk = plugin.pk
            text.id = plugin.pk
            text.placeholder = placeholder
            text.position = plugin.position
            text.plugin_type = plugin.plugin_type
            text.tree_id = plugin.tree_id
            text.lft = plugin.lft
            text.rght = plugin.rght
            text.level = plugin.level
            text.cmsplugin_ptr = plugin
            text.publisher_public_id = None
            text.public_id = None
            text.published = False
            text.language = language
            text.body = desc
            text.save()
Exemple #8
0
    def test_delete_with_plugins(self):
        """
        Check that plugins and placeholders get correctly deleted when we delete
        a page!
        """
        home = create_page("home", "nav_playground.html", "en")
        page = create_page("page", "nav_playground.html", "en")
        page.rescan_placeholders() # create placeholders
        placeholder = page.placeholders.all()[0]
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=settings.LANGUAGES[0][0]
        )
        plugin_base = plugin_base.add_root(instance=plugin_base)

        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        self.assertEqual(CMSPlugin.objects.count(), 1)
        self.assertEqual(Text.objects.count(), 1)
        self.assertTrue(Placeholder.objects.count() > 2)
        page.delete()
        home.delete()
        self.assertEqual(CMSPlugin.objects.count(), 0)
        self.assertEqual(Text.objects.count(), 0)
        self.assertEqual(Placeholder.objects.count(), 0)
        self.assertEqual(Page.objects.count(), 0)
Exemple #9
0
    def test_delete_with_plugins(self):
        """
        Check that plugins and placeholders get correctly deleted when we delete
        a page!
        """
        home = create_page("home", "nav_playground.html", "en")
        page = create_page("page", "nav_playground.html", "en")
        page.rescan_placeholders() # create placeholders
        placeholder = page.placeholders.all()[0]
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=settings.LANGUAGES[0][0]
        )
        plugin_base.insert_at(None, position='last-child', save=False)

        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        self.assertEqual(CMSPlugin.objects.count(), 1)
        self.assertEqual(Text.objects.count(), 1)
        self.assertTrue(Placeholder.objects.count() > 2)
        page.delete()
        home.delete()
        self.assertEqual(CMSPlugin.objects.count(), 0)
        self.assertEqual(Text.objects.count(), 0)
        self.assertEqual(Placeholder.objects.count(), 0)
        self.assertEqual(Page.objects.count(), 0)
    def add_plugin(self, request):
        # only allow POST
        if request.method != "POST":
            raise Http404
        plugin_type = request.POST['plugin_type']
        if not has_plugin_permission(request.user, plugin_type, "add"):
            return HttpResponseForbidden("You don't have permission to add plugins")

        placeholder_id = request.POST.get('placeholder', None)
        position = None
        language = get_language_from_request(request)
        parent = None
        # check if we got a placeholder (id)
        if placeholder_id:
            placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
        else: # else get the parent_id
            parent_id = request.POST.get('parent_id', None)
            if not parent_id: # if we get neither a placeholder nor a parent, bail out
                raise Http404
            parent = get_object_or_404(CMSPlugin, pk=parent_id)
            placeholder = parent.placeholder
        
        # check add permissions on placeholder
        if not placeholder.has_add_permission(request):
            return HttpResponseForbidden(_("You don't have permission to add content here."))
        
        # check the limits defined in CMS_PLACEHOLDER_CONF for this placeholder
        limits = settings.CMS_PLACEHOLDER_CONF.get(placeholder.slot, {}).get('limits', None)
        if limits:
            count = placeholder.cmsplugin_set.count()
            global_limit = limits.get("global", None)
            type_limit = limits.get(plugin_type, None)
            # check the global limit first
            if global_limit and count >= global_limit:
                return HttpResponseBadRequest(
                    "This placeholder already has the maximum number of plugins."
                )
            elif type_limit: # then check the type specific limit
                type_count = CMSPlugin.objects.filter(
                    language=language, placeholder=placeholder, plugin_type=plugin_type
                ).count()
                if type_count >= type_limit:
                    return HttpResponseBadRequest(
                        "This placeholder already has the maximum number (%s) "
                        "of %s plugins." % (type_limit, plugin_type)
                    )

        # position plugin at the end of the list
        position = CMSPlugin.objects.filter(placeholder=placeholder).count()

        # actually add the plugin
        plugin = CMSPlugin(language=language, plugin_type=plugin_type,
            position=position, placeholder=placeholder, parent=parent) 
        plugin.save()
        
        # returns it's ID as response
        return HttpResponse(str(plugin.pk))
 def add_plugin(self, request):
     if request.method != "POST":
         raise Http404
     plugin_type = request.POST['plugin_type']
     placeholder_id = request.POST['placeholder']
     placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
     position = None
     language = get_language_from_request(request)
     plugin = CMSPlugin(language=language, plugin_type=plugin_type,
         position=position, placeholder=placeholder) 
     plugin.save()
     return HttpResponse(str(plugin.pk))
Exemple #12
0
    def test_list_plugins(self):
        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        link_plugin = add_plugin(placeholder,
                                 "LinkPlugin",
                                 "en",
                                 name="A Link",
                                 url="https://www.django-cms.org")
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 2)
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type="LinkPlugin").count(), 1)

        # create a CMSPlugin with an unsaved instance
        instanceless_plugin = CMSPlugin(language="en",
                                        plugin_type="TextPlugin")
        instanceless_plugin.save()

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        report = plugin_report()

        # there should be reports for three plugin types
        self.assertEqual(len(report), 3)

        # check the bogus plugin
        bogus_plugins_report = report[0]
        self.assertEqual(bogus_plugins_report["model"], None)

        self.assertEqual(bogus_plugins_report["type"], u'BogusPlugin')

        self.assertEqual(bogus_plugins_report["instances"][0], bogus_plugin)

        # check the link plugin
        link_plugins_report = report[1]
        self.assertEqual(link_plugins_report["model"], link_plugin.__class__)

        self.assertEqual(link_plugins_report["type"], u'LinkPlugin')

        self.assertEqual(
            link_plugins_report["instances"][0].get_plugin_instance()[0],
            link_plugin)

        # check the text plugins
        text_plugins_report = report[2]
        self.assertEqual(text_plugins_report["model"], TextPlugin.model)

        self.assertEqual(text_plugins_report["type"], u'TextPlugin')

        self.assertEqual(len(text_plugins_report["instances"]), 3)

        self.assertEqual(text_plugins_report["instances"][2],
                         instanceless_plugin)

        self.assertEqual(text_plugins_report["unsaved_instances"],
                         [instanceless_plugin])
Exemple #13
0
    def test_check_plugin_instances(self):
        self.assertCheck(True, warnings=0, errors=0)

        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder,
                   "LinkPlugin",
                   "en",
                   name="A Link",
                   external_link="https://www.django-cms.org")

        # create a CMSPlugin with an unsaved instance
        instanceless_plugin = CMSPlugin(language="en",
                                        plugin_type="TextPlugin")
        instanceless_plugin.save()

        self.assertCheck(False, warnings=0, errors=2)

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        self.assertCheck(False, warnings=0, errors=3)
    def test_check_plugin_instances(self):
        self.assertCheck(True, warnings=0, errors=0)

        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp"]
        with SettingsOverride(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            link_plugin = add_plugin(placeholder,
                                     "LinkPlugin",
                                     "en",
                                     name="A Link",
                                     url="https://www.django-cms.org")

            # create a CMSPlugin with an unsaved instance
            instanceless_plugin = CMSPlugin(language="en",
                                            plugin_type="TextPlugin")
            instanceless_plugin.save()

            self.assertCheck(False, warnings=0, errors=2)

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            self.assertCheck(False, warnings=0, errors=3)
Exemple #15
0
    def test_empty_plugin_is_ignored(self):
        page = create_page("page", "nav_playground.html", "en")

        placeholder = page.placeholders.get(slot='body')

        plugin = CMSPlugin(plugin_type='TextPlugin',
                           placeholder=placeholder,
                           position=1,
                           language=self.FIRST_LANG)
        plugin.insert_at(None, position='last-child', save=True)

        # this should not raise any errors, but just ignore the empty plugin
        out = placeholder.render(self.get_context(), width=300)
        self.assertFalse(len(out))
        self.assertFalse(len(placeholder._en_plugins_cache))
Exemple #16
0
    def test_delete_orphaned_plugins(self):
        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp"]
        with SettingsOverride(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            link_plugin = add_plugin(placeholder,
                                     "LinkPlugin",
                                     "en",
                                     name="A Link",
                                     url="https://www.django-cms.org")

            instanceless_plugin = CMSPlugin(language="en",
                                            plugin_type="TextPlugin")
            instanceless_plugin.save()

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            report = plugin_report()

            # there should be reports for three plugin types
            self.assertEqual(len(report), 3)

            # check the bogus plugin
            bogus_plugins_report = report[0]
            self.assertEqual(len(bogus_plugins_report["instances"]), 1)

            # check the link plugin
            link_plugins_report = report[1]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[2]
            self.assertEqual(len(text_plugins_report["instances"]), 3)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 1)

            management.call_command('cms',
                                    'delete_orphaned_plugins',
                                    stdout=StringIO(),
                                    interactive=False)
            report = plugin_report()

            # there should be reports for two plugin types (one should have been deleted)
            self.assertEqual(len(report), 2)

            # check the link plugin
            link_plugins_report = report[0]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[1]
            self.assertEqual(len(text_plugins_report["instances"]), 2)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 0)
Exemple #17
0
    def test_empty_plugin_is_ignored(self):
        page = create_page("page", "nav_playground.html", "en")

        placeholder = page.placeholders.get(slot='body')

        plugin = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=self.FIRST_LANG)
        plugin.insert_at(None, position='last-child', save=True)

        # this should not raise any errors, but just ignore the empty plugin
        out = placeholder.render(self.get_context(), width=300)
        self.assertFalse(len(out))
        self.assertFalse(len(placeholder._en_plugins_cache))
    def _cut_plugin(self, request, plugin, target_language,  target_placeholder):
        if not self.has_move_plugin_permission(request, plugin, target_placeholder):
            message = force_str(_("You have no permission to cut this plugin"))
            raise PermissionDenied(message)

        plugin_data = {
            'language': target_language,
            'placeholder': target_placeholder,
        }

        source_language = plugin.language
        source_placeholder = plugin.placeholder
        source_tree_order = source_placeholder.get_plugin_tree_order(
            language=source_language,
            parent_id=plugin.parent_id,
        )

        action_token = self._send_pre_placeholder_operation(
            request,
            operation=operations.CUT_PLUGIN,
            plugin=plugin,
            clipboard=target_placeholder,
            clipboard_language=target_language,
            source_language=source_language,
            source_placeholder=source_placeholder,
            source_parent_id=plugin.parent_id,
            source_order=source_tree_order,
        )

        # Empty the clipboard
        target_placeholder.clear()

        target = CMSPlugin.get_last_root_node()
        updated_plugin = plugin.update(refresh=True, parent=None, **plugin_data)
        updated_plugin = updated_plugin.move(target, pos='right')

        # Update all children to match the parent's
        # language and placeholder (clipboard)
        updated_plugin.get_descendants().update(**plugin_data)

        # Avoid query by removing the plugin being moved
        # from the source order
        new_source_order = list(source_tree_order)
        new_source_order.remove(updated_plugin.pk)

        source_placeholder.mark_as_dirty(target_language, clear_cache=False)

        self._send_post_placeholder_operation(
            request,
            operation=operations.CUT_PLUGIN,
            token=action_token,
            plugin=updated_plugin.get_bound_plugin(),
            clipboard=target_placeholder,
            clipboard_language=target_language,
            source_language=source_language,
            source_placeholder=source_placeholder,
            source_parent_id=plugin.parent_id,
            source_order=new_source_order,
        )
        return updated_plugin
Exemple #19
0
    def _copy_plugin_to_clipboard(self, request, source_placeholder,
                                  target_placeholder):
        source_language = request.POST['source_language']
        source_plugin_id = request.POST.get('source_plugin_id')
        target_language = request.POST['target_language']

        source_plugin = get_object_or_404(
            CMSPlugin,
            pk=source_plugin_id,
            language=source_language,
        )

        old_plugins = (CMSPlugin.get_tree(parent=source_plugin).filter(
            placeholder=source_placeholder).order_by('path'))

        if not self.has_copy_plugins_permission(request, old_plugins):
            message = _('You do not have permission to copy these plugins.')
            raise PermissionDenied(force_text(message))

        # Empty the clipboard
        target_placeholder.clear()

        plugin_pairs = copy_plugins.copy_plugins_to(
            old_plugins,
            to_placeholder=target_placeholder,
            to_language=target_language,
        )
        return plugin_pairs[0][0]
Exemple #20
0
    def test_delete_orphaned_plugins(self):
        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder,
                   "LinkPlugin",
                   "en",
                   name="A Link",
                   external_link="https://www.django-cms.org")

        instanceless_plugin = CMSPlugin(language="en",
                                        plugin_type="TextPlugin")
        instanceless_plugin.save()

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        report = plugin_report()

        # there should be reports for three plugin types
        self.assertEqual(len(report), 3)

        # check the bogus plugin
        bogus_plugins_report = report[0]
        self.assertEqual(len(bogus_plugins_report["instances"]), 1)

        # check the link plugin
        link_plugins_report = report[1]
        self.assertEqual(len(link_plugins_report["instances"]), 1)

        # check the text plugins
        text_plugins_report = report[2]
        self.assertEqual(len(text_plugins_report["instances"]), 3)

        self.assertEqual(len(text_plugins_report["unsaved_instances"]), 1)

        out = io.StringIO()
        management.call_command('cms',
                                'delete-orphaned-plugins',
                                interactive=False,
                                stdout=out)
        report = plugin_report()

        # there should be reports for two plugin types (one should have been deleted)
        self.assertEqual(len(report), 2)

        # check the link plugin
        link_plugins_report = report[0]
        self.assertEqual(len(link_plugins_report["instances"]), 1)

        # check the text plugins
        text_plugins_report = report[1]
        self.assertEqual(len(text_plugins_report["instances"]), 2)

        self.assertEqual(len(text_plugins_report["unsaved_instances"]), 0)
Exemple #21
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 #22
0
def add_plugin(placeholder, plugin_type, language, position='last-child', **data):
    """
    Taken from django-cms api (in newer versions)
    https://github.com/divio/django-cms/blob/b8633b42efcd137d96e1e3f42e004cb7595768fe/cms/api.py
    """
    assert isinstance(placeholder, Placeholder)
    plugin_model = plugin_type.model
    plugin_type = plugin_type.__name__
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=1,
        language=language
    )
    plugin_base.insert_at(None, position='last-child', commit=False)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #23
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')
 def add_plugin(self, request):
     if request.method != "POST":
         raise Http404
     plugin_type = request.POST['plugin_type']
     placeholder_id = request.POST.get('placeholder', None)
     position = None
     language = get_language_from_request(request)
     if not placeholder_id:
         parent_id = request.POST.get('parent_id', None)
         if not parent_id:
             raise Http404
         parent = get_object_or_404(CMSPlugin, pk=parent_id)
         plugin = CMSPlugin(language=language, plugin_type=plugin_type,
             position=position, parent=parent, placeholder=parent.placeholder)
     else:
         placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
         plugin = CMSPlugin(language=language, plugin_type=plugin_type,
             position=position, placeholder=placeholder) 
     plugin.save()
     return HttpResponse(str(plugin.pk))
Exemple #25
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language, parent=target, tree_id=target.tree_id).count()
        elif position == 'first-child':
            new_pos = 0
        elif position == 'left':
            new_pos = target.position
        elif position == 'right':
            new_pos = target.position + 1
        else:
            raise Exception('position not supported: %s' % position)
        for pl in CMSPlugin.objects.filter(language=language, parent=target.parent_id, tree_id=target.tree_id, position__gte=new_pos):
            pl.position += 1
            pl.save()
    else:
        new_pos = CMSPlugin.objects.filter(language=language, parent__isnull=True, placeholder=placeholder).count()

    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder,
        position=new_pos,
        language=language
    )
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #26
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               target=None,
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)

    max_pos = CMSPlugin.objects.filter(
        language=language, placeholder=placeholder).aggregate(
            Max('position'))['position__max'] or 0

    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=max_pos + 1,
                            language=language)
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #27
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 #28
0
    def setUp(self):
        super().setUp()

        self.hats = Theme.objects.create(
            name='Hats',
            slug='hats',
            blurb='People must wear hats to the party',
            description='Any hat goes but Red Hat or Fedora get extra points')

        self.orange = Theme.objects.create(
            name='Orange clothes',
            slug='orange-clothes',
            blurb='People must wear orange clothes to the party',
            description='Come dressed as an orange for extra points')

        self.instance = CMSPlugin()
Exemple #29
0
def copy_plugins_to_placeholder(plugins,
                                placeholder,
                                language=None,
                                root_plugin=None):
    plugin_pairs = []
    plugins_by_id = {}

    for source_plugin in get_bound_plugins(plugins):
        parent = plugins_by_id.get(source_plugin.parent_id, root_plugin)
        plugin_model = get_plugin_model(source_plugin.plugin_type)

        if plugin_model != CMSPlugin:
            new_plugin = deepcopy(source_plugin)
            new_plugin.pk = None
            new_plugin.id = None
            new_plugin._state.adding = True
            new_plugin.language = language or new_plugin.language
            new_plugin.placeholder = placeholder
            new_plugin.parent = parent
            new_plugin.numchild = 0
        else:
            new_plugin = plugin_model(
                language=(language or source_plugin.language),
                parent=parent,
                plugin_type=source_plugin.plugin_type,
                placeholder=placeholder,
                position=source_plugin.position,
            )

        if parent:
            new_plugin = parent.add_child(instance=new_plugin)
        else:
            new_plugin = CMSPlugin.add_root(instance=new_plugin)

        if plugin_model != CMSPlugin:
            new_plugin.copy_relations(source_plugin)
            plugin_pairs.append((new_plugin, source_plugin))

        plugins_by_id[source_plugin.pk] = new_plugin

    # Backwards compatibility
    # This magic is needed for advanced plugins like Text Plugins that can have
    # nested plugins and need to update their content based on the new plugins.
    for new_plugin, old_plugin in plugin_pairs:
        new_plugin.post_copy(old_plugin, plugin_pairs)
    return [pair[0] for pair in plugin_pairs]
Exemple #30
0
    def test_list_plugins(self):
        out = StringIO()
        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp"]
        with SettingsOverride(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            link_plugin = add_plugin(placeholder, "LinkPlugin", "en", name="A Link", url="https://www.django-cms.org")
            self.assertEqual(CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 2)
            self.assertEqual(CMSPlugin.objects.filter(plugin_type="LinkPlugin").count(), 1)

            # create a CMSPlugin with an unsaved instance
            instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin")
            instanceless_plugin.save()

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            report = plugin_report()

            # there should be reports for three plugin types
            self.assertEqual(len(report), 3)

            # check the bogus plugin
            bogus_plugins_report = report[0]
            self.assertEqual(bogus_plugins_report["model"], None)

            self.assertEqual(bogus_plugins_report["type"], u"BogusPlugin")

            self.assertEqual(bogus_plugins_report["instances"][0], bogus_plugin)

            # check the link plugin
            link_plugins_report = report[1]
            self.assertEqual(link_plugins_report["model"], link_plugin.__class__)

            self.assertEqual(link_plugins_report["type"], u"LinkPlugin")

            self.assertEqual(link_plugins_report["instances"][0].get_plugin_instance()[0], link_plugin)

            # check the text plugins
            text_plugins_report = report[2]
            self.assertEqual(text_plugins_report["model"], TextPlugin.model)

            self.assertEqual(text_plugins_report["type"], u"TextPlugin")

            self.assertEqual(len(text_plugins_report["instances"]), 3)

            self.assertEqual(text_plugins_report["instances"][2], instanceless_plugin)

            self.assertEqual(text_plugins_report["unsaved_instances"], [instanceless_plugin])
Exemple #31
0
    def test_delete_orphaned_plugins(self):
        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp"]
        with SettingsOverride(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            link_plugin = add_plugin(placeholder, "LinkPlugin", "en", name="A Link", url="https://www.django-cms.org")

            instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin")
            instanceless_plugin.save()

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            report = plugin_report()

            # there should be reports for three plugin types
            self.assertEqual(len(report), 3)

            # check the bogus plugin
            bogus_plugins_report = report[0]
            self.assertEqual(len(bogus_plugins_report["instances"]), 1)

            # check the link plugin
            link_plugins_report = report[1]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[2]
            self.assertEqual(len(text_plugins_report["instances"]), 3)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 1)

            management.call_command("cms", "delete_orphaned_plugins", stdout=StringIO(), interactive=False)
            report = plugin_report()

            # there should be reports for two plugin types (one should have been deleted)
            self.assertEqual(len(report), 2)

            # check the link plugin
            link_plugins_report = report[0]
            self.assertEqual(len(link_plugins_report["instances"]), 1)

            # check the text plugins
            text_plugins_report = report[1]
            self.assertEqual(len(text_plugins_report["instances"]), 2)

            self.assertEqual(len(text_plugins_report["unsaved_instances"]), 0)
Exemple #32
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               target=None,
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language,
                                               parent=target,
                                               tree_id=target.tree_id).count()
        elif position == 'first-child':
            new_pos = 0
        elif position == 'left':
            new_pos = target.position
        elif position == 'right':
            new_pos = target.position + 1
        else:
            raise Exception('position not supported: %s' % position)
        for pl in CMSPlugin.objects.filter(language=language,
                                           parent=target.parent_id,
                                           tree_id=target.tree_id,
                                           position__gte=new_pos):
            pl.position += 1
            pl.save()
    else:
        new_pos = CMSPlugin.objects.filter(language=language,
                                           parent__isnull=True,
                                           placeholder=placeholder).count()

    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=new_pos,
                            language=language)
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #33
0
 def add_plugin(self, user=None, page=None, placeholder=None, language='en', body=''):
     if not placeholder:
         if page:
             placeholder = page.placeholders.get(slot__iexact='Right-Column')
         else:
             placeholder = page.placeholders.get(slot__iexact='Right-Column')
         
     plugin_base = CMSPlugin(
         plugin_type='TextPlugin',
         placeholder=placeholder, 
         position=1, 
         language=language
     )
     plugin_base.insert_at(None, position='last-child', commit=False)
             
     plugin = Text(body=body)
     plugin_base.set_base_attr(plugin)
     plugin.save()
     return plugin.pk
 def add_plugin(self, request):
     if request.method != "POST":
         raise Http404
     plugin_type = request.POST['plugin_type']
     placeholder_id = request.POST.get('placeholder', None)
     position = None
     language = get_language_from_request(request)
     if not placeholder_id:
         parent_id = request.POST.get('parent_id', None)
         if not parent_id:
             raise Http404
         parent = get_object_or_404(CMSPlugin, pk=parent_id)
         plugin = CMSPlugin(language=language, plugin_type=plugin_type,
             position=position, parent=parent, placeholder=parent.placeholder)
     else:
         placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
         plugin = CMSPlugin(language=language, plugin_type=plugin_type,
             position=position, placeholder=placeholder) 
     plugin.save()
     return HttpResponse(str(plugin.pk))
Exemple #35
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               **data):
    """
    Taken from django-cms api (in newer versions)
    https://github.com/divio/django-cms/blob/b8633b42efcd137d96e1e3f42e004cb7595768fe/cms/api.py
    """
    assert isinstance(placeholder, Placeholder)
    plugin_model = plugin_type.model
    plugin_type = plugin_type.__name__
    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=1,
                            language=language)
    plugin_base.insert_at(None, position='last-child', commit=False)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #36
0
    def test_check_plugin_instances(self):
        self.assertCheck(True, warnings=0, errors=0 )

        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, "LinkPlugin", "en",
                   name="A Link", external_link="https://www.django-cms.org")

        # create a CMSPlugin with an unsaved instance
        instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin")
        instanceless_plugin.save()

        self.assertCheck(False, warnings=0, errors=2)

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        self.assertCheck(False, warnings=0, errors=3)
Exemple #37
0
    def test_check_plugin_instances(self):
        self.assertCheck(True, warnings=0, errors=0 )

        apps = ["cms", "menus", "sekizai", "cms.test_utils.project.sampleapp", "treebeard"]
        with self.settings(INSTALLED_APPS=apps):
            placeholder = Placeholder.objects.create(slot="test")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, TextPlugin, "en", body="en body")
            add_plugin(placeholder, "LinkPlugin", "en",
                name="A Link", url="https://www.django-cms.org")

            # create a CMSPlugin with an unsaved instance
            instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin")
            instanceless_plugin.save()

            self.assertCheck(False, warnings=0, errors=2)

            # create a bogus CMSPlugin to simulate one which used to exist but
            # is no longer installed
            bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
            bogus_plugin.save()

            self.assertCheck(False, warnings=0, errors=3)
    def test_16_delete_with_plugins(self):
        """
        Check that plugins and placeholders get correctly deleted when we delete
        a page!
        """
        page = self.create_page()
        page.rescan_placeholders()  # create placeholders
        placeholder = page.placeholders.all()[0]
        plugin_base = CMSPlugin(plugin_type='TextPlugin',
                                placeholder=placeholder,
                                position=1,
                                language=settings.LANGUAGES[0][0])
        plugin_base.insert_at(None, position='last-child', save=False)

        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        self.assertEqual(CMSPlugin.objects.count(), 1)
        self.assertEqual(Text.objects.count(), 1)
        self.assertTrue(Placeholder.objects.count() > 0)
        page.delete()
        self.assertEqual(CMSPlugin.objects.count(), 0)
        self.assertEqual(Text.objects.count(), 0)
        self.assertEqual(Placeholder.objects.count(), 0)
    def _move_plugin(self, request, plugin, target_language,
                     target_placeholder, tree_order, target_parent=None):
        if not self.has_move_plugin_permission(request, plugin, target_placeholder):
            message = force_text(_("You have no permission to move this plugin"))
            raise PermissionDenied(message)

        plugin_data = {
            'language': target_language,
            'placeholder': target_placeholder,
        }

        source_language = plugin.language
        source_placeholder = plugin.placeholder
        source_tree_order = source_placeholder.get_plugin_tree_order(
            language=source_language,
            parent_id=plugin.parent_id,
        )

        if target_parent:
            target_parent_id = target_parent.pk
        else:
            target_parent_id = None

        if target_placeholder != source_placeholder:
            target_tree_order = target_placeholder.get_plugin_tree_order(
                language=target_language,
                parent_id=target_parent_id,
            )
        else:
            target_tree_order = source_tree_order

        action_token = self._send_pre_placeholder_operation(
            request,
            operation=operations.MOVE_PLUGIN,
            plugin=plugin,
            source_language=source_language,
            source_placeholder=source_placeholder,
            source_parent_id=plugin.parent_id,
            source_order=source_tree_order,
            target_language=target_language,
            target_placeholder=target_placeholder,
            target_parent_id=target_parent_id,
            target_order=target_tree_order,
        )

        if target_parent and plugin.parent != target_parent:
            # Plugin is being moved to another tree (under another parent)
            updated_plugin = plugin.update(refresh=True, parent=target_parent, **plugin_data)
            updated_plugin = updated_plugin.move(target_parent, pos='last-child')
        elif target_parent:
            # Plugin is being moved within the same tree (different position, same parent)
            updated_plugin = plugin.update(refresh=True, **plugin_data)
        else:
            # Plugin is being moved to the root (no parent)
            target = CMSPlugin.get_last_root_node()
            updated_plugin = plugin.update(refresh=True, parent=None, **plugin_data)
            updated_plugin = updated_plugin.move(target, pos='right')

        # Update all children to match the parent's
        # language and placeholder
        updated_plugin.get_descendants().update(**plugin_data)

        # Avoid query by removing the plugin being moved
        # from the source order
        new_source_order = list(source_tree_order)
        new_source_order.remove(updated_plugin.pk)

        # Reorder all plugins in the target placeholder according to the
        # passed order
        new_target_order = [int(pk) for pk in tree_order]
        reorder_plugins(
            target_placeholder,
            parent_id=target_parent_id,
            language=target_language,
            order=new_target_order,
        )

        # Refresh plugin to get new tree and position values
        updated_plugin.refresh_from_db()

        self._send_post_placeholder_operation(
            request,
            operation=operations.MOVE_PLUGIN,
            plugin=updated_plugin.get_bound_plugin(),
            token=action_token,
            source_language=source_language,
            source_placeholder=source_placeholder,
            source_parent_id=plugin.parent_id,
            source_order=new_source_order,
            target_language=target_language,
            target_placeholder=target_placeholder,
            target_parent_id=target_parent_id,
            target_order=new_target_order,
        )
        return updated_plugin
Exemple #40
0
class PlaceholderAdmin(ModelAdmin):
    render_placeholder_language_tabs = True
    change_form_template = 'admin/placeholders/placeholder/change_form.html'

    class Media:
        css = {
            'all': [
                cms_static_url(path) for path in (
                    'css/rte.css',
                    'css/change_form.css',
                    'css/jquery.dialog.css',
                    'css/plugin_editor.css',
                )
            ]
        }
        js = [
            cms_static_url(path) for path in [
                'js/plugins/admincompat.js',
                'js/csrf.js',
                'js/libs/jquery.query.js',
                'js/libs/jquery.ui.core.js',
                'js/libs/jquery.ui.dialog.js',
            ]
        ]

    def get_fieldsets(self, request, obj=None):
        """
        Get fieldsets to enforce correct fieldsetting of placeholder fields
        """
        form = self.get_form(request, obj)
        placeholder_fields = self._get_placeholder_fields(form)
        if self.declared_fieldsets:
            # check those declared fieldsets
            fieldsets = list(deepcopy(self.declared_fieldsets))
            for label, fieldset in fieldsets:
                fields = list(fieldset['fields'])
                for field in fieldset['fields']:
                    if field in placeholder_fields:
                        if (len(fieldset['fields']) == 1
                                and 'classes' in fieldset
                                and 'plugin-holder' in fieldset['classes'] and
                                'plugin-holder-nopage' in fieldset['classes']):
                            placeholder_fields.remove(field)
                        else:
                            fields.remove(field)
                if fields:
                    fieldset['fields'] = fields
                else:
                    # no fields in the fieldset anymore, delete the fieldset
                    fieldsets.remove((label, fieldset))
            for placeholder in placeholder_fields:
                fieldsets.append((
                    self.get_label_for_placeholder(placeholder),
                    {
                        'fields': (placeholder, ),
                        'classes': (
                            'plugin-holder',
                            'plugin-holder-nopage',
                        ),
                    },
                ))
            return fieldsets
        fieldsets = []
        fieldsets.append((None, {
            'fields': [
                f for f in form.base_fields.keys()
                if not f in placeholder_fields
            ]
        }))
        for placeholder in placeholder_fields:
            fieldsets.append((self.get_label_for_placeholder(placeholder), {
                'fields': (placeholder, ),
                'classes': (
                    'plugin-holder',
                    'plugin-holder-nopage',
                ),
            }))
        readonly_fields = self.get_readonly_fields(request, obj)
        if readonly_fields:
            fieldsets.append((None, {'fields': list(readonly_fields)}))
        return fieldsets

    def get_label_for_placeholder(self, placeholder):
        return ' '.join([
            x.capitalize() for x in self.model._meta.get_field_by_name(
                placeholder)[0].verbose_name.split(' ')
        ])

    def formfield_for_dbfield(self, db_field, **kwargs):
        """
        Hook for specifying the form Field instance for a given database Field
        instance.

        If kwargs are given, they're passed to the form Field's constructor.
        """
        if isinstance(db_field, PlaceholderField):
            request = kwargs.pop("request", None)
            return db_field.formfield_for_admin(request,
                                                self.placeholder_plugin_filter,
                                                **kwargs)
        return super(PlaceholderAdmin,
                     self).formfield_for_dbfield(db_field, **kwargs)

    def get_language_from_request(self, request):
        language = request.REQUEST.get('language', None)
        if not language:
            language = get_language()
        return language

    def placeholder_plugin_filter(self, request, queryset):
        if self.render_placeholder_language_tabs:
            language = self.get_language_from_request(request)
            if language:
                queryset = queryset.filter(language=language)
        return queryset

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context.update(self.language_tab_context(request))
        tab_language = request.GET.get("language", None)
        response = super(PlaceholderAdmin,
                         self).change_view(request,
                                           object_id,
                                           extra_context=extra_context)

        if tab_language and response.status_code == 302 and response._headers[
                'location'][1] == request.path:
            location = response._headers['location']
            response._headers['location'] = (location[0], "%s?language=%s" %
                                             (location[1], tab_language))
        return response

    def language_tab_context(self, request):
        language = self.get_language_from_request(request)
        languages = [(lang, lang_name)
                     for lang, lang_name in settings.LANGUAGES]
        context = {
            'language':
            language,
            'language_tabs':
            languages,
            'show_language_tabs':
            len(languages) > 1 and self.render_placeholder_language_tabs,
        }
        return context

    def _get_placeholder_fields(self, form):
        placeholder_fields = []
        for key, value in form.base_fields.items():
            if isinstance(value, PlaceholderFormField):
                placeholder_fields.append(key)
        return placeholder_fields

    def get_urls(self):
        """
        Register the plugin specific urls (add/edit/copy/remove/move)
        """
        from django.conf.urls.defaults import patterns, url

        info = "%s_%s" % (self.model._meta.app_label,
                          self.model._meta.module_name)
        pat = lambda regex, fn: url(regex,
                                    self.admin_site.admin_view(fn),
                                    name='%s_%s' % (info, fn.__name__))

        url_patterns = patterns(
            '',
            pat(r'add-plugin/$', self.add_plugin),
            pat(r'edit-plugin/([0-9]+)/$', self.edit_plugin),
            pat(r'remove-plugin/$', self.remove_plugin),
            pat(r'move-plugin/$', self.move_plugin),
            pat(r'copy-plugins/$', self.copy_plugins),
        )
        return url_patterns + super(PlaceholderAdmin, self).get_urls()

    @xframe_options_sameorigin
    def add_plugin(self, request):
        # only allow POST
        if request.method != "POST":
            raise Http404
        plugin_type = request.POST['plugin_type']
        if not has_plugin_permission(request.user, plugin_type, "add"):
            return HttpResponseForbidden(
                "You don't have permission to add plugins")

        placeholder_id = request.POST.get('placeholder', None)
        position = None
        language = self.get_language_from_request(request)
        parent = None
        # check if we got a placeholder (id)
        if placeholder_id:
            placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
        else:  # else get the parent_id
            parent_id = request.POST.get('parent_id', None)
            if not parent_id:  # if we get neither a placeholder nor a parent, bail out
                raise Http404
            parent = get_object_or_404(CMSPlugin, pk=parent_id)
            placeholder = parent.placeholder

        # check add permissions on placeholder
        if not placeholder.has_add_permission(request):
            return HttpResponseForbidden(
                _("You don't have permission to add content here."))

        try:
            has_reached_plugin_limit(placeholder, plugin_type, language)
        except PluginLimitReached, e:
            return HttpResponseBadRequest(str(e))

        # actually add the plugin
        plugin = CMSPlugin(language=language,
                           plugin_type=plugin_type,
                           position=position,
                           placeholder=placeholder,
                           parent=parent)
        plugin.save()

        # returns it's ID as response
        return HttpResponse(str(plugin.pk))
Exemple #41
0
    def test_11_copy_textplugin(self):
        """
        Test that copying of textplugins replaces references to copied plugins
        """
        
        page = self.create_page()
        
        placeholder = page.placeholders.get(slot='body')
        
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=1, 
            language=self.FIRST_LANG)
        plugin_base.insert_at(None, position='last-child', commit=False)
                
        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        
        plugin_ref_1_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=1, 
            language=self.FIRST_LANG)
        plugin_ref_1_base.insert_at(plugin_base, position='last-child', commit=False)    
        
        plugin_ref_1 = Text(body='')
        plugin_ref_1_base.set_base_attr(plugin_ref_1)
        plugin_ref_1.save()
        
        plugin_ref_2_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=2, 
            language=self.FIRST_LANG)
        plugin_ref_2_base.insert_at(plugin_base, position='last-child', commit=False)    
        
        plugin_ref_2 = Text(body='')
        plugin_ref_2_base.set_base_attr(plugin_ref_2)

        plugin_ref_2.save()
        
        plugin.body = plugin_tags_to_admin_html(' {{ plugin_object %s }} {{ plugin_object %s }} ' % (str(plugin_ref_1.pk), str(plugin_ref_2.pk)))
        plugin.save()
        self.assertEquals(plugin.pk, 1)
        page_data = self.get_new_page_data()

        #create 2nd language page
        page_data.update({
            'language': self.SECOND_LANG,
            'title': "%s %s" % (page.get_title(), self.SECOND_LANG),
        })
        response = self.client.post(URL_CMS_PAGE_CHANGE % page.pk + "?language=%s" % self.SECOND_LANG, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        
        self.assertEquals(CMSPlugin.objects.filter(language=self.FIRST_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.filter(language=self.SECOND_LANG).count(), 0)
        self.assertEquals(CMSPlugin.objects.count(), 3)
        self.assertEquals(Page.objects.all().count(), 1)
        
        copy_data = {
            'placeholder': placeholder.pk,
            'language': self.SECOND_LANG,
            'copy_from': self.FIRST_LANG,
        }
        response = self.client.post(URL_CMS_PAGE + "copy-plugins/", copy_data)
        self.assertEquals(response.status_code, 200)
        self.assertEqual(response.content.count('<li '), 3)
        # assert copy success
        self.assertEquals(CMSPlugin.objects.filter(language=self.FIRST_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.filter(language=self.SECOND_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.count(), 6)

        new_plugin = Text.objects.get(pk=6)
        self.assertEquals(plugin_tags_to_id_list(new_plugin.body), [u'4', u'5'])
Exemple #42
0
        """
        must return a unicode string
        """
        return str(self.latest_entries).decode('utf8')

    def copy_relations(self, oldinstance):
        self.tags = oldinstance.tags.all()

    def get_posts(self):
        posts = Post.published.filter_by_language(self.language)
        tags = list(self.tags.all())
        if tags:
            posts = posts.filter(tags__in=tags)
        return posts[:self.latest_entries]


class AuthorsPlugin(CMSPlugin):
    def get_authors(self):
        return generate_slugs(get_blog_authors())


def force_language(sender, instance, **kwargs):
    if issubclass(
            sender, CMSPlugin
    ) and instance.placeholder and instance.placeholder.slot == 'aldryn_blog_post_content':
        instance.language = settings.ALDRYN_BLOG_PLUGIN_LANGUAGE


for model in CMSPlugin.__subclasses__():
    models.signals.pre_save.connect(force_language, sender=model)
Exemple #43
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder

    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            if CMSPlugin.node_order_by:
                position = 'sorted-child'
            new_pos = CMSPlugin.objects.filter(parent=target).count()
            parent_id = target.pk
        elif position == 'first-child':
            new_pos = 0
            if CMSPlugin.node_order_by:
                position = 'sorted-child'
            parent_id = target.pk
        elif position == 'left':
            new_pos = target.position
            if CMSPlugin.node_order_by:
                position = 'sorted-sibling'
            parent_id = target.parent_id
        elif position == 'right':
            new_pos = target.position + 1
            if CMSPlugin.node_order_by:
                position = 'sorted-sibling'
            parent_id = target.parent_id
        else:
            raise Exception('position not supported: %s' % position)
        if position == 'last-child' or position == 'first-child':
            qs = CMSPlugin.objects.filter(language=language, parent=target, position__gte=new_pos,
                                          placeholder=placeholder)
        else:
            qs = CMSPlugin.objects.filter(language=language, parent=target.parent_id, position__gte=new_pos,
                                          placeholder=placeholder)
        for pl in qs:
            pl.position += 1
            pl.save()
    else:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language, parent__isnull=True, placeholder=placeholder).count()
        else:
            new_pos = 0
            for pl in CMSPlugin.objects.filter(language=language, parent__isnull=True, position__gte=new_pos,
                                               placeholder=placeholder):
                pl.position += 1
                pl.save()
        parent_id = None
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder,
        position=new_pos,
        language=language,
        parent_id=parent_id,
    )

    plugin_base = plugin_base.add_root(instance=plugin_base)

    if target:
        plugin_base = plugin_base.move(target, pos=position)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
    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')
Exemple #45
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder

    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            if CMSPlugin.node_order_by:
                position = 'sorted-child'
            new_pos = CMSPlugin.objects.filter(parent=target).count()
            parent_id = target.pk
        elif position == 'first-child':
            new_pos = 0
            if CMSPlugin.node_order_by:
                position = 'sorted-child'
            parent_id = target.pk
        elif position == 'left':
            new_pos = target.position
            if CMSPlugin.node_order_by:
                position = 'sorted-sibling'
            parent_id = target.parent_id
        elif position == 'right':
            new_pos = target.position + 1
            if CMSPlugin.node_order_by:
                position = 'sorted-sibling'
            parent_id = target.parent_id
        else:
            raise Exception('position not supported: %s' % position)
        if position == 'last-child' or position == 'first-child':
            qs = CMSPlugin.objects.filter(language=language, parent=target, position__gte=new_pos,
                                          placeholder=placeholder)
        else:
            qs = CMSPlugin.objects.filter(language=language, parent=target.parent_id, position__gte=new_pos,
                                          placeholder=placeholder)
        for pl in qs:
            pl.position += 1
            pl.save()
    else:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language, parent__isnull=True, placeholder=placeholder).count()
        else:
            new_pos = 0
            for pl in CMSPlugin.objects.filter(language=language, parent__isnull=True, position__gte=new_pos,
                                               placeholder=placeholder):
                pl.position += 1
                pl.save()
        parent_id = None
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder,
        position=new_pos,
        language=language,
        parent_id=parent_id,
    )

    plugin_base = plugin_base.add_root(instance=plugin_base)

    if target:
        plugin_base = plugin_base.move(target, pos=position)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #46
0
    def _paste_plugin(self,
                      request,
                      plugin,
                      target_language,
                      target_placeholder,
                      tree_order,
                      target_parent=None):
        plugins = (CMSPlugin.get_tree(parent=plugin).filter(
            placeholder=plugin.placeholder_id).order_by('path'))
        plugins = list(plugins)

        if not self.has_copy_from_clipboard_permission(
                request, target_placeholder, plugins):
            message = force_text(
                _("You have no permission to paste this plugin"))
            raise PermissionDenied(message)

        if target_parent:
            target_parent_id = target_parent.pk
        else:
            target_parent_id = None

        target_tree_order = [
            int(pk) for pk in tree_order if not pk == '__COPY__'
        ]

        action_token = self._send_pre_placeholder_operation(
            request,
            operation=operations.PASTE_PLUGIN,
            plugin=plugin,
            target_language=target_language,
            target_placeholder=target_placeholder,
            target_parent_id=target_parent_id,
            target_order=target_tree_order,
        )

        plugin_pairs = copy_plugins.copy_plugins_to(
            plugins,
            to_placeholder=target_placeholder,
            to_language=target_language,
            parent_plugin_id=target_parent_id,
        )
        root_plugin = plugin_pairs[0][0]

        # If an ordering was supplied, replace the item that has
        # been copied with the new copy
        target_tree_order.insert(tree_order.index('__COPY__'), root_plugin.pk)

        reorder_plugins(
            target_placeholder,
            parent_id=target_parent_id,
            language=target_language,
            order=target_tree_order,
        )
        target_placeholder.mark_as_dirty(target_language, clear_cache=False)

        # Fetch from db to update position and other tree values
        root_plugin.refresh_from_db()

        self._send_post_placeholder_operation(
            request,
            operation=operations.PASTE_PLUGIN,
            plugin=root_plugin.get_bound_plugin(),
            token=action_token,
            target_language=target_language,
            target_placeholder=target_placeholder,
            target_parent_id=target_parent_id,
            target_order=target_tree_order,
        )
        return root_plugin
def convert(request, slug = "dryrun"):
    # this dictionary store the information for the conversions
    execute=slug
    models_dictionary = {
        "messages": {},                             # a general set of messages for the user
        "modules":  {
            "news_and_events.models": {             # each module containing the models must be represented, like this
                "application": "News & Events",     # this is the human-friendly name of the module
                "models": {                         # a dictionary with each model in that module
                    "NewsArticle": {                # the actual name of the class
                        "fields": [                 # a list of the fields we're working on
                            {                       # a dictionary for each field
                                "old_field": "content",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "News articles",   # the human-friendly name of the model
                        "actions": {},              # an empty dictionary where we we store the results
                        },
                    "Event": {                      # a second model in that module
                        "fields": [                 
                            {                       
                                "old_field": "content",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "Events",
                        "actions": {},
                        },
                    },
                },
            "vacancies_and_studentships.models": {  # and a second module
                "application": "Vacancies & Studentships",
                "models": {
                    "Vacancy": {
                        "fields": [                 
                            {                       
                                "old_field": "description",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "Vacancies",
                        "actions": {},
                        },
                    "Studentship": {
                        "fields": [                 
                            {                       
                                "old_field": "description",
                                "new_field": "body",                
                                "slot": "body",
                                },
                                ],
                        "model": "Studentships",
                        "actions": {},
                        },
                    },
                },
            "publications.models": {                
                "application": "Publications",
                "models": {
                    "Researcher": {
                        "fields": [                 
                            {                       
                                "old_field": "research_synopsis",
                                "new_field": "synopsis_of_research",                
                                "slot": "body",
                                },
                            {                       
                                "old_field": "research_description",
                                "new_field": "description_of_research",                
                                "slot": "body",
                                },
                            ],
                        "model": "Researcher",
                        "actions": {},
                        },
                    },
                },
            },
        }

    # loop over the modules
    for module, module_values in models_dictionary["modules"].items():

        # loop over the models in the module
        for model, model_values in module_values["models"].items():
            
            # mmodel is the human-readable name of the model, used for the report summary
            mmodel = models_dictionary["modules"][module]["models"][model]["model"]
            models_dictionary["messages"][mmodel]={}

            # import the model
            actual_model = getattr(__import__(module, globals(), locals(), module_values["models"], -1), model)
                                            
            # loop over the fields that need converting
            for field in model_values["fields"]:
                print field

                
                old_field = field["old_field"]
                new_field = field["new_field"]
                slot = field["slot"]

                # create a summary report for this field
                models_dictionary["messages"][mmodel][old_field]={}

                try:
                    getattr(actual_model, new_field)
                except AttributeError:
                    message = "field " + new_field + " is missing - check the model and try agin"
                    models_dictionary["messages"][mmodel][old_field]["Error"]=message
                    continue
                    
                junk_content = []   # a record of those items with nothing but <br /> in them
                moved_items =[]     # a record of the items we migrated to placeholders

                # loop over each item in the class
                for item in actual_model.objects.all():

                    old_field_content = getattr(item, old_field)  # the old field we want to convert

                    # first get rid of junk content (change "<br />" to "")
                    if old_field_content == "<br />":
                        old_field_content = ""
                        setattr(item, old_field, "") # item.content = ""
                        if execute == "convert":
                            item.save()
                    
                    # now the serious business of converting the fields
            
                    # if the item lacks a placeholder, create the placeholder and the reference to it
                    if old_field_content and not getattr(item, new_field, None):

                        # check to see if it's worth converting
                        if len(old_field_content) > 60:

                            # create the placeholder
                            placeholder=Placeholder(slot=slot)
                            if execute == "convert":
                                placeholder.save()
        
                            # refer to the placeholder from the item
                            setattr(item, new_field, placeholder)
        
                            # I copied this from one of the test files
                            plugin_base = CMSPlugin(
                                plugin_type='TextPlugin',
                                placeholder=placeholder, 
                                position=1, 
                                language=settings.LANGUAGES[0][0]) # we assume the original field was in the first language
                            plugin_base.insert_at(None, position='last-child', commit=False)
        
                            # create a text plugin
                            plugin = Text(body='')
                            plugin_base.set_base_attr(plugin)
                            plugin.body = getattr(item, old_field)
                            if execute == "convert":
                                plugin.save()
        
                            # set the old field to ""
                            setattr(item, old_field, "")
                            if execute == "convert":
                                item.save()
                                item.status = "Converted to placeholder"
                            else:
                                item.status = "Unconverted"
                                        
                        else:
                            print "too short", old_field_content
                            # this item is so short it must be junk
                            if execute == "convert":
                                setattr(item, old_field, "")
                                item.status = "Junk field - too short; was deleted instead of converted:" + old_field_content
                                item.save()
                            else:    
                                item.status = "Junk field - too short; will be deleted instead of converted:" + old_field_content
                            # make a note that this was a junk item
                            junk_content.append(item)
                                # make a note that we moved this item

                        moved_items.append(item)    
 
                # information about junk content items
                if execute == "convert":
                    message = " ".join((str(len(junk_content)), "junk items not converted items"))
                else:
                    message = " ".join((str(len(junk_content)), "junk items found"))                    

                models_dictionary["messages"][mmodel][old_field]["Junk fields"]=message

                # information about items that have been/need to be converted
                if execute == "convert":
                    message = str(len(moved_items)) + " items were converted to placeholder " + new_field
                else:
                    message = str(len(moved_items)) + " items need to be converted to placeholder " + new_field
            
                models_dictionary["messages"][mmodel][old_field]["Conversions"]=message
            
                # list every item that was copied for the full report
                if execute == "convert":
                    action = "Fields that were copied"
                else:
                    action = "Fields to be copied"
                    
                models_dictionary["modules"][module]["models"][model]["actions"][action]=moved_items
                

    return shortcuts.render_to_response(
        "housekeeping/convert_to_placeholders.html", {
            "execute": execute,
            "converted": models_dictionary,
            },
        RequestContext(request),
        )
Exemple #48
0
    def test_delete_orphaned_plugins(self):
        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, "LinkPlugin", "en",
                   name="A Link", url="https://www.django-cms.org")

        instanceless_plugin = CMSPlugin(
            language="en", plugin_type="TextPlugin")
        instanceless_plugin.save()

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        report = plugin_report()

        # there should be reports for three plugin types
        self.assertEqual(
            len(report),
            3)

        # check the bogus plugin
        bogus_plugins_report = report[0]
        self.assertEqual(
            len(bogus_plugins_report["instances"]),
            1)

        # check the link plugin
        link_plugins_report = report[1]
        self.assertEqual(
            len(link_plugins_report["instances"]),
            1)

        # check the text plugins
        text_plugins_report = report[2]
        self.assertEqual(
            len(text_plugins_report["instances"]),
            3)

        self.assertEqual(
            len(text_plugins_report["unsaved_instances"]),
            1)

        out = StringIO()
        management.call_command('cms', 'delete-orphaned-plugins', interactive=False, stdout=out)
        report = plugin_report()

        # there should be reports for two plugin types (one should have been deleted)
        self.assertEqual(
            len(report),
            2)

        # check the link plugin
        link_plugins_report = report[0]
        self.assertEqual(
            len(link_plugins_report["instances"]),
            1)

        # check the text plugins
        text_plugins_report = report[1]
        self.assertEqual(
            len(text_plugins_report["instances"]),
            2)

        self.assertEqual(
            len(text_plugins_report["unsaved_instances"]),
            0)
Exemple #49
0
        must return a unicode string
        """
        return str(self.latest_entries).decode('utf8')

    def copy_relations(self, oldinstance):
        self.tags = oldinstance.tags.all()

    def get_posts(self):
        posts = Post.published.filter_by_language(self.language)
        tags = self.tags.values_list('pk', flat=True)

        if tags.exists():
            posts = posts.filter(tags__in=tags)
        return posts[:self.latest_entries]


class AuthorsPlugin(CMSPlugin):

    def get_authors(self):
        return generate_slugs(get_blog_authors())


def force_language(sender, instance, **kwargs):
    if issubclass(sender, CMSPlugin) and instance.placeholder \
            and instance.placeholder.slot == 'aldryn_blog_post_content':
        instance.language = settings.ALDRYN_BLOG_PLUGIN_LANGUAGE


for model in CMSPlugin.__subclasses__():
    models.signals.pre_save.connect(force_language, sender=model)
    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 #51
0
    def test_list_plugins(self):
        out = io.StringIO()
        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        link_plugin = add_plugin(placeholder,
                                 "LinkPlugin",
                                 "en",
                                 name="A Link",
                                 external_link="https://www.django-cms.org")
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 2)
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type="LinkPlugin").count(), 1)

        # create a CMSPlugin with an unsaved instance
        instanceless_plugin = CMSPlugin(language="en",
                                        plugin_type="TextPlugin")
        instanceless_plugin.save()

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        with mock.patch(
                'cms.management.commands.subcommands.list.plugin_report'
        ) as report_fn:
            management.call_command('cms',
                                    'list',
                                    'plugins',
                                    interactive=False,
                                    stdout=out)
            report_fn.assert_called_once()

        report = plugin_report()

        # there should be reports for three plugin types
        self.assertEqual(len(report), 3)

        # check the bogus plugin
        bogus_plugins_report = report[0]
        self.assertEqual(bogus_plugins_report["model"], None)

        self.assertEqual(bogus_plugins_report["type"], u'BogusPlugin')

        self.assertEqual(bogus_plugins_report["instances"][0], bogus_plugin)

        # check the link plugin
        link_plugins_report = report[1]
        self.assertEqual(link_plugins_report["model"], link_plugin.__class__)

        self.assertEqual(link_plugins_report["type"], u'LinkPlugin')

        self.assertEqual(
            link_plugins_report["instances"][0].get_plugin_instance()[0],
            link_plugin)

        # check the text plugins
        text_plugins_report = report[2]
        self.assertEqual(text_plugins_report["model"], TextPlugin.model)

        self.assertEqual(text_plugins_report["type"], u'TextPlugin')

        self.assertEqual(len(text_plugins_report["instances"]), 3)

        self.assertEqual(text_plugins_report["instances"][2],
                         instanceless_plugin)

        self.assertEqual(text_plugins_report["unsaved_instances"],
                         [instanceless_plugin])
Exemple #52
0
    def test_list_plugins(self):
        out = StringIO()
        placeholder = Placeholder.objects.create(slot="test")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        add_plugin(placeholder, TextPlugin, "en", body="en body")
        link_plugin = add_plugin(placeholder, "LinkPlugin", "en",
                                 name="A Link", url="https://www.django-cms.org")
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type=PLUGIN).count(),
            2)
        self.assertEqual(
            CMSPlugin.objects.filter(plugin_type="LinkPlugin").count(),
            1)

        # create a CMSPlugin with an unsaved instance
        instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin")
        instanceless_plugin.save()

        # create a bogus CMSPlugin to simulate one which used to exist but
        # is no longer installed
        bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin")
        bogus_plugin.save()

        management.call_command('cms', 'list', 'plugins', interactive=False, stdout=out)
        report = plugin_report()

        # there should be reports for three plugin types
        self.assertEqual(
            len(report),
            3)

        # check the bogus plugin
        bogus_plugins_report = report[0]
        self.assertEqual(
            bogus_plugins_report["model"],
            None)

        self.assertEqual(
            bogus_plugins_report["type"],
            u'BogusPlugin')

        self.assertEqual(
            bogus_plugins_report["instances"][0],
            bogus_plugin)

        # check the link plugin
        link_plugins_report = report[1]
        self.assertEqual(
            link_plugins_report["model"],
            link_plugin.__class__)

        self.assertEqual(
            link_plugins_report["type"],
            u'LinkPlugin')

        self.assertEqual(
            link_plugins_report["instances"][0].get_plugin_instance()[0],
            link_plugin)

        # check the text plugins
        text_plugins_report = report[2]
        self.assertEqual(
            text_plugins_report["model"],
            TextPlugin.model)

        self.assertEqual(
            text_plugins_report["type"],
            u'TextPlugin')

        self.assertEqual(
            len(text_plugins_report["instances"]),
            3)

        self.assertEqual(
            text_plugins_report["instances"][2],
            instanceless_plugin)

        self.assertEqual(
            text_plugins_report["unsaved_instances"],
            [instanceless_plugin])
    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")