Repository: django-cms/djangocms-alias (language: python)

Issue:
djangocms-versioning draft deletion causes plugins to disappear from pages
When I use djangocms-alias with djangocms-versioning and I delete a draft of an alias, the alias does not get reset to the previous version on the pages using it. Instead, it gets removed entirely from all pages.

Steps to reproduce:
1. Create a Page and publish it
2. Create a Content Alias on that page and publish it
3. Create a new draft for the Content Alias
4. Delete the draft

I think the problem is rooted in this [line](https://github.com/django-cms/djangocms-alias/blob/master/djangocms_alias/models.py#L308) in `models.AliasContent.delete`. From the code, it looks like this is wanted behavior because it deliberately deletes all plugins using the deleted Alias Content. Hence I am not sure how to fix it (just removing it works for me).

I use django-cms 4.1, and I was able to reproduces this behavior in all djangocms-alias versions I tried, including the latest master.


Discussion / hints:
Just to clarify: how do you delete the draft alias?
@fsbraun: i went to the preview of the alias, clicked on "Versions" in the top-bar, and clicked on the trash icon of the draft in the table of listed versions
From the code I fear the plugins are even deleted if there are alias contents available in other languages. To me it only makes sense to delete thos plugins if the whole Alias is deleted.
Hm, I think this is a serious bug. It would also imply that an alias plugin is removed from a published page. I can only assume that the following happened:

* Someone deleted the last `AliasContent` of an alias.
* Viewed the page where the alias used, triggering an automatic creation of a new draft
* Got a bad user experience, since the just deleted draft magically reappeared. 

One solution for me would be to remove the mechanism and to add a warning message (using the message framework) which would trigger if the last alias content of a language was deleted.

@fscherf Would you be interested to create a pull request?
@fsbraun: Yes! Alias plugins are disappearing from published pages definitely.

Ok. That would mean, the deletion of an AliasContent object wouldn't trigger the deletion of cms plugins anymore. What do we do with orphaned cms plugins that point to no longer existing AliasContents then?

Yes, I would be interested in opening a pull-request, once we decided on how to fix this issue.
They'll point to an `Alias` object (which is still there). Upon rendering the alias plugins with no `AliasContent` for the selected language, they should be treated as empty.

Deleting `Alias` objects should automatically trigger a cascade to either also delete the alias plugins (if possible) or deny deleting the alias.

For now, I would be fine with the warning through the message framework. In the alias's admin delete view:
```
    if <last content object of language deleted>:
        message = _('Draft deleted. A new empty draft will be created automatically if needed.')  # Or something better
        self.message_user(request, message, level=messages.WARNING)
```

Fix patch:
diff --git a/djangocms_alias/admin.py b/djangocms_alias/admin.py
index d28e415..daac102 100644
--- a/djangocms_alias/admin.py
+++ b/djangocms_alias/admin.py
@@ -1,6 +1,6 @@
 from cms.utils.permissions import get_model_permission_codename
 from cms.utils.urlutils import admin_reverse
-from django.contrib import admin
+from django.contrib import admin, messages
 from django.db.models.functions import Lower
 from django.template.loader import render_to_string
 from django.utils.translation import gettext_lazy as _
@@ -168,6 +168,17 @@ def delete_model(self, request, obj):
         if not is_versioning_enabled():
             emit_content_delete([obj], sender=self.model)
 
+        if obj.alias._default_manager.filter(language=obj.language).count() == 1:
+            message = _(
+                "Alias content for language {} deleted. A new empty alias content will be created if needed."
+            ).format(obj.language)
+            self.message_user(request, message, level=messages.WARNING)
+
+        return super().delete_model(
+            request=request,
+            obj=obj,
+        )
+
     def get_list_actions(self):
         """
         Collect rendered actions from implemented methods and return as list
diff --git a/djangocms_alias/models.py b/djangocms_alias/models.py
index d63099e..f027b70 100644
--- a/djangocms_alias/models.py
+++ b/djangocms_alias/models.py
@@ -305,11 +305,6 @@ def get_absolute_url(self):
     def get_template(self):
         return "djangocms_alias/alias_content.html"
 
-    @transaction.atomic
-    def delete(self, *args, **kwargs):
-        super().delete(*args, **kwargs)
-        self.alias.cms_plugins.filter(language=self.language).delete()
-
     @transaction.atomic
     def populate(self, replaced_placeholder=None, replaced_plugin=None, plugins=None):
         if not replaced_placeholder and not replaced_plugin:


Test patch:
diff --git a/tests/requirements/django_42.txt b/tests/requirements/django_42.txt
index e268f69..778ac26 100644
--- a/tests/requirements/django_42.txt
+++ b/tests/requirements/django_42.txt
@@ -7,4 +7,4 @@ django-sekizai
 django-parler
 
 https://github.com/django-cms/django-cms/tarball/release/4.0.1.x#egg=django-cms
-https://github.com/joshyu/djangocms-versioning/tarball/feat/django-42-compatible#egg=djangocms-versioning
\ No newline at end of file
+https://github.com/django-cms/djangocms-versioning/tarball/support/django-cms-4.0.x#egg=djangocms-versioning