MarkE Posted January 3, 2023 Share Posted January 3, 2023 A simple question: Is there any way, when a template or field is saved of getting the previous properties (i.e. before the save)? Link to comment Share on other sites More sharing options...
Jan Romero Posted January 3, 2023 Share Posted January 3, 2023 Before changes are saved to the database, you can load the previous values from there. Here is a snippet that does this: It’s a bit old, maybe there are better ways of doing it now? Link to comment Share on other sites More sharing options...
MarkE Posted January 3, 2023 Author Share Posted January 3, 2023 Thanks @Jan Romero, but that deals with pages (and the values of their fields). What I am after are the field and template objects themselves. Link to comment Share on other sites More sharing options...
MarkE Posted January 3, 2023 Author Share Posted January 3, 2023 FWIW I have made a little work-round that saves $template->getExportData() as a session var on 'ready' then compares it with the changed value, hooked in 'saved'. It seems to work, but there must be a less clumsy way. trackChanges etc is not very helpful. 1 Link to comment Share on other sites More sharing options...
MarkE Posted February 10, 2023 Author Share Posted February 10, 2023 Just bumping this in case anyone has any ideas. As stated above, my work-round is rather clumsy and inefficient. Surely there must be an easier way?! EDIT: I notice that WireSaveableItems has a hookable method ___saved(Saveable $item, array $changes = array()) but I can't find anything calling it with the $changes parameter set. Link to comment Share on other sites More sharing options...
MarkE Posted February 11, 2023 Author Share Posted February 11, 2023 So here's a (hopefully better and working) solution. Add the following as a hook to (i.e. new method for) WireSaveableItems: public function getFreshSaveableItem($event) { $saveables = $event->object; $item = $event->arguments(0); $database = $this->wire()->database; $sql = $saveables->getLoadQuery()->getQuery(); $query = $database->prepare($sql); $query->execute(); $rows = $query->fetchAll(\PDO::FETCH_ASSOC); $newItem = null; if($item) { foreach ($rows as $key => $val) { if ($val['id'] == $item->id) { $row = $rows[$key]; $newItem = $saveables->initItem($row); // there should be only one matching item break; } } } $event->return = $newItem; } This returns the item as it is in the database, so if you call (say) wire('fields')->getFreshSaveableItem($myfield) in a beforeSave hook, you will get the version of $myfield that is in the database - i.e before it is saved and can compare it with the version about to be saved. But if you want to use this, test it out well first! Maybe someone else can come up with something better (or even a PR for the core?!) Link to comment Share on other sites More sharing options...
Jan Romero Posted February 11, 2023 Share Posted February 11, 2023 I just tested this: //ready.php /* Turn on tracking of changed values for all Templates. * Couldn’t find a hook for this, so I’m just iterating * all templates on every request. Should be fine? * Both calls to setTrackChanges() are needed. */ foreach (wire('templates') as $template) { /** @var Template $template */ $template->setTrackChanges(Wire::trackChangesValues); $template->setTrackChanges(true); } /* Dump tracked changes when Templates are saved, or * do whatever with them */ wire()->addHookBefore('Templates::save', function (HookEvent $event) { /** @var Template $template */ $template = $event->arguments(0); bd($template->getChanges(true)); //var_dump($template->getChanges(true)); }); This doesn’t get changes to a template’s fields, but you can probably do something similar with Fieldgroups and Fields themselves. Link to comment Share on other sites More sharing options...
MarkE Posted February 11, 2023 Author Share Posted February 11, 2023 1 hour ago, Jan Romero said: I just tested this: That seems to work and might be sufficient if you just want to know if there are any changes. The test that I did - adding a field to a template - gave a curious array of changes in the bar dump, viz: array 'compile' => array 0 => 3 'noParents' => array 0 => '' i.e. nothing about the field that had been added. I have no idea why this is. On the other hand, my getFreshSaveableItem() method returns the complete template before any changes, so includes the related fieldgroup. However it may be slower - I haven't benchmarked them. Link to comment Share on other sites More sharing options...
Jan Romero Posted February 11, 2023 Share Posted February 11, 2023 Yes, it’s not going to pick up changes to the Fields, because behind the scenes you’re actually adding the Field to the Template’s Fieldgroup. Can’t figure out how to get added fields, but getting removed fields seems to work reliably: foreach(wire('templates') as $template) { /** @var Template $template */ $template->setTrackChanges(Wire::trackChangesValues); $template->setTrackChanges(true); $template->fieldgroup->setTrackChanges(Wire::trackChangesValues); $template->fieldgroup->setTrackChanges(true); } wire()->addHookBefore('Templates::save', function (HookEvent $event) { /** @var Template $template */ $template = $event->arguments(0); bd($template->getChanges(true)); }); wire()->addHookBefore('Fieldgroups::save', function (HookEvent $event) { /** @var Fieldgroup $fieldgroup */ $fieldgroup = $event->arguments(0); bd($fieldgroup->getChanges(true)); //says NULL for added fields, because the previous value of the added field was no field, works well for removed fields bd($fieldgroup->getItemsAdded()); //gives all fields in the set for some reason bd($fieldgroup->removedFields); //this seems to work well }); If you have a use case for this there may be opportunities for PRs here. For example it doesn’t seem reasonable to me that removing a field tracks the change as "removed:<fieldname>" (plus the field itself as the old value) while adding one tracks as "add" without the field name (and no old value, because it was an add). 1 Link to comment Share on other sites More sharing options...
MarkE Posted February 11, 2023 Author Share Posted February 11, 2023 Thanks for all the ideas @Jan Romero . Personally I got a bit frustrated with TrackChanges because it seems to be a bit random about what it records - for pages as well as fields etc. That’s why I started using getFresh() for pages with a home-built compare function because it gave me full control and understanding. So my idea was to do something similar for fields and templates (and fieldgroups) - the code above is my attempt at this and no doubt can be improved. The getFresh() for pages is hugely more complex! Nevertheless, I agree that a more robust and consistent TrackChanges is desirable. 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