Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by johnstephens

  1. Ok, I've made some headway and wanted to post a field note. First, I realized the selector string in the above text would only search the default language fields for each page, which isn't useful for getting content from the other languages. I created a function to append the language ID to each field: $search_fields = [ 'title' , 'headline' , 'subtitle' , 'summary' ]; function fields_selector_string ($search_fields, $language) { $lang_search_fields = $language->isDefault() ? $search_fields : preg_filter('/$/', '.data' . $language, $search_fields); return implode('|', $lang_search_fields); } Then I replaced that part of the selector string with the language-aware version: $matches = pages()->find(fields_selector_string($search_fields, user()->language) . "%=$q, has_parent!=2, limit=$limit"); bd($matches, 'Current lang matches'); // Dump the matches for the current language using TracyDebugger foreach (languages() as $language) { if ($language === $current_lang) continue; user()->language = $language; $lang_matches = pages()->find(fields_selector_string($search_fields, $language) . "%=$q, has_parent!=2, limit=$limit"); bd($lang_matches, 'Otras lang matches'); // Dump mathces for other languages using TracyDebugger $matches->append($lang_matches); user()->language = $current_lang; } The good news is, the Tracy barDumps list a reasonable number of matches for each language, and spot checking the pages included, they appear to be correct. The trouble is, pagination is still messed up. For one, for a sample search query, "Current lang matches" has 30 items, and "Otras lang matches" has 17. But after appending them, $matches->getTotal() shows 42. But the bigger issue is that the pagination shows links to 5 pages of results, of which only the first 3 are populated. My hunch is, the page will only display results in the current language, even though the $matches PageArray has additional items in it. Does anyone here know how to display the content from the non-current language that is appended? Thanks in advance!
  2. Hi! I'm working on a search page for a multi-lingual website. I want to start by showing matches for the user's current language, then append matches for other languages. Here's what I currently have: $current_lang = user()->language; // $q = the query input, sanitized as a selector $matches = pages()->find("title|headline|subtitle|topics|summary%=$q, has_parent!=2, limit=$limit"); foreach (languages() as $language) { if ($language !== $current_lang) { user()->language = $language; $matches->append(pages()->find("title|headline|subtitle|topics|summary%=$q, has_parent!=2, limit=$limit")); } } user()->language = $current_lang; This appears to have two issues: The pagination gets all wonky, showing more pages of results than actual content; and, (I think this is related) It doesn't seem to append any actual content from the other languages. When I noticed the pagination bug, I realized it could be because I set the limit selector twice. I removed it from the selectors above and added another line after appending the matches from other languages as follows: $matches = $matches->find("limit=$limit"); Of course, that didn't work either. I'm curious, what is the correct way to set a limit for a pagearray which has been assembled with append() (or prepend()). And what is the correct way to query all content, while giving priority to content in the current language? Thanks in advance!
  3. I've done a lot of testing, and my hunch is that the script is running out of memory—specifically when I invoke bd(). What I'm doing is this: Query a MySQL database with $database->query(). Use foreach to loop through the results. Each iteration of the loop, I select a $parent page based on data from the query and create a new page with $pages->add(). If I invoke bd() within the loop, TracyDebugger fails to load. If I don't invoke bd() in the loop, the debug bar loads.
  4. I'm willing to share it, but I don't know how much would be useful. I started with something like this: This problem of TracyDebugger failing to load came up after adding code to compose the site's parent/child hierarchy using the imported articles. The specific lines that throw the fatal error are these: $newArticle->alert->setLanguageValue($en, $article['alert_en']); $newArticle->alert->setLanguageValue($es, $article['alert_es']); When those lines are included, Tracy's debug bar loads and shows me the stack trace of the error. The reported error is "Call to a member function setLanguageValue() on null", which doesn't make sense to me. I verified that the 'alert' field is attached to the template AND that it's correctly configured as a multi-language textarea (as opposed to a regular textarea, which wouldn't support the setLanguageValue() method). I commented out those lines to simply dump the $newArticle object using bd(), and the actual script executes without any errors or warnings—but then Tracy's debug bar vanishes. I wonder what could stop the debug bar from loading? I hope this helps. Thank you, @adrian!
  5. No. No errors in the browser console, nor do I see any errors logged in ProcessWire's error log under "Setup » Logs". For what it's worth, the page does not seem to be loading any front-end scripts at all from TracyDebugger. On other pages where the debug bar loads, I see a huge wodge of markup appended to the markup I wrote, starting with <!-- Tracy Debug Bar -->. The affected page has no appended script elements at all. I see I can make the debug bar appear if I uncomment two lines of code that were throwing a fatal error.
  6. Hello! I wondered if anyone knows how to troubleshoot this. I have one specific page where the the Tracy debug bar doesn't load, so I can't access the output of bd() and other Tracy functions. The debug bar does appear in the ProcessWire back-end and every other front-end page I checked. My first thought was that, for some reason, ProcessWire didn't think I was logged in as a superuser on that page, but I echoed $user->name, and it showed my superuser username. For good measure, I also echoed $user->hasPermission('tracy-debugger'), and got the output "1". I checked the TracyDebugger module settings to see if I misconfigured something, and couldn't find anything obviously wrong: "Enable TracyDebugger" is checked. "Output mode" is set to "DEVELOPMENT". "Force superusers" and "guest users into DEVELOPMENT mode" are both unchecked. I checked them and reloaded just in case and got the same behavior. "Show debug bar" is checked for "Frontend" and "Backend". "No debug bar in…" is unchecked for all modes. I'm sure the solution will seem obvious in hindsight, I just can't foresee it. Thanks in advance for any guidance!
  7. I wanted to update this thread because I had to solve some unexpected problems when importing my content. Maybe documenting this will save someone else the struggle—even me, if my memory fails and I search the forum for answers to the same question. Firstly, my site requires multi-language URLs, and titles. This requires some deliberate configuration with the multi-language modules that must be taken care of BEFORE attempting to import data. This seems obvious in hindsight, but I assumed that these features were enabled by default once the core Multi-language module was active. One thing I noticed when attempting to import data was that the setLanguageValue() method would not work for the name field, even after enabling multi-language URLs. I had to do a lot of searching the forum before finding out that the language-specific name fields have a different way of assigning values via the API than what I could find in the Multi-language documentation. In the end, using the API to assign appropriate data to the fields in ProcessWire required two incantations that I failed to find in the Multi-language docs: In order to make the non-default language(s) "active", I had to use the page()->set() method to establish a hidden property "status$language". This property did not appear as unset when I buffer dumped the page() using TracyDebugger. Assigning the URL title (commonly called the "name" in ProcessWire) in the non-default language(s) required using the same set method to establish a "name$language" property. Here's a stripped down, abstracted example of my working import script, so far. <?php namespace ProcessWire; $en = languages()->get("default"); $es = languages()->get("es-es"); $articles = = database()->query(" // Magic SQL query here "); foreach ($articles as $article) { $parent = pages()->get('/' . IMPORT_SECTION); $template = templates()->get('my-article-template'); $newArticle = pages()->add($template, $parent); $newArticle->set("status$es", 1); $newArticle->title->setLanguageValue($en, $article['Title_en']); $newArticle->title->setLanguageValue($es, $article['Title_es']); $newArticle->name = sanitizer()->pageName($article['url_title_en']); $newArticle_name_es = sanitizer()->pageName($article['url_title_es']); $newArticle->set("name$es", $newArticle_name_es); $newArticle->body->setLanguageValue($en, $article['Body_en']); $newArticle->body->setLanguageValue($es, $article['Body_en']); // Etc., setting each field's value using setLanguageValue() method $newArticle->save(); } I have moved on to other aspects of the project, but I wanted to post this before I forget. It makes me wonder what else I'm missing out on, and how I might learn to do this better. Thank you!
  8. Supposing I have pages that include the comments fieldtype in their template. How do I sort those pages with the page with the most recent comment first, descending by less recent comments? Thank you!
  9. 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().
  10. 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!
  11. 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!
  12. 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.
  13. 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?
  14. 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.
  15. 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!
  16. 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.
  17. 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.
  18. 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!
  19. 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.
  20. 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!
  21. 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?
  22. 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) -->
  23. 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?
  24. 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.
  25. 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!
  • Create New...