processwire-issues
processwire-issues copied to clipboard
Hooks on unpublished and off-status repeater items are executed when saving the repeater field and noHooks is true
Assume the following code:
// init.php
wire()->addHookAfter('Pages::saved', function(HookEvent $event) {
$page = $event->arguments('page');
if($page->template->name!='repeater_order_line_items') return;
echo "running the hook!";
});
// elsewhere in my codebase
$order = $pages->get(1234);
// unpublish the repeater items
foreach($order->order_line_items as $order_line_item) {
$order_line_item->addStatus(Page::statusUnpublished);
$order_line_item->removeStatus(Page::statusOn);
$order_line_item->save(['noHooks'=>true]);
}
// now let's save the overall order_line_items field and make sure to prevent hooks
// remember, using noHooks=>true on the save method of a page is technically not the "correct" way to do it
// but it doesn't matter; either of these will still make the hooks fire when they shouldn't!
// https://github.com/processwire/processwire-issues/issues/1405#issuecomment-3152818716
// doesn't matter which one you use... the hooks still fire since the pages were unpublished and status turned off
$order->save('order_line_items', ['noHooks'=>true,'quiet'=>true]);
wire('pages')->___saveField($order, 'order_line_items', ['noHooks'=>true,'quiet'=>true]);
So as you can see above, in that scenario, the hooks will fire when they shouldn't. This drove me nuts.
Related to #1405
@jlahijani The noHooks option refers to the page being saved, $order in your example. Individual repeater pages are separate pages where the save is initiated by FieldtypeRepeater, which does not use a noHooks option. Your $order_line_item->save(['noHooks' => true ]); shouldn't call hooks. But the following $order->save() or $page->saveField() should still trigger your Pages::saved hook if FieldtypeRepeater is saving any repeater items.