DrQuincy Posted June 17, 2022 Posted June 17, 2022 I am preventing pages with a specific template from being deleted. I have it working with Pages::trash(template=foo), Pages::delete(template=foo). I'm after a better understanding of why this works please. Why does it work with Pages and not Page, what's the difference? Why is it Pages::trash(template=foo) and not Pages(template=foo)::trash? I have read the docs page on hooks but still don't quite get it. ?
bernhard Posted June 17, 2022 Posted June 17, 2022 That are good and important questions if you want to understand hooks ? Pages::trash() is a hook that you attach to the method "trash" of the "Pages" class (that's the file /wire/core/Pages.php). In that file you'll find the method ___trash() which indicates that it is hookable. You'll also find helpful comments on top of that method in the code. The same concept applies to Page::trash() where the hook is attached to the method trash() of the "Page" class (which is the file /wire/core/Page.php) and represents a single page object. 50 minutes ago, DrQuincy said: Why is it Pages::trash(template=foo) and not Pages(template=foo)::trash? See my link in the signature "afraid of hooks" - does that answer your question? 1
DrQuincy Posted June 17, 2022 Author Posted June 17, 2022 Thank you. I never knew about the relationship between the hook and the class and function name so that is a huge help. Studying the Page and Pages class shows me how different they are — so that makes sense! ? I'm still not 100% on the second point. From reading about hooks I thought the first condition in parenthesis in a hook was a selector and the second was a filter for fields. So to me, this should work since I want to filter out saves where the page has a specific template: \ProcessWire\wire()->addHookBefore('Pages(template=typeface)::saveReady', function(\ProcessWire\HookEvent $event) { \ProcessWire\wire('session')->error('Hook called'); }); But instead this is what works: \ProcessWire\wire()->addHookBefore('Pages::saveReady(template=typeface)', function(\ProcessWire\HookEvent $event) { \ProcessWire\wire('session')->error('Hook called'); }); Why is that? I'm sure I'm missing something really obvious!
bernhard Posted June 17, 2022 Posted June 17, 2022 The part in the braces tells PW to apply a selector. The position where you add this selector tells PW where to apply the selector. And that "WHERE" depends on the hook and it's structure. In your example you hook Pages::saveReady, which looks like this: That means the object is the "Pages" class and the method is the "saveReady" function. As you can see above on line 2287 that method takes one argument: The "Page" object that is being saved. That means: In the HookEvent $event, the object will be the "Pages" class. Try that with tracy: bd($event->object) In the HookEvent, you'll have one argument and that will be the "Page" object being saved. Try bd($event->arguments(0)) You could also use $event->arguments('page') because the first argument of saveReady() is $page. If it were $foo you could do $event->arguments('foo') If you apply a condition like Pages::saveReady(template=foo) that means that you apply the selector "template=foo" to the first argument of the saveReady method which is the "Page" object (on line 2287) that is referenced as $page. What you are doing when using Pages(template=foo)::saveReady is that you apply the selector "template=foo" to the "Pages" class, but the Pages class is not a single Page object and therefore has no template! Hope that makes sense ? 1
DrQuincy Posted June 17, 2022 Author Posted June 17, 2022 Ah, I get it now. Thanks for such a great explanation! 1
bernhard Posted June 17, 2022 Posted June 17, 2022 Glad it helped. Happy hooking - it's a lot more fun if you understand what's going on ? 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now