angrybeanie_wagtail/env/lib/python3.12/site-packages/wagtail/actions/move_page.py

108 lines
3.7 KiB
Python
Raw Permalink Normal View History

2025-07-25 21:32:16 +10:00
import logging
from django.core.exceptions import PermissionDenied
from django.db import transaction
from treebeard.mp_tree import MP_MoveHandler
from wagtail.log_actions import log
from wagtail.signals import post_page_move, pre_page_move
logger = logging.getLogger("wagtail")
class MovePagePermissionError(PermissionDenied):
"""
Raised when the page move cannot be performed due to insufficient permissions.
"""
pass
class MovePageAction:
def __init__(self, page, target, pos=None, user=None):
self.page = page
self.target = target
self.pos = pos
self.user = user
def check(self, parent_after, skip_permission_checks=False):
if self.user and not skip_permission_checks:
if not self.page.permissions_for_user(self.user).can_move_to(parent_after):
raise MovePagePermissionError(
"You do not have permission to move the page to the target specified."
)
def _move_page(self, page, target, parent_after):
from wagtail.models import Page
# Determine old and new url_paths
# Fetching new object to avoid affecting `page`
parent_before = page.get_parent()
old_page = Page.objects.get(id=page.id)
old_url_path = old_page.url_path
new_url_path = old_page.set_url_path(parent=parent_after)
url_path_changed = old_url_path != new_url_path
# Emit pre_page_move signal
pre_page_move.send(
sender=page.specific_class or page.__class__,
instance=page,
parent_page_before=parent_before,
parent_page_after=parent_after,
url_path_before=old_url_path,
url_path_after=new_url_path,
)
# Only commit when all descendants are properly updated
with transaction.atomic():
# Allow treebeard to update `path` values
MP_MoveHandler(page, target, self.pos).process()
# Treebeard's move method doesn't actually update the in-memory instance,
# so we need to work with a freshly loaded one now
new_page = Page.objects.get(id=page.id)
new_page.url_path = new_url_path
new_page.save()
# Update descendant paths if url_path has changed
if url_path_changed:
new_page._update_descendant_url_paths(old_url_path, new_url_path)
# Emit post_page_move signal
post_page_move.send(
sender=page.specific_class or page.__class__,
instance=new_page,
parent_page_before=parent_before,
parent_page_after=parent_after,
url_path_before=old_url_path,
url_path_after=new_url_path,
)
# Log
log(
instance=page,
action="wagtail.move" if url_path_changed else "wagtail.reorder",
user=self.user,
data={
"source": {
"id": parent_before.id,
"title": parent_before.specific_deferred.get_admin_display_title(),
},
"destination": {
"id": parent_after.id,
"title": parent_after.specific_deferred.get_admin_display_title(),
},
},
)
logger.info('Page moved: "%s" id=%d path=%s', page.title, page.id, new_url_path)
def execute(self, skip_permission_checks=False):
if self.pos in ("first-child", "last-child", "sorted-child"):
parent_after = self.target
else:
parent_after = self.target.get_parent()
self.check(parent_after, skip_permission_checks=skip_permission_checks)
return self._move_page(self.page, self.target, parent_after)