Jump to content

Preventing Hook Loop


ZGD
 Share

Recommended Posts

I'm creating a simple module for hooks, but have run into a small problem.

The hook is basically to keep two fields in sync. I have two templates "template1" and "template2" each with a Page Field that references the other. So a page using "template1" has a Page Field that contains multiple pages using "template2", and a page using "template2" has a Page Field that contains multiple pages using "template1".

I'm hooking Pages::saveReady to detect any pages added/removed from the Page Field on either of these templates, and then adding/removing the relevant pages from the other's Page Field. However as each hook saves other pages before it saves itself, I assume this will create some kind of loop? The actual code is more complex, but I've tried to give some example code below:
 

public function init() {
    $this->addHookBefore('Pages::saveReady', $this, 'save');
}

public function save($event) {

    $page = $event->arguments[0];

    if ($page->template->name == "template1" || $page->template->name == "template2") {
        $clone = clone($page);
        $this->pages->uncache($clone);
        $prev = $this->pages->get($clone->id);

        $prev_related = $prev->related_pages;
        $page_related = $page->related_pages;

        $deleted_ids = array_diff($prev_related->explode('id'), $page_related->explode('id'));
        $added_ids = array_diff($page_related->explode('id'), $prev_related->explode('id'));

        $pagesToSave = new PageArray();

        foreach($added_ids as $added_id) {
            $added = $this->pages->get($added_id);
            if (!$added->relatedPageField->has($page)) {
                $added->relatedPageField->add($page);
                $pagesToSave->add($added);
            }
        }

        foreach ($deleted_ids as $deleted_id) {
            $removed = $this->pages->get($deleted_id);
            if ($removed->relatedPageField->has($page)) {
                $removed->relatedPageField->remove($page);
                $pagesToSave->add($removed);
            }
        }

        $this->message("saving ".count($pagesToSave)." pages.");
        foreach ($pagesToSave as $pageToSave) {
            $pageToSave->save();
        }

    }
}
Link to comment
Share on other sites

Typically the easiest way to avoid loops with save hooks is to just save the field, rather than the whole page. So, do:

$pageToSave->save('relatedPageField'); // or whatever the name of the field is
  • Like 4
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...