Template change permissions

Can you somehow prevent users from changing a specific template to another one using permissions or a hook?

So a permission like that: (pseudo code)

'panel.page.update' => function() {
  
  if ($this->old()->page()->intendedTemplate() == "text" AND $this->target()->page()->intendedTemplate() == "images") {
    return false;
  }
  else {
    return false;
  }
  
}

Or a hook like that:

kirby()->hook('panel.page.update', function($page, $oldPage) {
  if ($oldPage->intendedTemplate() == "text" AND $page->intendedTemplate == "images") {
    // Do something.
  }
});

It seems like there is no way to check what the old value was, neither with permissions nor with a hook. Or am I missing something?

The hook knows the old page object, but a hook won’t work because hooks are only triggered AFTER an event has happened, so the only thing you could do via a hook is change the template back to the original again, but by then it might be too late.

As regards permissions, I doubt that this is possible, because there is not old page object.

Your best bet is probably to change your content structure in a way as to only allow certain templates via the parent page.

Thanks for your quick answer!

Are you sure the hook has access to the old page object before the update? For me $oldPage->template() and $page->template() return the exact same thing. There is an $oldPage argument in the docs for panel.page.update after all. But it only seems to work with panel.page.move for me.

I don’t think it would be “too late” to change the template back again as the content stays the same.

Unless there is some sort of bug (need to check that), the old page object is available since 2.3.2.

Edit: Well, the hook works as expected for content changes, but it seems that the template or intended template is not taken into account, even though the hook is triggered.

Edit2: Maybe we should create a feature request on GitHub for both storing all page data in the old page object as well as for more specific permissions.

As a workaround, I just had the idea to save the template name in a hidden field in the text file and then compare the template name against the field value on panel.page.update.

Thank you for checking! That indeed seems like the best workaround.

I will add an issue on GitHub, anyway. I think the $oldPage should contain all the information $page contains.