forked from ungleich-public/dynamicweb
176 lines
6.2 KiB
Python
176 lines
6.2 KiB
Python
from django import forms
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import transaction
|
|
from django.utils.html import strip_tags
|
|
from django.utils.text import slugify
|
|
from django.utils.translation import gettext, gettext_lazy as _
|
|
|
|
from cms.admin.forms import AddPageForm
|
|
from cms.plugin_pool import plugin_pool
|
|
from cms.utils import permissions
|
|
from cms.utils.conf import get_cms_setting
|
|
from cms.utils.page import get_available_slug
|
|
from cms.utils.page_permissions import user_can_add_page, user_can_add_subpage
|
|
|
|
try:
|
|
# djangocms_text is not guaranteed to be available
|
|
from djangocms_text.widgets import TextEditorWidget
|
|
text_widget = TextEditorWidget
|
|
except ImportError:
|
|
text_widget = forms.Textarea
|
|
|
|
|
|
class CreateCMSPageForm(AddPageForm):
|
|
sub_page_form = False
|
|
|
|
# Field overrides
|
|
menu_title = None
|
|
page_title = None
|
|
meta_description = None
|
|
|
|
content = forms.CharField(
|
|
label=_('Content'), widget=text_widget, required=False,
|
|
help_text=_("Optional. If supplied, will be automatically added "
|
|
"within a new text plugin.")
|
|
)
|
|
|
|
class Media:
|
|
js = (
|
|
# This simply adds some JS for
|
|
# hiding/showing the content field based on the selection of this select.
|
|
'cms/js/widgets/wizard.pagetypeselect.js',
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields['title'].help_text = _("Provide a title for the new page.")
|
|
self.fields['slug'].required = False
|
|
self.fields['slug'].help_text = _("Leave empty for automatic slug, or override as required.")
|
|
|
|
def get_placeholder(self, page_content, slot=None):
|
|
"""
|
|
Returns the named placeholder or, if no «slot» provided, the first
|
|
editable, non-static placeholder or None.
|
|
"""
|
|
placeholders = page_content.get_placeholders()
|
|
|
|
if slot:
|
|
placeholders = placeholders.filter(slot=slot)
|
|
|
|
for ph in placeholders:
|
|
if not ph.is_static and ph.is_editable:
|
|
return ph
|
|
return None
|
|
|
|
@property
|
|
def _language(self):
|
|
return self.language_code
|
|
|
|
def clean(self):
|
|
"""
|
|
Validates that either the slug is provided, or that slugification from
|
|
`title` produces a valid slug.
|
|
:return:
|
|
"""
|
|
data = self.cleaned_data
|
|
|
|
if self._errors:
|
|
return data
|
|
|
|
slug = slugify(data.get('slug')) or slugify(data['title'])
|
|
if not slug:
|
|
data["slug"] = ""
|
|
forms.ValidationError({
|
|
"slug": [_("Cannot automatically create slug. Please provide one manually.")],
|
|
})
|
|
|
|
parent_page = data.get('parent_page')
|
|
|
|
if parent_page:
|
|
base = parent_page.get_path(self._language)
|
|
path = f'{base}/{slug}' if base else slug
|
|
else:
|
|
base = ''
|
|
path = slug
|
|
|
|
data['slug'] = get_available_slug(self._site, path, self._language, suffix=None)
|
|
data['path'] = '{}/{}'.format(base, data['slug']) if base else data['slug']
|
|
|
|
if not data['slug']:
|
|
raise forms.ValidationError(_("Please provide a valid slug."))
|
|
return data
|
|
|
|
def clean_content(self):
|
|
# A rich-text editor submits an empty value as an empty paragraph
|
|
# (e.g. ``<p></p>`` or ``<p> </p>``) rather than an empty string.
|
|
# Treat any value without visible text as empty so the wizard does not
|
|
# create a blank text plugin on the new page.
|
|
content = self.cleaned_data.get("content")
|
|
if content and not strip_tags(content).replace("\xa0", "").replace(" ", "").strip():
|
|
return ""
|
|
return content
|
|
|
|
def clean_parent_page(self):
|
|
# Check to see if this user has permissions to make this page. We've
|
|
# already checked this when producing a list of wizard entries, but this
|
|
# is to prevent people from possible form-hacking.
|
|
if self._page and self.sub_page_form:
|
|
# User is adding a page which will be a direct
|
|
# child of the current page.
|
|
parent_page = self._page
|
|
elif self._page and self._page.parent:
|
|
# User is adding a page which will be a right
|
|
# sibling to the current page.
|
|
parent_page = self._page.parent
|
|
else:
|
|
parent_page = None
|
|
|
|
if parent_page:
|
|
if parent_page.site_id != self._site.pk:
|
|
raise ValidationError("Site doesn't match the parent's page site")
|
|
has_perm = user_can_add_subpage(self._user, target=parent_page, site=self._site)
|
|
else:
|
|
has_perm = user_can_add_page(self._user, site=self._site)
|
|
|
|
if not has_perm:
|
|
message = gettext('You don\'t have the permissions required to add a page.')
|
|
raise ValidationError(message)
|
|
return parent_page if parent_page else None
|
|
|
|
def get_template(self):
|
|
return get_cms_setting('PAGE_WIZARD_DEFAULT_TEMPLATE')
|
|
|
|
@transaction.atomic
|
|
def save(self, **kwargs):
|
|
from cms.api import add_plugin
|
|
|
|
new_translation = super().save(**kwargs)
|
|
new_page = new_translation.page
|
|
|
|
if self.cleaned_data.get("page_type"):
|
|
return new_page
|
|
|
|
# If the user provided content, then use that instead.
|
|
content = self.cleaned_data.get('content')
|
|
plugin_type = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN')
|
|
plugin_body = get_cms_setting('PAGE_WIZARD_CONTENT_PLUGIN_BODY')
|
|
slot = get_cms_setting('PAGE_WIZARD_CONTENT_PLACEHOLDER')
|
|
|
|
if plugin_type in plugin_pool.plugins and plugin_body:
|
|
if content and permissions.has_plugin_permission(
|
|
self._user, plugin_type, "add"):
|
|
placeholder = self.get_placeholder(new_translation, slot=slot)
|
|
if placeholder:
|
|
opts = {
|
|
'placeholder': placeholder,
|
|
'plugin_type': plugin_type,
|
|
'language': self.language_code,
|
|
plugin_body: content,
|
|
}
|
|
add_plugin(**opts)
|
|
return new_page
|
|
|
|
|
|
class CreateCMSSubPageForm(CreateCMSPageForm):
|
|
|
|
sub_page_form = True
|