Jump to content

froot

Members
  • Posts

    683
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by froot

  1. Thanks, I like it, but HannaCode seems to not. Syntax error, unexpected '?' and it doesn't work. If that's getting too difficult, I might consider just adding an attribute by which you can manually specify the index.
  2. apologies, I'm a bit puzzled, what would that look like in my case? I learn so much from an example so I would very much appreciate the same advice in this very context.
  3. I tried, but no luck… if (!$page->hanna_counter) : $page->hanna_counter = 0; echo 'nope'; else : echo $page->hanna_counter; $page->hanna_counter = $page->hanna_counter + 1; echo 'yep'; endif; $i = $page->hanna_counter; $nextimage = $page->images->eq($i); echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>'; always echoes 'nope' defining $page->hanna_counter on the template doesn't help either, nor does defining a addHookProperty if (!$i) : $i = 0; else: $i = $i++; and I think that's overkill, hannacode should be able to solve that independently…
  4. I'm trying to pass a variable from one hannacode occurence to the next. hannacode: [[nextimage]] if (isset($next)) : $next++; else: $next=0; endif; $nextimage = $page->images->eq($next); echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>'; But everytime the hannacode runs, it's a different scope so to say. Any ideas?
  5. Still haven't resolved this issue I thought I move my issue to a separate thread. I'm in SnipWire/SnipCart test mode, SnipWire version 0.8.7, PW version 3.0.169 I'm struggling with the taxes, they just won't get applied to the products, what appears in the cart is always – all the way to the confirm order dialogue – without taxes. Here's everything I'm working with: SnipWire Settings Taxes Provider, I can choose between: - Snipcart (no effect - I added additional taxes on snipcart.com which just won't appear) - Integrated (SnipWire) On snipcart.com: - "included in price" (no effect, checked or unchecked) - "applies on shippings" (no effect, checked or unchecked) So I selected Integrated (SnipWire). Then… - Taxes Included in Prices (no effect, checked or unchecked) Taxes Configuration: - 10 % VAT, Shipping: unchecked Shipping Taxes Handling - No shipping taxes (for now) SnipWire Webhooks Endpoint: /webhooks/snipcart (also added to the Snipcart dashboard like this: http://mywebshop/webhooks/snipcart) Product Settings Taxable - Product is taxable (no effect, checked or unchecked) VAT (select field) - 10% VAT (no effect, selected or not) Ironically enough, I entered the products' gross prices yet in the cart their net prices appear. Snipcart Products click "Refresh" – no effect Snipcart.com Settings prices are wrong here. I entered "," as a decimal seperator, now the prices are all hundredfold, i.e. 14,80 -> 1,480.00 - refreshed products - no effect ____ Also tried the usual suspects, deleting cache, incognito mode. What else can I try? If I contact to snipcart.com, they always advise me to talk to the PW "SnipWire" module developer @Gadgetto Please help!
  6. OK, picking up where I left off months later but still confused. Still trying to figure out how to hook after the event of changing a field. $wire->addHookAfter('Pages::savedPageOrField(snipcart_item_image)', function($event) use($item) { doesn't work. I also tried with… $wire->addHookAfter('Pages::saveField(snipcart_item_image)', function($event) use($item) { which accords to what is described here: https://processwire.com/api/ref/pages/save-field/ but the hook is not triggered and It's not logic to me. For a different hooking-scenario I tried 'Pages::trashed' which doesn't work but also 'Pages::trash' which in turn does work. Why, I know not. Both hooks are described in the API documentation in different places however. (below is the related thread) Help is much appreciated!
  7. OK so I made some adjustments because I figured the best way to remove a row in the table of contents when that page is deleted is to make use of a addHookBefore, because at this point the page "still knows" its parents and siblings. However, if I go that way, updating the table only when saving the table of contents page gets in the way because the script would check the pages (siblings) and since it's a addHookBefore (hooked before it's deleted) it would still exist at this point so basically would be deleted with the hook but also re-added with the hook that runs when the table of contents page is saved. Pretty confusing for newcomers I guess but not for this community, I'm sure you had dilemmas like that yourself before. So I did the following instead: $wire->addHookAfter('Pages::saved', function($event) { if ($page->parent->template == 'magazine' && $page->template != 'tableofcontents') : $parent = $page->parent; $toc = $parent->child("template=tableofcontents"); $rows = $toc->tableofcontents_table; $contents = $page->siblings(true); $page_id = $page->id; $page_url = $page->url; $page_number = $page->page_number; $page_title = $page->title; $toc->of(false); // creating a new row for this page if ($rows->has("content_id=$page_id") == false) { $item = $rows->makeBlankItem(); $item->content_id = $page_id; $item->content_url = $page_url; $item->content_title = $page_title; $item->content_page = $page_number; $rows->add($item); $event->message("row created"); // updating an existing row for this page } else { $item = $rows->get("content_id=$page_id"); $item->content_url = $page_url; $item->content_title = $page_title; $item->content_page = $page_number; $event->message("row updated"); } // this is new: also loop through the rows and delete any which don't have a corresponding page foreach ($rows as $row) : $row_id = $row->content_id; if ($contents->has("id=$row_id") == false) { $rows->remove($row); $event->message("row deleted"); } endforeach; $toc->save("tableofcontents_table"); $toc->of(true); endif; }); and the other hook: $wire->addHookBefore('Pages::trashed', function($event) { $page = $event->arguments[0]; $parent = $page->parent; if ($parent->template == 'magazine') : $toc = $parent->child("template=tableofcontents"); $rows = $toc->tableofcontents_table; $page_id = $page->id; $toc->of(false); $item = $rows->get("content_id=$page_id"); $rows->remove($item); $event->message("row deleted"); $toc->save("tableofcontents_table"); $toc->of(true); endif; }); creating, unpublishing, hiding and editing pages do change the rows of the table of contents as intended but I can't get it to delete a row when trashed. Any ideas why?
  8. need to continue this thread, trying to improve my script but I'm out of ideas. What I want is a hook that adds a row to the table-of-contents-table with certain details when a page (sibling to the table-of-content) is saved and removed when it's changing status, i.e. trashed, hidden or unpublished. I tried in many ways already, I never get it to do what I need upon trashing a page plus the code was getting too complicated anyway so I tried something else. I just want the rows to be created or deleted when the table-of-contents-page itself is saved. Then, when I save any other siblingspage, just run a hook that saves the table-of-contents-page. Sounds like a plan? The code is quite short… But again, I just can't seem to hook the trash event. My guess is that when I'm trashing the page, the parent and siblings change and so I cannot refer to them this way? $wire->addHookafter('Pages::saved', function($event) { $page = $event->arguments[0]; if ($page->parent->template == 'magazine' && $page->template != 'tableofcontents') : $page->siblings("template=tableofcontents")->save("tableofcontents_table"); endif; if ($page->template == 'tableofcontents') : $parent = $page->parent; $page->of(false); $toc = $page->tableofcontents_table; $contents = $page->siblings(true); foreach ($contents as $content) : $content_id = (int)$content->id; $content_url = $content->url; $content_page = $content->page_number; $content_title = $content->title; if ($parent->child("id=$content_id") == false) { $item = $toc->get("content_id=$content_id"); $toc->remove($item); $event->message("deleted row"); } else { if ($toc->has("content_id=$content_id") == false) { $item = $toc->makeBlankItem(); $item->content_url = $content_url; $item->content_page = $content_page; $item->content_title = $content_title; $item->content_id = $content_id; $toc->add($item); $event->message("create row"); } else { $item = $toc->get("content_id=$content_id"); $item->content_url = $content_url; $item->content_title = $content_title; $item->content_page = $content_page; $event->message("update row"); } } endforeach; $page->save("tableofcontents_table"); $page->of(true); endif; });
  9. need to dig this thread. I have a setup where the page parents's and page parents parents's name and title are repetitive, so when filtering certain children of a specific page, I can never just filter for their parent's name or title, nor for their parent's parent name or title. Long story short, in order to uniquely identify a page, I would need something better than to filter by id, because that one is never apparent. So I tried with filtering "path" "contains", but obviously I need to install this PagePaths module as it says below the filter options. But that module is nowhere to be found… What to do?
  10. yes, again, the issue was something like that. Many thanks!
  11. I managed to accomplish all that I mentioned here and what I internded. I can now batch create pages with a csv file and on these pages batch import images and create a new repeater-item for each image and add a html caption for each image. One more small thing though, more out of curiosity than out of requirement in my case, how can I sort the repeater images according to the image-filename in use? page when iterating is $p repeater field is $image_and_caption image field on that repeater is $post_image Not sure if anyone else would need an AdminAction like that, if so, I could share it publicly. cheers
  12. @adrian you were exactly right, unlinking before returning was the issue. My bad, the reason it didn't work was a stupid mistake from my side not even worth mentioning. AdminActions is awesome, now that I get the hang of it I can make those actions that I code and that I change the arguments of manually in the code easily usable for the client, no need for them to ever look at code, just clicky-clicky. That said, I do still have a small issue that may or may not have to do with the module (probably not but I mention it anyway). When I do $img_field->deleteAll(); ($img_field being $p->images; see above) it deletes the images alright but leaves "orphaned images" (I think that's what it's called, i.e. images with 0KB in the page. Any ideas what that's about? I also tried ->removeVariations(); before ->deleteAll(); but no luck. Thanks a lot!
  13. I tried exactly that just now, doesn't work though, unfortunately the .csv file stays in /site/assets/files/1443/ folder
  14. protected function defineOptions() { return array( array( 'name' => 'csv_upload', 'label' => 'CSV upload', 'description' => 'Upload a CSV file.', 'type' => 'file', 'extensions' => 'csv txt', 'overwrite' => true, 'maxFiles' => 1, 'required' => true, ), array( 'name' => 'template', 'label' => 'Template', 'description' => 'Choose the template you want to import content to', 'type' => 'select', 'required' => true, 'options' => array( '1' => 'article', '2' => 'blog_repeater' ), ), array( 'name' => 'deleteimages', 'label' => 'delete current images', 'description' => 'delete current images', 'type' => 'checkbox' ), array( 'name' => 'addimages', 'label' => 'add new images', 'description' => 'add new images', 'type' => 'checkbox' ) ); } protected function executeAction($options) { $parent = ''; $parent_title = ''; $url = config()->paths->assets.'cache/AdminActions/'; if(count($options['csv_upload'])) { $n = 0; $file = $options['csv_upload']->first(); $fp = fopen($file->filename, 'r'); if ($options['template'] != 2) : // different actions for different templates while(($row = fgetcsv($fp)) !== false) { if(++$n === 1) : // skip the csv-file's first line continue; endif; if ($options['template'] == 1) : list($parent_title, $title, $author, $summary, $body, $page_number, $img_folder) = $row; $parent = pages()->get("template=magazine, title=$parent_title"); $name = sanitizer()->pageName($title, true); if ($parent->id != 0) : // check if parent exists if($parent->hasChildren("name=$name") == false) { // create the page if it doesn't exist $p = new Page(); $p->template = 'article'; $p->parent = $parent; $p->name = $name; $this->message("Creating new page: $p->path"); } else { // ...or merely update it $p = $parent->child("name=$name"); $this->message("Updating existing page: $p->path"); } else: $this->message("$parent_title has the wrong template"); endif; // set the field's values according to the csv-input $p->title = $title; $p->author = $author; $p->summary = $summary; $p->body = $body; $p->page_number = $page_number; $img_folder = sanitizer()->removeWhitespace($img_folder); $img_field = $p->images; if(!$parent->id) { $this->message("row $n: Sorry parent $parent_title does not exist"); continue; } $specs = array( // prepare the import of the images via ftp 'sourceFolder' => $url.$img_folder.'/', 'destinationPage' => "$p->id", 'deleteFolder' => 0, 'field' => fields()->get('images')->id, ); // optionally DELETE all images before importing (i.e. replacing the images) if ($options['deleteimages'] === 1) : $img_field->deleteAll(); $this->message("images deleted"); endif; // optionally ADD new images if ($options['addimages'] === 1) : if ($options['template'] === 1 || $options['template'] === 2) : modules()->get("ProcessAdminActions")->FtpFilesToPage($specs); $this->message("images added"); endif; endif; $p->of(false); $p->save(); $p->of(true); endif; } else : while(($row = fgetcsv($fp)) !== false) { if(++$n === 1) : // skip the csv-file's first line continue; endif; list($parent, $title, $date, $image, $caption, $img_folder) = $row; $parent = pages()->get("name=blog"); $name = sanitizer()->pageName($title, true); if($parent->hasChildren("name=$name") == false) { // create the page if it doesn't exist $p = new Page(); $p->of(false); $p->template = 'blog_repeater'; $p->parent = $parent; $p->name = $name; $this->message("Creating new page: $p->path"); $p->title = $title; $p->date = $date; $p->save(); $this->successMessage = 'post created'; } else { // ...or merely update it $this->message("Updating existing page: $p->path"); $p = $parent->child("name=$name"); $p->of(false); $p->title = $title; $p->date = $date; $p->save(); $this->successMessage = 'post updated'; } $p = $parent->child("name=$name"); if(!$parent->id) { $this->message("row $n: Sorry parent $parent_title does not exist"); continue; } // optionally DELETE all images before importing (i.e. replacing the images) if ($options['deleteimages'] === 1) : $p->of(false); $p->image_and_caption->deleteAll(); $this->message("images deleted"); $p->save(image_and_caption); $p->of(true); endif; // optionally ADD new images if ($options['addimages'] === 1) : $p->of(false); $img_folder = sanitizer()->removeWhitespace($img_folder); $sourceFolder = $url.$img_folder.'/'; $item = $sourceFolder.$image; $newItem = $p->image_and_caption->getNew(); $newItem->save(); $newItem->post_image->add($item); $newItem->ckeditor_caption = $caption; $newItem->save(); $p->save(image_and_caption); $p->of(true); $this->successMessage = 'image added'; endif; } endif; return true; fclose($fp); } else { $this->failureMessage = 'Please upload a CSV file'; return false; } fclose($fp); // the following are 3 of many attempts to solve the issue, none of them work :( $options['csv_upload']->unlink($file->getPathname()); $options['csv_upload']->unlink($file->filename, $limitPath=true); $this->wire('files')->unlink($file->filename); } } It's quite long (and it's even a bit shortened here in the post, because there's more elseif statement for very similar actions for different templates) and possibly redundant at this point but I'd rather get it all to work and then think about how to shorten it. As you can see I make use of another AdminAction within this AdminAction, namely FtpFilesToPage. I don't see an issue with that though, works fine. So either of these elseif subaction above face the same problem as described in the initial post of this thread. I'm actually a step further, I realised all the 65 (!) csv files that I used to test my AdminAction with are stored in the AdminAction's /site/assets/files/1443/ folder (1443 only in my case obviously). So when I delete those, everything works as it should, just don't know how to have the script delete it automatically. ->unlink() is not helpful. Maybe $pages->get('1443')->deleteAll(); or something? Best practice? Thanks for looking into that @adrian
  15. so long story short, I'm currently working on an AdminAction by which I can attach a .csv file, loop through the rows and do some more code on what I get from there. My problem is, I can never upload the same file again, i.e. cannot unlink the file it appears, which is quite annoying, particularly when developing (but also when actually using the AdminAction in the future), because it says it's already in the system and belongs to another field. I have to rename the file each time I did some changes and want to execute the action. Where is that file actually? In the session variable? in a cache folder somewhere? Anyways, my code starts somewhat like this $url = config()->paths->assets.'cache/AdminActions/'; if(count($options['csv_upload'])) { $file = $options['csv_upload']->first(); $fp = fopen($file->filename, 'r'); while(($row = fgetcsv($fp)) !== false) { ... and at the very end of the code, after all the different if-conditions and while-loops I do include… fclose($fp); unlink($file->filename); but that doesn't work. – hope you don't mind tagging you here @adrian
  16. but what about .csv files? why would they trigger that error? @horst
  17. OK great, that actually worked with a few adjustments. Firstly, I had to add FieldtypeRepeater to the fields selector for it to be a field option in the AdminAction dialogue. 'options' => $this->wire('fields')->find("type=FieldtypeFile|FieldtypeImage|FieldtypeRepeater")->getArray() Secondly, had to save the newItem before continuing… $newItem = $destinationPage->$fieldName->getNew(); $newItem->save(); // << this one $newItem->post_image->add($item->getPathname()); $newItem->save(); Now that the images are nicely distributed among different repeater items, I need to figure out a way to csv-import the captions. Not sure how to access a subfield of a repeater item and especially how to access them specifically, it seems like all the images of any of those pages are in one table cell and all the captions are in another. Thoughts?
  18. actually, this module is pretty cOoL, does what it promises, thank you. But, let's suppose I want to import over 3000 pages, a couple of images each. I tried to use @adrian's Admin Action FTP Files to Page (a process I also managed to automate before (i.e. batch-import for other images-fields)) in combination with @Robin S's repeater-images module to import images to my images field. It imports the images alright, but the repeater-items are not created automatically, I need to save the page manually in admin (an API call $page->save(); doesn't work either). I guess it's a problem with the hooks, one module is waiting for an action that the other module never triggers, so it cannot hook. And now let's not just suppose but just accept the fact that it is indeed that many pages. Normally, I wouldn't mind saving each page manually, cause it's a one-time-migration, but with that amount, it's undoable. Thanks for your ideas
  19. @teppo just some basic questions, no issues (yet) ? I have different pro-tables throughout the site and their content is distinct, thus should be indexed separately, is that at all possible? If not, we can stop right here. I set it up like this: Selected indexed fields: the table-field Indexed templates: the table-field's parent-template Select index field: search_index (already auto-added to the parent-template) sort and operator is unclear to me. I will need to look into adding custom operators using the aforementioned PW-doc on selectors. However, how do I make the sort direction and the operator optional depending on the user input? How can I select the subfields of the table (i.e. columns) to be indexed? Only when I check the "Index pages now?" option I can select those subfields. I indexed the table and/or the template, did a search and got a result. But since it is not pages that it's finding but say 6 matching rows on 1 page, it only shows 1 result instead of 6 and links to the parent page. Can I adjust the results to list the rows? I have the entire markup already (you may or may not have noticed, I've been trying to accomplish a search function without SearchEngine for some time now), any chance I can just use that markup somewhere? That's all the questions I have so far. Thanks for help, have a nice weekend.
  20. @Jonathan Dart can you use this module to search Profields Table as well?
  21. @teppo any chance you can use the SearchEngine to search ProFields Table?
  22. OK Hannacode ist cool and I think to know how to use it, however, it doesn't really solve the issue here. Basically I have a pool of images and each image has exactly one HTML-caption preferably created with a CKEditor field. If I use a repeater field for the bodies, I shouldn't have any problem doing a one-by-one loop of images and bodies (i.e. image - body - image - body - …) in order of appearance. There is no benefit in using Hannacode for this at all. My concern is rather, that the "caption" is not really assigned to the image in regards to the database structure. If I ever want to return the same on a different page, or search it, there would be no API call for that. Is it clear what I mean?
  23. yes I agree, it's quite hard-coded this way, I should make more options available.
  24. Thanks for your suggestion, but I don't think I like that one, reminds me of WordPress and the way it handles media. I don't need new pages or separate IDs for each image, just an editor in the caption field. What I had in place was almost perfect. I tried with TinyMCE which throws no errors and renders in the image field, but it doesn't work, I cannot type. I might just add an images-array-field to upload all images for the page and add a repeater field width CKEditor that also includes a Hannacode somehow.
×
×
  • Create New...