valan Posted November 19, 2015 Share Posted November 19, 2015 There is a need to send mail when (1) some fields (2) in some template (3) at some page (4) were changed from "one value" to "another value" (5) via API (e.g. not only from admin). Questions: 1. Please could you help with right hook for that? "Fields::save"? 2. How to get $page from hook method, e.g. $page where field is planned to be changed? 3. Finally, would this piece of code work? - specifically getting old and new values, plus messaging to admin (in case changes are not from API) public function init() { $this->addHookAfter("Field::save", $this, "validateAndMail"); } public function validateAndMail($event) { $field = $event->object; if($field->name == 'my_field') { $page = ? // some code here to get page where this field is planned to be saved $is_this_page = $page->id === 12345; // needed page $is_this_template = $page->template->name === 'my_template'; // needed template $oldValue = $page->get($field->name); $newValue = $field->value; if($oldValue === "foo" && $newValue==="bar" && $is_this_page && && $is_this_template) { my_mail_func($page, $oldValue, $newValue); $this->message($this->_("$newValue !!!")); // would it work in case of changes from admin? } } } Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 19, 2015 Share Posted November 19, 2015 First of all your hooked function is the wrong one. Field::save is called when a fieldsettings should be saved, but not when fielddata should be saved. You should rather use Page::saved, which is called right after a page is saved. $this->addHookAfter('Pages::saved', $this, 'afterSaved'); /** * DocBlock from wire/core/Pages.php * @param Page $page The page that was saved * @param array $changes Array of field names that changed * @param array $values Array of values that changed, if values were being recorded, see Wire::getChanges(true) for details. */ public function afterSaved($event) { $page = $event->arguments(0); $changes = $event->arguments(1); $values = $event->arguments(2); // Check for your conditions and send email } Link to comment Share on other sites More sharing options...
Ivan Gretsky Posted November 19, 2015 Share Posted November 19, 2015 I think this example by Ryan looks quite similar to what you're describing. Check it out. 3 Link to comment Share on other sites More sharing options...
valan Posted November 20, 2015 Author Share Posted November 20, 2015 As far as I understand "Pages::saved" is called on $page->save(). Is it also called when field is saved from API, e.g. called on $page->save($field, $value) and on $page->setAndSave($field, $value)? Link to comment Share on other sites More sharing options...
Ivan Gretsky Posted November 20, 2015 Share Posted November 20, 2015 I guess not. If it is something like Pages::saveReady, it is only called on $page->save() but not on $page->save($field, $value). Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 20, 2015 Share Posted November 20, 2015 There's Pages::saved, which is called on every $pages->save() execution and there's Pages::savedField, which is called on every $pages->saveField() execution. You probably need to hook both, to cover all posibilities. 2 Link to comment Share on other sites More sharing options...
valan Posted November 20, 2015 Author Share Posted November 20, 2015 @Ivan, thanks - I missed somehow intro of conditional hooks - looks like syntax sugar) @LostKobrakai, thanks for advice with two hooks - it is not so obvious. Two Qs left: 1. How to get old and new values from Pages::savedField? I see only $page and $field among args... sorry still can't catch logic here. 2. What if you want to check new field value - compare it with old value and prevent saving on some condition? e.g. Which hook to use in this case? and I guess set it with addHookBefore? Again - I'm saving from API with $page->save($field) and $page->save() Link to comment Share on other sites More sharing options...
Ivan Gretsky Posted November 20, 2015 Share Posted November 20, 2015 @LostKobrakai: But Pages::savedField does have different arguments to Pages::saved. So you would probably have to write different code for the hook functions? @valan: I managed to solve similar task hooking FieldtypeMulti::savePageField. This works for something derived from FieldtypeMulti. To hook fieldtypes extending Fieldtype class you can hook Fieldtype::savePageField. Here is the code: public function init() { $this->addHookBefore('FieldtypeMulti::savePageField', $this, 'saveFieldtypeMulti'); } public function saveFieldtypeMulti($event) { // Get current page and field $page = $event->arguments[0]; $field = $event->arguments[1]; // Perform all the check to execute only when needed if ($page->template != 'your-template') return; if ($field->name != 'your-field') return; // Get the instance of the page from db as it was before the edit session. $pageBeforeChange = $this->wire('pages')->getById($page->id, array( 'cache' => false, 'getFromCache' => false, 'getOne' => true, )); if($page->your-field == "now-value" && $pageBeforeChange->your-field == "before-value") { /* send email */ } } This should work whether you save the page or just the field. 1 Link to comment Share on other sites More sharing options...
Ivan Gretsky Posted November 20, 2015 Share Posted November 20, 2015 2. What if you want to check new field value - compare it with old value and prevent saving on some condition? e.g. Which hook to use in this case? and I guess set it with addHookBefore? If you only want to prevent saving the current field, you probably could modify the code above to be hooked before FieldtypeMulti::savePageField and add something like this in the end: if($page->your-field == "now-value" && $pageBeforeChange->your-field == "before-value") { $event->replace = true; } This should replace the whole FieldtypeMulti::savePageField and prevent the field from being saved. Not tested. No guarantees . 1 Link to comment Share on other sites More sharing options...
valan Posted November 20, 2015 Author Share Posted November 20, 2015 Ivan, thank! Just tested code - works perfectly. Link to comment Share on other sites More sharing options...
valan Posted November 25, 2015 Author Share Posted November 25, 2015 One more point - FieldtypeMulti extends Fieldtype, so hook to Fieldtype::savePageField catches both events. Link to comment Share on other sites More sharing options...
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