Jump to content

Shut-down / post-request hook?


Recommended Posts

Is there a reliable shut-down or post-request hook in ProcessWire?

I tried ProcessPageView::___finished() but it doesn't get triggered when there's a redirect - most admin-forms use a post/redirect/get approach, so there's no hook until the following request, which is too late.

What I'm trying to do, is raise a flag on a number of different events - if templates or fields are saved, for example, I need to do some work when the request ends. Since the Session::redirect() method does a hard exit() the invokation of finished() in "index.php" is missed...

Any ideas?

Link to comment
Share on other sites

Yeah, I tried a before-hook on Session::redirect() but that doesn't seem to work either...

I've resorted to __destruct() before but don't feel comfortable doing that in this case, since the order in which other objects get destroyed is unpredictable and might cause weird side-effects - if wire('templates') or one of the Template objects have been destroyed by the time my __destruct() method is called, for example, iterating through Templates or saving them could go horribly wrong.

I posted the code here...

Link to comment
Share on other sites

Hmm, you're not hooking redirect() in *Session* but ProcessPageView (where no such method even exists):

$this->addHookBefore('ProcessPageView::redirect', $this, 'rebuild');
Is it a typo explaining why it didn't work or am I just missing something? :)
Link to comment
Share on other sites

Seems like we do need another shutdown hook of some sort here that gets called regardless of whether it was a pageview or a redirect. Semantically, it probably makes sense that ProcessPageView::finished doesn't get called on a redirect, though not sure it really matters. What do you guys think would be best of these 3 options: 

  • Make $session->redirect() call $processPageView->finished(); before exiting.
  • Add a new ProcessWire::shutdown hookable method that always gets called. 
  • Add an optional finished() method to the module interface. Like the ready() method, but gets called automatically (on modules that have it) when the request is done. 
Link to comment
Share on other sites

@nik Gotcha! Thanks, that works better :-)

@ryan I favor the first option - I would prefer to have execute() and finished() trigger consistently. However, it may break backwards compatibility with existing modules that rely on finished() not getting triggered. Probably very marginal, though in theory it could cause a hiccup in some module...

ProcessWire::shutdown() would be my second choice - if that's what you choose to do, I think it would also make sense to pass an argument to the hook, indicating what the result of the request is, e.g. the HTTP status code, or maybe just a true/false flag indicating whether the result is a redirect?

Link to comment
Share on other sites

@ryan I favor the first option - I would prefer to have execute() and finished() trigger consistently. However, it may break backwards compatibility with existing modules that rely on finished() not getting triggered. Probably very marginal, though in theory it could cause a hiccup in some module...

I agree. We already have a hookable function that one could use to target a pageview vs. redirect (after Page::render). I've already updated Session::redirect locally to trigger ProcessPageView::finished, so it'll be in the dev source soon. I don't think it'll break any backwards compatibility just because I can't think of any module or situation that relies on finished() not getting triggered. 

Link to comment
Share on other sites

  • 4 weeks later...

Hmm, finished() still isn't being called.

In Session::redirect() line 361:

if(wire('process') == 'ProcessPageView') wire('process')->finished();

I did a var_dump(wire('process').'') and it looks like when you submit the Field editor form, wire('process') returns the Field instance you're editing - not the ProcessPageView instance.

I'm currently using two hooks to work around this issue:


        $this->addHookBefore('Session::redirect', $this, 'flushChanges');
        $this->addHookAfter('ProcessPageView::finished', $this, 'flushChanges');

  • Like 1
Link to comment
Share on other sites

Are you sure it's not a ProcessField instance? That's what it is when I test here in that scenario. In either case, you are right that the test for ProcessPageView isn't right and needs to be changed. Currently it would only work on the front-end. I am changing it to this locally and will test before committing:

if(wire('page')) wire('modules')->get('ProcessPageView')->finished();
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...