diff --git a/wagtail/core/management/commands/create_log_entries_from_revisions.py b/wagtail/core/management/commands/create_log_entries_from_revisions.py index deed9e4c15..126a84e562 100644 --- a/wagtail/core/management/commands/create_log_entries_from_revisions.py +++ b/wagtail/core/management/commands/create_log_entries_from_revisions.py @@ -13,9 +13,13 @@ def get_comparison(page, revision_a, revision_b): class Command(BaseCommand): def handle(self, *args, **options): current_page_id = None + missing_models_content_type_ids = set() for revision in PageRevision.objects.order_by('page_id', 'created_at').select_related('page').iterator(): + # This revision is for a page type that is no longer in the database. Bail out early. + if revision.page.content_type_id in missing_models_content_type_ids: + continue if not revision.page.specific_class: - # This revision is for a page type that is no longer in the database. Bail out early. + missing_models_content_type_ids.add(revision.page.content_type_id) continue is_new_page = revision.page_id != current_page_id @@ -37,7 +41,7 @@ class Command(BaseCommand): if current_revision_as_page.live_revision_id == previous_revision.id: # Log the previous revision publishing. - self.log_action('wagtail.publish', previous_revision, True) + self.log_page_action('wagtail.publish', previous_revision, True) if is_new_page or has_content_changes or published: if is_new_page: @@ -49,13 +53,13 @@ class Command(BaseCommand): if published and has_content_changes: # When publishing, also log the 'draft save', but only if there have been content changes - self.log_action('wagtail.edit', revision, has_content_changes) + self.log_page_action('wagtail.edit', revision, has_content_changes) - self.log_action(action, revision, has_content_changes) + self.log_page_action(action, revision, has_content_changes) previous_revision = revision - def log_action(self, action, revision, has_content_changes): + def log_page_action(self, action, revision, has_content_changes): PageLogEntry.objects.log_action( instance=revision.page.specific, action=action, diff --git a/wagtail/core/tests/test_management_commands.py b/wagtail/core/tests/test_management_commands.py index c39bf06b5f..3b4117b63d 100644 --- a/wagtail/core/tests/test_management_commands.py +++ b/wagtail/core/tests/test_management_commands.py @@ -1,5 +1,6 @@ from datetime import timedelta from io import StringIO +from unittest import mock from django.contrib.auth import get_user_model from django.core import management @@ -7,7 +8,7 @@ from django.db import models from django.test import TestCase from django.utils import timezone -from wagtail.core.models import Page, PageRevision +from wagtail.core.models import Page, PageLogEntry, PageRevision from wagtail.core.signals import page_published, page_unpublished from wagtail.tests.testapp.models import EventPage, SimplePage @@ -420,3 +421,47 @@ class TestPurgeRevisionsCommand(TestCase): # revision is now older than 30 days, so should be deleted self.assertNotIn(old_revision, PageRevision.objects.filter(page=self.page)) + + +class TestCreateLogEntriesFromRevisionsCommand(TestCase): + fixtures = ['test.json'] + + def setUp(self): + self.page = SimplePage( + title="Hello world!", + slug="hello-world", + content="hello", + live=False, + expire_at=timezone.now() - timedelta(days=1), + ) + + Page.objects.get(id=2).add_child(instance=self.page) + + # Create empty revisions, which should not be converted to log entries + for i in range(3): + self.page.save_revision() + + # Add another revision with a content change + self.page.title = "Hello world!!" + revision = self.page.save_revision() + revision.publish() + + # clean up log entries + PageLogEntry.objects.all().delete() + + def test_log_entries_created_from_revisions(self): + management.call_command('create_log_entries_from_revisions') + + # Should not create entries for empty revisions. + self.assertListEqual( + list(PageLogEntry.objects.values_list("action", flat=True)), + ['wagtail.publish', 'wagtail.edit', 'wagtail.create'] + ) + + def test_command_doesnt_crash_for_revisions_without_page_model(self): + with mock.patch( + 'wagtail.core.models.ContentType.model_class', + return_value=None, + ): + management.call_command('create_log_entries_from_revisions') + self.assertEqual(PageLogEntry.objects.count(), 0)