diff --git a/.gitignore b/.gitignore index 55a062bc..76e29a7c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .idea/ .tox/ .eggs/ +.vscode/ dist/ !djangocms_alias/static/djangocms_alias/js/dist/ build/ diff --git a/djangocms_alias/cms_plugins.py b/djangocms_alias/cms_plugins.py index 4bc764a2..630903b2 100644 --- a/djangocms_alias/cms_plugins.py +++ b/djangocms_alias/cms_plugins.py @@ -1,5 +1,3 @@ -from copy import copy - from cms.plugin_base import CMSPluginBase, PluginMenuItem from cms.plugin_pool import plugin_pool from cms.toolbar.utils import get_object_edit_url @@ -140,26 +138,24 @@ def can_detach(cls, user, target_placeholder, plugins): @classmethod def detach_alias_plugin(cls, plugin, language): - source_placeholder = plugin.alias.get_placeholder(language, show_draft_content=True) # We're in edit mode + source_plugins = plugin.alias.get_plugins(language, show_draft_content=True) # We're in edit mode target_placeholder = plugin.placeholder + plugin_position = plugin.position + plugin_parent = plugin.parent + target_placeholder.delete_plugin(plugin) + if source_plugins: + if target_last_plugin := target_placeholder.get_last_plugin(plugin.language): + target_placeholder._shift_plugin_positions( + language, + start=plugin_position, + offset=len(source_plugins) + target_last_plugin.position + 1, # enough space to shift back + ) - # Deleting uses a copy of a plugin to preserve pk on existing - # ``plugin`` object. This is done due to - # plugin.get_plugin_toolbar_info requiring a PK in a passed - # instance. - target_placeholder.delete_plugin(copy(plugin)) - target_placeholder._shift_plugin_positions( - language, - plugin.position, - offset=target_placeholder.get_last_plugin_position(language), - ) - if source_placeholder: - source_plugins = source_placeholder.get_plugins_list() - copied_plugins = copy_plugins_to_placeholder( + return copy_plugins_to_placeholder( source_plugins, placeholder=target_placeholder, language=language, - start_positions={language: plugin.position}, + root_plugin=plugin_parent, + start_positions={language: plugin_position}, ) - return copied_plugins return [] diff --git a/djangocms_alias/models.py b/djangocms_alias/models.py index 3c99cdec..6a7f172c 100644 --- a/djangocms_alias/models.py +++ b/djangocms_alias/models.py @@ -193,16 +193,17 @@ def get_placeholder(self, language=None, show_draft_content=False): content = self.get_content(language=language, show_draft_content=show_draft_content) return getattr(content, "placeholder", None) - def get_plugins(self, language=None): + def get_plugins(self, language=None, show_draft_content=False): if not language: language = get_language() + cache_key = f"{language}-{show_draft_content}" try: - return self._plugins_cache[language] + return self._plugins_cache[cache_key] except KeyError: - placeholder = self.get_placeholder(language) + placeholder = self.get_placeholder(language, show_draft_content=show_draft_content) plugins = placeholder.get_plugins_list() if placeholder else [] - self._plugins_cache[language] = plugins - return self._plugins_cache[language] + self._plugins_cache[cache_key] = plugins + return self._plugins_cache[cache_key] def get_languages(self): if not self._content_languages_cache: @@ -307,25 +308,27 @@ def populate(self, replaced_placeholder=None, replaced_plugin=None, plugins=None placeholder=self.placeholder, ) return - if replaced_placeholder: - plugins = replaced_placeholder.get_plugins(self.language) - placeholder = replaced_placeholder - add_plugin_kwargs = {} - else: - plugins = CMSPlugin.objects.filter( - id__in=[replaced_plugin.pk] + replaced_plugin._get_descendants_ids(), + replaced_placeholder.cmsplugin_set.update(placeholder=self.placeholder) + return add_plugin( + replaced_placeholder, + plugin_type="Alias", + language=self.language, + alias=self.alias, ) - placeholder = replaced_plugin.placeholder - add_plugin_kwargs = {"position": "left", "target": replaced_plugin} + + placeholder = replaced_plugin.placeholder + plugins = CMSPlugin.objects.filter( + id__in=[replaced_plugin.pk] + replaced_plugin._get_descendants_ids(), + ) + add_plugin_kwargs = {"position": "left", "target": replaced_plugin} copy_plugins_to_placeholder( plugins, placeholder=self.placeholder, language=self.language, ) - plugins.delete() - placeholder._recalculate_plugin_positions(self.language) + replaced_plugin.delete() new_plugin = add_plugin( placeholder, @@ -334,9 +337,6 @@ def populate(self, replaced_placeholder=None, replaced_plugin=None, plugins=None alias=self.alias, **add_plugin_kwargs, ) - if replaced_plugin: - new_plugin.position = replaced_plugin.position - new_plugin.save(update_fields=["position"]) return new_plugin diff --git a/djangocms_alias/views.py b/djangocms_alias/views.py index 1ade7d2f..a12aa818 100644 --- a/djangocms_alias/views.py +++ b/djangocms_alias/views.py @@ -136,6 +136,8 @@ def create_alias_view(request): "Plugins are required to create an alias", ) + plugin = create_form.cleaned_data.get("plugin") + plugin_pk = plugin.pk if plugin else None replace = create_form.cleaned_data.get("replace") if not Alias.can_create_alias(user, plugins, replace): raise PermissionDenied @@ -144,8 +146,9 @@ def create_alias_view(request): emit_content_change([alias_content]) if replace: - plugin = create_form.cleaned_data.get("plugin") placeholder = create_form.cleaned_data.get("placeholder") + if plugin is not None: + plugin.pk = plugin_pk # Restore pk after it was set to None in form.save() return render_replace_response( request, new_plugins=[alias_plugin],