joer80 Posted February 9, 2017 Share Posted February 9, 2017 I have a module that is not working and I cant figure out why. When an admin page is saved, I want to update another page. This is my code: public function init() { $this->pages->addHookAfter('save', $this, 'UpdateAnotherPage'); //save, saved, saveReady, saveFieldReady } public function UpdateAnotherPage($event) { $page = $event->arguments(0); //Update Another page $OtherPage = wire('pages')->get('id=1240'); $OtherPage->setOutputFormatting(false); $OtherPage->ThemeCachedCSS = '123'; $OtherPage->save(); //this breaks it } It will save the data in the new page, but the admin page doesnt load, it tries to load my homepage. If I comment out the ->save(); line, it stays on the admin page and says page saved, but just doesnt update the other page. I am probably missing something simple! Thanks! Link to comment Share on other sites More sharing options...
Robin S Posted February 9, 2017 Share Posted February 9, 2017 You are missing the crucial step in your hook where you check what page was saved and then decide if you want your page update code to run. You don't want that update to occur on any page save like it does now, because then it will trigger again when the updated page is saved in the hook, and so on until the cows come home. 1 Link to comment Share on other sites More sharing options...
joer80 Posted February 9, 2017 Author Share Posted February 9, 2017 If I run this, it only shows the message one time if I save one page. public function UpdateAnotherPage($event) { //Show saved message $this->message("Save Ran"); } I know the code is bare min and doesnt look useful right now. I did that to make it easier to figure out. I can edit any page to see the bug. Hope that makes sense and I am not misunderstanding. Link to comment Share on other sites More sharing options...
Robin S Posted February 9, 2017 Share Posted February 9, 2017 You misunderstand what I'm saying: you are hooking page save, but saving a page inside your hook - that recurs indefinitely. Link to comment Share on other sites More sharing options...
joer80 Posted February 9, 2017 Author Share Posted February 9, 2017 Ah, so I need to figure out how to make it only save the first time! Link to comment Share on other sites More sharing options...
Robin S Posted February 9, 2017 Share Posted February 9, 2017 If you want your hook to fire on the saving of all pages but the one you are updating in your hook you would do: public function UpdateAnotherPage($event) { $page = $event->arguments('page'); if($page->id !== 1240) { // update page 1240 } } 3 Link to comment Share on other sites More sharing options...
joer80 Posted February 9, 2017 Author Share Posted February 9, 2017 9 minutes ago, Robin S said: You misunderstand what I'm saying: you are hooking page save, but saving a page inside your hook - that recurs indefinitely. Do you think this is a good way to approach the problem? Or do you know of a better way? public function init() { $this->pages->addHookAfter('save', $this, 'UpdateAnotherPage'); //save, saved, saveReady, saveFieldReady } public function UpdateAnotherPage($event) { $page = $event->arguments(0); //Update Another page $OtherPage = wire('pages')->get('id=1240'); $OtherPage->setOutputFormatting(false); $OtherPage->ThemeCachedCSS = '123'; if($OtherPage->ThemeCachedCSS != '123'){ $OtherPage->save(); } } Link to comment Share on other sites More sharing options...
joer80 Posted February 9, 2017 Author Share Posted February 9, 2017 4 minutes ago, Robin S said: If you want your hook to fire on the saving of all pages but the one you are updating in your hook you would do: public function UpdateAnotherPage($event) { $page = $event->arguments('page'); if($page->id !== 1240) { // update page 1240 } } Ah, I see you posted before me! Thank you for all of your help! Link to comment Share on other sites More sharing options...
adrian Posted February 10, 2017 Share Posted February 10, 2017 You can also avoid recursive issues with hooks on save by just saving the field you have changed, rather than the entire page, eg. $OtherPage->save('ThemeCachedCSS'); 4 Link to comment Share on other sites More sharing options...
joer80 Posted February 10, 2017 Author Share Posted February 10, 2017 Very nice idea! Link to comment Share on other sites More sharing options...
joer80 Posted February 10, 2017 Author Share Posted February 10, 2017 I thought about doing this: if($page->id == $_GET['id']){ $OtherPage->save('ThemeCachedCSS'); //only save the one field instead of whole page } The admin page save click would work because the get var would be set to the page you are on, but it wouldn't loop because the api call page id would be different. It would still loop when editing the theme page though. You would always need it to be a different page than the one you are on. Link to comment Share on other sites More sharing options...
joer80 Posted February 10, 2017 Author Share Posted February 10, 2017 The page tree would be something like: Page 1 Page 2 Theme The gist I was playing with was each page would have a ace rich text box with css in it. On page save it would grab all css from all pages and save to theme. The theme page may want to add to it also though. May have to keep thinking this out. I will make it spit out a css file from that cached field that holds the total output. Add a timestamp for cache busting and have my Page template link the most recent file. Link to comment Share on other sites More sharing options...
joer80 Posted February 10, 2017 Author Share Posted February 10, 2017 Ok, I think I have it figured out. I ended up putting the cached field in the page also and making 2 functions instead of one. What do you think about this? <?php class CacheThemeCSS extends WireData implements Module { public function init() { $this->pages->addHookBefore('save', $this, 'updateMyCachedCSS'); $this->pages->addHookAfter('save', $this, 'updateThemeCachedCSS'); } //Update the Cached CSS of the page I am on. public function updateMyCachedCSS($event) { //ini $CachedCSS = ''; //Update CSS Cache for page I am on $page = $event->arguments(0); //Prepare CSS for this page $CachedCSS .= '/* ' . $page->title . ' CSS Start */' . "\n"; //Load Item Styles if given if($page->Styles){ $CachedCSS .= '#' . $page->template . '-' . $page->id . '{ ' . $page->Styles . '}' . "\n"; } //Load CSS File Additions if given if($page->CSSAdditions){ $CachedCSS .= $page->CSSAdditions . "\n"; } //$CachedCSS .= '/* ' . $page->title . ' CSS End */' . "\n"; if($CachedCSS){ $page->CachedCSS = $CachedCSS; } } //Update the Themes AllCachedCSS public function updateThemeCachedCSS($event) { //ini $CachedCSS = ''; //Get all CachedCSS and add them to the active themes AllCachedCSS field $results = $this->wire('pages')->find("CachedCSS!=''"); foreach($results as $result){ $CachedCSS .= $result->CachedCSS; } //Get Active Theme $Settings = $this->wire('pages')->get("template=settings"); //Update Active Themes Cached CSS $ActiveTheme = wire('pages')->get($Settings->ActiveTheme->id); $ActiveTheme->setOutputFormatting(false); $ActiveTheme->AllCachedCSS = $CachedCSS; //Set the new value $ActiveTheme->save('AllCachedCSS'); } } //end class Link to comment Share on other sites More sharing options...
joer80 Posted February 10, 2017 Author Share Posted February 10, 2017 Here is the version that drops the Themes All Merge field and makes a file instead. (Each page still has a css cache field.) I am using a timestamp on the css filename for cache busting. That way you can set a 6 month time frame on css files and bust out every page save. <?php class CacheThemeCSS extends WireData implements Module { public function init() { $this->pages->addHookBefore('save', $this, 'updateMyCachedCSS'); $this->pages->addHookAfter('save', $this, 'updateThemeCachedCSS'); } //Update the Cached CSS of the page I am on. public function updateMyCachedCSS($event) { //ini $CachedCSS = ''; //Update CSS Cache for page I am on $page = $event->arguments(0); //Prepare CSS for this page $CachedCSS .= '/* ' . $page->title . ' CSS Start */' . "\n"; //Load Item Styles if given if($page->Styles){ $CachedCSS .= '#' . $page->template . '-' . $page->id . '{ ' . $page->Styles . '}' . "\n"; } //Load CSS File Additions if given if($page->CSSAdditions){ $CachedCSS .= $page->CSSAdditions . "\n"; } $CachedCSS .= "\n"; if($CachedCSS){ $page->CachedCSS = $CachedCSS; } } //Update the Themes CachedCSSFilename and make file public function updateThemeCachedCSS($event) { //ini $CachedCSS = ''; //Get all CachedCSS styles $results = $this->wire('pages')->find("CachedCSS!=''"); foreach($results as $result){ $CachedCSS .= $result->CachedCSS; } //Get Active Theme ID $Settings = $this->wire('pages')->get("template=settings"); $FileNameFormat = 'merged_' . date("Y-m-d_H:i:s"); //Get Active Theme so I can update its CachedCSSFilename $ActiveTheme = wire('pages')->get($Settings->ActiveTheme->id); $PreviousCachedCSSFilename = $ActiveTheme->CachedCSSFilename; $ActiveTheme->setOutputFormatting(false); $ActiveTheme->CachedCSSFilename = $FileNameFormat . '.css'; //Set the new value $ActiveTheme->save('CachedCSSFilename'); //make a file with $CachedCSS $myfile = fopen('styles/' . $ActiveTheme->CachedCSSFilename, "w"); fwrite($myfile, $CachedCSS); fclose($myfile); //Delete previous merge file. unlink('styles/' . $PreviousCachedCSSFilename); //$event->message("Old file: $PreviousCachedCSSFilename deleted"); } } //end class 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