diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f4f611a402..6c622b9635 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,6 +5,7 @@ Changelog ~~~~~~~~~~~~~~~~ * `get_context` methods on StreamField blocks can now access variables from the parent context (Mikael Svensson, Peter Baumgartner) + * Added `before_copy_page` and `after_copy_page` hooks (Matheus Bratfisch) * View live / draft links in the admin now consistently open in a new window (Marco Fucci) * `ChoiceBlock` now omits the blank option if the block is required and has a default value (Andreas Nüßlein) * Fix: Help text for StreamField is now visible and does not cover block controls (Stein Strindhaug) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 895b5b2326..cdc9177f88 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -204,6 +204,7 @@ Contributors * glassresistor * Mikael Svensson * Peter Baumgartner +* Matheus Bratfisch Translators =========== diff --git a/docs/reference/hooks.rst b/docs/reference/hooks.rst index 05534eab00..97772c8aa0 100644 --- a/docs/reference/hooks.rst +++ b/docs/reference/hooks.rst @@ -453,6 +453,24 @@ Hooks for customising the way users are directed through the process of creating Uses the same behavior as ``before_create_page``. +.. _after_copy_page: + +``after_copy_page`` +~~~~~~~~~~~~~~~~~~~ + + Do something with a ``Page`` object after it has been copied pasing in the request, page object and the new copied page. Uses the same behavior as ``after_create_page``. + + +.. _before_copy_page: + +``before_copy_page`` +~~~~~~~~~~~~~~~~~~~~~ + + Called at the beginning of the "copy page" view passing in the request and the page object. + + Uses the same behavior as ``before_create_page``. + + .. _construct_wagtail_userbar: ``construct_wagtail_userbar`` diff --git a/docs/releases/1.9.rst b/docs/releases/1.9.rst index aca660fc07..72e21b06d0 100644 --- a/docs/releases/1.9.rst +++ b/docs/releases/1.9.rst @@ -19,6 +19,7 @@ The ``get_context`` method on StreamField blocks now receives a ``parent_context Other features ~~~~~~~~~~~~~~ + * Added :ref:`before_copy_page` and :ref:`after_copy_page` hooks (Matheus Bratfisch) * View live / draft links in the admin now consistently open in a new window (Marco Fucci) * ``ChoiceBlock`` now omits the blank option if the block is required and has a default value (Andreas Nüßlein) diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index 3e395bf35e..b3ff6acf51 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -2300,6 +2300,62 @@ class TestPageCopy(TestCase, WagtailTestUtils): # treebeard should report no consistency problems with the tree self.assertFalse(any(Page.find_problems()), 'treebeard found consistency problems') + def test_before_copy_page_hook(self): + def hook_func(request, page): + self.assertIsInstance(request, HttpRequest) + self.assertIsInstance(page.specific, SimplePage) + + return HttpResponse("Overridden!") + + with self.register_hook('before_copy_page', hook_func): + response = self.client.get(reverse('wagtailadmin_pages:copy', args=(self.test_page.id,))) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, b"Overridden!") + + def test_before_copy_page_hook_post(self): + def hook_func(request, page): + self.assertIsInstance(request, HttpRequest) + self.assertIsInstance(page.specific, SimplePage) + + return HttpResponse("Overridden!") + + with self.register_hook('before_copy_page', hook_func): + post_data = { + 'new_title': "Hello world 2", + 'new_slug': 'hello-world-2', + 'new_parent_page': str(self.root_page.id), + 'copy_subpages': False, + 'publish_copies': False, + } + response = self.client.post(reverse('wagtailadmin_pages:copy', args=(self.test_page.id,)), post_data) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, b"Overridden!") + + def test_after_copy_page_hook(self): + def hook_func(request, page, new_page): + self.assertIsInstance(request, HttpRequest) + self.assertIsInstance(page.specific, SimplePage) + self.assertIsInstance(new_page.specific, SimplePage) + + return HttpResponse("Overridden!") + + with self.register_hook('after_copy_page', hook_func): + post_data = { + 'new_title': "Hello world 2", + 'new_slug': 'hello-world-2', + 'new_parent_page': str(self.root_page.id), + 'copy_subpages': False, + 'publish_copies': False, + } + response = self.client.post(reverse('wagtailadmin_pages:copy', args=(self.test_page.id,)), post_data) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, b"Overridden!") + + + class TestPageUnpublish(TestCase, WagtailTestUtils): def setUp(self): diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index f44a09c5fa..9f0ff21c12 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -809,6 +809,11 @@ def copy(request, page_id): next_url = get_valid_next_url_from_request(request) + for fn in hooks.get_hooks('before_copy_page'): + result = fn(request, page) + if hasattr(result, 'status_code'): + return result + # Check if user is submitting if request.method == 'POST': # Prefill parent_page in case the form is invalid (as prepopulated value for the form field, @@ -848,6 +853,11 @@ def copy(request, page_id): else: messages.success(request, _("Page '{0}' copied.").format(page.get_admin_display_title())) + for fn in hooks.get_hooks('after_copy_page'): + result = fn(request, page, new_page) + if hasattr(result, 'status_code'): + return result + # Redirect to explore of parent page if next_url: return redirect(next_url)