Jump to content

Run code after page save


Pete
 Share

Recommended Posts

If you add a hook before page save you don't need the last line where you save the page (it'll do that anyway), otherwise it will infinitely loop as you're making it go in circles.

Take out $p->save; and it should be fine.

  • Like 1
Link to comment
Share on other sites

This is little different, since you are creating a new page. My comments below with code:

public function init() {
 // now we want to hook after page save, since we are not manipulating the saved page, but creating/removing others
 $this->pages->addHookAfter('save', $this, 'afterPageSave');
}

public function afterPageSave($event) {
 // $page will keep the page that user has just saved
 $page = $event->arguments[0];

 // you probably want to have some conditions whether or not to do something. If you don't have any conditions here, then you go into a loop.
 if ($page->id == 12345) {
  $p = new Page();
  $p->template = $this->templates->get("basic-page");
  $p->parent = $page;
  $p->title = "New page under the saved page";
  $p->save();
 }

 // Removing of pages, could be in the same if or then some other conditionals. Now we check if field "delete_children" is checked (or has value of 1)
 if ($page->delete_children == 1) {
  foreach($page->children() as $p) {
    $p->delete();
  }
  $this->message("Children removed.");
  $page->delete_children = 0;
  $page->save();
 }
}
  • Like 2
Link to comment
Share on other sites

The recursive loop comes from your $p->save(); which is again triggering your pageSaved() hook, and continues doing so infinitely to a deeper and deeper level.

There's probably a bunch of ways to solve this. But here's two really simple ways. First is to just set some landmark variable (we'll call it skipMe) so that your hook will know to skip over pages that it is creating itself. Your landmark variable (skipMe) doesn't need to be a PW field or anything, as you can make up any name/value on the fly and set it to a $page for temporary use like this.

public function pageSaved($event) {
 $page = $event->arguments[0];
 if($page->skipMe) return;
 $p = new Page();
 $p->template = 'basic-page';
 $p->parent = '/about/';
 $p->status = Page::statusUnpublished;
 $p->title = "This is the pagename";
 // set some landmark so pageSaved knows to skip this one
 $p->skipMe = true; 
 $p->save();
}

The next option would be to just have your $p->save(); skip over all hooks:

$p->___save();

When you call the function name with 3 underscores in front of it, it does so without executing any hooks, thereby preventing the infinite loop. However, this may or may not be what you want, because it would also skip over any other Pages::save hooks that might be present.

  • Like 2
Link to comment
Share on other sites

Thanks guys, awesome replies and a real insight into how the hooks system works. I'll have a tinker with these ideas and see how I go. Love the way you can hook into PW at different stages and do almost anything.

One thing I have struggled with a bit is getting my head around the way the page, pages etc objects work, what they contain and when, but I guess that's just a matter of trying things out. Apeisas commented code above for example was helpful...

// $page will keep the page that user has just saved
 $page = $event->arguments[0];

as I was wondering exactly what $event->arguments[0] was all about! Thanks again guys, the answers on this forum are amazing.

  • Like 1
Link to comment
Share on other sites

The $event->arguments is just an array of arguments that were passed to the function you hooked, in the order they were passed to the function. You can also retrieve them by name if you prefer, i.e. $event->arguments('page') would retrieve the argument named '$page'. In addition to being able to read these arguments, you can also change them if your hook is a "before" hook… letting you modify what ultimately gets sent to the function you are hooking.

There's also $event->object, which is the object instance containing the function you hooked. So in the example from my previous post, $event->object would be $pages. That's probably not very useful, but when dealing with hooked methods on other things (like a Page or a PageArray) it might be exactly what you need.

Lastly want to mention $event->return. If your hook is an "after" hook, then $event->return will contain the value returned from the function you hooked. Like with arguments you can modify this value if you want to.

If you add a hook somewhere, and there isn't any function to hook, then you've just added a new function to that class. When someone tries to call that function, it'll call your hook instead.

There are other things you can do with hooks too, like add properties to an object (rather than just methods) and entirely replace a function with your own. But these are less used things.

  • Like 1
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...