MarkE Posted November 27, 2022 Share Posted November 27, 2022 I have been trying to add some hooks to prevent pages from being moved in certain circumstances. It seems (to me) that this is not entirely straightforward. First off, just a simple hook before the page save does not always work. In my use case, the 'circumstances' are when the page path is in some given array. In hooking before page save, the page path is the new page path after the move, rather than before it, so I need to do something like this: // .... In the before page:saveReady hook // $page is the page :) The code below operates when (isset($page->parentPrevious) && $object->parentPrevious != $object->parent) $name = $page->parentPrevious->path . $page->name . '/'; // need the path before it was moved // Because this hook operates after the move, we need to reverse the move if(in_array($name, $blockedNames)) { // $blockedNames are the ones where we don't want moves $page->parent = $page->parentPrevious; $page->of(false); $this->wire()->session->set('bypassSaveHook', true); // to prevent loops $page->save(); $this->wire()->session->remove('bypassSaveHook'); } //... rest of hook This prevents the page being moved, both in the page hierarchy (by dragging) or in the page editor by changing the parent in the settings tab. I also tried hooking before Page:moveable with something like this /** @var Page $page */ $page = $event->object; $moveable = $event->return; // ... code to set $moveable to false if conditions met $event->return = $moveable; Interestingly, the (not documented?) moveable method is created as a hook by PagePermissions and so is hookable. However, this appears to catch only the situation where the move is effected by dragging the page in the tree, not when the parent is changed in the settings. If anyone knows of any smarter way of doing this stuff, I would be interested, otherwise maybe this could be moved to a tutorial? 1 Link to comment Share on other sites More sharing options...
gebeer Posted November 28, 2022 Share Posted November 28, 2022 Thanks for sharing this. Looking at the implementation of parentPrevious inside wire/core/Page.php I thnk your solution is perfectly viable and the parentPrevious property was implemented so we can use it in circumstances like these. At which point in your logic are you using the bypassSaveHook session variable to prevent loops, is it inside a different hook to Pages::save? And since you are inside a Pages::saveReady hook, I think you do not need to set $page->of(false) because output formatting is already turned off at that stage. Also you do not need to do $page->save() because this is happening after the hook was executed and the page is saved with the values that you assigned inside the saveReady hook. So the loop most likely is being caused by the redundant $page->save(). Try removing that line and see if you need the bypassSaveHook session variable at all. 1 Link to comment Share on other sites More sharing options...
MarkE Posted November 28, 2022 Author Share Posted November 28, 2022 7 hours ago, gebeer said: At which point in your logic are you using the bypassSaveHook session variable to prevent loops, is it inside a different hook to Pages::save? And since you are inside a Pages::saveReady hook, I think you do not need to set $page->of(false) because output formatting is already turned off at that stage. Also you do not need to do $page->save() because this is happening after the hook was executed Thanks @gebeer. In reality it's not quite as simple as that because my code is inside a method that is called by six different hooks, rather than in a single hook. However, passing the object argument to that method by reference, rather than by value, means that I can then avoid the unnecessary saves, as you suggest. I'll post an amended version in the tutorials thread. 1 Link to comment Share on other sites More sharing options...
MarkE Posted June 21 Author Share Posted June 21 An alternative approach here is to use an idea from @Robin S here to prevent access to the settings tab thus preventing changing the parent there, then the hook on Page::moveable covers the interaction in the page tree, in which case no need for the slightly complex first hook in my OP. Link to comment Share on other sites More sharing options...
da² Posted June 22 Share Posted June 22 On 11/28/2022 at 12:59 AM, MarkE said: this appears to catch only the situation where the move is effected by dragging the page in the tree, not when the parent is changed in the settings Maybe open a bug report for this, that looks like this is not intended. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now