Jump to content

Stop execution of a function via hook


Nico Knoll
 Share

Recommended Posts

Nico, this is something that is technically possible with the way the hook system is designed, but I've not implemented it yet. The idea behind it was that there would be a 'replace' hook, where you can have your own function completely replace the functionality of a core function, so that the core one is never called. I haven't implemented this because it's not so friendly in an environment where there may be multiple modules hooked to a given function. If one module completely takes over a core function, it alters program flow and the behavior that other modules may be expecting. So I've left it out because I think it's a bit too unpredictable, though may still add it in if there's interest. However, you can achieve the same effect by using an 'after' hook and completely replacing the $event->return value with your own. Not as efficient as replacing the execution too, but much more predictable.

Link to comment
Share on other sites

Nico, this has been added in the latest commit of 2.2. To make use of it, have your hooked function (getPage in your case) do this:

$event->replace = true; // now original function won't be called
$event->return = 'you are now providing the return value';

Also your hook obviously must be a 'before' hook in order to replace the original. So you'd init the hook like this:

$this->addHookBefore('ProcessPageView::execute', $this, 'getPage');

Unrelated to the above, but another cool addition: I upgraded the hook system so that it will let you set or get hooked function arguments by name rather than just by position. So if you'd hooked into Pages::save, and you wanted to refer to the 'page' argument, you can now do this:

$page = $event->arguments('page');

Before you could only do this, having to know what position the argument was in:

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

You can also set arguments back to the event by name if you want to, i.e.

$event->arguments('page', $mypage); 
  • Like 1
Link to comment
Share on other sites

But I'm not quite getting the last one. Maybe a little example could make it more clear?

Antti's right about what that example is doing, but let me do another. Lets say we've hooked in before $session->redirect(). If I go look at the function definition in /wire/core/Session.php, I can see it has two arguments: $url and $http301. So lets say I want to hook into that and automatically add a GET variable to every redirected URL, like "url.com/path/?is_redirected=1", I'd do this:

public function hookSessionRedirect(HookEvent $event) {
   $url = $event->arguments('url'); // get the existing value 
   $url .= (strpos($url, '?') === false ? "?" : "&") . "is_redirected=1";
   $event->arguments('url', $url); // set the new value that gets sent to $session->redirect
}

Btw, there is some overhead in using the argument names as opposed to the position (it involves using Reflection), so in most cases I think it's still better to use the argument position rather than the name. But have wanted to make both options available because I think some people will find it more straightforward to to use the argument names... and it no doubt makes code examples more readable.

  • 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...