Jump to content

Help make to work a nested conditional hook (and/or alternatives)


LAPS
 Share

Recommended Posts

Hello,

I'm implementing the third conditional hook example here (the one that "taken a little further on the implementation side"), but for the User and Users classes.

Sadly, I cannot make it to work. In fact, the following code does log only the message "running in main hook".

In my ready.php file, with primitive debugging, I've:

wire()->addHookAfter("User::changed(user_bookmarks)", function(HookEvent $event) {
  $user = $event->object; // User
  $old = $event->arguments(1); // old value
  $new = $event->arguments(2); // new value

  wire('log')->message("running in main hook");

  // debug01
  $event->addHookAfter("Users::saved($user)", function($event) use($user, $old, $new) {
    wire('log')->message("debug01");
    $event->removeHook(null);
  });
  // debug02
  $event->addHookAfter("Users::save($user)", function($event) use($user, $old, $new) {
    wire('log')->message("debug02");
    $event->removeHook(null);
  });
  // debug03
  $event->addHookAfter("User($user)::saved", function($event) use($user, $old, $new) {
    wire('log')->message("debug03");
    $event->removeHook(null);
  });
  // debug04
  $event->addHookAfter("User($user)::save", function($event) use($user, $old, $new) {
    wire('log')->message("debug04");
    $event->removeHook(null);
  });
});

In a template.php file, I modify the $user like this:

// ...
$user_bookmarks = $user->getUnformatted('user_bookmarks');
// ...
$user_bookmarks->add($a_page);
$user_bookmarks->remove($another_page);
// ...
$user->setAndSave('user_bookmarks', $user_bookmarks);

Since by successfully running setAndSave() no one of the above-mentioned debug messages gets logged, no one hook gets triggered. How can I properly make those hooks to be triggered?

I would like to take some actions each time the user's user_bookmarks field get updated.

Link to comment
Share on other sites

  • LAPS changed the title to Help make to work a nested conditional hook (and/or alternatives)

Thanks @Jan Romero.

I'm experimenting with the savedPageOrField hook to limit it to run for user pages (because I'm working on Users), and I report this:

// ready.php
wire()->addHookAfter("Pages::savedPageOrField", function($event)  { ... // does work
wire()->addHookAfter("Page(template=user)::savedPageOrField", function($event)  { ... // does not work
wire()->addHookAfter("Pages(template=user)::savedPageOrField", function($event)  { ... // does not work
wire()->addHookAfter("User::savedPageOrField", function($event)  { ... // does not work
wire()->addHookAfter("Users::savedPageOrField", function($event)  { ... // does not work

// template.php // ...
$user->setAndSave('user_bookmarks', $user_bookmarks);

A say in the PW community is "users are pages too", so I expect hooks to work with Users as they work with Pages. Am I going to be victim of another of the classic blunders? ?

Any help about achieving with hooks (even the savedPageOrField one) the goal to take custom actions each time the user's user_bookmarks field get updated?

Link to comment
Share on other sites

Hi, this works for me:

wire()->addHookAfter("User::changed(user_bookmarks)", function(HookEvent $event) {
    $user = $event->object; // User
    $old = $event->arguments(1); // old value
    $new = $event->arguments(2); // new value
    
    wire()->addHookAfter("Pages::savedPageOrField($user)", function(HookEvent $event) use($user, $old, $new) {
        var_dump($user);
        var_dump($old);
        var_dump($new);
        var_dump($event);
    });
});

Btw there is also savePageOrFieldReady(). Might be of interest if you want to modify the user.

  • Thanks 1
Link to comment
Share on other sites

@Jan Romero I was too fast to say that worked for me. The log files seem gone crazy receiving many entries! ? ?

Probably, it's because within the Pages::savedPageOrField($user) hook function I'm updating other $user fields, which causes the infinite loop. In fact, if I don't update the $user within savedPageOrField($user), the whole hook subtly works.

I think the problem is related to the Pages::savedPageOrField($user) hook and I'm trying to limit the run of this hook by passing someway the second argument $changes...

// usage with all arguments
$pages->savedPageOrField(Page $page, array $changes = []);

... something like made in the official docs by using changed(0:order_status, 1:name=pending, 2:...)

// ??? = what? how to state the $changes array?
wire()->addHookAfter("Pages::savedPageOrField(0:$user, 1:???)", function(HookEvent $event) use($user, $old, $new) { ...

and by setting limiting conditions the more classic way

wire()->addHookAfter("User::changed(user_bookmarks)", function(HookEvent $event) {
  // ...
  wire()->addHookAfter("Pages::savedPageOrField($user)", function(HookEvent $event) use($user, $old, $new) {
    // if something, exit now
    ???

    // ...

Any help is appreciated.

Link to comment
Share on other sites

Do you specifically need to use that nested hooks technique? If you want to update related user fields when a specific field is about to be saved, you can just hook savePageOrFieldReady() and evaluate the changes:

wire()->addHookAfter("Pages::savePageOrFieldReady(template=user)", function(HookEvent $event) {
    $user = $event->arguments(0);

	if (!$user->isChanged('user_bookmarks'))
		return; //bookmarks weren’t changed, nothing to do

	$user->of(false);
	$user->set('title', 'that user who keeps changing their bookmarks');
});

Note you don’t need to call save() or anything, you’re piggybacking off of the hooked save operation. <-- doesn’t work if the hook was triggered by a field save.

Otherwise, did you remove the nested hook according to the example in the docs?

Link to comment
Share on other sites

@Jan Romero I used your code and some other weird functions to come up with a solution, without success.

2 hours ago, Jan Romero said:
wire()->addHookAfter("Pages::savePageOrFieldReady(template=user)", function(HookEvent $event) {
    $user = $event->arguments(0);

	if (!$user->isChanged('user_bookmarks'))
		return; //bookmarks weren’t changed, nothing to do

	$user->of(false);
	$user->set('title', 'that user who keeps changing their bookmarks');
});

It seems ignoring all-known-to-me $user->set('title', '...')-like functions for saving the user. User changes (except user_bookmarks) are not saved after the process ends.

Link to comment
Share on other sites

Yeah, you’re right, the piggybacking I mentioned only works with full page saves… Guess you’ll have to call save() after all. You can do so by specifying the noHooks option, so that you don’t call your hook infinite times:

$user->setAndSave('title', 'that user who keeps changing their bookmarks', ['noHooks' => true]);

You can also hook savedPageOrField(), in which case the names of the changed fields will be in $event->arguments(1).

Link to comment
Share on other sites

By using ['noHooks' => true] I still run into trouble.. and the hook runs between 3-8000+ times (var_dump, log, etc.)!

wire()->addHookAfter("User::changed(user_bookmarks)", function(HookEvent $event) {
  // ...
  // here something that handles the following hook creation or updating and that avoids running into infinite loop
  // ...
  wire()->addHookAfter("Pages::savedPageOrField($user)", function(HookEvent $event) use($user, $old, $new) {
    // here something that save $user
    // $user->save() or $user->setAndSave() with $options ['noHooks' => true]
     
    // ...
    $event->removeHook(null);

 

19 hours ago, Jan Romero said:

You can also hook savedPageOrField(), in which case the names of the changed fields will be in $event->arguments(1).

Do you mean to use the savedPageOrField() hook "standalone"? Or "nested" within another hook as in the above code?

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