Jump to content
Jozsef

Hooking after Pages::saveReady causes the page not saving in admin

Recommended Posts

I added a hook in ready.php to do some extra processing when the "price" field is changed in a page with "event" template.
Now the hook is triggered but the price reverts back to the original one on the page after saving it in the admin.
Changing and saving the second time saves the new price.
Running ProcessWire 3.0.114.

Why could that be? I presume this is not the expected behaviour.
Here's my code:

// Change prices and totals in orders on ticket price change
$this->addHookAfter('Pages::saveReady(template=event)', function($event) {
  $page = $event->arguments('page');
  if($page->isChanged('price')) {
    $price = $page->price;
    // Get all orders for this event
    $orders = wire('pages')->find("template=order, order_event=$page->id");
    if (count($orders) > 0) {
      // Change order values based on the new ticket price
      foreach ($orders as $o) {
        $o->of(false); // Turn off output formatting so field values can be changed
        // Calculate new order values
        $o->price = $price; // Single price
        $o->total = $price * $o->quantity; // Total price for all tickets
        $o->handling = $o->total * 0.05; // 5% handling fee on the total price
        $payments_sum = wire('pages')->sum("template=payment, order_id=$o->id", "total"); // Calculate the total payments
        $o->balance = $o->total + $o->handling - $payments_sum; // Calculate the new balance based on the new price
        $o->save(['uncacheAll' => false]); // Save order but don't reset the page cache
        $o->of(); // Turn back on output formatting
      }
      // Add a new notification to confirm the changes
      $no_changed = count($orders);
      wire('notices')->message("{$no_changed} orders have been updated with the new price.");
    }
  }
  // Save field otherwise it only saves for the second time
  $page->save('price');
});

The only way I could get the page to save properly (for the fist time) was to add this at the end of the hook:

// Save field otherwise it only saves for the second time
$page->save('price');

Can someone spot anything wrong with the code? Or is this a bug?

Share this post


Link to post
Share on other sites

If you change the hook from "after" to "before" you shouldn't have to save the field explicitly.

Share this post


Link to post
Share on other sites

Thanks, Adrian but the result was the same with "before" too. The field is only saved for the second time.

Share this post


Link to post
Share on other sites

Ah, sorry, I didn't read your code fully - I assumed you were trying to adjust the price on the main $page, but you're using it to adjust the price on the order pages.

Sorry, I am not seeing anything wrong with your code at the moment - maybe someone else will spot something 🙂

Share this post


Link to post
Share on other sites

@Jozsef, I'm not sure but the failure to save changes and the fact that the order pages you are getting have a reference to the current page being saved makes me think it could be this issue: https://github.com/processwire/processwire-issues/issues/1092

But as far as I know this issue should only occur if you get the value of the order_event field (i.e. the page that is currently being saved) and I don't see that in your code. If you have "Autojoin" enabled for that field this could also cause the issue.

Share this post


Link to post
Share on other sites

@Robin S, Thanks that's well spotted, I haven't thought about the circular reference, I did run into that one when trying to preselect the current page in a form page reference field. But in that case I guess there's not much I could do, except for saving the field manually that doesn't seem to do any harm.
Thanks again, I would have never thought about this.

I do get the current page in the selector for $orders but that's why I tried to use the $page->id instead of the $page object itself. Didn't help much though, the changes only save for the second time. The strange thing is that the changed field values do populate in the hook and saved to all order but than it's lost between the hook and the actual save.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...