Jump to content

smart hook on field save


valan
 Share

Recommended Posts

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

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

@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

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

  • Like 1
Link to comment
Share on other sites

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

  • Like 1
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...