Jump to content

johnstephens

Members
  • Posts

    103
  • Joined

  • Last visited

Everything posted by johnstephens

  1. Thank you all! I did some initial testing on ProcessWire 3.0.165 with confusing results. When I set $config->sessionAllow using a function, as described here and in the linked article, there was no set-cookie header when I looked at a public-facing URL with curl, but my browser was still getting a cookie—even in Private mode, and even after deleting the cookie and doing a hard refresh of the page. It worked as expected when logging in to ProcessWire. When I set $config->sessionAllow to false (without checking for cookies or an admin URL), I still got a cookie when visiting a public-facing URL in my browser; again, even in Private mode, and even after deleting the cookie and doing a hard refresh of the page. curl still showed me no set-cookie header. Unsurprisingly, I could not log in to ProcessWire with sessionAllow set to false. ? Maybe I did something wrong. I did not add configuration for any of the other session settings mentioned by @horst, and that might be the root of my problem. The blog article @Robin S linked to did not mention those under the heading "More Session Control", so I thought that the sessionAllow setting could operate independently of altering other default configurations. Thanks again! I'll try looking this again later in the week, but I welcome any insight anyone may offer before then!
  2. Hi! I'm puzzling over what it would take to make the public side of my ProcessWire-driven website entirely cookieless. This site doesn't use public-side editing or $page->editURLs or anything like that, and I haven't added any features that get or set cookie info directly. I can't think of any interaction where the public site needs to know that I'm logged in to ProcessWire. But I do see that ProcessWire sends a set-cookie header for each page URL request, regardless. I imagine there are several or many possibilities along a gradient of complexity, based on different needs. But I don't know where to start looking into this. What paths are available? And what are the tradeoffs for serving a site entirely without cookies? Don't get me wrong: I am very happy with the way it works by default, making it super easy to implement front-end functionality for logged-in users! For most of my sites, I use that in some form or another. Thanks in advance for any guidance you can offer!
  3. Thank you, @wbmnfktr! This looks doable and helped me estimate the work involved. Thanks for the Textpattern import tips, too! I became intimately familiar with Textpattern's database scheme before writing my first TXP content importer for anther ProcessWire site migration, and I remembered to import from the body_html field then. ? But I did not know about the "Import External Images" plugin, and wound up writing my own image import scripts, which got a little hairy.
  4. I have a database where most of the content has versions in two languages. Suppose I want to import that content into a ProcessWire instance where I have configured mult-language support for those languages. How could I write an import script that iterates over each article, and pairs it with it's partner so that they both appear together in the article's language tabs? Here's what I'm thinking so far: // Get the data from the old database $articles = database()->query(" SELECT * FROM textpattern WHERE section='" . IMPORT_SECTION . "' // Join to l10n_articles ORDER BY posted desc "); // Create each article in ProcessWire foreach($articles as $article) { if ($article['Status'] == 4) { $newArticle = new Page(); $newArticle->template = 'article'; $newArticle->parent = pages()->get("/" . IMPORT_SECTION); $newArticle->name = $article['url_title']; // Import each field into the appropriate ProcessWire field here. // I understand how to do this already. // Determine this article's language from the l10n_articles table here. // Determine the ID of the article's other-language partner here. // This should be pretty straightforward. // TBD: Insert this content into the appropriate language tab in ProcessWire here. // I have no idea how to do this. $newArticle->save(); } } I imagine the API for this works according to principles I already understand, but I don't know where to look. Thanks in advance for any guidance you can offer! Also, any notes about expected obstacles and challenges would be great. Has anyone here solved this problem before?
  5. I just stumbled across this video, and wasn't sure if it found its way here already. It's a very different take than the tutorials that were available when I was first trying to learn ProcessWire, and I think something like this might have been helpful for me. Trying out ProcessWire (Part 1) [YouTube]
  6. Hello, ProcessWire friends! I have a template that includes a Cache field to combine other fields for full-text search. I wonder if it's possible to add the titles from a Page Reference field on the same template. If so, how would one do that? To clarify, suppose my template includes fields like this: Title: "#DungeonWorldDay 2020: Saturday, 22 August" Body: "The Dungeon World Discord server is hosting Dungeon World Day on Saturday, 22 August. GMs will be running pick-up games, intelligentsia will be offering how-to sessions and Q&A, and fledgling players are welcome to storm dungeons galore alongside hardened veterans. ¶ Please spread the word, invite your friends, invite your enemies if they are fun to play with, and invite your ambivalent associates." Tags (Page Reference) "Role-playing" "Events for Hipsters" Cache Is there a way to configure the Cache field to include "Role-playing" and "Events for Hipsters" (referenced page titles) in addition to the Title and Body? Thanks in advance!
  7. I tried that, and I tried DefaultRepeaterPage too, placing them both in the /site/classes directory like my custom DefaultPage class which works. Alas, calling my Repeater field content still instantiates ProcessWire\RepeaterPage. I may try your addHookMethod() suggestion shortly. Thanks for the tip!
  8. Thanks, @elabx! Perhaps module development is the next step on my ProcessWire education path. I hope I can figure out extending RepeaterPage first. ?
  9. I have a third question that is unrelated to this problem: How do I associate a new custom Page class with a template in ProcessWire, if the template doesn't have a template file (because it is used in other templates)?
  10. Hi! I'm using ProcessWire's ability to recognize custom Page classes, and I have added some very useful methods to my DefaultPage class. I just tried using one of the methods on a Repeater field item and got the error saying, "Method RepeaterPage::meta_description does not exist or is not callable in this context". Makes sense! My method is attached to DefaultPage, not RepeaterPage. That surfaces two questions: How do I extend RepeaterPage? By creating a DefaultRepeaterPage.php file in the /site/classes directory? What is the proper way to abstract methods that I want to use for both DefaultPage and RepeaterPage, so I don't have to repeat the same code in both classes? I think I understand how to do it if they both extended the same parent class, but I don't see how that can be the case here. Thank you in advance!
  11. Thanks, @rick! In my current implementation, I have the file field attached to a repeater, and limited to one upload per repeater item. As a consequence, I'm realizing that the page ID in the path is unique for each file in this case. Thank you for the insight! Cheers!
  12. Hi! I'm trying to retrieve a unique identifier of a file uploaded by a file fieldtype. For articles, I can simply use $page->id, but that doesn't work for files. $page->url and $page->file->url both give the the URL, by contrast. Suppose I have a file uploaded to "/site/assets/files/11067/test.pdf". The number "11067" would have to be unique. Is there any way to get that number using the API? The immediate problem is I need an identifier I can append to an HTML id attribute for interaction with JavaScript. <a id="D11067">, for example, would work fine. Thanks in advance!
  13. Of course, the simplest solution to my specific issue was to use page()->siblings() instead of rootParent()->children(). Fixed.
  14. Hi! I'm trying to create a list of related pages to display on the current page. First, I'm setting a variable with the first element of the "topics" page reference field, like so: $topic1 = page()->if('topics', function() { return page()->topics->first(); }, false); Then, I want to check all the sibling pages and gather those who have the same topic. This code works, but the result will include the current page in the results. $related_articles = $topic1->id ? page()->rootParent()->children("topics=$topic1, sort=-datePublished, limit=3") : new PageArray(); I can remove the current page by appending the remove method… page()->rootParent()->children("topics=$topic1, sort=-datePublished, limit=3")->remove(page()) …but that sometimes results in the list producing fewer results than the limit, even when there are more pages tagged with the same topic beyond the "limit" offset. What I'd like to do is exclude the current page first, and then set the limit. Thanks in advance for any guidance you can offer!
  15. I figured it out! Sub-selectors was the wrong approach, but a subfield selector seems to do the trick: $articles = page()->children('sort=authors.lastname'); Woo. Love it!
  16. This feels like a case for sub-selectors, but I'm not sure how to put it together.
  17. I have a list of articles that I want to sort alphabetically by the author's lastname. The author(s) are linked to each article's page using a page reference field, and the author pages have a field for their lastname. Most articles have only one linked author page, but some may have more than one. For sorting, I only want to consider the first author in the list. I'm stumped how to make this work. $articles = page()->children('sort=FIRSTAUTHOR'); // ?? If I get one page from the list, I would be able to select the field I want to sort by like so: foreach ($articles as $article) { $sortfield = $article->authors->first()->lastname; } Thanks in advance for any guidance you can offer!
  18. Don't use that code. I found a better way. What I discovered was, using the Iterator interface from PHP's standard library did not cause the same problems as DOMNodeList. I still can't account for why calling a function inside my foreach block caused the DOMNodeList to skip alternate nodes, but using an Iterator seems to just work. Unfortunately, there's no Iterator that deals directly with DOM nodes, and you can't feed a DOMNodeList to any Iterator's constructor. That proved to be simple enough to solve by converting the DOMNodeList to an array first: function array_from($listable) { $new_array = []; foreach($listable as $item) { $new_array[] = $item; } return $new_array; } Once I had an array, I could feed it to a new ArrayIterator, and then use foreach to go reliably do stuff to each DOMNode item. Here's a sample of what it looks like in action. Since I'm importing content from Textpattern, the source includes images as HTML img elements as well as a variety of Textpattern tags (including txp:image tags and some smd_macros) // Regular HTML img elements $img_elements = new \ArrayIterator(array_from($dom->getElementsByTagName('img'))); // txp:image tags $images = new \ArrayIterator(array_from($dom->getElementsByTagName('image'))); // smd_macro called txp:image_hd $hd_images = new \ArrayIterator(array_from($dom->getElementsByTagName('image_hd'))); // smd_macro called txp:picture $pictures = new \ArrayIterator(array_from($dom->getElementsByTagName('picture'))); // Combine them all using AppendIterator $source_images = new \AppendIterator(); $source_images->append($img_elements); $source_images->append($images); $source_images->append($hd_images); $source_images->append($pictures); // Do the stuff that needs to be done to each DOMNode item foreach ($source_images as $image) { // Handle a single image here… } I hope this helps someone in the future! Or, maybe me if I have to solve a similar problem again…
  19. I think I've solved the problem. I have no idea why this is necessary, but running the foreach block inside a recursive function seems to rapidly pick up all the images: function add_to_page_recursor($images, $image_prefix, $all_images, $newpage, $dom) { foreach($images as $image) { handle_picture($image, $image_prefix, $all_images, $newpage, $dom); $count = $images ? $images->count() : 0; if ($count > 0) add_to_page_recursor($images, $image_prefix, $all_images, $newpage, $dom); } } One obstacle to this solution is that DOMNodeList does not have the count() method before PHP 7.2, so this code requires PHP 7.2+. But for my publication server, it works. Now I just need to refactor the handle_picture function to handle all the variations of images I'm importing, but that should be simple. If anyone can shed any light on why the foreach block would be skipping images in the source that it can pick up in iterative passes, I'd love to learn what's going on here better. Thank you!
  20. Is this a known feature of PHP, that a function inside a foreach block can just blot out everything else happening inside the block for that iteration? The handle_picture() function works perfectly fine on the odd-numbered iterations (even array indices), no matter what image it is processing. And it fails on every even-numbered iteration (odd array indices). If I shuffle the source order, I get the same odd/even success/failure breakdown. So it's not choking on specific images, just whatever image happens to fall on even iterations. And then, it just ignores the whole iteration without an error or any indication.
  21. Thank you, @DV-JF! I had Tracy installed already, so this was a simple next step. Unfortunately, it confirms something I knew already without giving me new information. // Get txp:image tags $images = $dom->getElementsByTagName('image'); $list_a = []; $i = 0; // Iterate through all the images and just add their names to the $list_a array foreach($images as $image) { $list_a[] = $i . ' => ' . $image->getAttribute('name'); $i++; } $list_b = []; $j = 0; // Iterate through all the images AGAIN: // Add their names to the $list_b array, AND // Try to import them with the handle_picture function foreach($images as $image) { $list_b[] = $j . ' => ' . $image->getAttribute('name'); $j++; handle_picture($image, $image_prefix, $all_images, $newpage, $dom); } bd($list_a); bd($list_b); What I'm seeing in the bd dumps is exactly what I said above: Every alternate image item is being skipped in the second foreach block. Completely skipped: Their names don't get added to the array, and the variable $j doesn't increment. It's not just that the handle_picture() function chokes on them. Or rather, when the handle_picture() function doesn't work, $list_b and $j don't get any information either. Here is the output of my bd dumps—first $list_a: array (6) 0 => "0 => image_1.jpg" (16) 1 => "1 => image_2.jpg" (16) 2 => "2 => image_3.jpg" (16) 3 => "3 => image_4.jpg" (16) 4 => "4 => image_5.jpg" (16) 5 => "5 => image_6.jpg" (16) …and $list_b: array (3) 0 => "0 => image_1.jpg" (16) 1 => "1 => image_3.jpg" (16) 2 => "2 => image_5.jpg" (16) Likewise, if I bd() anything at all inside the handle_picture() function definition, Tracy only shows me the output for every other image, ie. the items that got added to $list_b above. This doesn't get me any closer to seeing what's going on. What am I missing? Thanks in advance for any guidance you can offer!
  22. Oops, the code snippet above should conclude with this: if ($i) echo "<pre>Second count: I counted <b>{$j}</b> txp:image tags in this document.\n\n</pre>"; Not that it matters a lot—it's just part of my troubleshooting.
  23. Hi, @adrian! (and anyone else who reads this) I'm running into a problem, I wonder if there's some simple way to solve. I found that my import script was failing to import images from the content. So I added this to the script so that I could see what was going on: $i = 0; foreach($dom->getElementsByTagName('image') as $image) { $i++; } if ($i) echo "<pre>First count: I counted <b>{$i}</b> txp:image tags in this document.\n</pre>"; $j = 0; foreach($dom->getElementsByTagName('image') as $image) { $j++; // Code that creates img tag from txp:image, adds image src to ProcessWire page, and replaces txp:image tag with img } The first foreach block just counts the number of txp:image tags in the body, so I can print it out afterward. The second block counts the same elements AGAIN, while also running code to import the images into the current ProcessWire page. Then it prints out the second count, for comparison with the first. When an article has just 1 image, the two counts match: 1 image was found, 1 was imported. When the article has more than that, the second foreach block appears to skip every alternate image. My hunch is, the script gets stuck when importing an image, and that's why it only imports images 1, 3, 5, …. If that's the actual choke point, how could I find out? Is there an obvious workaround? Is there a way to make the image import function asynchronous? Some other solution? Thanks for any guidance or suggestions you can offer!
  24. That should solve the ProcessWire API side of the problem! Now I have to figure out how to join the comments into the record returned as `$article` in my code above… Is that a LEFT JOIN?
  25. Thank you, @elabx! I'll look this over right away.
×
×
  • Create New...