Pete Posted March 16, 2012 Share Posted March 16, 2012 Is it possible to do this inside a module? I tried before page save to get the page using something like $previousVersion = wire('pages')->get($page->id); but that didn't work (and certainly wouldn't work after page save ). It's probably something simple like $_POST vars I bet, but just wanted to check. Link to comment Share on other sites More sharing options...
ryan Posted March 16, 2012 Share Posted March 16, 2012 ProcessWire keeps a memory cache of pages loaded, so when you retrieve a page, its going to be the same instance of that page when you retrieve it elsewhere. But once you save a page (in the API) that memory cache gets cleared. If you wanted to keep an in-memory copy of it before it was saved, you'd want to clone it sometime before the page is saved: $pageCopy = clone $page; From that point forward, any changes to $page won't be seen in $pageCopy. This clone will cease to exist once it is out of memory scope. For obvious reasons, file-based assets aren't cloned here. So if your clone depends on file/image assets, then you have to create a new page not just in memory, but on database/disk too. Here's how you do that: $pageCopy = $pages->clone($page); That does a recursive clone, cloning not just that page, but any children too. See the parameters to the $pages->clone() function for additional options to control this. You can also specify that you want it to clone to a different parent. Be careful with the cloning as it's something you probably don't want to do on every page save. It can be an expensive operation if there are lots of files or subpages associated with the cloned page. 1 Link to comment Share on other sites More sharing options...
Pete Posted March 16, 2012 Author Share Posted March 16, 2012 So is there no way when you click Save on a page to have a module access the page's field contents as they were before you hit Save or are you saying that even before save the copy of that page in the memory would be the new one even if it's not saved yet? Surely the old copy in the database should be accessible somehow since we're hookig before page save without the need to clone it? Literally all I want to do is compare the value of a field before the person hit Save and what the value is after they click Save by using a beforePageSave hook if that makes sense. Link to comment Share on other sites More sharing options...
ryan Posted March 16, 2012 Share Posted March 16, 2012 Okay I think I understand what you are saying. So you want to just load a fresh copy from the database, not keep an existing copy at some state in memory. Do this to load a fresh copy from the database: wire('pages')->uncacheAll(); $oldPage = wire('pages')->get($page->id); 2 Link to comment Share on other sites More sharing options...
Radon Posted April 20, 2022 Share Posted April 20, 2022 On 3/16/2012 at 4:06 PM, ryan said: Okay I think I understand what you are saying. So you want to just load a fresh copy from the database, not keep an existing copy at some state in memory. Do this to load a fresh copy from the database: wire('pages')->uncacheAll(); $oldPage = wire('pages')->get($page->id); I have the same request like Pete and the autor of Hooks, compare page before and after save , I need the unchanged page in the state like it was before the page was saved. Before reading this post, I tried to implement a hook before Pages::save, but I always get the changed page there. I tried to add your code to get the old page, but 1. it still gives me the already changed page, and 2. adding this code reverts the changes after saving. I mean, I change something in the page, save this page, (my hook is triggered), when the saved page in backend is reloaded, my changes are gone. That is my code: $this->addHookBefore('Pages::save', function (HookEvent $event) { $page = $event->arguments(0); if ($page->hasField('my_questions')) { wire('pages')->uncacheAll(); $oldPage = wire('pages')->get($page->id); $this->log("Questions before: " . $page->my_questions); $this->log("Questions after : " . $oldPage->my_questions); } }); Any ideas how I can get the "oldPage" that realy works? p.s. I am working in ProcessWire 3.0.184 Link to comment Share on other sites More sharing options...
Radon Posted April 20, 2022 Share Posted April 20, 2022 Finally after a half day if searching an testing I think I have found a solution that works in how-to-get-a-list-of-all-changes-on-page-save#comment-203833 if anyone needs this, use this code: $oldPage = $this->pages->getById($page->id, array( 'cache' => false, // don't let it write to cache 'getFromCache' => false,// don't let it read from cache 'getOne' => true, // return a Page instead of a PageArray )); it gives the unsaved page and works in the current master version. Link to comment Share on other sites More sharing options...
Zeka Posted April 20, 2022 Share Posted April 20, 2022 Not sure, but probably getFresh method is applicable in such a case. https://processwire.com/api/ref/pages/get-fresh/ 1 Link to comment Share on other sites More sharing options...
Radon Posted April 21, 2022 Share Posted April 21, 2022 12 hours ago, Zeka said: Not sure, but probably getFresh method is applicable in such a case. https://processwire.com/api/ref/pages/get-fresh/ Intern it seems that getFresh() works similar like my example above, in my tests both methods work exacly identical. I would prefer getFresh(), because it looks more understandable in code. But I still discovered one issue with both methods... When I remove an item from my field, it works like expected, and the "oldPage" still contains the the removed item, while the current page doesn`t contain it. But in the oposide way, when I add a new Item, BOTH variables oldPage AND current page already contain the new item (no matter if I use getFresh() or the code from my post). I think the reason is, because the field is a repeater and repeater items are created as separate page. Maybe the creation of the Repeater Item comes even before my hook, and already adds the item to the page. Any ideas how to fix this ? Link to comment Share on other sites More sharing options...
Radon Posted April 22, 2022 Share Posted April 22, 2022 I discovered that new items in $oldPage have the status 3073 (what matches Page::statusHidden, Page::statusUnpublished). So my way to detect new pages to check if($item->isHidden() && $item->isUnpublished()) $newItem = true; Link to comment Share on other sites More sharing options...
szabesz Posted April 22, 2022 Share Posted April 22, 2022 On 4/21/2022 at 9:35 AM, Radon said: I think the reason is, because the field is a repeater and repeater items are created as separate page. Maybe the creation of the Repeater Item comes even before my hook, and already adds the item to the page. For those who do no have access to the Pro fields support forum, Ryan expains a similar issue like this: "One thing about repeaters is that they sometimes have extra pages in them called "ready pages", which are basically abandoned new items that are saved for the next time you need to add an item to the repeater. So in your loop that iterates the repeater items, you'll want to check that the items are published and/or not hidden before considering them valid for your calculations. if($child->isUnpublished() || $child->isHidden()) continue." see: https://processwire.com/talk/topic/24967-hook-says-there-are-twice-as-much-repeater-items/?do=findComment&comment=210451 1 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