Skip to content

feat: Reintroduce default_plugins setting #7919

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion cms/tests/test_permmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from cms.admin.forms import save_permissions
from cms.api import assign_user_to_page, create_page, create_page_user
from cms.cms_menus import get_visible_nodes
from cms.models import ACCESS_PAGE, Page, PageContent
from cms.models import ACCESS_PAGE, CMSPlugin, Page, PageContent
from cms.models.permissionmodels import (
ACCESS_PAGE_AND_DESCENDANTS,
GlobalPagePermission,
Expand Down Expand Up @@ -139,6 +139,28 @@ def test_slave_cannot_add_page_to_root(self):
response = self.client.get(self.get_page_add_uri('en'))
self.assertEqual(response.status_code, 403)

@override_settings(
CMS_PLACEHOLDER_CONF={
'col_left': {
'default_plugins': [
{
'plugin_type': 'TextPlugin',
'values': {
'body': 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa, repellendus, delectus, quo quasi ullam inventore quod quam aut voluptatum aliquam voluptatibus harum officiis officia nihil minus unde accusamus dolorem repudiandae.'
},
},
]
},
},
)
def test_default_plugins(self):
with self.login_user_context(self.user_slave):
self.assertEqual(CMSPlugin.objects.count(), 0)
response = self.client.get(self.slave_page.get_absolute_url(), {'edit': 1})
self.assertEqual(response.status_code, 200)
self.assertEqual(CMSPlugin.objects.count(), 1)


def test_super_can_add_plugin(self):
self._add_plugin(self.user_super, page=self.slave_page)

Expand Down
86 changes: 83 additions & 3 deletions cms/tests/test_placeholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,14 @@ def test_get_placeholder_conf(self):
'main': {
'name': 'main content',
'plugins': ['TextPlugin', 'LinkPlugin'],
'require_parent': False,
'default_plugins': [
{
'plugin_type': 'TextPlugin',
'values': {
'body': '<p>Some default text</p>'
},
},
],
},
'layout/home.html main': {
'name': 'main content with FilerImagePlugin and limit',
Expand Down Expand Up @@ -642,8 +649,8 @@ def test_get_placeholder_conf(self):
returned = get_placeholder_conf('excluded_plugins', 'main', 'layout/other.html')
self.assertEqual(returned, TEST_CONF['layout/other.html main']['excluded_plugins'])
# test grandparent inherited value
returned = get_placeholder_conf('require_parent', 'main', 'layout/other.html')
self.assertEqual(returned, TEST_CONF['main']['require_parent'])
returned = get_placeholder_conf('default_plugins', 'main', 'layout/other.html')
self.assertEqual(returned, TEST_CONF['main']['default_plugins'])
# test generic configuration
returned = get_placeholder_conf('plugins', 'something')
self.assertEqual(returned, TEST_CONF[None]['plugins'])
Expand Down Expand Up @@ -738,6 +745,79 @@ def test_placeholder_field_dynamic_slot_update(self):
self.assertEqual(old_placeholder_1_plugin_count, current_placeholder_1_plugin_count)
self.assertEqual(old_placeholder_2_plugin_count, current_placeholder_2_plugin_count)

def test_plugins_prepopulate(self):
""" Tests prepopulate placeholder configuration """

conf = {
'col_left': {
'default_plugins' : [
{
'plugin_type':'TextPlugin',
'values':{'body':'<p>en default body 1</p>'},
},
{
'plugin_type':'TextPlugin',
'values':{'body':'<p>en default body 2</p>'},
},
]
},
}
with self.settings(CMS_PLACEHOLDER_CONF=conf):
page = create_page('page_en', 'col_two.html', 'en')
placeholder = page.get_placeholders("en").get(slot='col_left')
context = SekizaiContext()
context['request'] = self.get_request(language="en", page=page)
# Our page should have "en default body 1" AND "en default body 2"
content = _render_placeholder(placeholder, context)
self.assertRegex(content, r"^<p>en default body 1</p>\s*<p>en default body 2</p>$")

def test_plugins_children_prepopulate(self):
"""
Validate a default textplugin with a nested default link plugin
"""

conf = {
'col_left': {
'default_plugins': [
{
'plugin_type': 'TextPlugin',
'values': {
'body': '<p>body %(_tag_child_1)s and %(_tag_child_2)s</p>'
},
'children': [
{
'plugin_type': 'LinkPlugin',
'values': {
'name': 'django',
'external_link': 'https://www.djangoproject.com/'
},
},
{
'plugin_type': 'LinkPlugin',
'values': {
'name': 'django-cms',
'external_link': 'https://www.django-cms.org'
},
},
]
},
]
},
}

with self.settings(CMS_PLACEHOLDER_CONF=conf):
page = create_page('page_en', 'col_two.html', 'en')
placeholder = page.get_placeholders("en").get(slot='col_left')
context = SekizaiContext()
context['request'] = self.get_request(language="en", page=page)
_render_placeholder(placeholder, context)
plugins = placeholder.get_plugins_list()
self.assertEqual(len(plugins), 3)
self.assertEqual(plugins[0].plugin_type, 'TextPlugin')
self.assertEqual(plugins[1].plugin_type, 'LinkPlugin')
self.assertEqual(plugins[2].plugin_type, 'LinkPlugin')
self.assertTrue(plugins[1].parent == plugins[2].parent and plugins[1].parent == plugins[0])

def test_placeholder_pk_thousands_format(self):
page = create_page("page", "nav_playground.html", "en")
title = page.get_content_obj("en")
Expand Down
1 change: 1 addition & 0 deletions cms/tests/test_rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ def test_inherit_placeholder_override(self):
r = self.render(self.test_page5)
self.assertEqual(r, '|' + self.test_data5['text_main'] + '|' + self.test_data5['text_sub'])

@override_settings(CMS_PLACEHOLDER_CONF={None: {'language_fallback': False}})
def test_inherit_placeholder_queries(self):
with self.assertNumQueries(FuzzyInt(6, 10)):
r = self.render(self.test_page2)
Expand Down
47 changes: 47 additions & 0 deletions cms/utils/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from collections import OrderedDict, defaultdict, deque
from copy import deepcopy
from functools import lru_cache
from itertools import starmap
from operator import itemgetter

from django.utils.encoding import force_str
from django.utils.translation import gettext as _
Expand All @@ -12,6 +14,7 @@
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from cms.utils import get_language_from_request
from cms.utils.permissions import has_plugin_permission
from cms.utils.placeholder import get_placeholder_conf

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -91,6 +94,9 @@ def assign_plugins(request, placeholders, template=None, lang=None):
.objects
.filter(placeholder__in=placeholders, language=lang)
)
if not plugins:
# Create default plugins if enabled
plugins = create_default_plugins(request, placeholders, template, lang)
plugins = downcast_plugins(plugins, placeholders, request=request)

# split the plugins up by placeholder
Expand All @@ -112,6 +118,47 @@ def assign_plugins(request, placeholders, template=None, lang=None):
placeholder._plugins_cache = layered_plugins


def create_default_plugins(request, placeholders, template, lang):
"""
Create all default plugins for the given ``placeholders`` if they have
a "default_plugins" configuration value in settings.
return all plugins, children, grandchildren (etc.) created
"""
from cms.api import add_plugin

def _create_default_plugins(placeholder, confs, parent=None):
"""
Auxiliary function that builds all of a placeholder's default plugins
at the current level and drives the recursion down the tree.
Returns the plugins at the current level along with all descendants.
"""
plugins, descendants = [], []
addable_confs = (conf for conf in confs
if has_plugin_permission(request.user,
conf['plugin_type'], 'add'))
for conf in addable_confs:
plugin = add_plugin(placeholder, conf['plugin_type'], lang,
target=parent, **conf['values'])
if 'children' in conf:
args = placeholder, conf['children'], plugin
descendants += _create_default_plugins(*args)
plugin.notify_on_autoadd(request, conf)
plugins.append(plugin)
if parent:
parent.notify_on_autoadd_children(request, conf, plugins)
return plugins + descendants

unfiltered_confs = ((ph, get_placeholder_conf('default_plugins',
ph.slot, template))
for ph in placeholders)
# Empty confs must be filtered before filtering on add permission
mutable_confs = ((ph, default_plugin_confs)
for ph, default_plugin_confs
in filter(itemgetter(1), unfiltered_confs)
if ph.has_change_permission(request.user))
return sum(starmap(_create_default_plugins, mutable_confs), [])


def get_plugins_as_layered_tree(plugins):
"""
Given an iterable of plugins ordered by position,
Expand Down