Repository: django-cms/django-cms

Issue:
Saving a PageExtension does not mark the page as dirty
Looks like a regression caused by cf0af3d9

It appears that despite the comment on [this line of extensions/models.py](https://github.com/divio/django-cms/blob/develop/cms/extensions/models.py#L47), the page is not actually marked dirty as `self.is_new_dirty()` in `Page.save_base()` is `False`.   



Discussion:

Resolving patch:
diff --git a/cms/extensions/models.py b/cms/extensions/models.py
--- a/cms/extensions/models.py
+++ b/cms/extensions/models.py
@@ -1,3 +1,4 @@
+from cms.constants import PUBLISHER_STATE_DIRTY
 from django.db import models
 
 from cms.models import Page, Title
@@ -42,16 +43,6 @@ def copy_to_public(self, public_object, language):
 
         return this
 
-    def save(self, *args, **kwargs):
-        if kwargs.pop('mark_page', True):
-            self.get_page().save(no_signals=True)  # mark page unpublished
-        return super(BaseExtension, self).save(*args, **kwargs)
-
-    def delete(self, *args, **kwargs):
-        if kwargs.pop('mark_page', True):
-            self.get_page().save(no_signals=True)  # mark page unpublished
-        return super(BaseExtension, self).delete(*args, **kwargs)
-
 
 class PageExtension(BaseExtension):
     extended_object = models.OneToOneField(Page, editable=False)
@@ -62,6 +53,16 @@ class Meta:
     def get_page(self):
         return self.extended_object
 
+    def save(self, *args, **kwargs):
+        if kwargs.pop('mark_page', True):
+            self.get_page().title_set.update(publisher_state=PUBLISHER_STATE_DIRTY)  # mark page dirty
+        return super(BaseExtension, self).save(*args, **kwargs)
+
+    def delete(self, *args, **kwargs):
+        if kwargs.pop('mark_page', True):
+            self.get_page().title_set.update(publisher_state=PUBLISHER_STATE_DIRTY)  # mark page dirty
+        return super(BaseExtension, self).delete(*args, **kwargs)
+
 
 class TitleExtension(BaseExtension):
     extended_object = models.OneToOneField(Title, editable=False)
@@ -72,5 +73,17 @@ class Meta:
     def get_page(self):
         return self.extended_object.page
 
+    def save(self, *args, **kwargs):
+        if kwargs.pop('mark_page', True):
+            Title.objects.filter(pk=self.extended_object.pk).update(
+                publisher_state=PUBLISHER_STATE_DIRTY) # mark title dirty
+        return super(BaseExtension, self).save(*args, **kwargs)
+
+    def delete(self, *args, **kwargs):
+        if kwargs.pop('mark_page', True):
+            Title.objects.filter(pk=self.extended_object.pk).update(
+                publisher_state=PUBLISHER_STATE_DIRTY) # mark title dirty
+        return super(BaseExtension, self).delete(*args, **kwargs)
+
 
 
diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py
--- a/cms/models/pagemodel.py
+++ b/cms/models/pagemodel.py
@@ -458,11 +458,11 @@ def is_published(self, language, force_reload=False):
         except Title.DoesNotExist:
             return False
 
-    def get_publisher_state(self, language):
+    def get_publisher_state(self, language, force_reload=False):
         from cms.models import Title
 
         try:
-            return self.get_title_obj(language, False).publisher_state
+            return self.get_title_obj(language, False, force_reload=force_reload).publisher_state
         except Title.DoesNotExist:
             return None
 


Test patch:
diff --git a/cms/tests/extensions.py b/cms/tests/extensions.py
--- a/cms/tests/extensions.py
+++ b/cms/tests/extensions.py
@@ -1,4 +1,5 @@
 from cms.api import create_page
+from cms.constants import PUBLISHER_STATE_DIRTY
 from cms.models import Page
 from cms.test_utils.project.extensionapp.models import MyPageExtension, MyTitleExtension
 from cms.test_utils.testcases import SettingsOverrideTestCase as TestCase
@@ -88,17 +89,19 @@ def test_publish_page_extension(self):
         # publish first time
         page.publish('en')
         self.assertEqual(page_extension.extra, page.publisher_public.mypageextension.extra)
-
+        self.assertEqual(page.get_publisher_state('en'), 0)
         # change and publish again
         page = Page.objects.get(pk=page.pk)
         page_extension = page.mypageextension
         page_extension.extra = 'page extension 1 - changed'
         page_extension.save()
+        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)
         page.publish('en')
-
+        self.assertEqual(page.get_publisher_state('en', True), 0)
         # delete
         page_extension.delete()
         self.assertFalse(MyPageExtension.objects.filter(pk=page_extension.pk).exists())
+        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)
 
     def test_publish_title_extension(self):
         page = create_page('Test Title Extension', "nav_playground.html", "en")
@@ -110,6 +113,7 @@ def test_publish_title_extension(self):
         # publish first time
         page.publish('en')
         # import ipdb; ipdb.set_trace()
+        self.assertEqual(page.get_publisher_state('en'), 0)
         self.assertEqual(title_extension.extra_title, page.publisher_public.get_title_obj().mytitleextension.extra_title)
 
         # change and publish again
@@ -118,7 +122,9 @@ def test_publish_title_extension(self):
         title_extension = title.mytitleextension
         title_extension.extra_title = 'title extension 1 - changed'
         title_extension.save()
+        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)
         page.publish('en')
+        self.assertEqual(page.get_publisher_state('en', True), 0)
 
         # delete
         title_extension.delete()