Skip to content

Commit

Permalink
Merge 956ccb0 into a4d4905
Browse files Browse the repository at this point in the history
  • Loading branch information
g3rb3n committed Apr 30, 2020
2 parents a4d4905 + 956ccb0 commit 389b5d5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Expand Up @@ -15,6 +15,7 @@ Changelog
* added ``--force-color`` and ``--skip-checks`` in base commands when using Django 3
* replaced ``staticfiles`` and ``admin_static`` with ``static``
* replaced djangocms-helper with django-app-helper
* Added ability to set placeholder global limit on children only


3.7.1 (2019-11-26)
Expand Down
3 changes: 2 additions & 1 deletion cms/admin/forms.py
Expand Up @@ -1305,7 +1305,8 @@ def clean(self):
placeholder,
data['plugin_type'],
language,
template=template
template=template,
parent_plugin=parent_plugin
)
except PluginLimitReached as error:
self.add_error(None, force_text(error))
Expand Down
7 changes: 6 additions & 1 deletion cms/admin/placeholderadmin.py
Expand Up @@ -632,11 +632,16 @@ def move_plugin(self, request):

order = request.POST.getlist("plugin_order[]")

parent_plugin = None
if parent_id != None:
parent_plugin = self._get_plugin_from_id(parent_id)

if placeholder != source_placeholder:
try:
template = self.get_placeholder_template(request, placeholder)
has_reached_plugin_limit(placeholder, plugin.plugin_type,
target_language, template=template)
target_language, template=template,
parent_plugin=parent_plugin)
except PluginLimitReached as er:
return HttpResponseBadRequest(er)

Expand Down
6 changes: 6 additions & 0 deletions cms/models/placeholdermodel.py
Expand Up @@ -361,6 +361,12 @@ def get_plugins(self, language=None):
else:
return self.cmsplugin_set.all().order_by('path')

def get_child_plugins(self, language=None):
if language:
return self.cmsplugin_set.filter(language=language, parent__isnull=True).order_by('path')
else:
return self.cmsplugin_set.filter(parent__isnull=True).order_by('path')

def get_filled_languages(self):
"""
Returns language objects for every language for which the placeholder
Expand Down
34 changes: 34 additions & 0 deletions cms/tests/test_admin.py
Expand Up @@ -645,6 +645,40 @@ def test_too_many_plugins_type(self):
response = self.client.post(url, data)
self.assertEqual(response.status_code, HttpResponseBadRequest.status_code)

def test_too_many_plugins_global_children(self):
from urllib.parse import urlencode
conf = {
'body': {
'limits': {
'global_children': 1,
},
},
}
admin_user = self.get_admin()
url = admin_reverse('cms_page_add_plugin')
with self.settings(CMS_PERMISSION=False, CMS_PLACEHOLDER_CONF=conf):
page = create_page('somepage', 'nav_playground.html', 'en')
body = page.placeholders.get(slot='body')
link = add_plugin(body, 'LinkPlugin', 'en', name='text', external_link='http://test.test/')
with self.login_user_context(admin_user):
data = {
'plugin_type': 'TextPlugin',
'placeholder_id': body.pk,
'plugin_language': 'en',
}
url = admin_reverse('cms_page_add_plugin')
response = self.client.post('{}?{}'.format(url,urlencode(data)))
self.assertEqual(response.status_code, HttpResponseBadRequest.status_code)
with self.login_user_context(admin_user):
data = {
'plugin_type': 'TextPlugin',
'placeholder_id': body.pk,
'plugin_parent': link.pk,
'plugin_language': 'en',
}
response = self.client.post('{}?{}'.format(url,urlencode(data)))
self.assertEqual(response.status_code, 302)

def test_edit_title_dirty_bit(self):
language = "en"
admin_user = self.get_admin()
Expand Down
37 changes: 35 additions & 2 deletions cms/tests/test_placeholder.py
Expand Up @@ -13,7 +13,7 @@

from cms import constants
from cms.api import add_plugin, create_page, create_title
from cms.exceptions import DuplicatePlaceholderWarning
from cms.exceptions import DuplicatePlaceholderWarning, PluginLimitReached
from cms.models.fields import PlaceholderField
from cms.models.placeholdermodel import Placeholder
from cms.models.pluginmodel import CMSPlugin
Expand All @@ -36,7 +36,7 @@
from cms.utils.placeholder import (PlaceholderNoAction, MLNGPlaceholderActions,
get_placeholder_conf, get_placeholders, _get_nodelist,
_scan_placeholders)
from cms.utils.plugins import assign_plugins
from cms.utils.plugins import assign_plugins, has_reached_plugin_limit
from cms.utils.urlutils import admin_reverse


Expand Down Expand Up @@ -1047,3 +1047,36 @@ def test_get_all_plugins_inherit(self):
plugins = plugin_pool.get_all_plugins(placeholder, page)
self.assertEqual(len(plugins), 1, plugins)
self.assertEqual(plugins[0], LinkPlugin)

def test_plugins_limit_global(self):
""" Tests placeholder limit configuration for nested plugins"""
page = create_page('page', 'col_two.html', 'en')
placeholder = page.placeholders.get(slot='col_left')
conf = {
'col_left': {
'limits': {
'global': 1,
},
},
}
with self.settings(CMS_PLACEHOLDER_CONF=conf):
add_plugin(placeholder, 'LinkPlugin', 'en', name='name', external_link='http://example.com/en')
self.assertRaises(PluginLimitReached, has_reached_plugin_limit, placeholder=placeholder, plugin_type='LinkPlugin', language='en', template=None, parent_plugin=None)


def test_plugins_limit_global_children(self):
""" Tests placeholder limit configuration for nested plugins"""
page = create_page('page', 'col_two.html', 'en')
placeholder = page.placeholders.get(slot='col_left')
conf = {
'col_left': {
'limits': {
'global_children': 1,
},
},
}
with self.settings(CMS_PLACEHOLDER_CONF=conf):
link = add_plugin(placeholder, 'LinkPlugin', 'en', name='name', external_link='http://example.com/en')
add_plugin(placeholder, 'TextPlugin', 'en', target=link)
add_plugin(placeholder, 'TextPlugin', 'en', target=link)
self.assertRaises(PluginLimitReached, has_reached_plugin_limit, placeholder=placeholder, plugin_type='LinkPlugin', language='en', template=None, parent_plugin=None)
6 changes: 5 additions & 1 deletion cms/utils/plugins.py
Expand Up @@ -330,7 +330,7 @@ def reorder_plugins(placeholder, parent_id, language, order=None):
return plugins


def has_reached_plugin_limit(placeholder, plugin_type, language, template=None):
def has_reached_plugin_limit(placeholder, plugin_type, language, template=None, parent_plugin=None):
"""
Checks if placeholder has reached it's global plugin limit,
if not then it checks if it has reached it's plugin_type limit.
Expand All @@ -356,4 +356,8 @@ def has_reached_plugin_limit(placeholder, plugin_type, language, template=None):
raise PluginLimitReached(_(
"This placeholder already has the maximum number (%(limit)s) of allowed %(plugin_name)s plugins.") \
% {'limit': type_limit, 'plugin_name': plugin_name})
global_children_limit = limits.get("global_children")
children_count = placeholder.get_child_plugins(language=language).count()
if not parent_plugin and global_children_limit and children_count >= global_children_limit:
raise PluginLimitReached(_("This placeholder already has the maximum number of child plugins (%s)." % children_count))
return False

0 comments on commit 389b5d5

Please sign in to comment.