Tom. Posted November 11, 2017 Posted November 11, 2017 Solution: $p->save(["uncacheAll" => false]); Edit: Added step by step Hey guys, I'm building an eCommerce for ProcessWire which is coming along nicely. However I've come across a bug which I can't seem to figure out what's going off and why. I've put up a post on GitHub, but I know Ryan is a busy man and I am currently working on this 6-8 hours a day. https://github.com/processwire/processwire-issues/issues/434 Here is a link to the issue.
Macrura Posted November 11, 2017 Posted November 11, 2017 don't you need to call $new_option->of(false); before saving? 1
Tom. Posted November 11, 2017 Author Posted November 11, 2017 3 hours ago, Macrura said: don't you need to call $new_option->of(false); before saving? Tried setting both $page->of(false); and $new_option->of(false); problem still exists.
Robin S Posted November 11, 2017 Posted November 11, 2017 Your code copied from the GitHub issue: $options = wirecommerce_get_all_variations($page); $variations = $page->wirecommerce_variations; // Detect added $added = 0; foreach($options as $option) { if(!$variations->has("wirecommerce_variation_value='$option'")) { $new_option = $variations->getNewItem(); $new_option->wirecommerce_variation_value = $option; $new_option->save(); $added++; } } if($added > 0) $this->message("$added variations added."); The code example for adding a repeater item from the documentation: $building = $page->buildings->getNew(); $building->title = 'One Atlantic Center'; $building->feet_high = 880; $building->num_floors = 50; $building->year_built = 1997; $building->save(); $page->buildings->add($building); $page->save(); So I think your code should be: $options = wirecommerce_get_all_variations($page); $variations = $page->wirecommerce_variations; // Detect added $added = 0; foreach($options as $option) { if(!$variations->has("wirecommerce_variation_value='$option'")) { $new_option = $variations->getNew(); // Or getNewItem(), they are the same thing $new_option->wirecommerce_variation_value = $option; $new_option->save(); $variations->add($new_option); $added++; } } $page->save(); if($added > 0) $this->message("$added variations added."); 3
Tom. Posted November 11, 2017 Author Posted November 11, 2017 1 hour ago, Robin S said: Your code copied from the GitHub issue: $options = wirecommerce_get_all_variations($page); $variations = $page->wirecommerce_variations; // Detect added $added = 0; foreach($options as $option) { if(!$variations->has("wirecommerce_variation_value='$option'")) { $new_option = $variations->getNewItem(); $new_option->wirecommerce_variation_value = $option; $new_option->save(); $added++; } } if($added > 0) $this->message("$added variations added."); The code example for adding a repeater item from the documentation: $building = $page->buildings->getNew(); $building->title = 'One Atlantic Center'; $building->feet_high = 880; $building->num_floors = 50; $building->year_built = 1997; $building->save(); $page->buildings->add($building); $page->save(); So I think your code should be: $options = wirecommerce_get_all_variations($page); $variations = $page->wirecommerce_variations; // Detect added $added = 0; foreach($options as $option) { if(!$variations->has("wirecommerce_variation_value='$option'")) { $new_option = $variations->getNew(); // Or getNewItem(), they are the same thing $new_option->wirecommerce_variation_value = $option; $new_option->save(); $variations->add($new_option); $added++; } } $page->save(); if($added > 0) $this->message("$added variations added."); Thanks for the suggestion, but sadly not the case. Here is a quote from Ryan: "It shouldn't be necessary to do the $page->repeater->add($repeater); as the getNew() method already does that."
adrian Posted November 12, 2017 Posted November 12, 2017 In a rush, but take a look at this post: https://processwire.com/talk/topic/6435-cant-figure-out-how-to-create-a-repeater-through-the-api/?do=findComment&comment=62987 Can't remember why I say that the docs are wrong, but for some reason I save the new item before adding any subfields - maybe something to that for some reason?
Robin S Posted November 12, 2017 Posted November 12, 2017 1 minute ago, adrian said: Can't remember why I say that the docs are wrong, but for some reason I save the new item before adding any subfields - maybe something to that for some reason? I think that is because in that example you are adding files to the repeater page. A page has to be saved before you can add files or images to it. 1
Tom. Posted November 12, 2017 Author Posted November 12, 2017 Yeah, I'm starting to think this is something to do with mod_security or timeout. The script seems good? That or it's a bug with ProcessWire. It has the appearance of a mod_security issue blocking the fields from saving. But I don't know. Usually when that happens if effects all fields. Edit: Checked, mod security is turned off
Tom. Posted November 18, 2017 Author Posted November 18, 2017 Added step by step guide: 1. Create a new template called bug. 2. Create two repeaters one called repeater_1 and repeater_2. 3. Create a text field called text and add that to repeater_1 and repeater_2. 4. Add repeater_1 and repeater_2 to the bug template. 5. Add this code to ready.php: $wire->addHookBefore("Pages::save", function($event) { $page = $event->arguments("page"); if($page->template == "bug") { for($i = 0; $i < 3; $i++) { $p = $page->repeater_2->getNew(); $p->text = "Bug"; $p->save(); } } }); 6. Create a bug template page and add content to repeater_1. 7. Click save, you will see that the content for repeater_2 isn't saved, however 3 repeater_2's are added. 8. Remove $p->save(); from the provided code. 9. Add content to repeater_1, you will see that content is added however only 1 repeater is added to repeater_2. $p->save() causes any other repeater to not save, I believe this also applies to Page Reference (see: https://github.com/processwire/processwire-issues/issues/430)
adrian Posted November 18, 2017 Posted November 18, 2017 I haven't followed closely, but please try: $p->save('text'); Or something like that depending on what field(s) you are trying to save. Sorry, I should probably look at this more thoroughly, but not enough time Saving the entire page in a save hook will always cause problems because of recursion. 1
Tom. Posted November 18, 2017 Author Posted November 18, 2017 6 minutes ago, adrian said: I haven't followed closely, but please try: $p->save('text'); Or something like that depending on what field(s) you are trying to save. Sorry, I should probably look at this more thoroughly, but not enough time Saving the entire page in a save hook will always cause problems because of recursion. Thanks, sadly that returns the error "Can't save field from a new page - please save the entire page first". Maybe I will just have to rethink how this is going to work if that's the case, shame I thought it was a really user friendly way of handling product variations.
adrian Posted November 18, 2017 Posted November 18, 2017 2 minutes ago, Tom. said: Thanks, sadly that returns the error "Can't save field from a new page - please save the entire page first" Makes sense - tricky because you are adding a repeater item. I am sure there is a fix, but really have to go now Have a read of this: https://processwire.com/talk/topic/315-run-code-after-page-save/?do=findComment&comment=2206 - might put you on the right track!
Robin S Posted November 18, 2017 Posted November 18, 2017 @Tom., there does seem to be something funny going on in this case when hooking before Pages::save. Will do some more testing, but to allow you to move forward with your project the quick solution is just to hook after Pages::save. So in the test case: $wire->addHookAfter("Pages::save", function(HookEvent $event) { $page = $event->arguments('page'); if($page->template == 'bug' && !$page->skip_me) { for($i = 0; $i < 3; $i++) { $p = $page->repeater_2->getNew(); $p->text = 'Bug'; $p->save(); $page->repeater_2->add($p); $page->skip_me = true; // prevent recursion $page->save(); } } }); Edit: did some more testing using a Page Reference field and managed to trace it back to the "uncacheAll" option in PagesEditor::save(). Posted a comment on the other GitHub issue, which is definitely related to your issue. Hopefully Ryan can fix it soon. 3
Tom. Posted November 18, 2017 Author Posted November 18, 2017 5 hours ago, Robin S said: @Tom., there does seem to be something funny going on in this case when hooking before Pages::save. Will do some more testing, but to allow you to move forward with your project the quick solution is just to hook after Pages::save. So in the test case: $wire->addHookAfter("Pages::save", function(HookEvent $event) { $page = $event->arguments('page'); if($page->template == 'bug' && !$page->skip_me) { for($i = 0; $i < 3; $i++) { $p = $page->repeater_2->getNew(); $p->text = 'Bug'; $p->save(); $page->repeater_2->add($p); $page->skip_me = true; // prevent recursion $page->save(); } } }); Edit: did some more testing using a Page Reference field and managed to trace it back to the "uncacheAll" option in PagesEditor::save(). Posted a comment on the other GitHub issue, which is definitely related to your issue. Hopefully Ryan can fix it soon. Thank you so much Robin, I really appreciate it! 2
adrian Posted November 18, 2017 Posted November 18, 2017 For reference for other who come across this and don't see the github issue: https://github.com/processwire/processwire-issues/issues/434#issuecomment-345437293 Ryan talks about the uncacheAll issue and how to deal with it. 3
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