Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by johnstephens

  1. Excellent, thank you @bernhard! That was exactly what I needed. I’m glad I didn’t have to manually like them to files imported in bulk with filesManager->importFiles().
  2. Hi! I want to import files into a specific ProcessWire page that has a "files" field. I wrote this snippet and it successfully copies the files to the correct directory under /site/assets: const PATH_PREFIX = '/path/to/files/'; $parent = pages()->get('/my-files-page'); $parent->of(false); $parent->filesManager->importFiles(PATH_PREFIX); $parent->save(); But I also want the files to show up in ProcessWire’s admin panel for that page, linked to the "files" field. Having done this with images, comments, and page reference fields, I know that it involves iterating through the files with code like this: $newFile = new Pagefile(); $parent->files->add($newFile); …but I can’t figure out how to set the file information (name, description, extension, etc.), nor how to associate it with the file imported into the assets directory. Luckily, I do have all the files referenced in a database, which I can access like so: $files = database()->query(" SELECT id, filename, title, category, permissions, description, downloads, status, modified, created, size, author FROM txp_file WHERE 1 ORDER BY id "); foreach ($files as $file) { // PROFIT! } But it’s not clear to me how to both import the file into the files field AND link the file’s metadata. I’m sure that I am overlooking something simple, but I’m grateful for any guidance you might offer. Thank you!
  3. Thanks again, @wbmnfktr! Hidden characters was one of my thoughts too. I see that all the hidden characters exposed by these two sites are also visible by default in my Vim configuration: spaces and linefeeds. Comparing both the original content and the version that works after my unsubstantial revisions using those two sites, I don't see any significant difference between the problem version and the working version. The problem version didn't have any suspicious hidden unicode characters or sequences that these tools exposed. I'm still stumped, but at least now I know some new angles for troubleshooting that I didn't know before!
  4. It seems to be fixed. I don’t know why. What I did was copy the Source markup from the CKEditor field into Vim and scour it. Since the content had a lot of link anchors, I added new lines around each one so that I could see them separately. But then… I found nothing unusual. I added blockquote tags around one paragraph that was a quotation, and I switched a few em tags to cite since they were book titles, and I changed a few straight quotes (") and apostrophes (') in the markup to the curly versions (“, ”, and ’). I pasted the result back into CKEditor's Source panel and saved the page. And that fixed the problem. Even though the problem is solved for now, it would be great to learn more about what went wrong, how it went wrong, and how we could prevent this again. Thanks in advance for any guidance! P.S. Is this the right sub-forum for this issue? I chose API because I thought that it was related to the interaction between my page reference field and the template markup, but that doesn't seem to be the case.
  5. I narrowed down the issue again, but I’m not sure what it means. I’ll do some more testing and see if I can turn up something. Here’s what I found: I duplicated the page again by creating a fresh page with the same template, just like before. The only content in the original page was a title and CKEditor field, so I copied the title first and tested it before copying the CKEditor field content. It worked! The navigation link appeared as expected on other pages and on the page itself. Then I copied the original content from the CKEditor field into the new page's CKEditor field and Saved again. It broke! Clearing the CKEditor field restored the article to the favor of ProcessWire. I glanced over the markup yesterday and didn’t spot anything egregious, but now I’ll take a closer look at it. I’m pretty sure the site owner wrote and formatted the content in a word processor and copied it into the CKEditor field, but I thought CKEditor would filter out anything that might cause problems. I would love to hear any additional insight anyone has. How can HTML markup in a CKEditor field create a "corrupted" status?
  6. I’m not aware of the database ever crashing, but I don't know how I would detect that. I've never seen this in a ProcessWire project either. Here is the how the page reference field is configured: { "navigation_main": { "id": 130, "name": "navigation_main", "label": "Main navigation menu", "flags": 0, "type": "FieldtypePage", "description": "Select pages for main navigation menu", "derefAsPage": 0, "inputfield": "InputfieldAsmSelect", "parent_id": "/", "labelFieldName": "title", "collapsed": 0, "usePageEdit": 0, "findPagesSelector": "template=basic-page|template-a|template-b|template-c|template-d|template-e|template-f, has_parent!=7", "notes": "Pages in navigation must be direct children of the site's homepage.", "allowUnpub": "", "defaultValue": "", "template_id": "", "template_ids": "", "findPagesSelect": "", "labelFieldFormat": "", "addable": "", "showIf": "", "themeOffset": "", "themeBorder": "", "themeColor": "", "columnWidth": 100, "required": "", "requiredIf": "" } } And here is the code that generates the menu markup using that field's input: $menu_main = $settings->navigation_main; $menu_main->prepend(pages()->get('/')); $menu_main_iterator = 0; foreach ($menu_main as $item) { $menu_main_iterator++; $item_class = 'nav--item'; $item_class .= $item->rootParent == $page->rootParent ? ' nav--active uk-active' : ''; $item_class .= ' nav--' . $menu_main_iterator . 'th'; echo "<li pw-append='nav-main' class='nav-main__item {$item_class}'><a class='nav-main__link' href='{$item->url}'>{$item->title}</a></li>"; } I have another menu in the footer which lists the same page, but the PageArray() used by the footer menu is generated by a different API call which does not involve the navigation_menu field.
  7. Since the github issue references saving the page, I guessed that this might be associated with using the PageFrontEdit module on this site. As a test, I uninstalled PageFrontEdit, and there was no effect. Still unclear on the diagnosis and steps to troubleshoot. I’ll keep banging around. Thank you again!
  8. Thank you, @wbmnfktr! I will read over the two links. As a test, I already created a new page and copied the content over to the new one by hand (not using the API), and the new one is having the same problem. I will check the links to see if I can make any sense of it.
  9. I was able to remove the "flagged" status by opening the page in ProcessWire and re-saving it. That didn't affect the "corrupted" status, though, and the page still does not show up in the navigation menu when viewing the problem page URL.
  10. AHA! I found a datum that sets the problem page apart. When I look at the TracyDebugger bd() output for the problem page (ie. bd(pages()->get('/problem-page'))), I see it has a property called "status". When I output this on any other page, the "status" property has the value of "flagged". But the same bd() outputs a value of "flagged, corrupted" when I view this output on the problem page URL. I still don't know how to fix it, but I'll post more here if I find anything. I still welcome any insight from those of you who recognize what may be going on! Thanks in advance!
  11. Here’s an unusual issue I’ve never seen before. I have a page called "Settings" that uses a page reference field to allow an administrator to construct and reorder pages for the main navigation menu. That field references 6 separate pages. The navigation menu template gets its PageArray() from the page reference field I just described, and prepends the site's homepage ('/'). That makes a total of 7 pages in the PageArray(). On just about every page of the site, I see all 7 pages in the navigation menu, no matter where I navigate. But on one particular page, only 6 pages appear in the menu. Missing is the current page being viewed. I’ll call this the problem page. If I change the template of the problem page to some other template, it appears in the navigation again, even at the problem page's URL. But I have other pages that appear in the navigation that use the same template as the problem page, and they don’t disappear from the navigation when I navigate to their URLs. I can’t find any difference in publication status or permissions between the problem page and the working pages that have the same template as the problem page. But maybe I’m not looking in the right place. I’m totally baffled. Can anyone suggest steps I might take to troubleshoot this? Using TracyDebugger, I have already used bd() to output the navigation PageArray() on the problem page and other pages, and verified that the problem page really is absent from the array when viewing the problem page URL. But I don’t understand why or how to fix it.
  12. Thank you for the perfectly comprehensible explanation! Not only does this solve the problem, but I see that it's a setting I can adjust form-by-form, in case I need something more complex in other contexts!
  13. Thank you, @netcarver and @DV-JF! So I go into this with my eyes open, what are the implications of turning off CSRF protection? Based on the description above, matching the submission with the session that saw the form may mitigate spam. Are there other perils I should know about that the default CSRF protection may defend against? Or is it an overzealous countermeasure when it comes to a simple contact form?
  14. Thank you, netcarver! I grepped my whole site directory for "sessionAllow" earlier and couldn't find anything. I just had a chance to dump $config into ready.php and here was some of the session-relevant output: <!-- ["sessionAllow"]=> object(Closure)#6 (1) { ["parameter"]=> array(1) { ["$session"]=> string(10) "<required>" } } ["sessionChallenge"]=> bool(true) ["sessionFingerprint"]=> int(1) ["sessionForceIP"]=> string(0) "" ["sessionCookieSecure"]=> int(1) ["sessionCookieDomain"]=> NULL ["sessionHistory"]=> int(0) -->
  15. OOOOOOOHH! That makes sense. Yes, I am using a FormBuilder form on the site. Disabling cross-site scripting protection sounds bad, but I don't understand the relative risks or dangers. What are the trade-offs? If you disable XSS protection for the plugin, are there other reasonable countermeasures one can take?
  16. Thank you, @netcarver! Yes. The code in the blog post had the admin path as /processwire/, and I changed it to /my-admin-path/ —but that was the only change I made. I replaced it with the code you posted, and I'm seeing the same behavior. I feel stumped.
  17. Same test: $config->sessionAllow = true; curl -I https://cyclexo.com/ HTTP/2 200 date: Tue, 01 Jun 2021 18:02:34 GMT server: Apache expires: Thu, 19 Nov 1981 08:52:00 GMT cache-control: no-store, no-cache, must-revalidate pragma: no-cache x-powered-by: ProcessWire CMS set-cookie: wires=puiah8o9og8bspm6frk2q2litk; path=/; secure; HttpOnly tt-server: t=1622570554533288 D=64984 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block content-security-policy: upgrade-insecure-requests; strict-transport-security: max-age=300 content-type: text/html; charset=utf-8 And $config->sessionAllow = false; curl -I https://cyclexo.com/ HTTP/2 200 date: Tue, 01 Jun 2021 17:59:52 GMT server: Apache x-powered-by: ProcessWire CMS expires: Thu, 19 Nov 1981 08:52:00 GMT cache-control: no-store, no-cache, must-revalidate pragma: no-cache set-cookie: wires=uiid7c27b3gfnh3tkds12283lv; path=/; secure; HttpOnly tt-server: t=1622570392087006 D=433082 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block content-security-policy: upgrade-insecure-requests; strict-transport-security: max-age=300 content-type: text/html; charset=utf-8 This is with $config->sessionAllow at the bottom of my config.php file, without any other session config. Is that the right place to set this? Is there anything that might be overriding this elsewhere? Thanks again!
  18. 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!
  19. 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!
  20. 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.
  21. 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?
  22. 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]
  23. 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!
  24. 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!
  25. Thanks, @elabx! Perhaps module development is the next step on my ProcessWire education path. I hope I can figure out extending RepeaterPage first. 🙂
  • Create New...