diff --git a/AUTHORS b/AUTHORS
index 1e7846809d2..e6d0f418a65 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -165,7 +165,6 @@ Contributors (in alphabetical order):
* wid
* wildermesser
* Yann Malet
-* Yann Malet
* yedpodtrzitko
* yohanboniface
* Yosuke Ikeda
diff --git a/cms/__init__.py b/cms/__init__.py
index 21447e892c9..64cd33e047b 100644
--- a/cms/__init__.py
+++ b/cms/__init__.py
@@ -1,10 +1,5 @@
# -*- coding: utf-8 -*-
-VERSION = (2, 1, 3, 'final')
-if VERSION[-1] != "final": # pragma: no cover
- __version__ = '.'.join(map(str, VERSION))
-else: # pragma: no cover
- __version__ = '.'.join(map(str, VERSION[:-1]))
-
+__version__ = '2.2.dev0'
# patch settings
try:
diff --git a/cms/admin/forms.py b/cms/admin/forms.py
index d604588b9b6..4a30595ed25 100644
--- a/cms/admin/forms.py
+++ b/cms/admin/forms.py
@@ -1,4 +1,14 @@
# -*- coding: utf-8 -*-
+from cms.apphook_pool import apphook_pool
+from cms.forms.widgets import UserSelectAdminWidget
+from cms.models import (Page, PagePermission, PageUser, ACCESS_PAGE,
+ PageUserGroup)
+from cms.utils.mail import mail_page_user_change
+from cms.utils.page import is_valid_page_slug
+from cms.utils.page_resolver import get_page_from_path
+from cms.utils.permissions import (get_current_user, get_subordinate_users,
+ get_subordinate_groups)
+from cms.utils.urlutils import any_path_re
from django import forms
from django.conf import settings
from django.contrib.auth.forms import UserCreationForm
@@ -11,18 +21,9 @@
from django.forms.widgets import HiddenInput
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _, get_language
+from menus.menu_pool import menu_pool
-from cms.apphook_pool import apphook_pool
-from cms.forms.widgets import UserSelectAdminWidget
-from cms.models import (Page, PagePermission, PageUser,
- ACCESS_PAGE, PageUserGroup)
-from cms.utils.mail import mail_page_user_change
-from cms.utils.page import is_valid_page_slug
-from cms.utils.permissions import (get_current_user, get_subordinate_users,
- get_subordinate_groups)
-from cms.utils.urlutils import any_path_re
-from menus.menu_pool import menu_pool
def get_permission_acessor(obj):
@@ -158,7 +159,7 @@ def __init__(self, *args, **kwargs):
self.fields['navigation_extenders'].widget = forms.Select({}, [('', "---------")] + menu_pool.get_menus_by_attribute("cms_enabled", True))
if 'application_urls' in self.fields:
self.fields['application_urls'].choices = [('', "---------")] + apphook_pool.get_apphooks()
-
+
def clean(self):
cleaned_data = super(PageForm, self).clean()
if 'reverse_id' in self.fields:
@@ -175,6 +176,8 @@ def clean_overwrite_url(self):
if url:
if not any_path_re.match(url):
raise forms.ValidationError(_('Invalid URL, use /my/url format.'))
+ if get_page_from_path(url.strip('/')):
+ raise forms.ValidationError(_('Page with redirect url %r already exist') % url)
return url
class PagePermissionInlineAdminForm(forms.ModelForm):
diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py
index eb605475f88..b61d284c6f2 100644
--- a/cms/admin/pageadmin.py
+++ b/cms/admin/pageadmin.py
@@ -1033,7 +1033,8 @@ def preview_page(self, request, object_id):
site = Site.objects.get_current()
if not site == page.site:
- url = "http://%s%s" % (page.site.domain, url)
+ url = "http%s://%s%s" % ('s' if request.is_secure() else '',
+ page.site.domain, url)
return HttpResponseRedirect(url)
def change_status(self, request, page_id):
diff --git a/cms/admin/placeholderadmin.py b/cms/admin/placeholderadmin.py
index 188fc255720..281abe4e38c 100644
--- a/cms/admin/placeholderadmin.py
+++ b/cms/admin/placeholderadmin.py
@@ -225,8 +225,26 @@ def move_plugin(self, request):
# only allow POST
if request.method != "POST":
return HttpResponse(str("error"))
+
+ if 'plugin_id' in request.POST: # single plugin moving
+ plugin = CMSPlugin.objects.get(pk=int(request.POST['plugin_id']))
+
+ if 'placeholder_id' in request.POST:
+ placeholder = Placeholder.objects.get(pk=int(request.POST['placeholder_id']))
+ else:
+ placeholder = plugin.placeholder
+
+ # check permissions
+ if not placeholder.has_change_permission(request):
+ raise Http404
+
+ # plugin positions are 0 based, so just using count here should give us 'last_position + 1'
+ position = CMSPlugin.objects.filter(placeholder=placeholder).count()
+ plugin.placeholder = placeholder
+ plugin.position = position
+ plugin.save()
pos = 0
- if 'ids' in request.POST: # multiple plugins
+ if 'ids' in request.POST: # multiple plugins/ reordering
whitelisted_placeholders = []
for id in request.POST['ids'].split("_"):
plugin = CMSPlugin.objects.get(pk=id)
@@ -244,18 +262,7 @@ def move_plugin(self, request):
plugin.position = pos
plugin.save()
pos += 1
- elif 'plugin_id' in request.POST: # single plugin moving
- plugin = CMSPlugin.objects.get(pk=int(request.POST['plugin_id']))
-
- # check permissions
- if not plugin.placeholder.has_change_permission(request):
- raise Http404
-
- placeholder = plugin.placeholder
- # plugin positions are 0 based, so just using count here should give us 'last_position + 1'
- position = CMSPlugin.objects.filter(placeholder=placeholder).count()
- plugin.position = position
- plugin.save()
+
else:
HttpResponse(str("error"))
return HttpResponse(str("ok"))
diff --git a/cms/api.py b/cms/api.py
index f6dfa5b9e8a..8000e732523 100644
--- a/cms/api.py
+++ b/cms/api.py
@@ -142,11 +142,11 @@ def create_page(title, template, language, menu_title=None, slug=None,
# validate publication date
if publication_date:
- assert isinstance(publication_date, datetime.datetime)
+ assert isinstance(publication_date, datetime.date)
# validate publication end date
if publication_end_date:
- assert isinstance(publication_date, datetime.datetime)
+ assert isinstance(publication_end_date, datetime.date)
# validate softroot
assert settings.CMS_SOFTROOT or not soft_root
diff --git a/cms/cms_toolbar.py b/cms/cms_toolbar.py
index b659465232e..b403a3fb932 100644
--- a/cms/cms_toolbar.py
+++ b/cms/cms_toolbar.py
@@ -57,12 +57,15 @@ class CMSToolbar(Toolbar):
"""
def __init__(self, request):
super(CMSToolbar, self).__init__(request)
- self.is_staff = request.user.is_staff
- self.can_change = (request.current_page and
- request.current_page.has_change_permission(request))
+ self.init()
+
+ def init(self):
+ self.is_staff = self.request.user.is_staff
+ self.can_change = (self.request.current_page and
+ self.request.current_page.has_change_permission(self.request))
self.edit_mode_switcher = Switcher(LEFT, 'editmode', 'edit', 'edit-off',
_('Edit mode'))
- self.edit_mode = self.is_staff and self.edit_mode_switcher.get_state(request)
+ self.edit_mode = self.is_staff and self.edit_mode_switcher.get_state(self.request)
def get_items(self, context, **kwargs):
@@ -73,6 +76,8 @@ def get_items(self, context, **kwargs):
Anchor(LEFT, 'logo', _('django CMS'), 'https://www.django-cms.org'),
]
+ self.page_states = []
+
if self.is_staff:
@@ -81,7 +86,9 @@ def get_items(self, context, **kwargs):
)
if self.request.current_page:
- has_states = self.request.current_page.last_page_states().exists()
+ states = self.request.current_page.last_page_states()
+ has_states = states.exists()
+ self.page_states = states
if has_states:
items.append(
TemplateHTML(LEFT, 'status',
@@ -132,9 +139,14 @@ def get_items(self, context, **kwargs):
def get_template_menu(self, context, can_change, is_staff):
menu_items = []
+ url = reverse('admin:cms_page_change_template', args=(self.request.current_page.pk,))
for path, name in settings.CMS_TEMPLATES:
+ args = urllib.urlencode({'template': path})
+ css = 'template'
+ if self.request.current_page.get_template() == path:
+ css += ' active'
menu_items.append(
- ListItem('template', name, '#%s' % path),
+ ListItem(css, name, '%s?%s' % (url, args), 'POST'),
)
return List(RIGHT, 'templates', _('Template'),
'', items=menu_items)
@@ -146,26 +158,26 @@ def get_page_menu(self, context, can_change, is_staff):
menu_items = [
ListItem('overview', _('Move/add Pages'),
reverse('admin:cms_page_changelist'),
- 'cms/images/toolbar/icons/icon_sitemap.png'),
+ icon='cms/images/toolbar/icons/icon_sitemap.png'),
]
menu_items.append(
ListItem('addchild', _('Add child page'),
_get_add_child_url,
- 'cms/images/toolbar/icons/icon_child.png')
+ icon='cms/images/toolbar/icons/icon_child.png')
)
menu_items.append(
ListItem('addsibling', _('Add sibling page'),
_get_add_sibling_url,
- 'cms/images/toolbar/icons/icon_sibling.png')
+ icon='cms/images/toolbar/icons/icon_sibling.png')
)
menu_items.append(
ListItem('delete', _('Delete Page'), _get_delete_url,
- 'cms/images/toolbar/icons/icon_delete.png')
+ icon='cms/images/toolbar/icons/icon_delete.png')
)
- return List(RIGHT, 'page', _('Page'), 'cms/images/toolbar/icons/icon_page.png',
- items=menu_items)
+ return List(RIGHT, 'page', _('Page'),
+ 'cms/images/toolbar/icons/icon_page.png', items=menu_items)
def get_admin_menu(self, context, can_change, is_staff):
"""
@@ -174,25 +186,24 @@ def get_admin_menu(self, context, can_change, is_staff):
admin_items = [
ListItem('admin', _('Site Administration'),
reverse('admin:index'),
- 'cms/images/toolbar/icons/icon_admin.png'),
+ icon='cms/images/toolbar/icons/icon_admin.png'),
]
if can_change:
admin_items.append(
ListItem('settings', _('Page Settings'),
_get_page_admin_url,
- 'cms/images/toolbar/icons/icon_page.png')
+ icon='cms/images/toolbar/icons/icon_page.png')
)
if 'reversion' in settings.INSTALLED_APPS:
admin_items.append(
ListItem('history', _('View History'),
_get_page_history_url,
- 'cms/images/toolbar/icons/icon_history.png')
+ icon='cms/images/toolbar/icons/icon_history.png')
)
return List(RIGHT, 'admin', _('Admin'), 'cms/images/toolbar/icons/icon_admin.png',
items=admin_items)
def request_hook(self):
- self.request.session['cms_edit'] = True
if self.request.method != 'POST':
return self._request_hook_get()
else:
@@ -212,3 +223,4 @@ def _request_hook_post(self):
user = authenticate(username=username, password=password)
if user:
login(self.request, user)
+ self.init()
diff --git a/cms/forms/widgets.py b/cms/forms/widgets.py
index 779d1be498f..dc7fc42ce21 100644
--- a/cms/forms/widgets.py
+++ b/cms/forms/widgets.py
@@ -207,7 +207,7 @@ def render(self, name, value, attrs=None):
)
context = {
'plugin_list': plugin_list,
- 'installed_plugins': plugin_pool.get_all_plugins(ph.slot),
+ 'installed_plugins': plugin_pool.get_all_plugins(ph.slot, include_page_only=False),
'copy_languages': copy_languages,
'language': language,
'show_copy': bool(copy_languages) and ph.actions.can_copy,
diff --git a/cms/management/commands/cms.py b/cms/management/commands/cms.py
index 9ba6cb90be6..add0abfeba4 100644
--- a/cms/management/commands/cms.py
+++ b/cms/management/commands/cms.py
@@ -1,118 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
-import sys
+from cms.management.commands.subcommands.base import SubcommandsCommand
+from cms.management.commands.subcommands.list import ListCommand
+from cms.management.commands.subcommands.moderator import ModeratorCommand
+from cms.management.commands.subcommands.uninstall import UninstallCommand
+from django.core.management.base import BaseCommand
from optparse import make_option
-from django.core.management.base import BaseCommand, NoArgsCommand, LabelCommand, CommandError
-from cms.models.pluginmodel import CMSPlugin
-from cms.models.titlemodels import Title
-
-class SubcommandsCommand(BaseCommand):
- subcommands = {}
- command_name = ''
-
- def __init__(self):
- super(SubcommandsCommand, self).__init__()
- for name, subcommand in self.subcommands.items():
- subcommand.command_name = '%s %s' % (self.command_name, name)
-
- def handle(self, *args, **options):
- stderr = getattr(self, 'stderr', sys.stderr)
- stdout = getattr(self, 'stdout', sys.stdout)
- if len(args) > 0:
- if args[0] in self.subcommands.keys():
- handle_command = self.subcommands.get(args[0])()
- handle_command.stdout = stdout
- handle_command.stderr = stderr
- handle_command.handle(*args[1:], **options)
- else:
- stderr.write("%r is not a valid subcommand for %r\n" % (args[0], self.command_name))
- stderr.write("Available subcommands are:\n")
- for subcommand in sorted(self.subcommands.keys()):
- stderr.write(" %r\n" % subcommand)
- raise CommandError('Invalid subcommand %r for %r' % (args[0], self.command_name))
- else:
- stderr.write("%r must be called with at least one argument, it's subcommand.\n" % self.command_name)
- stderr.write("Available subcommands are:\n")
- for subcommand in sorted(self.subcommands.keys()):
- stderr.write(" %r\n" % subcommand)
- raise CommandError('No subcommand given for %r' % self.command_name)
-
-class UninstallApphooksCommand(LabelCommand):
-
- args = "APPHOK_NAME"
- label = 'apphook name (eg SampleApp)'
- help = 'Uninstalls (sets to null) specified apphooks for all pages'
-
- def handle_label(self, label, **options):
- queryset = Title.objects.filter(application_urls=label)
- number_of_apphooks = queryset.count()
-
- if number_of_apphooks > 0:
- if options.get('interactive'):
- confirm = raw_input("""
-You have requested to remove %d %r apphooks.
-Are you sure you want to do this?
-Type 'yes' to continue, or 'no' to cancel: """ % (number_of_apphooks, label))
- else:
- confirm = 'yes'
- if confirm == 'yes':
- queryset.update(application_urls=None)
- self.stdout.write('%d %r apphooks uninstalled\n' % (number_of_apphooks, label))
- else:
- self.stdout.write('no %r apphooks found\n' % label)
-
-class UninstallPluginsCommand(LabelCommand):
-
- args = "PLUGIN_NAME"
- label = 'plugin name (eg SamplePlugin)'
- help = 'Uninstalls (deletes) specified plugins from the CMSPlugin model'
- def handle_label(self, label, **options):
- queryset = CMSPlugin.objects.filter(plugin_type=label)
- number_of_plugins = queryset.count()
-
- if number_of_plugins > 0:
- if options.get('interactive'):
- confirm = raw_input("""
-You have requested to remove %d %r plugins.
-Are you sure you want to do this?
-Type 'yes' to continue, or 'no' to cancel: """ % (number_of_plugins, label))
- else:
- confirm = 'yes'
- queryset.delete()
- self.stdout.write('%d %r plugins uninstalled\n' % (number_of_plugins, label))
- else:
- self.stdout.write('no %r plugins found\n' % label)
-
-class UninstallCommand(SubcommandsCommand):
- help = 'Uninstall commands'
- subcommands = {
- 'apphooks': UninstallApphooksCommand,
- 'plugins': UninstallPluginsCommand
- }
-
-class ListApphooksCommand(NoArgsCommand):
-
- help = 'Lists all apphooks in pages'
- def handle_noargs(self, **options):
- urls = Title.objects.values_list("application_urls", flat=True)
- for url in urls:
- self.stdout.write(url+'\n')
-
-class ListPluginsCommand(NoArgsCommand):
-
- help = 'Lists all plugins in CMSPlugin'
- def handle_noargs(self, **options):
- plugins = CMSPlugin.objects.distinct().values_list("plugin_type", flat=True)
- for plugin in plugins:
- self.stdout.write(plugin+'\n')
-
-class ListCommand(SubcommandsCommand):
- help = 'List commands'
- subcommands = {
- 'apphooks': ListApphooksCommand,
- 'plugins': ListPluginsCommand
- }
class Command(SubcommandsCommand):
@@ -127,4 +21,5 @@ class Command(SubcommandsCommand):
subcommands = {
'uninstall': UninstallCommand,
'list': ListCommand,
+ 'moderator': ModeratorCommand,
}
\ No newline at end of file
diff --git a/cms/management/commands/subcommands/__init__.py b/cms/management/commands/subcommands/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/cms/management/commands/subcommands/base.py b/cms/management/commands/subcommands/base.py
new file mode 100644
index 00000000000..cb2de14caa2
--- /dev/null
+++ b/cms/management/commands/subcommands/base.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from django.core.management.base import BaseCommand, CommandError
+import sys
+
+
+
+class SubcommandsCommand(BaseCommand):
+ subcommands = {}
+ command_name = ''
+
+ def __init__(self):
+ super(SubcommandsCommand, self).__init__()
+ for name, subcommand in self.subcommands.items():
+ subcommand.command_name = '%s %s' % (self.command_name, name)
+
+ def handle(self, *args, **options):
+ stderr = getattr(self, 'stderr', sys.stderr)
+ stdout = getattr(self, 'stdout', sys.stdout)
+ if len(args) > 0:
+ if args[0] in self.subcommands.keys():
+ handle_command = self.subcommands.get(args[0])()
+ handle_command.stdout = stdout
+ handle_command.stderr = stderr
+ handle_command.handle(*args[1:], **options)
+ else:
+ stderr.write("%r is not a valid subcommand for %r\n" % (args[0], self.command_name))
+ stderr.write("Available subcommands are:\n")
+ for subcommand in sorted(self.subcommands.keys()):
+ stderr.write(" %r\n" % subcommand)
+ raise CommandError('Invalid subcommand %r for %r' % (args[0], self.command_name))
+ else:
+ stderr.write("%r must be called with at least one argument, it's subcommand.\n" % self.command_name)
+ stderr.write("Available subcommands are:\n")
+ for subcommand in sorted(self.subcommands.keys()):
+ stderr.write(" %r\n" % subcommand)
+ raise CommandError('No subcommand given for %r' % self.command_name)
\ No newline at end of file
diff --git a/cms/management/commands/subcommands/list.py b/cms/management/commands/subcommands/list.py
new file mode 100644
index 00000000000..ddf3d270cae
--- /dev/null
+++ b/cms/management/commands/subcommands/list.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+from cms.management.commands.subcommands.base import SubcommandsCommand
+from cms.models.pluginmodel import CMSPlugin
+from cms.models.titlemodels import Title
+from django.core.management.base import NoArgsCommand
+
+
+class ListApphooksCommand(NoArgsCommand):
+
+ help = 'Lists all apphooks in pages'
+ def handle_noargs(self, **options):
+ urls = Title.objects.values_list("application_urls", flat=True)
+ for url in urls:
+ self.stdout.write(url+'\n')
+
+class ListPluginsCommand(NoArgsCommand):
+
+ help = 'Lists all plugins in CMSPlugin'
+ def handle_noargs(self, **options):
+ plugins = CMSPlugin.objects.distinct().values_list("plugin_type", flat=True)
+ for plugin in plugins:
+ self.stdout.write(plugin+'\n')
+
+class ListCommand(SubcommandsCommand):
+ help = 'List commands'
+ subcommands = {
+ 'apphooks': ListApphooksCommand,
+ 'plugins': ListPluginsCommand
+ }
\ No newline at end of file
diff --git a/cms/management/commands/subcommands/moderator.py b/cms/management/commands/subcommands/moderator.py
new file mode 100644
index 00000000000..1c30fd8f4d7
--- /dev/null
+++ b/cms/management/commands/subcommands/moderator.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from cms.management.commands.subcommands.base import SubcommandsCommand
+from cms.models.pagemodel import Page
+from django.conf import settings
+from django.core.management.base import NoArgsCommand
+
+
+class ModeratorOnCommand(NoArgsCommand):
+ help = 'Turn moderation on, run AFTER setting CMS_MODERATOR = True'
+
+ def handle_noargs(self, **options):
+ assert settings.CMS_MODERATOR == True, 'Command can only be run if CMS_MODERATOR is True'
+ for page in Page.objects.filter(published=True):
+ page.publish()
+
+
+class ModeratorCommand(SubcommandsCommand):
+ help = 'Moderator utilities'
+ subcommands = {
+ 'on': ModeratorOnCommand,
+ }
diff --git a/cms/management/commands/subcommands/uninstall.py b/cms/management/commands/subcommands/uninstall.py
new file mode 100644
index 00000000000..b55eba4b9fe
--- /dev/null
+++ b/cms/management/commands/subcommands/uninstall.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+from cms.management.commands.subcommands.base import SubcommandsCommand
+from cms.models.pluginmodel import CMSPlugin
+from cms.models.titlemodels import Title
+from django.core.management.base import LabelCommand
+
+
+class UninstallApphooksCommand(LabelCommand):
+
+ args = "APPHOK_NAME"
+ label = 'apphook name (eg SampleApp)'
+ help = 'Uninstalls (sets to null) specified apphooks for all pages'
+
+ def handle_label(self, label, **options):
+ queryset = Title.objects.filter(application_urls=label)
+ number_of_apphooks = queryset.count()
+
+ if number_of_apphooks > 0:
+ if options.get('interactive'):
+ confirm = raw_input("""
+You have requested to remove %d %r apphooks.
+Are you sure you want to do this?
+Type 'yes' to continue, or 'no' to cancel: """ % (number_of_apphooks, label))
+ else:
+ confirm = 'yes'
+ if confirm == 'yes':
+ queryset.update(application_urls=None)
+ self.stdout.write('%d %r apphooks uninstalled\n' % (number_of_apphooks, label))
+ else:
+ self.stdout.write('no %r apphooks found\n' % label)
+
+class UninstallPluginsCommand(LabelCommand):
+
+ args = "PLUGIN_NAME"
+ label = 'plugin name (eg SamplePlugin)'
+ help = 'Uninstalls (deletes) specified plugins from the CMSPlugin model'
+
+ def handle_label(self, label, **options):
+ queryset = CMSPlugin.objects.filter(plugin_type=label)
+ number_of_plugins = queryset.count()
+
+ if number_of_plugins > 0:
+ if options.get('interactive'):
+ confirm = raw_input("""
+You have requested to remove %d %r plugins.
+Are you sure you want to do this?
+Type 'yes' to continue, or 'no' to cancel: """ % (number_of_plugins, label))
+ else:
+ confirm = 'yes'
+ queryset.delete()
+ self.stdout.write('%d %r plugins uninstalled\n' % (number_of_plugins, label))
+ else:
+ self.stdout.write('no %r plugins found\n' % label)
+
+class UninstallCommand(SubcommandsCommand):
+ help = 'Uninstall commands'
+ subcommands = {
+ 'apphooks': UninstallApphooksCommand,
+ 'plugins': UninstallPluginsCommand
+ }
\ No newline at end of file
diff --git a/cms/media/cms/css/plugins/cms.toolbar.css b/cms/media/cms/css/plugins/cms.toolbar.css
index 08ebb5653a2..93634770ade 100644
--- a/cms/media/cms/css/plugins/cms.toolbar.css
+++ b/cms/media/cms/css/plugins/cms.toolbar.css
@@ -98,10 +98,13 @@
.cms_toolbar-item_list li { padding:0; zoom:1; }
.cms_toolbar-item_list li a { display:block; padding:4px 10px !important; zoom:1; white-space:nowrap; }
/*.cms_toolbar-item_list li a span { float:left; text-indent:-1000px; overflow:hidden; }*/
-.cms_toolbar-item_list li a:hover { color:#fff !important; background:#5b80b2; }
+.cms_toolbar-item_list li a:hover { color:#fff !important; background:#5b80b2 !important; }
.cms_toolbar-item_list li:first-child a { -webkit-border-radius:4px 4px 0 0; -moz-border-radius:4px 4px 0 0; border-radius:4px 4px 0 0; }
.cms_toolbar-item_list li:last-child a { -webkit-border-radius:0 0 4px 4px; -moz-border-radius:0 0 4px 4px; border-radius:0 0 4px 4px; }
.cms_toolbar-item_list li:only-child a { -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; }
+.cms_toolbar-item_list li.active a { background:#ddd; }
+
+.cms_toolbar-item_list .cms_toolbar-item_admin { padding-top:0 !important; }
/* #TOOLBAR/list/icons# */
.cms_toolbar-item_list .cms_toolbar_icon { width:18px; margin-right:4px; background-position:left 1px; }
diff --git a/cms/media/cms/js/change_list.js b/cms/media/cms/js/change_list.js
index e633b09b55c..78365517be9 100644
--- a/cms/media/cms/js/change_list.js
+++ b/cms/media/cms/js/change_list.js
@@ -39,10 +39,10 @@
cookies : {},
callback: {
beforemove : function(what, where, position, tree) {
- var old_target, old_position;
- var item_id = what.id.split("page_")[1];
- var target_id = where.id.split("page_")[1];
- var old_node = what;
+ item_id = what.id.split("page_")[1];
+ target_id = where.id.split("page_")[1];
+ old_node = what;
+
if($(what).parent().children("li").length > 1){
if($(what).next("li").length){
old_target = $(what).next("li")[0];
@@ -63,9 +63,9 @@
return true;
},
onmove: function(what, where, position, tree){
- var position;
- var item_id = what.id.split("page_")[1];
- var target_id = where.id.split("page_")[1];
+ item_id = what.id.split("page_")[1];
+ target_id = where.id.split("page_")[1];
+
if (position == "before") {
position = "left";
}else if (position == "after") {
@@ -76,7 +76,7 @@
moveTreeItem(what, item_id, target_id, position, false);
},
onchange: function(node, tree){
- var url = $(node).find('a.title').attr("href");
+ url = $(node).find('a.title').attr("href");
window.location = url;
}
}
@@ -96,8 +96,8 @@
$(document).ready(function() {
$.fn.cmsPatchCSRF();
- var selected_page = false;
- var action = false;
+ selected_page = false;
+ action = false;
var _oldAjax = $.ajax;
@@ -106,7 +106,7 @@
// always
$('#loader-message').show();
- var callback = s.success || false;
+ callback = s.success || false;
s.success = function(data, status){
if (callback) {
callback(data, status);
@@ -153,12 +153,10 @@
});
}
-
// let's start event delegation
$('#changelist li').click(function(e) {
// I want a link to check the class
- var target, selected_page, action, id, page_id, view_page_url, admin_base_url, pageId, parent, value, position, target_id, site;
if(e.target.tagName == 'IMG' || e.target.tagName == 'SPAN') {
target = e.target.parentNode;
} else {
@@ -167,11 +165,11 @@
var jtarget = $(target);
if(jtarget.hasClass("move")) {
// prepare tree for move / cut paste
- id = e.target.id.split("move-link-")[1];
+ var id = e.target.id.split("move-link-")[1];
if(id==null){
id = e.target.parentNode.id.split("move-link-")[1];
}
- page_id = id;
+ var page_id = id;
selected_page = page_id;
action = "move";
$('span.move-target-container, span.line, a.move-target').show();
@@ -194,7 +192,7 @@
}
if(jtarget.hasClass("viewpage")) {
- view_page_url = $('#' + target.id + '-select').val();
+ var view_page_url = $('#' + target.id + '-select').val();
if(view_page_url){
window.open(view_page_url);
}
@@ -324,25 +322,39 @@
$('#sitemap ul .col-moderator').syncWidth(68);
$('#sitemap ul .col-draft').syncWidth(0);
}
- syncCols();
-
+ syncCols();
+
/* Site Selector */
$('#site-select').change(function(event){
var id = this.value;
var url = window.location.href;
+
if(action=="copy"){
- url = insert_into_url(url, "copy", selected_page);
+ //url = insert_into_url(url, "copy", selected_page);
+ url = CMS.API.Helpers.setUrl(document.location, {
+ 'addParam': "copy=" + selected_page,
+ 'removeParam': "copy"
+ });
}else{
- url = remove_from_url(url, "copy");
+ //url = remove_from_url(url, "copy");
+ url = CMS.API.Helpers.setUrl(document.location, {
+ 'addParam': "copy",
+ 'removeParam': "copy"
+ });
}
- url = insert_into_url(url, "site__exact", id);
+ //url = insert_into_url(url, "site__exact", id);
+ url = CMS.API.Helpers.setUrl(document.location, {
+ 'addParam': "site__exact=" + id,
+ 'removeParam': "site__exact"
+ });
+
window.location = url;
});
var copy_splits = window.location.href.split("copy=");
if(copy_splits.length > 1){
var id = copy_splits[1].split("&")[0];
- var selected_page = id;
- var action = mark_copy_node(id);
+ var action = mark_copy_node(id);
+ selected_page = id;
}
// moderation checkboxes over livequery
@@ -360,7 +372,7 @@
});
}
return _copyTreeItem(item_id, target_id, position, site);
- };
+ }
function _copyTreeItem(item_id, target_id, position, site, options) {
var data = {
@@ -413,9 +425,9 @@
if (/page_\d+/.test($(el).attr('id'))) {
// one level higher
- var target = $(el).find('div.cont:first');
+ target = $(el).find('div.cont:first');
} else {
- var target = $(el).parents('div.cont:first');
+ target = $(el).parents('div.cont:first');
}
var parent = target.parent();
@@ -424,6 +436,8 @@
}
target.replace(response);
parent.find('div.cont:first').yft();
+
+ return true;
}
function onError(XMLHttpRequest, textStatus, errorThrown) {
@@ -440,7 +454,7 @@
});
}
-
+
function moveTreeItem(jtarget, item_id, target_id, position, tree){
reloadItem(
jtarget, "./" + item_id + "/move-page/",
@@ -462,7 +476,7 @@
moveError($('#page_'+item_id + " div.col1:eq(0)"));
}
);
- };
+ }
var undos = [];
diff --git a/cms/media/cms/js/libs/classy.min.js b/cms/media/cms/js/libs/classy.min.js
index 5bae30d3212..00bb5aceb3c 100644
--- a/cms/media/cms/js/libs/classy.min.js
+++ b/cms/media/cms/js/libs/classy.min.js
@@ -13,9 +13,6 @@ if(window['console'] === undefined) {
log = console.debug || console.log || alert;
}
-/* initiate classy namespace */
-var CMS = CMS || {};
-
/* initialize classy */
(function() {
var CLASSY_VERSION = '1.3.1',
diff --git a/cms/media/cms/js/plugin_editor.js b/cms/media/cms/js/plugin_editor.js
index 7f81fd3e801..7df0afbd564 100644
--- a/cms/media/cms/js/plugin_editor.js
+++ b/cms/media/cms/js/plugin_editor.js
@@ -97,8 +97,14 @@
{
// moved to new placeholder
var plugin_id = ui.item.attr('id').split('plugin_')[1];
- var target = ui.item.parent().parent().data('name');
- $.post("move-plugin/", { placeholder: target, plugin_id: plugin_id, ids: d }, function(data){}, "json");
+ var slot_name = ui.item.parent().parent().data('name');
+ var placeholder_id = ui.item.parent().parent().data('id');
+ $.post("move-plugin/", {
+ placeholder: slot_name,
+ placeholder_id: placeholder_id,
+ plugin_id: plugin_id,
+ ids: d
+ }, function(data){}, "json");
}
else
{
diff --git a/cms/media/cms/js/plugins/cms.base.js b/cms/media/cms/js/plugins/cms.base.js
index 5a2e498a5f9..17e118f2849 100644
--- a/cms/media/cms/js/plugins/cms.base.js
+++ b/cms/media/cms/js/plugins/cms.base.js
@@ -6,6 +6,7 @@
* assign Class and CMS namespace */
var CMS = CMS || {};
CMS.Class = CMS.Class || Class.$noConflict();
+ CMS.API = CMS.API || {};
(function ($) {
/*##################################################|*/
@@ -13,12 +14,12 @@
jQuery(document).ready(function ($) {
/**
* Security
- * @version: 0.1.1
+ * @version: 1.0.0
* @description: Adds security layer to CMS namespace
* @public_methods:
- * - CMS.Security.csrf();
+ * - CMS.API.Security.csrf();
*/
- CMS.Security = {
+ CMS.API.Security = {
csrf: function () {
$.ajaxSetup({
@@ -51,69 +52,78 @@ jQuery(document).ready(function ($) {
}
}
});
+ return 'ready';
}
};
/**
* Helpers
- * @version: 0.1.0
+ * @version: 1.0.0
* @description: Adds helper methods to be invoked
* @public_methods:
- * - CMS.Helpers.reloadBrowser();
- * - CMS.Helpers.insertUrl(url, name, value);
- * - CMS.Helpers.removeUrl(url, name);
+ * - CMS.API.Helpers.reloadBrowser();
+ * - CMS.API.Helpers.getUrl(urlString);
+ * - CMS.API.Helpers.setUrl(urlString, options);
*/
- CMS.Helpers = {
+ CMS.API.Helpers = {
reloadBrowser: function () {
window.location.reload();
},
-
- insertUrl: function (url, name, value) {
- // this is a one to one copy from the old toolbar
- if(url.substr(url.length-1, url.length)== "&") url = url.substr(0, url.length-1);
- var dash_splits = url.split("#");
- url = dash_splits[0];
- var splits = url.split(name + "=");
- if(splits.length == 1) splits = url.split(name);
- var get_args = false;
- if(url.split("?").length>1) get_args = true;
- if(splits.length > 1){
- var after = "";
- if(splits[1].split("&").length > 1) after = splits[1].split("&")[1];
- url = splits[0] + name;
- if(value) url += "=" + value;
- url += "&" + after;
- } else {
- if(get_args) { url = url + "&" + name; } else { url = url + "?" + name; }
- if(value) url += "=" + value;
- }
- if(dash_splits.length>1) url += '#' + dash_splits[1];
- if(url.substr(url.length-1, url.length)== "&") url = url.substr(0, url.length-1);
-
- return url;
- },
-
- removeUrl: function (url, name) {
- // this is a one to one copy from the old toolbar
- var dash_splits = url.split("#");
- url = dash_splits[0];
- var splits = url.split(name + "=");
- if(splits.length == 1) splits = url.split(name);
- if(splits.length > 1){
- var after = "";
- if (splits[1].split("&").length > 1) after = splits[1].split("&")[1];
- if (splits[0].substr(splits[0].length-2, splits[0].length-1)=="?" || !after) {
- url = splits[0] + after;
- } else {
- url = splits[0] + "&" + after;
+
+ getUrl: function(str) {
+ var o = {
+ 'strictMode': false,
+ 'key': ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
+ 'q': { 'name': 'queryKey', 'parser': /(?:^|&)([^&=]*)=?([^&]*)/g },
+ 'parser': {
+ 'strict': /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
+ 'loose': /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
- }
- if(url.substr(url.length-1,1) == "?") url = url.substr(0, url.length-1);
- if(dash_splits.length > 1 && dash_splits[1]) url += "#" + dash_splits[1];
+ };
- return url;
+ var m = o.parser[o.strictMode ? 'strict' : 'loose'].exec(str), uri = {}, i = 14;
+
+ while(i--) uri[o.key[i]] = m[i] || '';
+
+ uri[o.q.name] = {};
+ uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
+ if($1) { uri[o.q.name][$1] = $2; }
+ });
+
+ return uri;
+ },
+
+ setUrl: function (str, options) {
+ var uri = str;
+
+ // now we neet to get the partials of the element
+ var getUrlObj = this.getUrl(uri);
+ var query = getUrlObj.queryKey;
+ var serialized = '';
+ var index = 0;
+
+ // we could loop the query and replace the param at the right place
+ // but instead of replacing it just append it to the end of the query so its more visible
+ if(options && options.removeParam) delete query[options.removeParam];
+ if(options && options.addParam) query[options.addParam.split('=')[0]] = options.addParam.split('=')[1];
+
+ $.each(query, function (key, value) {
+ // add &
+ if(index != 0) serialized += '&';
+ // if a value is given attach it
+ serialized += (value) ? (key + '=' + value) : (key);
+ index++;
+ });
+
+ // check if we should add the questionmark
+ var addition = (serialized === '') ? '' : '?';
+ var anchor = (getUrlObj.anchor) ? '#' + getUrlObj.anchor : '';
+
+ uri = getUrlObj.protocol + '://' + getUrlObj.authority + getUrlObj.directory + getUrlObj.file + addition + serialized + anchor;
+
+ return uri;
}
};
diff --git a/cms/media/cms/js/plugins/cms.placeholders.js b/cms/media/cms/js/plugins/cms.placeholders.js
index 9403b85bbfe..7d2403af391 100644
--- a/cms/media/cms/js/plugins/cms.placeholders.js
+++ b/cms/media/cms/js/plugins/cms.placeholders.js
@@ -10,14 +10,14 @@
jQuery(document).ready(function ($) {
/**
* Placeholders
- * @version: 0.1.2
+ * @version: 1.0.0
* @description: Handles placeholders when in editmode and adds "lightbox" to toolbar
* @public_methods:
- * - CMS.Placeholder.addPlugin(url, obj);
- * - CMS.Placeholder.editPlugin(placeholder_id, plugin_id);
- * - CMS.Placeholder.deletePlugin(placeholder_id, plugin_id, plugin);
- * - CMS.Placeholder.toggleFrame();
- * - CMS.Placeholder.toggleDim();
+ * - CMS.API.Placeholder.addPlugin(url, obj);
+ * - CMS.API.Placeholder.editPlugin(placeholder_id, plugin_id);
+ * - CMS.API.Placeholder.deletePlugin(placeholder_id, plugin_id, plugin);
+ * - CMS.API.Placeholder.toggleFrame();
+ * - CMS.API.Placeholder.toggleDim();
* @compatibility: IE >= 6, FF >= 2, Safari >= 4, Chrome > =4, Opera >= 10
*/
CMS.Placeholders = CMS.Class.$extend({
@@ -201,7 +201,7 @@ jQuery(document).ready(function ($) {
that.editPlugin.call(that, data.placeholder_id, response);
},
'error': function () {
- log('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
+ throw new Error('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
}
});
},
@@ -275,7 +275,7 @@ jQuery(document).ready(function ($) {
plugin.remove();
},
'error': function () {
- log('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
+ throw new Error('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
}
});
}
@@ -322,7 +322,7 @@ jQuery(document).ready(function ($) {
'data': { 'ids': array.join('_') },
'success': refreshPluginPosition,
'error': function () {
- log('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
+ throw new Error('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
}
});
@@ -379,6 +379,7 @@ jQuery(document).ready(function ($) {
var text = $('.cms_placeholder-bar[class$="cms_placeholder_slot::' + item + '"]').find('.cms_placeholder-title').text();
list.append($('
' +text + ' ').data({
'slot': item,
+ 'placeholder_id': values.placeholder,
'plugin_id': values.plugin_id
}));
});
@@ -388,16 +389,17 @@ jQuery(document).ready(function ($) {
e.preventDefault();
// save slot var
var slot = $(this).parent().data('slot');
+ var placeholder_id = $(this).parent().data('placeholder_id');
// now lets do the ajax request
$.ajax({
'type': 'POST',
'url': that.options.urls.cms_page_move_plugin,
- 'data': { 'placeholder': slot, 'plugin_id': $(this).parent().data('plugin_id') },
+ 'data': { 'placeholder': slot, 'placeholder_id': placeholder_id, 'plugin_id': $(this).parent().data('plugin_id') },
'success': function () {
refreshPluginPosition(slot);
},
'error': function () {
- log('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
+ throw new Error('CMS.Placeholders was unable to perform this ajax request. Try again or contact the developers.');
}
});
});
@@ -414,6 +416,9 @@ jQuery(document).ready(function ($) {
plugin.insertAfter($(els.toArray()[els.length-1]));
}
+ // close overlay
+ that._hideOverlay();
+
// show success overlay for a second
that.success.css({
'width': plugin.width()-2,
@@ -450,6 +455,7 @@ jQuery(document).ready(function ($) {
_showPluginList: function (el) {
// save reference to this class
+ // TODO: make sure the element is really shown over everything
var that = this;
var list = el.parent().find('.cms_placeholder-subnav');
list.show();
@@ -496,7 +502,7 @@ jQuery(document).ready(function ($) {
// frame should always have space on top
this.frame.css('top', pos+offset);
// make sure that toolbar is visible
- if(this.toolbar.data('collapsed')) CMS.Toolbar._showToolbar();
+ if(this.toolbar.data('collapsed')) CMS.Toolbar.API._showToolbar();
// listen to toolbar events
this.toolbar.bind('cms.toolbar.show cms.toolbar.hide', function (e) {
(e.handleObj.namespace === 'show.toolbar') ? that.frame.css('top', pos+offset) : that.frame.css('top', pos);
@@ -524,31 +530,18 @@ jQuery(document).ready(function ($) {
var that = this;
// clear timer when initiated within resize event
if(this.timer) clearTimeout(this.timer);
-
- /* cause IE's mother had sex with a sheep, we need to always usw window instead of document
- * we need to substract 4 pixel from the frame cause IE's vater has a small dick
- * TODO: Check if scrollbars are shown, than we dont need to substract 20px, they are forced now
- */
- var scrollbarWidth = ($.browser.msie && $.browser.version >= '8.0') ? 20 : 0;
-
// attach resize event to window
- $(document).bind('resize', function () {
- that.dim.css({
- 'width': $(document).width(),
- 'height': $(document).height()
- });
- that.frame.css('width', $(document).width());
- // adjust after resizing
+ $(window).bind('resize', function () {
+ // first we need to response to the window
+ that.dim.css('height', $(window).height());
+ // after a while we response to the document dimensions
that.timer = setTimeout(function () {
- that.dim.css({
- 'width': $(document).width()-scrollbarWidth,
- 'height': $(document).height()
- });
- that.frame.css('width', $(document).width()-scrollbarWidth);
+ that.dim.css('height', $(document).height());
}, 500);
});
// init dim resize
- $(document).resize();
+ // insure that onload it takes the document width
+ this.dim.css('height', $(document).height());
// change data information
this.dim.data('dimmed', true);
// show dim
@@ -574,4 +567,4 @@ jQuery(document).ready(function ($) {
});
});
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/cms/media/cms/js/plugins/cms.toolbar.js b/cms/media/cms/js/plugins/cms.toolbar.js
index 899d034e180..305b5ca83cb 100644
--- a/cms/media/cms/js/plugins/cms.toolbar.js
+++ b/cms/media/cms/js/plugins/cms.toolbar.js
@@ -11,20 +11,21 @@ jQuery(document).ready(function ($) {
/**
* Toolbar
- * @version: 0.1.2
+ * @version: 1.0.0
* @description: Implements and controls toolbar
* @public_methods:
- * - CMS.Toolbar.toggleToolbar();
- * - CMS.Toolbar.registerItem(obj);
- * - CMS.Toolbar.registerItems(array);
- * - CMS.Toolbar.removeItem(id);
- * - CMS.Toolbar.registerType(function);
+ * - CMS.API.Toolbar.toggleToolbar();
+ * - CMS.API.Toolbar.registerItem(obj);
+ * - CMS.API.Toolbar.registerItems(array);
+ * - CMS.API.Toolbar.removeItem(id);
+ * - CMS.API.Toolbar.registerType(function);
* @compatibility: IE >= 6, FF >= 2, Safari >= 4, Chrome > =4, Opera >= 10
* TODO: login needs special treatment (errors, login on enter)
+ * TODO: styling of the collapser button needs to be somehow transparent
*/
CMS.Toolbar = CMS.Class.$extend({
- implement: [CMS.Helpers, CMS.Security],
+ implement: [CMS.API.Helpers, CMS.API.Security],
options: {
'debug': false, // not integrated yet
@@ -35,7 +36,7 @@ jQuery(document).ready(function ($) {
// save reference to this class
var that = this;
// check if only one element is given
- if($(container).length > 2) { log('Toolbar Error: one element expected, multiple elements given.'); return false; }
+ if($(container).length > 2) { throw new Error('Toolbar Error: one element expected, multiple elements given.'); return false; }
// merge passed argument options with internal options
this.options = $.extend(this.options, options);
@@ -56,6 +57,9 @@ jQuery(document).ready(function ($) {
this._setup();
},
+ /**
+ * All methods with an underscore as prefix should not be called through the API namespace
+ */
_setup: function () {
// save reference to this class
var that = this;
@@ -78,17 +82,23 @@ jQuery(document).ready(function ($) {
// the toolbar needs to resize depending on the window size on motherfucking ie6
if($.browser.msie && $.browser.version <= '6.0') {
- $(window).bind('resize', function () { that.wrapper.css('width', $(window).width()); })
+ $(window).bind('resize', function () { that.wrapper.css('width', $(window).width()); });
$(window).trigger('resize');
}
},
+ /**
+ * Binds the collapsed data element to the toolbar
+ * Calls private methods _showToolbar and _hideToolbar when required
+ * Saves current state in a cookie
+ */
toggleToolbar: function () {
(this.toolbar.data('collapsed')) ? this._showToolbar() : this._hideToolbar();
- return this;
+ return this.toolbar.data('collapsed');
},
+ // sets collapsed data to false
_showToolbar: function () {
// add toolbar padding
var padding = parseInt($(document.body).css('margin-top'));
@@ -105,6 +115,7 @@ jQuery(document).ready(function ($) {
this.toolbar.trigger('cms.toolbar.show');
},
+ // sets collapsed data to true
_hideToolbar: function () {
// remove toolbar padding
var padding = parseInt($(document.body).css('margin-top'));
@@ -121,8 +132,13 @@ jQuery(document).ready(function ($) {
this.toolbar.trigger('cms.toolbar.hide');
},
+ /**
+ * Handles the different item types and redirects them to their private method
+ * @param: obj (object that represents the item data to be registered)
+ */
registerItem: function (obj) {
// error handling
+ if(typeof(obj) !== 'object') return false;
if(!obj.order) obj.dir = 0;
// check for internal types
@@ -149,9 +165,13 @@ jQuery(document).ready(function ($) {
return obj;
},
+ /**
+ * This public method allows multiple addition of registerItems within one call
+ * @param: items (array of objects)
+ */
registerItems: function (items) {
// make sure an array is passed
- if(typeof(items) != 'object') return false;
+ if(typeof(items) !== 'object') return false;
// save reference to this class
var that = this;
// loopp through all items and pass them to single function
@@ -162,19 +182,29 @@ jQuery(document).ready(function ($) {
return items;
},
+ /**
+ * Removes the item with a specific id. This is not in use yet
+ * @param: index
+ */
removeItem: function (index) {
+ if(typeof(index) !== 'number') return false;
// function to remove an item
- if(index) $($('.cms_toolbar-item:visible')[index]).remove();
+ $($('.cms_toolbar-item')[index]).remove();
return index;
},
+ // requires: type, order, dir, title, url
+ // optional: cls
_registerAnchor: function (obj) {
// take a copy of the template, append it, remove it, copy html... because jquery is stupid
var template = this._processTemplate('#cms_toolbar-item_anchor', obj);
+ // append item
this._injectItem(template, obj.dir, obj.order);
},
+ // required: type, order, dir, html || htmlElement
+ // optional: cls, redirect
_registerHtml: function (obj) {
// here we dont need processTemplate cause we create the template
var template = (obj.html) ? $(obj.html) : $(obj.htmlElement);
@@ -182,15 +212,18 @@ jQuery(document).ready(function ($) {
template.data('order', obj.order).css('display', 'block');
// add class if neccessary
if(obj.cls) template.addClass(obj.cls);
- // add events
+ // special case for form html
template.find('.cms_toolbar-btn').bind('click', function (e) {
e.preventDefault();
(obj.redirect) ? document.location = obj.redirect : $(this).parentsUntil('form').parent().submit();
});
+
// append item
this._injectItem(template, obj.dir, obj.order);
},
+ // required: type, order, dir, removeParameter, addParameter
+ // optional: cls, state
_registerSwitcher: function (obj) {
// save reference to this class
var that = this;
@@ -214,13 +247,18 @@ jQuery(document).ready(function ($) {
if(btn.data('state')) {
btn.stop().animate({'backgroundPosition': '-40px -198px'}, function () {
// disable link
- var url = that.removeUrl(document.location.href, obj.addParameter);
- document.location = that.insertUrl(url, obj.removeParameter, "")
+ document.location = that.setUrl(document.location, {
+ 'addParam': obj.removeParameter,
+ 'removeParam': obj.addParameter
+ });
});
} else {
btn.stop().animate({'backgroundPosition': '0px -198px'}, function () {
// enable link
- document.location = that.insertUrl(location.href, obj.addParameter, "");
+ document.location = that.setUrl(document.location, {
+ 'addParam': obj.addParameter,
+ 'removeParam': obj.removeParameter
+ });
});
}
});
@@ -228,6 +266,8 @@ jQuery(document).ready(function ($) {
this._injectItem(template, obj.dir, obj.order);
},
+ // required: type, order, dir, redirect
+ // optional: cls, icon, action, hidden
_registerButton: function (obj) {
// take a copy of the template, append it, remove it, copy html... because jquery is stupid
var template = this._processTemplate('#cms_toolbar-item_button', obj);
@@ -235,6 +275,8 @@ jQuery(document).ready(function ($) {
this._injectItem(template, obj.dir, obj.order);
},
+ // required: type, order, dir, items (title, url, method (get/post), cls, icon)
+ // optional: cls, icon
_registerList: function (obj) {
// take a copy of the template, append it, remove it, copy html... because jquery is stupid
var template = this._processTemplate('#cms_toolbar-item_list', obj);
@@ -247,11 +289,12 @@ jQuery(document).ready(function ($) {
// lets loop through the items
$(obj.items).each(function (index, value) {
// add icon if available
- // TODO: backend needs to return '' instead of '/media/None'
- var icon = (value.icon !== '/media/None') ? 'cms_toolbar_icon cms_toolbar_icon-enabled ' : '';
+ var icon = (value.icon !== '') ? 'cms_toolbar_icon cms_toolbar_icon-enabled ' : '';
// replace attributes
tmp += list.replace('[list_title]', value.title)
.replace('[list_url]', value.url)
+ .replace('[list_method]', value.method)
+ .replace('[list_class]', value.cls)
.replace('', '');
});
// add items
@@ -266,6 +309,33 @@ jQuery(document).ready(function ($) {
($(this).data('collapsed')) ? show_list() : hide_list();
});
+ // add form action if rel equals get or post
+ var anchors = container.find('a');
+ if(anchors.attr('rel') === 'POST') {
+ // loop through the items and attach post events
+ anchors.each(function (index, item) {
+ if($(item).attr('rel') === 'POST') {
+ $(item).unbind('click').bind('click', function (e) {
+ e.preventDefault();
+ // attach form action
+ $.ajax({
+ 'type': $(e.currentTarget).attr('rel'),
+ 'url': $(e.currentTarget).attr('href'),
+ 'data': $(e.currentTarget).attr('href').split('?')[1],
+ 'success': function () {
+ CMS.API.Helpers.reloadBrowser();
+ },
+ 'error': function () {
+ throw new Error('CMS.Toolbar was unable to perform this ajax request. Try again or contact the developers.');
+ }
+ });
+ // after clicking hide list
+ hide_list();
+ });
+ }
+ });
+ }
+
function show_list() {
// add event to body to hide the list needs a timout for late trigger
setTimeout(function () {
@@ -289,22 +359,26 @@ jQuery(document).ready(function ($) {
this._injectItem(template, obj.dir, obj.order);
},
+ /**
+ * Basic API to add more types rather than the predefined (anchor, html, switcher, button, list)
+ * @param: handler (function)
+ */
registerType: function (handler) {
// invoke function
- if(typeof(handler) == 'function') handler();
+ if(typeof(handler) === 'function') handler();
return handler;
},
- /* this private method processes each template and replaces the placeholders with the passed values */
- _processTemplate: function (cls, obj) {
+ // parses passed templates from items
+ _processTemplate: function (id, obj) {
// lets find the template and clone it
- var template = this.wrapper.find(cls).clone();
+ var template = this.wrapper.find(id).clone();
template = $('').append(template).clone().remove().html();
// replace placeholders
if(obj.title) template = template.replace('[title]', obj.title);
if(obj.url) template = template.replace('[url]', obj.url);
- if(!obj.icon && obj.type == 'button') template = template.replace(' ', '').replace(' ', '');
+ if(!obj.icon && obj.type === 'button') template = template.replace(' ', '').replace(' ', '');
// template = template.replace('[token]', this.options.csrf_token);
template = (obj.action) ? template.replace('[action]', obj.action) : template.replace('[action]', '');
template = (obj.hidden) ? template.replace('[hidden]', obj.hidden) : template.replace('[hidden]', '');
@@ -330,12 +404,13 @@ jQuery(document).ready(function ($) {
return template;
},
+ // appends item in correct order and position
_injectItem: function (el, dir, order) {
// save some vars
var left = this.toolbar.left;
var right = this.toolbar.right;
- if(dir == 'left') {
+ if(dir === 'left') {
var leftContent = left.find('> *');
if(!leftContent.length) { left.append(el); return false; }
@@ -351,7 +426,7 @@ jQuery(document).ready(function ($) {
});
}
- if(dir == 'right') {
+ if(dir === 'right') {
var rightContent = right.find('> *');
if(!rightContent.length) { right.append(el); return false; }
@@ -370,4 +445,4 @@ jQuery(document).ready(function ($) {
});
});
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/cms/media/cms/js/tools.js b/cms/media/cms/js/tools.js
deleted file mode 100644
index 3880915806a..00000000000
--- a/cms/media/cms/js/tools.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/* adds a parameter to an url */
-function insert_into_url(url, name, value){
- if(url.substr(url.length-1, url.length)== "&"){
- url = url.substr(0, url.length-1);
- }
- dash_splits = url.split("#");
- url = dash_splits[0];
- var splits = url.split(name + "=");
- if (splits.length == 1){
- splits = url.split(name);
- }
- var get_args = false;
- if(url.split("?").length>1){
- get_args = true;
- }
- if(splits.length > 1){
- var after = "";
- if (splits[1].split("&").length > 1){
- after = splits[1].split("&")[1];
- }
- url = splits[0] + name;
- if (value){
- url += "=" + value
- }
- url += "&" + after;
- }else{
- if(get_args){
- url = url + "&" + name;
- }else{
- url = url + "?" + name;
- }
- if(value){
- url += "=" + value;
- }
- }
- if(dash_splits.length>1){
- url += '#' + dash_splits[1];
- }
- if(url.substr(url.length-1, url.length)== "&"){
- url = url.substr(0, url.length-1);
- }
- return url;
-};
-
-/* removes a parameter from an url */
-function remove_from_url(url, name){
- var dash_splits = url.split("#");
- url = dash_splits[0];
- var splits = url.split(name + "=");
- if(splits.length == 1){
- splits = url.split(name);
- }
- if(splits.length > 1){
- var after = "";
- if (splits[1].split("&").length > 1){
- after = splits[1].split("&")[1];
- }
- if (splits[0].substr(splits[0].length-2, splits[0].length-1)=="?" || !after){
- url = splits[0] + after;
- }else{
- url = splits[0] + "&" + after;
- }
- }
- if(url.substr(url.length-1,1) == "?"){
- url = url.substr(0, url.length-1);
- }
- if(dash_splits.length > 1 && dash_splits[1]){
- url += "#" + dash_splits[1];
- }
- return url;
-}
\ No newline at end of file
diff --git a/cms/middleware/toolbar.py b/cms/middleware/toolbar.py
index 5f812af42b7..c8062b8c970 100755
--- a/cms/middleware/toolbar.py
+++ b/cms/middleware/toolbar.py
@@ -3,25 +3,9 @@
Edit Toolbar middleware
"""
from cms.cms_toolbar import CMSToolbar
-from django import template
-from django.core.urlresolvers import reverse, NoReverseMatch
from django.http import HttpResponse
-from django.template.context import RequestContext
from django.template.loader import render_to_string
-import re
-import warnings
-HTML_TYPES = ('text/html', 'application/xhtml+xml')
-
-try:
- ADMIN_BASE = reverse("admin:index")
-except NoReverseMatch:
- ADMIN_BASE = None
-
-BODY_RE = re.compile(r'
', re.IGNORECASE)
-BACKWARDS_COMPAT_TEMPLATE = template.Template(
- "{% load cms_tags %}{{ pre|safe }}{% cms_toolbar %}{{ post|safe }}"
-)
def toolbar_plugin_processor(instance, placeholder, rendered_content, original_context):
data = {
@@ -30,60 +14,22 @@ def toolbar_plugin_processor(instance, placeholder, rendered_content, original_c
}
return render_to_string('cms/toolbar/placeholder_wrapper.html', data)
-def _patch(data, request):
- match = BODY_RE.search(data)
- if not match:
- return data
- warnings.warn("You have to use the {% cms_toolbar %} tag in your templates "
- "if you use the cms.middleware.toolbar.ToolbarMiddleware.",
- DeprecationWarning)
- end = match.end()
- ctx = RequestContext(request)
- ctx['pre'] = data[:end]
- ctx['post'] = data[end:]
- return BACKWARDS_COMPAT_TEMPLATE.render(ctx)
-
class ToolbarMiddleware(object):
"""
Middleware to set up CMS Toolbar.
"""
- def should_show_toolbar(self, request):
- """
- Check if we should show the toolbar for this request or not.
- """
- if ADMIN_BASE and request.path.startswith(ADMIN_BASE):
- return False
- # check session
- if request.session.get('cms_edit', False):
- return True
- # check GET
- if 'edit' in request.GET:
- request.session['cms_edit'] = True
- return True
- return False
-
def process_request(self, request):
"""
If we should show the toolbar for this request, put it on
request.toolbar. Then call the request_hook on the toolbar.
"""
- if self.should_show_toolbar(request):
- request.toolbar = CMSToolbar(request)
- response = request.toolbar.request_hook()
- if isinstance(response, HttpResponse):
- return response
-
- def process_response(self, request, response):
- """
- For backwards compatibility, will be removed in 2.3
- """
-
- if not getattr(request, 'toolbar', False):
- return response
- if getattr(request, '_cms_toolbar_tag_used', False):
- return response
- if not response['Content-Type'].startswith(HTML_TYPES):
+ if 'edit' in request.GET and not request.session.get('cms_edit', False):
+ request.session['cms_edit'] = True
+ request.toolbar = CMSToolbar(request)
+
+ def process_view(self, request, view_func, view_args, view_kwarg):
+ response = request.toolbar.request_hook()
+ if isinstance(response, HttpResponse):
return response
- response.content = _patch(response.content, request)
- return response
\ No newline at end of file
+
diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py
index bfe12b3c1cf..689686b263b 100644
--- a/cms/models/pagemodel.py
+++ b/cms/models/pagemodel.py
@@ -551,6 +551,10 @@ def get_absolute_url(self, language=None, fallback=True):
home_pk = self.home_pk_cache
except NoHomeFound:
pass
+ """
+ this is pain slow! the code fetches all ancestors for all pages
+ and then checks if the root node is a home_pk, if yes, it cuts off the first path part.
+ """
ancestors = self.get_cached_ancestors(ascending=True)
# sometimes there are no ancestors
if len(ancestors) != 0:
diff --git a/cms/plugin_base.py b/cms/plugin_base.py
index c3fcc364b3c..45adc5eaa32 100644
--- a/cms/plugin_base.py
+++ b/cms/plugin_base.py
@@ -90,6 +90,7 @@ class CMSPluginBase(admin.ModelAdmin):
render_plugin = True
model = CMSPlugin
text_enabled = False
+ page_only = False
opts = {}
module = None #track in which module/application belongs
diff --git a/cms/plugin_pool.py b/cms/plugin_pool.py
index 90609df18ab..3e64a2abb8a 100644
--- a/cms/plugin_pool.py
+++ b/cms/plugin_pool.py
@@ -67,13 +67,14 @@ def unregister_plugin(self, plugin):
)
del self.plugins[plugin_name]
- def get_all_plugins(self, placeholder=None, page=None, setting_key="plugins"):
+ def get_all_plugins(self, placeholder=None, page=None, setting_key="plugins", include_page_only=True):
self.discover_plugins()
plugins = self.plugins.values()[:]
plugins.sort(key=lambda obj: unicode(obj.name))
- if placeholder:
- final_plugins = []
- for plugin in plugins:
+ final_plugins = []
+ for plugin in plugins:
+ include_plugin = False
+ if placeholder:
allowed_plugins = get_placeholder_conf(
setting_key,
placeholder,
@@ -81,9 +82,15 @@ def get_all_plugins(self, placeholder=None, page=None, setting_key="plugins"):
)
if allowed_plugins:
if plugin.__name__ in allowed_plugins:
- final_plugins.append(plugin)
+ include_plugin = True
elif setting_key == "plugins":
- final_plugins.append(plugin)
+ include_plugin = True
+ if plugin.page_only and not include_page_only:
+ include_plugin = False
+ if include_plugin:
+ final_plugins.append(plugin)
+
+ if final_plugins:
plugins = final_plugins
# plugins sorted by modules
diff --git a/cms/plugins/inherit/cms_plugins.py b/cms/plugins/inherit/cms_plugins.py
index 68a36456841..7d590004d56 100644
--- a/cms/plugins/inherit/cms_plugins.py
+++ b/cms/plugins/inherit/cms_plugins.py
@@ -18,6 +18,7 @@ class InheritPagePlaceholderPlugin(CMSPluginBase):
render_template = "cms/plugins/inherit_plugins.html"
form = InheritForm
admin_preview = False
+ page_only = True
def render(self, context, instance, placeholder):
template_vars = {
diff --git a/cms/plugins/text/templates/cms/plugins/text_plugin_change_form.html b/cms/plugins/text/templates/cms/plugins/text_plugin_change_form.html
index 9edf90230b1..7d17b5dd692 100644
--- a/cms/plugins/text/templates/cms/plugins/text_plugin_change_form.html
+++ b/cms/plugins/text/templates/cms/plugins/text_plugin_change_form.html
@@ -10,7 +10,7 @@
{% endblock %}
\ No newline at end of file
diff --git a/cms/templates/admin/cms/mail/base.html b/cms/templates/admin/cms/mail/base.html
index e3daed8f7d8..e74e27d3dbb 100644
--- a/cms/templates/admin/cms/mail/base.html
+++ b/cms/templates/admin/cms/mail/base.html
@@ -53,7 +53,7 @@ {{ title }}
{% blocktrans %}Log in to administration here .{% endblocktrans %}
- Generated by django cms {% now "d.m.Y H:i:s" %}.
+ Generated by django cms {% now "d.m.Y H:i:s" %}.
diff --git a/cms/templates/admin/cms/page/change_form.html b/cms/templates/admin/cms/page/change_form.html
index 2e9d0f19951..e5397bbe030 100644
--- a/cms/templates/admin/cms/page/change_form.html
+++ b/cms/templates/admin/cms/page/change_form.html
@@ -93,11 +93,11 @@ {{ title }}
{% if moderation_delete_request %} {% trans "Remove delete request" %} {% endif %}
{% if moderator_should_approve %}
{% if moderation_delete_request %}{% trans "Approve delete" %}{% else %}{% trans "Approve" %} {% trans "draft" %}{% endif %}
- {% trans "Preview" %} {% trans "draft" %}
+ {% trans "Preview" %} {% trans "draft" %}
{% endif %}
{% trans "History" %}
- {% if has_absolute_url %}{% trans "View on site" %} {% endif%}
+ {% if has_absolute_url %}{% trans "View on site" %} {% endif%}
{% endif %}{% endif %}
{% endblock %}
diff --git a/cms/templates/admin/cms/page/change_list.html b/cms/templates/admin/cms/page/change_list.html
index c8f29679ac1..a66d4a62f87 100644
--- a/cms/templates/admin/cms/page/change_list.html
+++ b/cms/templates/admin/cms/page/change_list.html
@@ -31,7 +31,8 @@
-
+
+
diff --git a/cms/templates/admin/cms/page/plugin_forms_ok.html b/cms/templates/admin/cms/page/plugin_forms_ok.html
index 6cc11314188..b4a62986ae0 100644
--- a/cms/templates/admin/cms/page/plugin_forms_ok.html
+++ b/cms/templates/admin/cms/page/plugin_forms_ok.html
@@ -16,7 +16,7 @@
jQuery(document).ready(function ($) {
// if it is an iframe
if(window.parent != self) {
- setTimeout(function () { window.parent.CMS.Helpers.reloadBrowser(); }, 1000);
+ setTimeout(function () { window.parent.CMS.API.Helpers.reloadBrowser(); }, 1000);
} else {
opener.dismissEditPluginPopup(window, "{{ plugin_id }}", "{{ icon }}", "{{ alt }}");
}
diff --git a/cms/templates/cms/new.html b/cms/templates/cms/new.html
index aab60453ee4..63a1b73206d 100644
--- a/cms/templates/cms/new.html
+++ b/cms/templates/cms/new.html
@@ -52,7 +52,7 @@
diff --git a/cms/templates/cms/toolbar/items/list.html b/cms/templates/cms/toolbar/items/list.html
index a695243f3cc..5c72b9832a0 100644
--- a/cms/templates/cms/toolbar/items/list.html
+++ b/cms/templates/cms/toolbar/items/list.html
@@ -7,6 +7,6 @@
\ No newline at end of file
diff --git a/cms/templates/cms/toolbar/items/status.html b/cms/templates/cms/toolbar/items/status.html
index 9b0f1a84603..83e2755fe0e 100644
--- a/cms/templates/cms/toolbar/items/status.html
+++ b/cms/templates/cms/toolbar/items/status.html
@@ -1,2 +1,2 @@
{% load i18n %}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/cms/templates/cms/toolbar/toolbar.html b/cms/templates/cms/toolbar/toolbar.html
index f4fe70b3a05..58d4c7b2eba 100644
--- a/cms/templates/cms/toolbar/toolbar.html
+++ b/cms/templates/cms/toolbar/toolbar.html
@@ -1,28 +1,21 @@
-{% load i18n sekizai_tags adminmedia %}
-
-
-
-
-
-
+{% load i18n adminmedia sekizai_tags %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "css" %} {% endaddtoblock %}
+{% addtoblock "css" %} {% endaddtoblock %}
+{% addtoblock "js" %}
+{% endaddtoblock %}
\ No newline at end of file
diff --git a/cms/templatetags/cms_tags.py b/cms/templatetags/cms_tags.py
index 21ecd7cab75..af4e96e786b 100644
--- a/cms/templatetags/cms_tags.py
+++ b/cms/templatetags/cms_tags.py
@@ -399,7 +399,6 @@ def render(self, context):
request = context.get('request', None)
if not request:
return ''
- request._cms_toolbar_tag_used = True
return super(CMSToolbar, self).render(context)
def get_context(self, context):
diff --git a/cms/test_utils/fixtures/__init__.py b/cms/test_utils/fixtures/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/cms/test_utils/fixtures/fakemlng.py b/cms/test_utils/fixtures/fakemlng.py
new file mode 100644
index 00000000000..8d215bd8dcf
--- /dev/null
+++ b/cms/test_utils/fixtures/fakemlng.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+from cms.api import add_plugin
+from project.fakemlng.models import MainModel, Translations
+
+class FakemlngFixtures(object):
+ def create_fixtures(self):
+ main = MainModel.objects.create()
+ en = Translations.objects.create(master=main, language_code='en')
+ Translations.objects.create(master=main, language_code='de')
+ Translations.objects.create(master=main, language_code='nl')
+ fr = Translations.objects.create(master=main, language_code='fr')
+ add_plugin(en.placeholder, 'TextPlugin', 'en', body='ENGLISH
')
+ add_plugin(fr.placeholder, 'TextPlugin', 'fr', body='FRENCH
')
\ No newline at end of file
diff --git a/cms/test_utils/fixtures/menus.py b/cms/test_utils/fixtures/menus.py
new file mode 100644
index 00000000000..1871030c34b
--- /dev/null
+++ b/cms/test_utils/fixtures/menus.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+from cms.api import create_page
+from cms.models.pagemodel import Page
+from cms.test_utils.util.context_managers import SettingsOverride
+
+
+class MenusFixture(object):
+ def create_fixtures(self):
+ """
+ Tree from fixture:
+
+ + P1
+ | + P2
+ | + P3
+ + P4
+ | + P5
+ + P6 (not in menu)
+ + P7
+ + P8
+ """
+ defaults = {
+ 'template': 'nav_playground.html',
+ 'language': 'en',
+ }
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ p1 = create_page('P1', published=True, in_navigation=True, **defaults)
+ p4 = create_page('P4', published=True, in_navigation=True, **defaults)
+ p6 = create_page('P6', published=True, in_navigation=False, **defaults)
+ p1 = Page.objects.get(pk=p1.pk)
+ p2 = create_page('P2', published=True, in_navigation=True, parent=p1, **defaults)
+ create_page('P3', published=True, in_navigation=True, parent=p2, **defaults)
+ p4 = Page.objects.get(pk=p4.pk)
+ create_page('P5', published=True, in_navigation=True, parent=p4, **defaults)
+ p6 = Page.objects.get(pk=p6.pk)
+ create_page('P7', published=True, in_navigation=True, parent=p6, **defaults)
+ p6 = Page.objects.get(pk=p6.pk)
+ create_page('P8', published=True, in_navigation=True, parent=p6, **defaults)
+
+
+class SubMenusFixture(object):
+ def create_fixtures(self):
+ """
+ Tree from fixture:
+
+ + P1
+ | + P2
+ | + P3
+ + P4
+ | + P5
+ + P6
+ + P7 (not in menu)
+ + P8
+ """
+ defaults = {
+ 'template': 'nav_playground.html',
+ 'language': 'en',
+ }
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ p1 = create_page('P1', published=True, in_navigation=True, **defaults)
+ p4 = create_page('P4', published=True, in_navigation=True, **defaults)
+ p6 = create_page('P6', published=True, in_navigation=True, **defaults)
+ p1 = Page.objects.get(pk=p1.pk)
+ p2 = create_page('P2', published=True, in_navigation=True, parent=p1, **defaults)
+ create_page('P3', published=True, in_navigation=True, parent=p2, **defaults)
+ p4 = Page.objects.get(pk=p4.pk)
+ create_page('P5', published=True, in_navigation=True, parent=p4, **defaults)
+ p6 = Page.objects.get(pk=p6.pk)
+ create_page('P7', published=True, in_navigation=False, parent=p6, **defaults)
+ p6 = Page.objects.get(pk=p6.pk)
+ create_page('P8', published=True, in_navigation=True, parent=p6, **defaults)
+
+
+class SoftrootFixture(object):
+ def create_fixtures(self):
+ """
+ top
+ root
+ aaa
+ 111
+ ccc
+ ddd
+ 222
+ bbb
+ 333
+ 444
+
+ # all in nav, published and NOT softroot
+ """
+ defaults = {
+ 'template': 'nav_playground.html',
+ 'language': 'en',
+ 'in_navigation': True,
+ 'published': True,
+ }
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ top = create_page('top', **defaults)
+ root = create_page('root', parent=top, **defaults)
+ aaa = create_page('aaa', parent=root, **defaults)
+ _111 = create_page('111', parent=aaa, **defaults)
+ ccc = create_page('ccc', parent=_111, **defaults)
+ create_page('ddd', parent=ccc, **defaults)
+ aaa = Page.objects.get(pk=aaa.pk)
+ create_page('222', parent=aaa, **defaults)
+ root = Page.objects.get(pk=root.pk)
+ bbb = create_page('bbb', parent=root, **defaults)
+ create_page('333', parent=bbb, **defaults)
+ bbb = Page.objects.get(pk=bbb.pk)
+ create_page('444', parent=bbb, **defaults)
diff --git a/cms/test_utils/fixtures/navextenders.py b/cms/test_utils/fixtures/navextenders.py
new file mode 100644
index 00000000000..dd7602ea094
--- /dev/null
+++ b/cms/test_utils/fixtures/navextenders.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+from cms.api import create_page
+from cms.models.pagemodel import Page
+from cms.test_utils.util.context_managers import SettingsOverride
+
+
+class NavextendersFixture(object):
+ def create_fixtures(self):
+ """
+ Tree from fixture:
+
+ page1
+ page2
+ page3
+ page4
+ page5
+ """
+ defaults = {
+ 'template': 'nav_playground.html',
+ 'language': 'en',
+ }
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ p1 = create_page('page1', published=True, in_navigation=True, **defaults)
+ p4 = create_page('page4', published=True, in_navigation=True, **defaults)
+ p1 = Page.objects.get(pk=p1.pk)
+ p2 = create_page('page2', published=True, in_navigation=True, parent=p1, **defaults)
+ create_page('page3', published=True, in_navigation=True, parent=p2, **defaults)
+ p4 = Page.objects.get(pk=p4.pk)
+ create_page('page5', published=True, in_navigation=True, parent=p4, **defaults)
diff --git a/cms/test_utils/fixtures/templatetags.py b/cms/test_utils/fixtures/templatetags.py
new file mode 100644
index 00000000000..0855b68c67b
--- /dev/null
+++ b/cms/test_utils/fixtures/templatetags.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from cms.api import create_page, create_title
+from cms.test_utils.util.context_managers import SettingsOverride
+
+
+class TwoPagesFixture(object):
+ def create_fixtures(self):
+ defaults = {
+ 'template': 'nav_playground.html',
+ 'published': True,
+ 'in_navigation': True,
+ }
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ first = create_page('first', language='en', **defaults)
+ create_title('de', 'erste', first)
+ second = create_page('second', language='en', reverse_id='myreverseid', **defaults)
+ create_title('de', 'zweite', second)
+
\ No newline at end of file
diff --git a/cms/test_utils/js_testcases.py b/cms/test_utils/js_testcases.py
deleted file mode 100644
index 8e436ba7cbd..00000000000
--- a/cms/test_utils/js_testcases.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-from django.test.testcases import TestCase
-from spidermonkey import Runtime
-import os
-
-THISDIR = os.path.abspath(os.path.dirname(__file__))
-MEDIADIR = os.path.join(THISDIR, '../media/cms/')
-
-class BaseJavascriptTestCase(TestCase):
- def _get_runtime(self):
- return Runtime()
-
- def _get_context(self):
- rt = self._get_runtime()
- return rt.new_context()
-
- def _get_file_path(self, *bits):
- return os.path.join(MEDIADIR, *bits)
-
- def _run_javascript(self, files, snippet):
- ctx = self._get_context()
- for filename in files:
- with open(filename, 'r') as fobj:
- lib = fobj.read()
- ctx.execute(lib)
- return ctx.execute(snippet)
diff --git a/cms/test_utils/testcases.py b/cms/test_utils/testcases.py
index c9d6f71f62e..b7701fc8d47 100644
--- a/cms/test_utils/testcases.py
+++ b/cms/test_utils/testcases.py
@@ -7,7 +7,6 @@
from django.core.exceptions import ObjectDoesNotExist
from django.core.handlers.wsgi import WSGIRequest
from django.core.urlresolvers import reverse
-from django.db.models.signals import pre_save, post_save
from django.template.context import Context
from django.test.client import (encode_multipart, BOUNDARY, MULTIPART_CONTENT,
FakePayload)
@@ -71,13 +70,11 @@ class CMSTestCase(TestCase):
counter = 1
def _fixture_setup(self):
- pre_save_receivers = pre_save.receivers
- pre_save.receivers = []
- post_save_receivers = post_save.receivers
- post_save.receivers = []
super(CMSTestCase, self)._fixture_setup()
- pre_save.receivers = pre_save_receivers
- post_save.receivers = post_save_receivers
+ self.create_fixtures()
+
+ def create_fixtures(self):
+ pass
def _post_teardown(self):
# Needed to clean the menu keys cache, see menu.menu_pool.clear()
diff --git a/cms/test_utils/util/fixtures.py b/cms/test_utils/util/fixtures.py
deleted file mode 100644
index daf67fdfb2f..00000000000
--- a/cms/test_utils/util/fixtures.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from cms.test_utils.util.context_managers import SettingsOverride # pragma: no cover
-from django.conf import settings # pragma: no cover
-from django.core.management import call_command # pragma: no cover
-from django.db import connections # pragma: no cover
-import os # pragma: no cover
-
-
-class Fixture(object): # pragma: no cover
- DB_OVERRIDE = {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': ':memory:'
- }
-
- def __init__(self, name, apps=['cms'], **settings_overrides):
- self.name = name
- self.apps = apps
- self.settings_overrides = settings_overrides
-
- def start(self):
- self.so = SettingsOverride(**self.settings_overrides)
- self.so.__enter__()
- self.old_db = connections.databases['default']
- connections.databases['default'] = self.DB_OVERRIDE
- if 'default' in connections._connections:
- del connections._connections['default']
- call_command('syncdb', migrate_all=True, interactive=False, verbosity=0)
-
- def save(self):
- filename = os.path.join(settings.FIXTURE_DIRS[0], self.name)
- with open(filename, 'wb') as fobj:
- call_command('dumpdata', *self.apps, stdout=fobj)
- self.so.__exit__(None, None, None)
- connections.databases['default'] = self.old_db
- if 'default' in connections._connections:
- del connections._connections['default']
\ No newline at end of file
diff --git a/cms/tests/__init__.py b/cms/tests/__init__.py
index 51318aadd8d..caf97282979 100644
--- a/cms/tests/__init__.py
+++ b/cms/tests/__init__.py
@@ -1,43 +1,30 @@
# -*- coding: utf-8 -*-
-from cms.tests.admin import (AdminTestCase, AdminFieldsetTests,
- AdminListFilterTests, AdminTests, NoDBAdminTests)
-from cms.tests.api import PythonAPITests
-from cms.tests.apphooks import ApphooksTestCase
-from cms.tests.docs import DocsTestCase
-from cms.tests.forms import FormsTestCase
-from cms.tests.mail import MailTestCase
-from cms.tests.menu import (FixturesMenuTests, MenuTests, AdvancedSoftrootTests,
- ShowSubMenuCheck)
-from cms.tests.menu_utils import MenuUtilsTests
-from cms.tests.middleware import MiddlewareTestCase
-from cms.tests.multilingual import MultilingualTestCase
-from cms.tests.navextender import NavExtenderTestCase
-from cms.tests.nonroot import NonRootCase
-from cms.tests.page import PagesTestCase, NoAdminPageTests
-from cms.tests.permmod import PermissionModeratorTests, PatricksMoveTest
-from cms.tests.placeholder import (PlaceholderModelTests, PlaceholderAdminTest,
- PlaceholderTestCase, PlaceholderActionTests)
-from cms.tests.plugins import (PluginManyToManyTestCase, PluginsTestCase,
- SekizaiTests, LinkPluginTestCase)
-from cms.tests.po import PoTest
-from cms.tests.publisher import PublisherTestCase
-from cms.tests.rendering import RenderingTestCase
-from cms.tests.reversion_tests import ReversionTestCase, ReversionFileFieldTests
-from cms.tests.security import SecurityTests
-from cms.tests.settings import SettingsTests
-from cms.tests.site import SiteTestCase
-from cms.tests.templatetags import TemplatetagTests, TemplatetagDatabaseTests
-from cms.tests.toolbar import (ToolbarTests, ToolbarModeratorTests,
- ToolbarNoModeratorTests)
-from cms.tests.urlutils import UrlutilsTestCase
-from cms.tests.views import ViewTests
-from cms.tests.management import ManagementTestCase
-
-try:
- from cms.tests.javascript import JavascriptTestCase
-except ImportError:
- import warnings
- import traceback
- exc = traceback.format_exc()
- warnings.warn("JavascriptTestCase cannot be run: %s" % exc)
+from cms.tests.admin import *
+from cms.tests.api import *
+from cms.tests.apphooks import *
+from cms.tests.docs import *
+from cms.tests.forms import *
+from cms.tests.mail import *
+from cms.tests.menu import *
+from cms.tests.menu_utils import *
+from cms.tests.middleware import *
+from cms.tests.multilingual import *
+from cms.tests.navextender import *
+from cms.tests.nonroot import *
+from cms.tests.page import *
+from cms.tests.permmod import *
+from cms.tests.placeholder import *
+from cms.tests.plugins import *
+from cms.tests.po import *
+from cms.tests.publisher import *
+from cms.tests.rendering import *
+from cms.tests.reversion_tests import *
+from cms.tests.security import *
+from cms.tests.settings import *
+from cms.tests.site import *
+from cms.tests.templatetags import *
+from cms.tests.toolbar import *
+from cms.tests.urlutils import *
+from cms.tests.views import *
+from cms.tests.management import *
diff --git a/cms/tests/admin.py b/cms/tests/admin.py
index 73ee6288473..64de1188155 100644
--- a/cms/tests/admin.py
+++ b/cms/tests/admin.py
@@ -319,7 +319,7 @@ def test_no_softroot(self):
def test_dates(self):
with SettingsOverride(CMS_SHOW_START_DATE=False, CMS_SHOW_END_DATE=False):
control = AttributeObject()
- contribute_fieldsets(control)
+ contribute_fieldsets(control)
with SettingsOverride(CMS_SHOW_START_DATE=True, CMS_SHOW_END_DATE=True):
experiment1 = AttributeObject()
contribute_fieldsets(experiment1)
diff --git a/cms/tests/javascript.py b/cms/tests/javascript.py
deleted file mode 100644
index 24a7083cd8f..00000000000
--- a/cms/tests/javascript.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- coding: utf-8 -*-
-from cms.test_utils.js_testcases import BaseJavascriptTestCase
-
-
-class JavascriptTestCase(BaseJavascriptTestCase):
- """
- These test will only run if python-spidermonkey is installed!
- """
- def test_insert_into_url(self):
- files = [self._get_file_path('js', 'tools.js')]
- base_snippet = "insert_into_url('%s', '%s', '%s')"
- tests = [
- ('http://www.mysite.com', 'edit', '', 'http://www.mysite.com?edit'),
- ('http://www.mysite.com?hello=world', 'edit', '',
- 'http://www.mysite.com?hello=world&edit'),
- ('http://www.mysite.com?hello=world&goodbye=universe', 'edit', '',
- 'http://www.mysite.com?hello=world&goodbye=universe&edit'),
- ('http://www.mysite.com#myanchor', 'edit', '',
- 'http://www.mysite.com?edit#myanchor'),
- ('http://www.mysite.com?hello=world#myanchor', 'edit', '',
- 'http://www.mysite.com?hello=world&edit#myanchor'),
- ('http://www.mysite.com?hello=world&goodbye=universe#myanchor',
- 'edit', '',
- 'http://www.mysite.com?hello=world&goodbye=universe&edit#myanchor'),
- ('http://www.mysite.com', 'edit', 'on', 'http://www.mysite.com?edit=on'),
- ('http://www.mysite.com?hello=world', 'edit', 'on',
- 'http://www.mysite.com?hello=world&edit=on'),
- ('http://www.mysite.com?hello=world&goodbye=universe', 'edit', 'on',
- 'http://www.mysite.com?hello=world&goodbye=universe&edit=on'),
- ('http://www.mysite.com#myanchor', 'edit', 'on',
- 'http://www.mysite.com?edit=on#myanchor'),
- ('http://www.mysite.com?hello=world#myanchor', 'edit', 'on',
- 'http://www.mysite.com?hello=world&edit=on#myanchor'),
- ('http://www.mysite.com?hello=world&goodbye=universe#myanchor',
- 'edit', 'on',
- 'http://www.mysite.com?hello=world&goodbye=universe&edit=on#myanchor'),
- ]
- for arg1, arg2, arg3, expected in tests:
- output = self._run_javascript(files, base_snippet % (arg1, arg2, arg3))
- self.assertEqual(output, expected)
-
- def test_remove_from_url(self):
- files = [self._get_file_path('js', 'tools.js')]
- base_snippet = "remove_from_url('%s', '%s')"
- tests = [
- ('http://www.mysite.com', 'edit', 'http://www.mysite.com'),
- ('http://www.mysite.com#edit', 'edit', 'http://www.mysite.com#edit'),
- ('http://www.mysite.com?edit', 'edit', 'http://www.mysite.com'),
- ('http://www.mysite.com?edit#edit', 'edit', 'http://www.mysite.com#edit'),
- ('http://www.mysite.com?hello=world&edit', 'edit',
- 'http://www.mysite.com?hello=world&'),
- ('http://www.mysite.com?hello=world&edit#edit', 'edit',
- 'http://www.mysite.com?hello=worldedit'),
- ]
- for arg1, arg2, expected in tests:
- output = self._run_javascript(files, base_snippet % (arg1, arg2))
- self.assertEqual(output, expected)
diff --git a/cms/tests/menu.py b/cms/tests/menu.py
index a25b2f309c5..5c9106476eb 100644
--- a/cms/tests/menu.py
+++ b/cms/tests/menu.py
@@ -3,6 +3,8 @@
from cms.api import create_page
from cms.menu import CMSMenu
from cms.models import Page
+from cms.test_utils.fixtures.menus import (MenusFixture, SubMenusFixture,
+ SoftrootFixture)
from cms.test_utils.testcases import SettingsOverrideTestCase
from cms.test_utils.util.mock import AttributeObject
from django.conf import settings
@@ -42,7 +44,7 @@ def tearDown(self):
super(BaseMenuTest, self).tearDown()
-class FixturesMenuTests(BaseMenuTest):
+class FixturesMenuTests(MenusFixture, BaseMenuTest):
"""
Tree from fixture:
@@ -55,10 +57,8 @@ class FixturesMenuTests(BaseMenuTest):
+ P7
+ P8
"""
- fixtures = ['menus.json']
-
def get_page(self, num):
- return Page.objects.get(pk=num)
+ return Page.objects.get(title_set__title='P%s' % num)
def get_level(self, num):
return Page.objects.filter(level=num)
@@ -537,7 +537,7 @@ def test_empty_menu(self):
self.assertEqual(len(nodes), 0)
-class AdvancedSoftrootTests(SettingsOverrideTestCase):
+class AdvancedSoftrootTests(SoftrootFixture, SettingsOverrideTestCase):
"""
Tree in fixture (as taken from issue 662):
@@ -566,7 +566,6 @@ class AdvancedSoftrootTests(SettingsOverrideTestCase):
'CMS_MODERATOR': False,
'CMS_PERMISSION': False
}
- fixtures = ['advanced_softroot.json']
def tearDown(self):
Page.objects.all().delete()
@@ -698,7 +697,7 @@ def test_top_in_nav(self):
self.assertTreeQuality(soft_root, mock_tree, 'title', 'level')
-class ShowSubMenuCheck(BaseMenuTest):
+class ShowSubMenuCheck(SubMenusFixture, BaseMenuTest):
"""
Tree from fixture:
@@ -711,13 +710,45 @@ class ShowSubMenuCheck(BaseMenuTest):
+ P7 (not in menu)
+ P8
"""
- fixtures = ['menus-sub.json']
-
def test_show_submenu(self):
- context = self.get_context('/test-page-6/')
+ page = Page.objects.get(title_set__title='P6')
+ context = self.get_context(page.get_absolute_url())
# test standard show_menu
tpl = Template("{% load menu_tags %}{% show_sub_menu %}")
tpl.render(context)
nodes = context['children']
self.assertEqual(len(nodes), 1)
self.assertEqual(nodes[0].id, 8)
+
+
+class ShowMenuBelowIdTests(BaseMenuTest):
+ def test_not_in_navigation(self):
+ """
+ Test for issue 521
+
+ Build the following tree:
+
+ A
+ |-B
+ |-C
+ \-D (not in nav)
+ """
+ a = create_page('A', 'nav_playground.html', 'en', published=True,
+ in_navigation=True, reverse_id='a')
+ b =create_page('B', 'nav_playground.html', 'en', parent=a,
+ published=True, in_navigation=True)
+ c = create_page('C', 'nav_playground.html', 'en', parent=b,
+ published=True, in_navigation=True)
+ create_page('D', 'nav_playground.html', 'en', parent=self.reload(b),
+ published=True, in_navigation=False)
+ context = self.get_context(a.get_absolute_url())
+ tpl = Template("{% load menu_tags %}{% show_menu_below_id 'a' 0 100 100 100 %}")
+ tpl.render(context)
+ nodes = context['children']
+ self.assertEqual(len(nodes), 1, nodes)
+ node = nodes[0]
+ self.assertEqual(node.id, b.id)
+ children = node.children
+ self.assertEqual(len(children), 1, repr(children))
+ child = children[0]
+ self.assertEqual(child.id, c.id)
diff --git a/cms/tests/navextender.py b/cms/tests/navextender.py
index 280a0047585..501889e663a 100644
--- a/cms/tests/navextender.py
+++ b/cms/tests/navextender.py
@@ -1,15 +1,15 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from cms.models import Page
+from cms.test_utils.fixtures.navextenders import NavextendersFixture
from cms.test_utils.testcases import SettingsOverrideTestCase
from cms.test_utils.util.menu_extender import TestMenu
from django.conf import settings
from django.template import Template
from menus.menu_pool import menu_pool
-class NavExtenderTestCase(SettingsOverrideTestCase):
+class NavExtenderTestCase(NavextendersFixture, SettingsOverrideTestCase):
settings_overrides = {'CMS_MODERATOR': False}
- fixtures = ['navextenders']
"""
Tree from fixture:
@@ -30,12 +30,18 @@ def setUp(self):
def tearDown(self):
menu_pool.menus = self.old_menu
+ def _get_page(self, num):
+ return Page.objects.get(title_set__title='page%s' % num)
+
+ def _update_page(self, num, **stuff):
+ Page.objects.filter(title_set__title='page%s' % num).update(**stuff)
+
def test_menu_registration(self):
self.assertEqual(len(menu_pool.menus), 2)
self.assertEqual(len(menu_pool.modifiers) >=4, True)
def test_extenders_on_root(self):
- Page.objects.filter(pk=1).update(navigation_extenders="TestMenu")
+ self._update_page(1, navigation_extenders="TestMenu")
menu_pool.clear(settings.SITE_ID)
context = self.get_context()
@@ -45,7 +51,7 @@ def test_extenders_on_root(self):
self.assertEqual(len(nodes), 2)
self.assertEqual(len(nodes[0].children), 4)
self.assertEqual(len(nodes[0].children[3].children), 1)
- Page.objects.filter(pk=1).update(in_navigation=False)
+ self._update_page(1, in_navigation=False)
menu_pool.clear(settings.SITE_ID)
tpl = Template("{% load menu_tags %}{% show_menu %}")
tpl.render(context)
@@ -53,7 +59,7 @@ def test_extenders_on_root(self):
self.assertEqual(len(nodes), 5)
def test_extenders_on_root_child(self):
- Page.objects.filter(pk=4).update(navigation_extenders="TestMenu")
+ self._update_page(4, navigation_extenders="TestMenu")
menu_pool.clear(settings.SITE_ID)
context = self.get_context()
tpl = Template("{% load menu_tags %}{% show_menu 0 100 100 100 %}")
@@ -66,8 +72,8 @@ def test_extenders_on_child(self):
"""
TestMenu has 4 flat nodes
"""
- Page.objects.filter(pk=1).update(in_navigation=False)
- Page.objects.filter(pk=2).update(navigation_extenders="TestMenu")
+ self._update_page(1, in_navigation=False)
+ self._update_page(2, navigation_extenders="TestMenu")
menu_pool.clear(settings.SITE_ID)
menu_pool.clear(settings.SITE_ID)
context = self.get_context()
@@ -79,10 +85,10 @@ def test_extenders_on_child(self):
self.assertEqual(nodes[0].children[1].get_absolute_url(), "/" )
def test_incorrect_nav_extender_in_db(self):
- Page.objects.filter(pk=2).update(navigation_extenders="SomethingWrong")
+ self._update_page(2, navigation_extenders="SomethingWrong")
menu_pool.clear(settings.SITE_ID)
context = self.get_context()
tpl = Template("{% load menu_tags %}{% show_menu %}")
tpl.render(context)
nodes = context['children']
- self.assertEqual(len(nodes), 2)
\ No newline at end of file
+ self.assertEqual(len(nodes), 2)
diff --git a/cms/tests/page.py b/cms/tests/page.py
index 10bef1d0de4..51d4b6cd097 100644
--- a/cms/tests/page.py
+++ b/cms/tests/page.py
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
+from cms.admin.forms import PageForm
from cms.api import create_page
from cms.models import Page, Title
from cms.models.placeholdermodel import Placeholder
from cms.models.pluginmodel import CMSPlugin
from cms.plugins.text.models import Text
from cms.sitemaps import CMSSitemap
-from cms.test_utils.testcases import CMSTestCase, URL_CMS_PAGE, URL_CMS_PAGE_ADD
+from cms.test_utils.testcases import (CMSTestCase, URL_CMS_PAGE,
+ URL_CMS_PAGE_ADD)
from cms.test_utils.util.context_managers import (LanguageOverride,
SettingsOverride)
from cms.utils.page_resolver import get_page_from_request
@@ -15,27 +17,19 @@
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.http import HttpRequest
+import datetime
import os.path
class PagesTestCase(CMSTestCase):
-
- def setUp(self):
- u = User(username="test", is_staff = True, is_active = True, is_superuser = True)
- u.set_password("test")
- u.save()
-
- self._login_context = self.login_user_context(u)
- self._login_context.__enter__()
-
- def tearDown(self):
- self._login_context.__exit__(None, None, None)
def test_add_page(self):
"""
Test that the add admin page could be displayed via the admin
"""
- response = self.client.get(URL_CMS_PAGE_ADD)
- self.assertEqual(response.status_code, 200)
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ response = self.client.get(URL_CMS_PAGE_ADD)
+ self.assertEqual(response.status_code, 200)
def test_create_page(self):
"""
@@ -43,19 +37,21 @@ def test_create_page(self):
"""
page_data = self.get_new_page_data()
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
- self.assertRedirects(response, URL_CMS_PAGE)
- title = Title.objects.get(slug=page_data['slug'])
- self.assertNotEqual(title, None)
- page = title.page
- page.published = True
- page.save()
- self.assertEqual(page.get_title(), page_data['title'])
- self.assertEqual(page.get_slug(), page_data['slug'])
- self.assertEqual(page.placeholders.all().count(), 2)
-
- # were public instanes created?
- title = Title.objects.drafts().get(slug=page_data['slug'])
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+ self.assertRedirects(response, URL_CMS_PAGE)
+ title = Title.objects.get(slug=page_data['slug'])
+ self.assertNotEqual(title, None)
+ page = title.page
+ page.published = True
+ page.save()
+ self.assertEqual(page.get_title(), page_data['title'])
+ self.assertEqual(page.get_slug(), page_data['slug'])
+ self.assertEqual(page.placeholders.all().count(), 2)
+
+ # were public instanes created?
+ title = Title.objects.drafts().get(slug=page_data['slug'])
def test_slug_collision(self):
@@ -64,89 +60,99 @@ def test_slug_collision(self):
"""
page_data = self.get_new_page_data()
# create first page
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
- self.assertRedirects(response, URL_CMS_PAGE)
-
- #page1 = Title.objects.get(slug=page_data['slug']).page
- # create page with the same page_data
-
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
-
- if settings.i18n_installed:
- self.assertEqual(response.status_code, 302)
- # did we got right redirect?
- self.assertEqual(response['Location'].endswith(URL_CMS_PAGE), True)
- else:
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response['Location'].endswith(URL_CMS_PAGE_ADD), True)
- # TODO: check for slug collisions after move
- # TODO: check for slug collisions with different settings
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+ self.assertRedirects(response, URL_CMS_PAGE)
+
+ #page1 = Title.objects.get(slug=page_data['slug']).page
+ # create page with the same page_data
+
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+
+ if settings.i18n_installed:
+ self.assertEqual(response.status_code, 302)
+ # did we got right redirect?
+ self.assertEqual(response['Location'].endswith(URL_CMS_PAGE), True)
+ else:
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response['Location'].endswith(URL_CMS_PAGE_ADD), True)
+ # TODO: check for slug collisions after move
+ # TODO: check for slug collisions with different settings
def test_details_view(self):
"""
Test the details view
"""
- response = self.client.get(self.get_pages_root())
- self.assertEqual(response.status_code, 404)
- page = create_page('test page 1', "nav_playground.html", "en")
- response = self.client.get(self.get_pages_root())
- self.assertEqual(response.status_code, 404)
- self.assertTrue(page.publish())
- create_page("test page 2", "nav_playground.html", "en",
- parent=page, published=True)
- homepage = Page.objects.get_home()
- self.assertTrue(homepage.get_slug(), 'test-page-1')
- response = self.client.get(self.get_pages_root())
- self.assertEqual(response.status_code, 200)
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ response = self.client.get(self.get_pages_root())
+ self.assertEqual(response.status_code, 404)
+ page = create_page('test page 1', "nav_playground.html", "en")
+ response = self.client.get(self.get_pages_root())
+ self.assertEqual(response.status_code, 404)
+ self.assertTrue(page.publish())
+ create_page("test page 2", "nav_playground.html", "en",
+ parent=page, published=True)
+ homepage = Page.objects.get_home()
+ self.assertTrue(homepage.get_slug(), 'test-page-1')
+ response = self.client.get(self.get_pages_root())
+ self.assertEqual(response.status_code, 200)
def test_edit_page(self):
"""
Test that a page can edited via the admin
"""
- page_data = self.get_new_page_data()
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
- page = Page.objects.get(title_set__slug=page_data['slug'])
- response = self.client.get('/admin/cms/page/%s/' %page.id)
- self.assertEqual(response.status_code, 200)
- page_data['title'] = 'changed title'
- response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
- self.assertRedirects(response, URL_CMS_PAGE)
- self.assertEqual(page.get_title(), 'changed title')
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ page_data = self.get_new_page_data()
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+ page = Page.objects.get(title_set__slug=page_data['slug'])
+ response = self.client.get('/admin/cms/page/%s/' %page.id)
+ self.assertEqual(response.status_code, 200)
+ page_data['title'] = 'changed title'
+ response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
+ self.assertRedirects(response, URL_CMS_PAGE)
+ self.assertEqual(page.get_title(), 'changed title')
def test_meta_description_and_keywords_fields_from_admin(self):
"""
Test that description and keywords tags can be set via the admin
"""
- page_data = self.get_new_page_data()
- page_data["meta_description"] = "I am a page"
- page_data["meta_keywords"] = "page,cms,stuff"
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
- page = Page.objects.get(title_set__slug=page_data['slug'])
- response = self.client.get('/admin/cms/page/%s/' %page.id)
- self.assertEqual(response.status_code, 200)
- page_data['meta_description'] = 'I am a duck'
- response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
- self.assertRedirects(response, URL_CMS_PAGE)
- page = Page.objects.get(title_set__slug=page_data["slug"])
- self.assertEqual(page.get_meta_description(), 'I am a duck')
- self.assertEqual(page.get_meta_keywords(), 'page,cms,stuff')
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ page_data = self.get_new_page_data()
+ page_data["meta_description"] = "I am a page"
+ page_data["meta_keywords"] = "page,cms,stuff"
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+ page = Page.objects.get(title_set__slug=page_data['slug'])
+ response = self.client.get('/admin/cms/page/%s/' %page.id)
+ self.assertEqual(response.status_code, 200)
+ page_data['meta_description'] = 'I am a duck'
+ response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
+ self.assertRedirects(response, URL_CMS_PAGE)
+ page = Page.objects.get(title_set__slug=page_data["slug"])
+ self.assertEqual(page.get_meta_description(), 'I am a duck')
+ self.assertEqual(page.get_meta_keywords(), 'page,cms,stuff')
def test_meta_description_and_keywords_from_template_tags(self):
from django import template
- page_data = self.get_new_page_data()
- page_data["title"] = "Hello"
- page_data["meta_description"] = "I am a page"
- page_data["meta_keywords"] = "page,cms,stuff"
- self.client.post(URL_CMS_PAGE_ADD, page_data)
- page = Page.objects.get(title_set__slug=page_data['slug'])
- self.client.post('/admin/cms/page/%s/' %page.id, page_data)
- t = template.Template("{% load cms_tags %}{% page_attribute title %} {% page_attribute meta_description %} {% page_attribute meta_keywords %}")
- req = HttpRequest()
- page.published = True
- page.save()
- req.current_page = page
- req.REQUEST = {}
- self.assertEqual(t.render(template.Context({"request": req})), "Hello I am a page page,cms,stuff")
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ page_data = self.get_new_page_data()
+ page_data["title"] = "Hello"
+ page_data["meta_description"] = "I am a page"
+ page_data["meta_keywords"] = "page,cms,stuff"
+ self.client.post(URL_CMS_PAGE_ADD, page_data)
+ page = Page.objects.get(title_set__slug=page_data['slug'])
+ self.client.post('/admin/cms/page/%s/' %page.id, page_data)
+ t = template.Template("{% load cms_tags %}{% page_attribute title %} {% page_attribute meta_description %} {% page_attribute meta_keywords %}")
+ req = HttpRequest()
+ page.published = True
+ page.save()
+ req.current_page = page
+ req.REQUEST = {}
+ self.assertEqual(t.render(template.Context({"request": req})), "Hello I am a page page,cms,stuff")
def test_copy_page(self):
@@ -164,59 +170,65 @@ def test_copy_page(self):
count = Page.objects.drafts().count()
- self.copy_page(page_a, page_b_a)
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ self.copy_page(page_a, page_b_a)
self.assertEqual(Page.objects.drafts().count() - count, 3)
def test_language_change(self):
- page_data = self.get_new_page_data()
- self.client.post(URL_CMS_PAGE_ADD, page_data)
- pk = Page.objects.all()[0].pk
- response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"en" })
- self.assertEqual(response.status_code, 200)
- response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"de" })
- self.assertEqual(response.status_code, 200)
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ page_data = self.get_new_page_data()
+ self.client.post(URL_CMS_PAGE_ADD, page_data)
+ pk = Page.objects.all()[0].pk
+ response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"en" })
+ self.assertEqual(response.status_code, 200)
+ response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"de" })
+ self.assertEqual(response.status_code, 200)
def test_move_page(self):
- page_data1 = self.get_new_page_data()
- self.client.post(URL_CMS_PAGE_ADD, page_data1)
- page_data2 = self.get_new_page_data()
- self.client.post(URL_CMS_PAGE_ADD, page_data2)
- page_data3 = self.get_new_page_data()
- self.client.post(URL_CMS_PAGE_ADD, page_data3)
- page1 = Page.objects.all()[0]
- page2 = Page.objects.all()[1]
- page3 = Page.objects.all()[2]
- # move pages
- response = self.client.post("/admin/cms/page/%s/move-page/" % page3.pk, {"target":page2.pk, "position":"last-child" })
- self.assertEqual(response.status_code, 200)
- response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"last-child" })
- self.assertEqual(response.status_code, 200)
- # check page2 path and url
- page2 = Page.objects.get(pk=page2.pk)
- self.assertEqual(page2.get_path(), page_data1['slug']+"/"+page_data2['slug'])
- self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/")
- # check page3 path and url
- page3 = Page.objects.get(pk=page3.pk)
- self.assertEqual(page3.get_path(), page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug'])
- self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug']+"/")
- # publish page 1 (becomes home)
- page1 = Page.objects.all()[0]
- page1.published = True
- page1.save()
- # check that page2 and page3 url have changed
- page2 = Page.objects.get(pk=page2.pk)
- self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/")
- page3 = Page.objects.get(pk=page3.pk)
- self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/"+page_data3['slug']+"/")
- # move page2 back to root and check path of 2 and 3
- response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"left" })
- self.assertEqual(response.status_code, 200)
- page2 = Page.objects.get(pk=page2.pk)
- self.assertEqual(page2.get_path(), page_data2['slug'])
- page3 = Page.objects.get(pk=page3.pk)
- self.assertEqual(page3.get_path(), page_data2['slug']+"/"+page_data3['slug'])
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ page_data1 = self.get_new_page_data()
+ self.client.post(URL_CMS_PAGE_ADD, page_data1)
+ page_data2 = self.get_new_page_data()
+ self.client.post(URL_CMS_PAGE_ADD, page_data2)
+ page_data3 = self.get_new_page_data()
+ self.client.post(URL_CMS_PAGE_ADD, page_data3)
+ page1 = Page.objects.all()[0]
+ page2 = Page.objects.all()[1]
+ page3 = Page.objects.all()[2]
+ # move pages
+ response = self.client.post("/admin/cms/page/%s/move-page/" % page3.pk, {"target":page2.pk, "position":"last-child" })
+ self.assertEqual(response.status_code, 200)
+ response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"last-child" })
+ self.assertEqual(response.status_code, 200)
+ # check page2 path and url
+ page2 = Page.objects.get(pk=page2.pk)
+ self.assertEqual(page2.get_path(), page_data1['slug']+"/"+page_data2['slug'])
+ self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/")
+ # check page3 path and url
+ page3 = Page.objects.get(pk=page3.pk)
+ self.assertEqual(page3.get_path(), page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug'])
+ self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug']+"/")
+ # publish page 1 (becomes home)
+ page1 = Page.objects.all()[0]
+ page1.published = True
+ page1.save()
+ # check that page2 and page3 url have changed
+ page2 = Page.objects.get(pk=page2.pk)
+ self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/")
+ page3 = Page.objects.get(pk=page3.pk)
+ self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/"+page_data3['slug']+"/")
+ # move page2 back to root and check path of 2 and 3
+ response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"left" })
+ self.assertEqual(response.status_code, 200)
+ page2 = Page.objects.get(pk=page2.pk)
+ self.assertEqual(page2.get_path(), page_data2['slug'])
+ page3 = Page.objects.get(pk=page3.pk)
+ self.assertEqual(page3.get_path(), page_data2['slug']+"/"+page_data3['slug'])
def test_move_page_inherit(self):
parent = create_page("Parent", 'col_three.html', "en")
@@ -274,11 +286,13 @@ def test_edit_page_other_site_and_language(self):
page_data['title'] = 'changed title'
TESTLANG = settings.CMS_SITE_LANGUAGES[site.pk][0]
page_data['language'] = TESTLANG
- response = self.client.post(URL_CMS_PAGE_ADD, page_data)
- self.assertRedirects(response, URL_CMS_PAGE)
- page = Page.objects.get(title_set__slug=page_data['slug'])
- with LanguageOverride(TESTLANG):
- self.assertEqual(page.get_title(), 'changed title')
+ superuser = self.get_superuser()
+ with self.login_user_context(superuser):
+ response = self.client.post(URL_CMS_PAGE_ADD, page_data)
+ self.assertRedirects(response, URL_CMS_PAGE)
+ page = Page.objects.get(title_set__slug=page_data['slug'])
+ with LanguageOverride(TESTLANG):
+ self.assertEqual(page.get_title(), 'changed title')
def test_flat_urls(self):
with SettingsOverride(CMS_FLAT_URLS=True):
@@ -392,6 +406,7 @@ def test_get_page_from_request_with_page_404(self):
def test_get_page_from_request_with_page_preview(self):
page = create_page("page", "nav_playground.html", "en")
request = self.get_request('%s?preview' % page.get_absolute_url())
+ request.user.is_staff = False
found_page = get_page_from_request(request)
self.assertEqual(found_page, None)
superuser = self.get_superuser()
@@ -416,6 +431,73 @@ def test_get_page_from_request_on_cms_admin_with_editplugin_nopage(self):
)
page = get_page_from_request(request)
self.assertEqual(page, None)
+
+ def test_page_already_expired(self):
+ """
+ Test that a page which has a end date in the past gives a 404, not a
+ 500.
+ """
+ yesterday = datetime.date.today() - datetime.timedelta(days=1)
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ page = create_page('page', 'nav_playground.html', 'en',
+ publication_end_date=yesterday, published=True)
+ resp = self.client.get(page.get_absolute_url('en'))
+ self.assertEqual(resp.status_code, 404)
+
+ def test_existing_overwrite_url(self):
+ with SettingsOverride(CMS_MODERATOR=False, CMS_PERMISSION=False):
+ create_page('home', 'nav_playground.html', 'en', published=True)
+ create_page('boo', 'nav_playground.html', 'en', published=True)
+ data = {
+ 'title': 'foo',
+ 'overwrite_url': '/boo/',
+ 'slug': 'foo',
+ 'language': 'en',
+ 'template': 'nav_playground.html',
+ 'site': 1,
+ }
+ form = PageForm(data)
+ self.assertFalse(form.is_valid())
+ self.assertTrue('overwrite_url' in form.errors)
+
+ def test_page_urls(self):
+ page1 = create_page('test page 1', 'nav_playground.html', 'en',
+ published=True)
+
+ page2 = create_page('test page 2', 'nav_playground.html', 'en',
+ published=True, parent=page1)
+
+ page3 = create_page('test page 3', 'nav_playground.html', 'en',
+ published=True, parent=page2)
+
+ page4 = create_page('test page 4', 'nav_playground.html', 'en',
+ published=True)
+
+ page5 = create_page('test page 5', 'nav_playground.html', 'en',
+ published=True, parent=page4)
+
+ self.assertEqual(page1.get_absolute_url(),
+ self.get_pages_root()+'')
+ self.assertEqual(page2.get_absolute_url(),
+ self.get_pages_root()+'test-page-2/')
+ self.assertEqual(page3.get_absolute_url(),
+ self.get_pages_root()+'test-page-2/test-page-3/')
+ self.assertEqual(page4.get_absolute_url(),
+ self.get_pages_root()+'test-page-4/')
+ self.assertEqual(page5.get_absolute_url(),
+ self.get_pages_root()+'test-page-4/test-page-5/')
+
+ page3 = self.move_page(page3, page1)
+ self.assertEqual(page3.get_absolute_url(),
+ self.get_pages_root()+'test-page-3/')
+
+ page5 = self.move_page(page5, page2)
+ self.assertEqual(page5.get_absolute_url(),
+ self.get_pages_root()+'test-page-2/test-page-5/')
+
+ page3 = self.move_page(page3, page4)
+ self.assertEqual(page3.get_absolute_url(),
+ self.get_pages_root()+'test-page-4/test-page-3/')
class NoAdminPageTests(CMSTestCase):
diff --git a/cms/tests/permmod.py b/cms/tests/permmod.py
index 084bea1513f..c7232eaab2f 100644
--- a/cms/tests/permmod.py
+++ b/cms/tests/permmod.py
@@ -6,10 +6,12 @@
from cms.models.moderatormodels import (ACCESS_DESCENDANTS,
ACCESS_PAGE_AND_DESCENDANTS)
from cms.test_utils.testcases import (URL_CMS_PAGE_ADD, URL_CMS_PLUGIN_REMOVE,
- SettingsOverrideTestCase, URL_CMS_PLUGIN_ADD)
+ SettingsOverrideTestCase, URL_CMS_PLUGIN_ADD, CMSTestCase)
from cms.test_utils.util.context_managers import SettingsOverride
+from cms.utils.page_resolver import get_page_from_path
from cms.utils.permissions import has_generic_permission
from django.contrib.auth.models import User
+from django.core.management import call_command
class PermissionModeratorTests(SettingsOverrideTestCase):
@@ -778,4 +780,21 @@ def test_patricks_move(self):
self.assertEqual(
self.ph.publisher_public.get_absolute_url(),
u'%smaster/slave-home/pc/pg/pe/ph/' % self.get_pages_root()
- )
\ No newline at end of file
+ )
+
+
+class ModeratorSwitchCommandTest(CMSTestCase):
+ def test_switch_moderator_on(self):
+ with SettingsOverride(CMS_MODERATOR=False):
+ page1 = create_page('page', 'nav_playground.html', 'en', published=True)
+ with SettingsOverride(CMS_MODERATOR=True):
+ call_command('cms', 'moderator', 'on')
+ page2 = get_page_from_path(page1.get_absolute_url().strip('/'))
+ self.assertEqual(page1.get_absolute_url(), page2.get_absolute_url())
+
+ def test_switch_moderator_off(self):
+ with SettingsOverride(CMS_MODERATOR=True):
+ page1 = create_page('page', 'nav_playground.html', 'en', published=True)
+ with SettingsOverride(CMS_MODERATOR=False):
+ page2 = get_page_from_path(page1.get_absolute_url().strip('/'))
+ self.assertEqual(page1.get_absolute_url(), page2.get_absolute_url())
diff --git a/cms/tests/placeholder.py b/cms/tests/placeholder.py
index 44ad5468261..b1094b24a84 100644
--- a/cms/tests/placeholder.py
+++ b/cms/tests/placeholder.py
@@ -4,14 +4,14 @@
from cms.exceptions import DuplicatePlaceholderWarning
from cms.models.placeholdermodel import Placeholder
from cms.plugin_rendering import render_placeholder
+from cms.plugins.text.cms_plugins import TextPlugin
+from cms.test_utils.fixtures.fakemlng import FakemlngFixtures
from cms.test_utils.testcases import CMSTestCase
from cms.test_utils.util.context_managers import (SettingsOverride,
UserLoginContext)
from cms.test_utils.util.mock import AttributeObject
from cms.utils.placeholder import PlaceholderNoAction, MLNGPlaceholderActions
from cms.utils.plugins import get_placeholders
-from cms.api import add_plugin
-from cms.plugins.text.cms_plugins import TextPlugin
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.models import User
@@ -19,8 +19,8 @@
from django.template import TemplateSyntaxError, Template
from django.template.context import Context, RequestContext
from project.fakemlng.models import Translations
-from project.placeholderapp.models import (Example1, Example2, Example3, Example4,
- Example5)
+from project.placeholderapp.models import (Example1, Example2, Example3,
+ Example4, Example5)
class PlaceholderTestCase(CMSTestCase):
@@ -107,6 +107,44 @@ def test_fieldsets(self):
self.assertTrue('plugin-holder-nopage' in fieldset['classes'])
phfields.remove(field)
self.assertEqual(phfields, [])
+
+ def test_page_only_plugins(self):
+ ex = Example1(
+ char_1='one',
+ char_2='two',
+ char_3='tree',
+ char_4='four'
+ )
+ ex.save()
+ response = self.client.get(reverse('admin:placeholderapp_example1_change', args=(ex.pk,)))
+ self.assertEqual(response.status_code, 200)
+ self.assertNotContains(response, 'InheritPagePlaceholderPlugin')
+
+ def test_inter_placeholder_plugin_move(self):
+ ex = Example5(
+ char_1='one',
+ char_2='two',
+ char_3='tree',
+ char_4='four'
+ )
+ ex.save()
+ ph1 = ex.placeholder_1
+ ph2 = ex.placeholder_2
+ ph1_pl1 = add_plugin(ph1, TextPlugin, 'en', body='ph1 plugin1').cmsplugin_ptr
+ ph1_pl2 = add_plugin(ph1, TextPlugin, 'en', body='ph1 plugin2').cmsplugin_ptr
+ ph1_pl3 = add_plugin(ph1, TextPlugin, 'en', body='ph1 plugin3').cmsplugin_ptr
+ ph2_pl1 = add_plugin(ph2, TextPlugin, 'en', body='ph2 plugin1').cmsplugin_ptr
+ ph2_pl2 = add_plugin(ph2, TextPlugin, 'en', body='ph2 plugin2').cmsplugin_ptr
+ ph2_pl3 = add_plugin(ph2, TextPlugin, 'en', body='ph2 plugin3').cmsplugin_ptr
+ response = self.client.post(reverse('admin:placeholderapp_example5_move_plugin'), {
+ 'placeholder': ph2.slot,
+ 'placeholder_id': str(ph2.pk),
+ 'plugin_id': str(ph1_pl2.pk),
+ 'ids': "_".join([str(p.pk) for p in [ph2_pl1, ph1_pl2, ph2_pl2, ph2_pl3]])
+ })
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual([ph1_pl1, ph1_pl3], list(ph1.cmsplugin_set.order_by('position')))
+ self.assertEqual([ph2_pl1, ph1_pl2, ph2_pl2, ph2_pl3], list(ph2.cmsplugin_set.order_by('position')))
def test_placeholder_scanning_fail(self):
self.assertRaises(TemplateSyntaxError, get_placeholders, 'placeholder_tests/test_eleven.html')
@@ -146,9 +184,12 @@ def push(self):
self.assertTrue('width' in context)
self.assertEqual(context['width'], 10)
+ def test_placeholder_scanning_nested_super(self):
+ placeholders = get_placeholders('placeholder_tests/nested_super_level1.html')
+ self.assertEqual(sorted(placeholders), sorted([u'level1', u'level2', u'level3', u'level4']))
+
-class PlaceholderActionTests(CMSTestCase):
- fixtures = ['fakemlng.json']
+class PlaceholderActionTests(FakemlngFixtures, CMSTestCase):
def test_placeholder_no_action(self):
actions = PlaceholderNoAction()
@@ -210,8 +251,9 @@ def test_mlng_placeholder_actions_empty_copy(self):
def test_mlng_placeholder_actions_no_placeholder(self):
actions = MLNGPlaceholderActions()
- nl = Translations.objects.get(language_code='nl')
+ Translations.objects.filter(language_code='nl').update(placeholder=None)
de = Translations.objects.get(language_code='de')
+ nl = Translations.objects.get(language_code='nl')
self.assertEqual(nl.placeholder, None)
self.assertEqual(de.placeholder.cmsplugin_set.count(), 0)
diff --git a/cms/tests/templatetags.py b/cms/tests/templatetags.py
index b280631674c..fb481bddc75 100644
--- a/cms/tests/templatetags.py
+++ b/cms/tests/templatetags.py
@@ -1,6 +1,7 @@
from __future__ import with_statement
from cms.models.pagemodel import Page
from cms.templatetags.cms_tags import get_site_id, _get_page_by_untyped_arg
+from cms.test_utils.fixtures.templatetags import TwoPagesFixture
from cms.test_utils.testcases import SettingsOverrideTestCase
from cms.test_utils.util.context_managers import SettingsOverride
from cms.utils.plugins import get_placeholders
@@ -34,15 +35,14 @@ def test_unicode_placeholder_name_fails_fast(self):
self.assertRaises(ImproperlyConfigured, get_placeholders, 'unicode_placeholder.html')
-class TemplatetagDatabaseTests(SettingsOverrideTestCase):
+class TemplatetagDatabaseTests(TwoPagesFixture, SettingsOverrideTestCase):
settings_overrides = {'CMS_MODERATOR': False}
- fixtures = ['twopages.json']
def _getfirst(self):
- return Page.objects.get(pk=1)
+ return Page.objects.get(title_set__title='first')
def _getsecond(self):
- return Page.objects.get(pk=2)
+ return Page.objects.get(title_set__title='second')
def test_get_page_by_untyped_arg_none(self):
control = self._getfirst()
@@ -65,7 +65,7 @@ def test_get_page_by_untyped_arg_reverse_id(self):
def test_get_page_by_untyped_arg_dict(self):
second = self._getsecond()
request = self.get_request('/')
- page = _get_page_by_untyped_arg({'pk': 2}, request, 1)
+ page = _get_page_by_untyped_arg({'pk': second.pk}, request, 1)
self.assertEqual(page, second)
def test_get_page_by_untyped_arg_dict_fail_debug(self):
diff --git a/cms/tests/toolbar.py b/cms/tests/toolbar.py
index cb3c0bb4bc6..6b19b5987e8 100644
--- a/cms/tests/toolbar.py
+++ b/cms/tests/toolbar.py
@@ -164,8 +164,9 @@ def test_toolbar_staff(self):
templates = items[2]
self.assertTrue(isinstance(templates, List))
self.assertEqual(len(templates.raw_items), len(settings.CMS_TEMPLATES))
+ base = reverse('admin:cms_page_change_template', args=(page.pk,))
for item, template in zip(templates.raw_items, settings.CMS_TEMPLATES):
- self.assertEqual(item.url, '#%s' % template[0])
+ self.assertEqual(item.url, '%s?template=%s' % (base, template[0]))
# check page menu
pagemenu = items[3]
@@ -191,6 +192,19 @@ def test_toolbar_staff(self):
logout = items[5]
self.assertTrue(isinstance(logout, GetButton))
self.assertEqual(logout.url, '?cms-toolbar-logout')
+
+ def test_toolbar_markup(self):
+ superuser = self.get_superuser()
+ create_page("toolbar-page", "nav_playground.html", "en",
+ created_by=superuser, published=True)
+
+ with self.login_user_context(superuser):
+ response = self.client.get('/?edit')
+ self.assertEquals(response.status_code, 200)
+ self.assertTemplateUsed(response, 'nav_playground.html')
+ self.assertContains(response, '