divio/django-cms

View on GitHub
cms/models/static_placeholder.py

Summary

Maintainability
A
25 mins
Test Coverage
import uuid

from django.contrib.auth import get_permission_codename
from django.contrib.sites.models import Site
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _

from cms.models.fields import PlaceholderField
from cms.utils.copy_plugins import copy_plugins_to


def static_slotname(instance):
    """
    Returns a string to be used as the slot
    for the static placeholder field.
    """
    return instance.code


class StaticPlaceholder(models.Model):
    CREATION_BY_TEMPLATE = 'template'
    CREATION_BY_CODE = 'code'
    CREATION_METHODS = (
        (CREATION_BY_TEMPLATE, _('by template')),
        (CREATION_BY_CODE, _('by code')),
    )
    name = models.CharField(
        verbose_name=_(u'static placeholder name'), max_length=255, blank=True, default='',
        help_text=_(u'Descriptive name to identify this static placeholder. Not displayed to users.'))
    code = models.CharField(
        verbose_name=_(u'placeholder code'), max_length=255, blank=True,
        help_text=_(u'To render the static placeholder in templates.'))
    draft = PlaceholderField(static_slotname, verbose_name=_(u'placeholder content'), related_name='static_draft')
    public = PlaceholderField(static_slotname, editable=False, related_name='static_public')
    dirty = models.BooleanField(default=False, editable=False)
    creation_method = models.CharField(
        verbose_name=_('creation_method'), choices=CREATION_METHODS,
        default=CREATION_BY_CODE, max_length=20, blank=True,
    )
    site = models.ForeignKey(Site, on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        verbose_name = _(u'static placeholder')
        verbose_name_plural = _(u'static placeholders')
        app_label = 'cms'
        unique_together = (('code', 'site'),)

    def __str__(self):
        return self.get_name()

    def get_name(self):
        return self.name or self.code or str(self.pk)
    get_name.short_description = _(u'static placeholder name')

    def clean(self):
        # TODO: check for clashes if the random code is already taken
        if not self.code:
            self.code = u'static-%s' % uuid.uuid4()
        if not self.site:
            placeholders = StaticPlaceholder.objects.filter(code=self.code, site__isnull=True)
            if self.pk:
                placeholders = placeholders.exclude(pk=self.pk)
            if placeholders.exists():
                raise ValidationError(_("A static placeholder with the same site and code already exists"))

    def publish(self, request, language, force=False):
        if force or self.has_publish_permission(request):
            self.public.clear(language=language)
            self.public.clear_cache(language=language)
            plugins = self.draft.get_plugins_list(language=language)
            copy_plugins_to(plugins, self.public, no_signals=True)
            self.dirty = False
            self.save()
            return True
        return False

    def has_change_permission(self, request):
        if request.user.is_superuser:
            return True
        opts = self._meta
        return request.user.has_perm(opts.app_label + '.' + get_permission_codename('change', opts))

    def has_publish_permission(self, request):
        if request.user.is_superuser:
            return True
        opts = self._meta
        return request.user.has_perm(opts.app_label + '.' + get_permission_codename('change', opts)) and \
               request.user.has_perm(opts.app_label + '.' + 'publish_page')