def test_toolbar_with_items(self): """ Test that PageTags/TitleTags items are present for superuser if PageTags/TitleTags exists for current page """ from cms.toolbar.toolbar import CMSToolbar page1, page2 = self.get_pages() page_ext = PageTags.objects.create(extended_object=page1) title_tags = TitleTags.objects.create(extended_object=page1.get_title_obj('en')) request = self.get_page_request(page1, self.user, '/', edit=True) toolbar = CMSToolbar(request) toolbar.get_left_items() page_menu = toolbar.find_items(Menu, name='Page')[0].item tags_menu = page_menu.find_items(SubMenu, name=force_text(PAGE_TAGS_MENU_TITLE))[0].item pagetags_menu = tags_menu.find_items(ModalItem, name="{0}...".format(force_text(PAGE_TAGS_ITEM_TITLE))) self.assertEqual(len(pagetags_menu), 1) self.assertEqual(len(pagetags_menu), 1) self.assertTrue(pagetags_menu[0].item.url.startswith(reverse('admin:djangocms_page_tags_pagetags_change', args=(page_ext.pk,)))) url_change = False url_add = False for title in page1.title_set.all(): language = get_language_object(title.language) titletags_menu = tags_menu.find_items(ModalItem, name='{0}...'.format(language['name'])) self.assertEqual(len(titletags_menu), 1) try: title_ext = TitleTags.objects.get(extended_object_id=title.pk) self.assertEqual(title_ext, title_tags) self.assertTrue(titletags_menu[0].item.url.startswith(reverse('admin:djangocms_page_tags_titletags_change', args=(title_ext.pk,)))) url_change = True except TitleTags.DoesNotExist: self.assertTrue(titletags_menu[0].item.url.startswith(reverse('admin:djangocms_page_tags_titletags_add'))) url_add = True self.assertTrue(url_change and url_add)
def get_context(self, context, template, i18n_mode): if template in MARKERS: _tmp = template if i18n_mode not in MARKERS: template = i18n_mode else: template = NOT_PROVIDED i18n_mode = _tmp if template is NOT_PROVIDED: template = "menu/language_chooser.html" if not i18n_mode in MARKERS: i18n_mode = 'raw' if 'request' not in context: # If there's an exception (500), default context_processors may not be called. return {'template': 'cms/content.html'} marker = MARKERS[i18n_mode] current_lang = get_language() site = Site.objects.get_current() request = context['request'] if request.user.is_staff: languages = get_language_list(site_id=site.pk) else: languages = get_public_languages(site_id=site.pk) languages_info = [] for language in languages: obj = get_language_object(language, site_id=site.pk) languages_info.append((obj['code'], marker(obj['name'], obj['code']))) context['languages'] = languages_info context['current_language'] = current_lang context['template'] = template return context
def populate(self): # setup the extension toolbar with permissions and sanity checks current_page_menu = self._setup_extension_toolbar() # if it's all ok if current_page_menu and self.toolbar.edit_mode_active: # create a sub menu labelled "Ratings" at position 1 in the menu sub_menu = self._get_sub_menu( current_page_menu, 'submenu_label', 'MSEO', position=1 ) # retrieves the instances of the current title extension (if any) # and the toolbar item URL urls = self.get_title_extension_admin() # we now also need to get the titleset (i.e. different language titles) # for this page page = self._get_page() titleset = page.title_set.filter( language__in=get_language_list(page.node.site_id)) # create a 3-tuple of (title_extension, url, title) nodes = [(title_extension, url, title) for ( (title_extension, url), title) in zip(urls, titleset) ] # cycle through the list of nodes for title_extension, url, title in nodes: language = get_language_object(title.language)['name'] # adds toolbar items sub_menu.add_modal_item( _('%s options') % language, url=url, disabled=not self.toolbar.edit_mode_active )
def test_toolbar_with_items(self): """ Test that PageMeta/TitleMeta items are present for superuser if PageMeta/TitleMeta exists for current page """ from cms.toolbar.toolbar import CMSToolbar page1, page2 = self.get_pages() page_ext = PageMeta.objects.create(extended_object=page1) request = self.get_page_request(page1, self.user, '/', edit=True) toolbar = CMSToolbar(request) toolbar.get_left_items() page_menu = toolbar.menus['page'] meta_menu = page_menu.find_items(SubMenu, name=force_text(PAGE_META_MENU_TITLE))[0].item try: pagemeta_menu = meta_menu.find_items(ModalItem, name="{0}...".format(force_text(PAGE_META_ITEM_TITLE))) self.assertEqual(len(pagemeta_menu), 1) except AssertionError: pagemeta_menu = meta_menu.find_items(ModalItem, name="{0} ...".format(force_text(PAGE_META_ITEM_TITLE))) self.assertEqual(len(pagemeta_menu), 1) self.assertTrue(pagemeta_menu[0].item.url.startswith(reverse('admin:djangocms_page_meta_pagemeta_change', args=(page_ext.pk,)))) for title in page1.title_set.all(): language = get_language_object(title.language) try: titlemeta_menu = meta_menu.find_items(ModalItem, name='{0}...'.format(language['name'])) self.assertEqual(len(titlemeta_menu), 1) except AssertionError: titlemeta_menu = meta_menu.find_items(ModalItem, name='{0} ...'.format(language['name'])) self.assertEqual(len(titlemeta_menu), 1) try: title_ext = TitleMeta.objects.get(extended_object_id=title.pk) self.assertTrue(titlemeta_menu[0].item.url.startswith(reverse('admin:djangocms_page_meta_titlemeta_change', args=(title_ext.pk,)))) except TitleMeta.DoesNotExist: self.assertTrue(titlemeta_menu[0].item.url.startswith(reverse('admin:djangocms_page_meta_titlemeta_add')))
def test_toolbar_with_items(self): """ Test that PageMeta/TitleMeta items are present for superuser if PageMeta/TitleMeta exists for current page """ from cms.toolbar.toolbar import CMSToolbar page1, page2 = self.get_pages() page_ext = PageMeta.objects.create(extended_object=page1) request = self.get_page_request(page1, self.user, '/', edit=True) toolbar = CMSToolbar(request) toolbar.get_left_items() page_menu = toolbar.menus['page'] meta_menu = page_menu.find_items( SubMenu, name=force_unicode(PAGE_META_MENU_TITLE))[0].item pagemeta_menu = meta_menu.find_items( ModalItem, name="%s ..." % force_unicode(PAGE_META_ITEM_TITLE)) self.assertEqual(len(pagemeta_menu), 1) self.assertTrue(pagemeta_menu[0].item.url.startswith( reverse('admin:djangocms_page_meta_pagemeta_change', args=(page_ext.pk, )))) for title in page1.title_set.all(): language = get_language_object(title.language) titlemeta_menu = meta_menu.find_items(ModalItem, name="%s ..." % language['name']) self.assertEqual(len(titlemeta_menu), 1) try: title_ext = TitleMeta.objects.get(extended_object_id=title.pk) self.assertTrue(titlemeta_menu[0].item.url.startswith( reverse('admin:djangocms_page_meta_titlemeta_change', args=(title_ext.pk, )))) except TitleMeta.DoesNotExist: self.assertTrue(titlemeta_menu[0].item.url.startswith( reverse('admin:djangocms_page_meta_titlemeta_add')))
def get_context(self, context): opts = context['opts'] change = context['change'] is_popup = context['is_popup'] save_as = context['save_as'] show_delete_translation = context.get('show_delete_translation') language = context['language'] return { 'onclick_attrib': (opts.get_ordered_objects() and change and 'onclick="submitOrderForm();"' or ''), 'show_delete_link': (not is_popup and context['has_delete_permission'] and (change or context['show_delete'])), 'show_save_as_new': not is_popup and change and save_as, 'show_save_and_add_another': context['has_add_permission'] and not is_popup and (not save_as or context['add']), 'show_save_and_continue': not is_popup and context['has_change_permission'], 'is_popup': is_popup, 'show_save': True, 'language': language, 'language_name': get_language_object(language)['name'], 'show_delete_translation': show_delete_translation }
def change_language_menu(self): language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER) if not language_menu: return None add = [] remove = self.page.get_languages() languages = get_language_objects(self.current_site.pk) for language in languages: code = language['code'] if not code in remove: add.append(code) if add: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) for code in add: language = get_language_object(code, self.current_site.pk) url = "%s?language=%s" % (reverse("admin:cms_page_change", args=[self.page.pk]), language['code']) language_menu.add_modal_item(_("Add %(language)s Translation") % {'language': language['name']}, url=url) if remove: language_menu.add_break(REMOVE_PAGE_LANGUAGE_BREAK) for code in remove: try: language = get_language_object(code, self.current_site.pk) language_code = language['code'] language_name = language['name'] except LanguageError: language_code = code language_name = code url = "%s?language=%s" % ( reverse("admin:cms_page_delete_translation", args=[self.page.pk]), language_code) language_menu.add_modal_item(_("Delete %(language)s Translation") % {'language': language_name}, url=url, disabled=len(remove) == 1) if len(languages) > 1 and self.current_lang and len(remove) > 1: language_menu.add_break(COPY_PAGE_LANGUAGE_BREAK) for language in languages: if self.current_lang == language['code'] or language['code'] in add: continue url = reverse('admin:cms_page_copy_language', args=[self.page.pk]) question = _('Are you sure you want copy all plugins from %s?') % language['name'] language_menu.add_ajax_item(_("Copy all plugins from %s") % language['name'], action=url, data={'source_language': language['code'], 'target_language': self.current_lang}, question=question, on_success=self.toolbar.REFRESH_PAGE)
def change_language_menu(self): language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER) if not language_menu: return None add = [] remove = self.page.get_languages() languages = get_language_objects(self.current_site.pk) for language in languages: code = language['code'] if not code in remove: add.append(code) if add: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) for code in add: language = get_language_object(code, self.current_site.pk) url = "%s?language=%s" % (reverse("admin:cms_page_change", args=[self.page.pk]), language['code']) language_menu.add_modal_item(_("Add %(language)s Translation") % {'language': language['name']}, url=url) if remove: language_menu.add_break(REMOVE_PAGE_LANGUAGE_BREAK) for code in remove: try: language = get_language_object(code, self.current_site.pk) language_code = language['code'] language_name = language['name'] except LanguageError: language_code = code language_name = code url = "%s?language=%s" % ( reverse("admin:cms_page_delete_translation", args=[self.page.pk]), language_code) language_menu.add_modal_item(_("Delete %(language)s Translation") % {'language': language_name}, url=url, disabled=len(remove) == 1) if len(languages) > 1 and self.current_lang and len(remove) > 1: language_menu.add_break(COPY_PAGE_LANGUAGE_BREAK) for language in languages: if self.current_lang == language['code'] or language['code'] in add: continue url = reverse('admin:cms_page_copy_language', args=[self.page.pk]) question = _('Are you sure you want copy all plugins from %s?') % language['name'] language_menu.add_ajax_item(_("Copy all plugins from %s") % language['name'], action=url, data={'source_language': language['code'], 'target_language': self.current_lang}, question=question)
def __init__(self, request, toolbar, is_current_app, app_path): self.request = request self.toolbar = toolbar self.is_current_app = is_current_app self.app_path = app_path self.current_site = Site.objects.get_current() try: self.current_lang = get_language_object(get_language_from_request(self.request), self.current_site.pk)['code'] except LanguageError: self.current_lang = None
def add_language_menu(self): try: current_lang = get_language_object(get_language_from_request(self.request), self.current_site.pk) except LanguageError: current_lang = None language_menu = self.toolbar.get_or_create_menu(LANGUAGE_MENU_IDENTIFIER, _('Language')) language_changer = getattr(self.request, '_language_changer', DefaultLanguageChanger(self.request)) for language in get_language_objects(self.current_site.pk): url = language_changer(language['code']) language_menu.add_link_item(language['name'], url=url, active=current_lang['code'] == language['code'])
def get_valid_languages(namespace, language_code, site_id=None): langs = [language_code] if site_id is None: site_id = getattr(Site.objects.get_current(), 'pk', None) current_language = get_language_object(language_code, site_id) fallbacks = current_language.get('fallbacks', None) if fallbacks: langs += list(fallbacks) valid_translations = [ lang_code for lang_code in langs if is_valid_namespace_for_language(namespace, lang_code)] return valid_translations
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check global permissions if CMS_PERMISSIONS is active if get_cms_setting("PERMISSION"): has_global_current_page_change_permission = has_page_change_permission(self.request) else: has_global_current_page_change_permission = False # check if user has page edit permission can_change = self.request.current_page and self.request.current_page.has_change_permission(self.request) if has_global_current_page_change_permission or can_change: not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu("page") super_item = current_page_menu.find_first(Break, identifier=PAGE_MENU_SECOND_BREAK) + 1 meta_menu = current_page_menu.get_or_create_menu("pagemeta", PAGE_META_MENU_TITLE, position=super_item) position = 0 # Page tags try: page_extension = PageMeta.objects.get(extended_object_id=self.page.pk) except PageMeta.DoesNotExist: page_extension = None try: if page_extension: url = reverse("admin:djangocms_page_meta_pagemeta_change", args=(page_extension.pk,)) else: url = "%s?extended_object=%s" % (reverse("admin:djangocms_page_meta_pagemeta_add"), self.page.pk) except NoReverseMatch: # not in urls pass else: meta_menu.add_modal_item(PAGE_META_ITEM_TITLE, url=url, disabled=not_edit_mode, position=position) # Title tags for title in self.page.title_set.all(): try: title_extension = TitleMeta.objects.get(extended_object_id=title.pk) except TitleMeta.DoesNotExist: title_extension = None try: if title_extension: url = reverse("admin:djangocms_page_meta_titlemeta_change", args=(title_extension.pk,)) else: url = "%s?extended_object=%s" % (reverse("admin:djangocms_page_meta_titlemeta_add"), title.pk) except NoReverseMatch: # not in urls pass else: position += 1 language = get_language_object(title.language) meta_menu.add_modal_item(language["name"], url=url, disabled=not_edit_mode, position=position)
def single_page_translation(self): current_site = Site.objects.get_current() try: current_lang = get_language_object(get_language_from_request(self.request), current_site.pk) except LanguageError: current_lang = None language_menu = self.toolbar.get_or_create_menu(LANGUAGE_MENU_IDENTIFIER, _('Language')) position = language_menu.find_first(Break, identifier=ADD_PAGE_LANGUAGE_BREAK) menu = language_menu.get_or_create_menu('aldryn-translator', _('Get this page translated'), position=position) for language in get_language_objects(current_site.pk): if language['code'] != current_lang['code']: menu.add_modal_item(_('to %s' % language['name']), "%s?from_lang=%s&to_lang=%s" % ( reverse('admin:aldryn_translator_translation_add'), current_lang['code'], language['code']))
def get_filled_languages(self): """ Returns language objects for every language for which the placeholder has plugins. This is not cached as it's meant to eb used in the frontend editor. """ languages = [] for lang_code in set(self.get_plugins().values_list('language', flat=True)): try: languages.append(get_language_object(lang_code)) except LanguageError: pass return languages
def add_language_menu(self): try: current_lang = get_language_object( get_language_from_request(self.request), self.current_site.pk) except LanguageError: current_lang = None language_menu = self.toolbar.get_or_create_menu( LANGUAGE_MENU_IDENTIFIER, _('Language')) language_changer = getattr(self.request, '_language_changer', DefaultLanguageChanger(self.request)) for language in get_language_objects(self.current_site.pk): url = language_changer(language['code']) language_menu.add_link_item( language['name'], url=url, active=current_lang['code'] == language['code'])
def unpublish(self, request, article_id, language): """ Publish or unpublish a language of a article """ article = get_object_or_404(self.model, pk=article_id) if not article.has_publish_permission(request): return HttpResponseForbidden( force_text( _('You do not have permission to unpublish this article'))) if not article.publisher_public_id: return HttpResponseForbidden( force_text(_('This article was never published'))) try: article.unpublish(language) message = _( 'The %(language)s article "%(article)s" was successfully unpublished' ) % { 'language': get_language_object(language)['name'], 'article': article } messages.info(request, message) LogEntry.objects.log_action( user_id=request.user.id, content_type_id=ContentType.objects.get_for_model(Article).pk, object_id=article_id, object_repr=article.get_title(), action_flag=CHANGE, change_message=message, ) except RuntimeError: exc = sys.exc_info()[1] messages.error(request, exc.message) except ValidationError: exc = sys.exc_info()[1] messages.error(request, exc.message) path = admin_reverse('cms_articles_article_changelist') if request.GET.get('redirect_language'): path = '%s?language=%s&article_id=%s' % ( path, request.GET.get('redirect_language'), request.GET.get('redirect_article_id')) return HttpResponseRedirect(path)
def unpublish(self, request, article_id, language): """ Publish or unpublish a language of a article """ article = get_object_or_404(self.model, pk=article_id) if not article.has_publish_permission(request): return HttpResponseForbidden(force_text(_('You do not have permission to unpublish this article'))) if not article.publisher_public_id: return HttpResponseForbidden(force_text(_('This article was never published'))) try: article.unpublish(language) message = _('The %(language)s article "%(article)s" was successfully unpublished') % { 'language': get_language_object(language)['name'], 'article': article} messages.info(request, message) LogEntry.objects.log_action( user_id=request.user.id, content_type_id=ContentType.objects.get_for_model(Article).pk, object_id=article_id, object_repr=article.get_title(), action_flag=CHANGE, change_message=message, ) except RuntimeError: exc = sys.exc_info()[1] messages.error(request, exc.message) except ValidationError: exc = sys.exc_info()[1] messages.error(request, exc.message) path = admin_reverse('cms_articles_article_changelist') if request.GET.get('redirect_language'): path = '%s?language=%s&article_id=%s' % ( path, request.GET.get('redirect_language'), request.GET.get('redirect_article_id') ) return HttpResponseRedirect(path)
def clean(self): cleaned_data = super(AdvancedSettingsForm, self).clean() language = cleaned_data.get('language') if not language: # Fail fast if no language is provided return cleaned_data # Language has been validated already # so we know it exists. language_name = get_language_object( language, site_id=cleaned_data['site'].pk )['name'] try: title = self.instance.title_set.get(language=language) except Title.DoesNotExist: # This covers all cases where users try to edit # page advanced settings without creating the page title. message = _("Please create the %(language)s page " "translation before editing its advanced settings.") raise ValidationError(message % {'language': language_name}) if not title.slug: # This covers all cases where users try to edit # page advanced settings without setting a title slug # for page titles that already exist. message = _("Please set the %(language)s slug " "before editing its advanced settings.") raise ValidationError(message % {'language': language_name}) if 'reverse_id' in self.fields: id = cleaned_data['reverse_id'] site_id = cleaned_data['site'] if id: if Page.objects.filter(reverse_id=id, site=site_id, publisher_is_draft=True).exclude( pk=self.instance.pk).count(): self._errors['reverse_id'] = self.error_class( [_('A page with this reverse URL id exists already.')]) apphook = cleaned_data.get('application_urls', None) # The field 'application_namespace' is a misnomer. It should be # 'instance_namespace'. instance_namespace = cleaned_data.get('application_namespace', None) application_config = cleaned_data.get('application_configs', None) if apphook: # application_config wins over application_namespace if application_config: # the value of the application config namespace is saved in # the 'usual' namespace field to be backward compatible # with existing apphooks config = apphook_pool.get_apphook(apphook).get_configs().get(pk=int(application_config)) if self._check_unique_namespace_instance(config.namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_configs'] = ErrorList([ _('An application instance using this configuration already exists.') ]) else: self.cleaned_data['application_namespace'] = config.namespace else: if instance_namespace: if self._check_unique_namespace_instance(instance_namespace): self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.') ]) else: # The attribute on the apps 'app_name' is a misnomer, it should be # 'application_namespace'. application_namespace = apphook_pool.get_apphook(apphook).app_name if application_namespace and not instance_namespace: if self._check_unique_namespace_instance(application_namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.') ]) else: # OK, there are zero instances of THIS app that use the # default instance namespace, so, since the user didn't # provide one, we'll use the default. NOTE: The following # line is really setting the "instance namespace" of the # new app to the app’s "application namespace", which is # the default instance namespace. self.cleaned_data['application_namespace'] = application_namespace if instance_namespace and not apphook: self.cleaned_data['application_namespace'] = None if application_config and not apphook: self.cleaned_data['application_configs'] = None return self.cleaned_data
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check global permissions if CMS_PERMISSIONS is active if get_cms_setting('PERMISSION'): if not has_page_change_permission: has_global_current_page_change_permission = has_page_permission( self.request.user, self.request.current_page, 'change') else: has_global_current_page_change_permission = has_page_change_permission( self.request) else: has_global_current_page_change_permission = False # check if user has page edit permission if not has_page_change_permission: can_change = (self.request.current_page and self.request.current_page.has_change_permission( self.request.user)) else: can_change = (self.request.current_page and self.request.current_page.has_change_permission( self.request)) if has_global_current_page_change_permission or can_change: not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page') super_item = current_page_menu.find_first( Break, identifier=PAGE_MENU_SECOND_BREAK) + 1 meta_menu = current_page_menu.get_or_create_menu( 'pagemeta', PAGE_META_MENU_TITLE, position=super_item) position = 0 # Page tags try: page_extension = PageMeta.objects.get( extended_object_id=self.page.pk) except PageMeta.DoesNotExist: page_extension = None try: if page_extension: url = reverse('admin:djangocms_page_meta_pagemeta_change', args=(page_extension.pk, )) else: url = '%s?extended_object=%s' % ( reverse('admin:djangocms_page_meta_pagemeta_add'), self.page.pk) except NoReverseMatch: # not in urls pass else: meta_menu.add_modal_item(PAGE_META_ITEM_TITLE, url=url, disabled=not_edit_mode, position=position) # Title tags for title in self.page.title_set.filter( language__in=get_language_list(self.page.site_id)): try: title_extension = TitleMeta.objects.get( extended_object_id=title.pk) except TitleMeta.DoesNotExist: title_extension = None try: if title_extension: url = reverse( 'admin:djangocms_page_meta_titlemeta_change', args=(title_extension.pk, )) else: url = '%s?extended_object=%s' % ( reverse('admin:djangocms_page_meta_titlemeta_add'), title.pk) except NoReverseMatch: # not in urls pass else: position += 1 language = get_language_object(title.language) meta_menu.add_modal_item(language['name'], url=url, disabled=not_edit_mode, position=position)
def add_page_menu(self): # menu for current page not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page', _('Page'), position=1) current_page_menu.add_link_item(_('Edit this Page'), disabled=self.toolbar.edit_mode, url='?edit') page_info_url = reverse('admin:cms_page_change', args=(self.page.pk,)) current_page_menu.add_modal_item(_('Page settings'), url=page_info_url, disabled=not_edit_mode, close_on_url=self.toolbar.URL_CHANGE, on_close=self.toolbar.REFRESH_PAGE) # Why are we doing this everywhere ? try: current_lang = get_language_object(get_language_from_request(self.request), self.current_site.pk) except LanguageError: current_lang = None if self.toolbar.build_mode or self.toolbar.edit_mode: # add templates templates_menu = current_page_menu.get_or_create_menu('templates', _('Templates')) action = reverse('admin:cms_page_change_template', args=(self.page.pk,)) for path, name in get_cms_setting('TEMPLATES'): active = self.page.template == path if path == TEMPLATE_INHERITANCE_MAGIC: templates_menu.add_break(TEMPLATE_MENU_BREAK) templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active) current_page_menu.add_break(PAGE_MENU_FIRST_BREAK) # advanced settings advanced_url = reverse('admin:cms_page_advanced', args=(self.page.pk,)) advanced_disabled = not self.page.has_advanced_settings_permission(self.request) or not self.toolbar.edit_mode current_page_menu.add_modal_item(_('Advanced settings'), url=advanced_url, close_on_url=self.toolbar.URL_CHANGE, disabled=advanced_disabled) # permissions if get_cms_setting('PERMISSION'): permissions_url = reverse('admin:cms_page_permissions', args=(self.page.pk,)) permission_disabled = not self.toolbar.edit_mode or not self.page.has_change_permissions_permission( self.request) current_page_menu.add_modal_item(_('Permissions'), url=permissions_url, close_on_url=self.toolbar.URL_CHANGE, disabled=permission_disabled) current_page_menu.add_break(PAGE_MENU_SECOND_BREAK) # navigation toggle if self.page.in_navigation: nav_title = _("Hide in navigation") else: nav_title = _("Display in navigation") nav_action = reverse('admin:cms_page_change_innavigation', args=(self.page.pk,)) current_page_menu.add_ajax_item(nav_title, action=nav_action, disabled=not_edit_mode) # publisher if self.page.published: publish_title = _('Unpublish page') else: publish_title = _('Publish page') publish_url = reverse('admin:cms_page_change_status', args=(self.page.pk,)) current_page_menu.add_ajax_item(publish_title, action=publish_url, disabled=not_edit_mode) current_page_menu.add_break(PAGE_MENU_THIRD_BREAK) # delete delete_url = reverse('admin:cms_page_delete', args=(self.page.pk,)) with force_language(current_lang['code']): # We use force_language because it makes no sense to redirect a user # who just deleted a german page to an english page (user's default language) # simply because the url /en/some-german-page-slug will show nothing if self.page.parent: # If this page has a parent, then redirect to it on_delete_redirect_url = self.page.parent.get_absolute_url(language=current_lang['code']) else: # If there's no parent, we redirect to the root. # Can't call Page.objects.get_home() because the user could very well delete the homepage # causing get_home to throw an error. # Let's keep in mind that if the user has deleted the last page, and django is running on DEBUG == False # this redirect will cause a 404... on_delete_redirect_url = reverse('pages-root') current_page_menu.add_modal_item(_('Delete page'), url=delete_url, close_on_url=self.toolbar.URL_CHANGE, on_close=on_delete_redirect_url, disabled=not_edit_mode)
def delete_translation(self, request, object_id, extra_context=None): if 'language' in request.GET: language = request.GET['language'] else: language = get_language_from_request(request) opts = Article._meta titleopts = Title._meta app_label = titleopts.app_label pluginopts = CMSPlugin._meta try: obj = self.get_queryset(request).get(pk=unquote(object_id)) except self.model.DoesNotExist: # Don't raise Http404 just yet, because we haven't checked # permissions yet. We don't want an unauthenticated user to be able # to determine whether a given object exists. obj = None if not self.has_delete_permission(request, obj): return HttpResponseForbidden(force_text(_('You do not have permission to change this article'))) if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) if not len(list(obj.get_languages())) > 1: raise Http404(_('There only exists one translation for this article')) titleobj = get_object_or_404(Title, article__id=object_id, language=language) saved_plugins = CMSPlugin.objects.filter(placeholder__article__id=object_id, language=language) using = router.db_for_read(self.model) kwargs = { 'admin_site': self.admin_site, 'user': request.user, 'using': using } deleted_objects, __, perms_needed = get_deleted_objects( [titleobj], titleopts, **kwargs )[:3] to_delete_plugins, __, perms_needed_plugins = get_deleted_objects( saved_plugins, pluginopts, **kwargs )[:3] deleted_objects.append(to_delete_plugins) perms_needed = set(list(perms_needed) + list(perms_needed_plugins)) if request.method == 'POST': if perms_needed: raise PermissionDenied message = _('Title and plugins with language %(language)s was deleted') % { 'language': force_text(get_language_object(language)['name']) } self.log_change(request, titleobj, message) messages.info(request, message) titleobj.delete() for p in saved_plugins: p.delete() public = obj.publisher_public if public: public.save() if not self.has_change_permission(request, None): return HttpResponseRedirect(admin_reverse('index')) return HttpResponseRedirect(admin_reverse('cms_articles_article_changelist')) context = { 'title': _('Are you sure?'), 'object_name': force_text(titleopts.verbose_name), 'object': titleobj, 'deleted_objects': deleted_objects, 'perms_lacking': perms_needed, 'opts': opts, 'root_path': admin_reverse('index'), 'app_label': app_label, } context.update(extra_context or {}) request.current_app = self.admin_site.name return render(request, self.delete_confirmation_template or [ 'admin/%s/%s/delete_confirmation.html' % (app_label, titleopts.object_name.lower()), 'admin/%s/delete_confirmation.html' % app_label, 'admin/delete_confirmation.html' ], context)
def add_page_menu(self): # menu for current page not_edit_mode = not self.toolbar.edit_mode current_page_menu = self.toolbar.get_or_create_menu('page', _('Page'), position=1) current_page_menu.add_link_item(_('Edit this Page'), disabled=self.toolbar.edit_mode, url='?edit') page_info_url = reverse('admin:cms_page_change', args=(self.page.pk, )) current_page_menu.add_modal_item(_('Page settings'), url=page_info_url, disabled=not_edit_mode, close_on_url=self.toolbar.URL_CHANGE, on_close=self.toolbar.REFRESH_PAGE) # Why are we doing this everywhere ? try: current_lang = get_language_object( get_language_from_request(self.request), self.current_site.pk) except LanguageError: current_lang = None if self.toolbar.build_mode or self.toolbar.edit_mode: # add templates templates_menu = current_page_menu.get_or_create_menu( 'templates', _('Templates')) action = reverse('admin:cms_page_change_template', args=(self.page.pk, )) for path, name in get_cms_setting('TEMPLATES'): active = self.page.template == path if path == TEMPLATE_INHERITANCE_MAGIC: templates_menu.add_break(TEMPLATE_MENU_BREAK) templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active) current_page_menu.add_break(PAGE_MENU_FIRST_BREAK) # advanced settings advanced_url = reverse('admin:cms_page_advanced', args=(self.page.pk, )) advanced_disabled = not self.page.has_advanced_settings_permission( self.request) or not self.toolbar.edit_mode current_page_menu.add_modal_item(_('Advanced settings'), url=advanced_url, close_on_url=self.toolbar.URL_CHANGE, disabled=advanced_disabled) # permissions if get_cms_setting('PERMISSION'): permissions_url = reverse('admin:cms_page_permissions', args=(self.page.pk, )) permission_disabled = not self.toolbar.edit_mode or not self.page.has_change_permissions_permission( self.request) current_page_menu.add_modal_item( _('Permissions'), url=permissions_url, close_on_url=self.toolbar.URL_CHANGE, disabled=permission_disabled) current_page_menu.add_break(PAGE_MENU_SECOND_BREAK) # navigation toggle if self.page.in_navigation: nav_title = _("Hide in navigation") else: nav_title = _("Display in navigation") nav_action = reverse('admin:cms_page_change_innavigation', args=(self.page.pk, )) current_page_menu.add_ajax_item(nav_title, action=nav_action, disabled=not_edit_mode) # publisher if self.page.published: publish_title = _('Unpublish page') else: publish_title = _('Publish page') publish_url = reverse('admin:cms_page_change_status', args=(self.page.pk, )) current_page_menu.add_ajax_item(publish_title, action=publish_url, disabled=not_edit_mode) current_page_menu.add_break(PAGE_MENU_THIRD_BREAK) # delete delete_url = reverse('admin:cms_page_delete', args=(self.page.pk, )) with force_language(current_lang['code']): # We use force_language because it makes no sense to redirect a user # who just deleted a german page to an english page (user's default language) # simply because the url /en/some-german-page-slug will show nothing if self.page.parent: # If this page has a parent, then redirect to it on_delete_redirect_url = self.page.parent.get_absolute_url( language=current_lang['code']) else: # If there's no parent, we redirect to the root. # Can't call Page.objects.get_home() because the user could very well delete the homepage # causing get_home to throw an error. # Let's keep in mind that if the user has deleted the last page, and django is running on DEBUG == False # this redirect will cause a 404... on_delete_redirect_url = reverse('pages-root') current_page_menu.add_modal_item(_('Delete page'), url=delete_url, close_on_url=self.toolbar.URL_CHANGE, on_close=on_delete_redirect_url, disabled=not_edit_mode)
def get_current_lang(request): current_site = Site.objects.get_current() try: return get_language_object(get_language_from_request(request), current_site.pk) except LanguageError: return False
def clean(self): cleaned_data = super(AdvancedSettingsForm, self).clean() if self._errors: # Fail fast if there's errors in the form return cleaned_data language = cleaned_data['language'] # Language has been validated already # so we know it exists. language_name = get_language_object( language, site_id=cleaned_data['site'].pk)['name'] try: title = self.instance.title_set.get(language=language) except Title.DoesNotExist: # This covers all cases where users try to edit # page advanced settings without creating the page title. message = _("Please create the %(language)s page " "translation before editing its advanced settings.") raise ValidationError(message % {'language': language_name}) if not title.slug: # This covers all cases where users try to edit # page advanced settings without setting a title slug # for page titles that already exist. message = _("Please set the %(language)s slug " "before editing its advanced settings.") raise ValidationError(message % {'language': language_name}) if 'reverse_id' in self.fields: id = cleaned_data['reverse_id'] site_id = cleaned_data['site'] if id: if Page.objects.filter(reverse_id=id, site=site_id, publisher_is_draft=True).exclude( pk=self.instance.pk).exists(): self._errors['reverse_id'] = self.error_class( [_('A page with this reverse URL id exists already.')]) apphook = cleaned_data.get('application_urls', None) # The field 'application_namespace' is a misnomer. It should be # 'instance_namespace'. instance_namespace = cleaned_data.get('application_namespace', None) application_config = cleaned_data.get('application_configs', None) if apphook: # application_config wins over application_namespace if application_config: # the value of the application config namespace is saved in # the 'usual' namespace field to be backward compatible # with existing apphooks config = apphook_pool.get_apphook(apphook).get_configs().get( pk=int(application_config)) if self._check_unique_namespace_instance(config.namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_configs'] = ErrorList([ _('An application instance using this configuration already exists.' ) ]) else: self.cleaned_data[ 'application_namespace'] = config.namespace else: if instance_namespace: if self._check_unique_namespace_instance( instance_namespace): self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.' ) ]) else: # The attribute on the apps 'app_name' is a misnomer, it should be # 'application_namespace'. application_namespace = apphook_pool.get_apphook( apphook).app_name if application_namespace and not instance_namespace: if self._check_unique_namespace_instance( application_namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.' ) ]) else: # OK, there are zero instances of THIS app that use the # default instance namespace, so, since the user didn't # provide one, we'll use the default. NOTE: The following # line is really setting the "instance namespace" of the # new app to the app’s "application namespace", which is # the default instance namespace. self.cleaned_data[ 'application_namespace'] = application_namespace if instance_namespace and not apphook: self.cleaned_data['application_namespace'] = None if application_config and not apphook: self.cleaned_data['application_configs'] = None return self.cleaned_data
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check global permissions if CMS_PERMISSIONS is active if get_cms_setting('PERMISSION'): has_global_current_page_change_permission = has_page_permission( self.request.user, self.request.current_page, 'change' ) else: has_global_current_page_change_permission = False # check if user has page edit permission has_change_permission = self.request.current_page.has_change_permission(self.request.user) can_change = (self.request.current_page and has_change_permission) if has_global_current_page_change_permission or can_change: try: not_edit_mode = not self.toolbar.edit_mode except AttributeError: not_edit_mode = not self.toolbar.edit_mode_active tags_menu = self.toolbar.get_or_create_menu('page') super_item = tags_menu.find_first(Break, identifier=PAGE_MENU_SECOND_BREAK) + 1 tags_menu = tags_menu.get_or_create_menu( 'pagetags', PAGE_TAGS_MENU_TITLE, position=super_item ) position = 0 # Page tags try: page_extension = PageTags.objects.get(extended_object_id=self.page.pk) except PageTags.DoesNotExist: page_extension = None try: if page_extension: url = reverse('admin:djangocms_page_tags_pagetags_change', args=(page_extension.pk,)) else: url = '%s?extended_object=%s' % ( reverse('admin:djangocms_page_tags_pagetags_add'), self.page.pk ) except NoReverseMatch: # pragma: no cover # not in urls pass else: tags_menu.add_modal_item(PAGE_TAGS_ITEM_TITLE, url=url, disabled=not_edit_mode, position=position) # Title tags try: site_id = self.page.node.site_id except AttributeError: # CMS_3_4 site_id = self.page.site_id for title in self.page.title_set.filter( language__in=get_language_list(site_id) ): try: title_extension = TitleTags.objects.get(extended_object_id=title.pk) except TitleTags.DoesNotExist: title_extension = None try: if title_extension: url = reverse('admin:djangocms_page_tags_titletags_change', args=(title_extension.pk,)) else: url = '%s?extended_object=%s' % ( reverse('admin:djangocms_page_tags_titletags_add'), title.pk) except NoReverseMatch: # pragma: no cover # not in urls pass else: position += 1 language = get_language_object(title.language) tags_menu.add_modal_item(language['name'], url=url, disabled=not_edit_mode, position=position)
def change_language_menu(self): language_menu = self.toolbar.get_or_create_menu( LANGUAGE_MENU_IDENTIFIER) add = [] remove = Title.objects.filter(page=self.page).values_list('language', flat=True) languages = get_language_objects(self.current_site.pk) for language in languages: code = language['code'] if not code in remove: add.append(code) if add: language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK) for code in add: language = get_language_object(code, self.current_site.pk) url = "%s?language=%s" % (reverse("admin:cms_page_change", args=[self.page.pk ]), language['code']) language_menu.add_modal_item( _("Add %(language)s Translation") % {'language': language['name']}, url=url) if remove: language_menu.add_break(REMOVE_PAGE_LANGUAGE_BREAK) for code in remove: try: language = get_language_object(code, self.current_site.pk) language_code = language['code'] language_name = language['name'] except LanguageError: language_code = code language_name = code url = "%s?language=%s" % (reverse( "admin:cms_page_delete_translation", args=[self.page.pk]), language_code) language_menu.add_modal_item( _("Delete %(language)s Translation") % {'language': language_name}, url=url, disabled=len(remove) == 1) try: current_lang = get_language_object( get_language_from_request(self.request), self.current_site.pk) except LanguageError: current_lang = None if len(languages) > 1 and current_lang and len(remove) > 1: language_menu.add_break(COPY_PAGE_LANGUAGE_BREAK) for language in languages: if current_lang['code'] == language['code'] or language[ 'code'] in add: continue url = reverse('admin:cms_page_copy_language', args=[self.page.pk]) question = _('Are you sure you want copy all plugins from %s?' ) % language['name'] language_menu.add_ajax_item(_("Copy all plugins from %s") % language['name'], action=url, data={ 'source_language': language['code'], 'target_language': current_lang['code'] }, question=question)
def delete_translation(self, request, object_id, extra_context=None): if 'language' in request.GET: language = request.GET['language'] else: language = get_language_from_request(request) opts = Article._meta titleopts = Title._meta app_label = titleopts.app_label pluginopts = CMSPlugin._meta try: obj = self.get_queryset(request).get(pk=unquote(object_id)) except self.model.DoesNotExist: # Don't raise Http404 just yet, because we haven't checked # permissions yet. We don't want an unauthenticated user to be able # to determine whether a given object exists. obj = None if not self.has_delete_permission(request, obj): return HttpResponseForbidden( force_text( _('You do not have permission to change this article'))) if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) if not len(list(obj.get_languages())) > 1: raise Http404( _('There only exists one translation for this article')) titleobj = get_object_or_404(Title, article__id=object_id, language=language) saved_plugins = CMSPlugin.objects.filter( placeholder__article__id=object_id, language=language) using = router.db_for_read(self.model) kwargs = { 'admin_site': self.admin_site, 'user': request.user, 'using': using } deleted_objects, __, perms_needed = get_deleted_objects([titleobj], titleopts, **kwargs)[:3] to_delete_plugins, __, perms_needed_plugins = get_deleted_objects( saved_plugins, pluginopts, **kwargs)[:3] deleted_objects.append(to_delete_plugins) perms_needed = set(list(perms_needed) + list(perms_needed_plugins)) if request.method == 'POST': if perms_needed: raise PermissionDenied message = _( 'Title and plugins with language %(language)s was deleted') % { 'language': force_text( get_language_object(language)['name']) } self.log_change(request, titleobj, message) messages.info(request, message) titleobj.delete() for p in saved_plugins: p.delete() public = obj.publisher_public if public: public.save() if not self.has_change_permission(request, None): return HttpResponseRedirect(admin_reverse('index')) return HttpResponseRedirect( admin_reverse('cms_articles_article_changelist')) context = { 'title': _('Are you sure?'), 'object_name': force_text(titleopts.verbose_name), 'object': titleobj, 'deleted_objects': deleted_objects, 'perms_lacking': perms_needed, 'opts': opts, 'root_path': admin_reverse('index'), 'app_label': app_label, } context.update(extra_context or {}) request.current_app = self.admin_site.name return render( request, self.delete_confirmation_template or [ 'admin/%s/%s/delete_confirmation.html' % (app_label, titleopts.object_name.lower()), 'admin/%s/delete_confirmation.html' % app_label, 'admin/delete_confirmation.html' ], context)
def clean(self): cleaned_data = super(AdvancedSettingsForm, self).clean() if self._errors: # Fail fast if there's errors in the form return cleaned_data # Language has been validated already # so we know it exists. language_name = get_language_object( self._language, site_id=self._site.pk, )['name'] if not self.title_obj.slug: # This covers all cases where users try to edit # page advanced settings without setting a title slug # for page titles that already exist. message = _("Please set the %(language)s slug " "before editing its advanced settings.") raise ValidationError(message % {'language': language_name}) if 'reverse_id' in self.fields: reverse_id = cleaned_data['reverse_id'] if reverse_id: lookup = Page.objects.drafts().on_site( self._site).filter(reverse_id=reverse_id) if lookup.exclude(pk=self.instance.pk).exists(): self._errors['reverse_id'] = self.error_class( [_('A page with this reverse URL id exists already.')]) apphook = cleaned_data.get('application_urls', None) # The field 'application_namespace' is a misnomer. It should be # 'instance_namespace'. instance_namespace = cleaned_data.get('application_namespace', None) application_config = cleaned_data.get('application_configs', None) if apphook: apphooks_with_config = self.get_apphooks_with_config() # application_config wins over application_namespace if apphook in apphooks_with_config and application_config: # the value of the application config namespace is saved in # the 'usual' namespace field to be backward compatible # with existing apphooks try: appconfig_pk = forms.IntegerField( required=True).to_python(application_config) except ValidationError: self._errors['application_configs'] = ErrorList( [_('Invalid application config value')]) return self.cleaned_data try: config = apphooks_with_config[apphook].get_configs().get( pk=appconfig_pk) except ObjectDoesNotExist: self._errors['application_configs'] = ErrorList( [_('Invalid application config value')]) return self.cleaned_data if self._check_unique_namespace_instance(config.namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_configs'] = ErrorList([ _('An application instance using this configuration already exists.' ) ]) else: self.cleaned_data[ 'application_namespace'] = config.namespace else: if instance_namespace: if self._check_unique_namespace_instance( instance_namespace): self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.' ) ]) else: # The attribute on the apps 'app_name' is a misnomer, it should be # 'application_namespace'. application_namespace = apphook_pool.get_apphook( apphook).app_name if application_namespace and not instance_namespace: if self._check_unique_namespace_instance( application_namespace): # Looks like there's already one with the default instance # namespace defined. self._errors['application_namespace'] = ErrorList([ _('An application instance with this name already exists.' ) ]) else: # OK, there are zero instances of THIS app that use the # default instance namespace, so, since the user didn't # provide one, we'll use the default. NOTE: The following # line is really setting the "instance namespace" of the # new app to the app’s "application namespace", which is # the default instance namespace. self.cleaned_data[ 'application_namespace'] = application_namespace if instance_namespace and not apphook: self.cleaned_data['application_namespace'] = None if application_config and not apphook: self.cleaned_data['application_configs'] = None return self.cleaned_data
def populate(self): # always use draft if we have a page self.page = get_page_draft(self.request.current_page) if not self.page: # Nothing to do return # check global permissions if CMS_PERMISSIONS is active if get_cms_setting("PERMISSION"): has_global_current_page_change_permission = has_page_permission( self.request.user, self.request.current_page, "change") else: has_global_current_page_change_permission = False # check if user has page edit permission permission = self.request.current_page.has_change_permission( self.request.user) can_change = self.request.current_page and permission if has_global_current_page_change_permission or can_change: not_edit_mode = not self.toolbar.edit_mode_active current_page_menu = self.toolbar.get_or_create_menu("page") super_item = current_page_menu.find_first( Break, identifier=PAGE_MENU_SECOND_BREAK) if super_item: super_item = super_item + 1 meta_menu = current_page_menu.get_or_create_menu( "pagemeta", PAGE_META_MENU_TITLE, position=super_item) position = 0 # Page tags try: page_extension = PageMeta.objects.get( extended_object_id=self.page.pk) except PageMeta.DoesNotExist: page_extension = None try: if page_extension: url = reverse("admin:djangocms_page_meta_pagemeta_change", args=(page_extension.pk, )) else: url = "{}?extended_object={}".format( reverse("admin:djangocms_page_meta_pagemeta_add"), self.page.pk) except NoReverseMatch: # not in urls pass else: meta_menu.add_modal_item(PAGE_META_ITEM_TITLE, url=url, disabled=not_edit_mode, position=position) # Title tags site_id = self.page.node.site_id titles = self.page.title_set.filter( language__in=get_language_list(site_id)) title_extensions = { t.extended_object_id: t for t in TitleMeta.objects.filter( extended_object_id__in=[title.id for title in titles]) } for title in titles: try: if title.pk in title_extensions: url = reverse( "admin:djangocms_page_meta_titlemeta_change", args=(title_extensions[title.pk].pk, )) else: url = "{}?extended_object={}".format( reverse("admin:djangocms_page_meta_titlemeta_add"), title.pk) except NoReverseMatch: # not in urls pass else: position += 1 language = get_language_object(title.language) meta_menu.add_modal_item(language["name"], url=url, disabled=not_edit_mode, position=position)