Jump to content

FireWire

Members
  • Posts

    582
  • Joined

  • Last visited

  • Days Won

    41

Everything posted by FireWire

  1. I'm pretty sure you're right about that. That's a good catch of my try (I'll show myself out) πŸšͺπŸƒβ€β™‚οΈ Embrace the fatal error, and if the situation demands it- ask for another πŸ˜†
  2. That's very interesting @BrendonKoz and good to know for everyone who stumbles upon this issue. I've been writing software for many years and haven't run into this, but I've never caught/rethrown database level exceptions for a few reasons, now this one as well. The main concern I have about casting the error code to an int will erase the code entirely since it has alphabetical characters, and that information may be important to debugging. Example: <?php // An unreasonably friendly error $error = 'hello1234'; echo (int) $error; // <= outputs 'int(0)' @Mark_invisu To get a true fix for your sites, it would be a good idea to get a better look at what is happening deeper in your setup. If you modify the core code to handle strings by casting to ints, you'll have modified the core code to bypass an issue that is not relevant to your problem. Take a look at L253 in /wire/core/FieldtypeMulti.php <?php try { // since we don't manage IDs of existing values for multi fields, we delete the existing data and insert all of it again $query = $database->prepare("DELETE FROM `$table` WHERE pages_id=:page_id"); // QA $query->bindValue(":page_id", $page_id, \PDO::PARAM_INT); $query->execute(); } catch(\Exception $e) { if($useTransaction) $database->rollBack(); if($config->allowExceptions) throw $e; // throw original (L253 HERE) throw new WireDatabaseQueryException($e->getMessage(), $e->getCode(), $e); } What you really want to be troubleshooting is the database issue that is causing the exception to be thrown in the first place. The original exception will contain the information and further details you need. My recommendation is to tell ProcessWire to throw the original Exception from PHP rather that catch/throw a WireException derived object. You're still going to get an exception, but it will contain all of the error details you need and doesn't require modifying the core. <?php // ... rest of /site/config.php $config->allowExceptions = true; I think this is the best way to fix your issue now, and then if/when the issue with the WireDatabaseQueryException is handled in the core, you can upgrade in the future where a patch may be implemented. The good news is that exposing the base exception should give you all of the information you need without possibly needing to dig through additional logs. It is worth noting that the logs will likely be inaccurate because they'll be logging the ProcessWire variable type exception and not the database exception. If you can share the stack trace that you should see when enabling exceptions it would be of interest to others that may be seeing this issue. I'm also personally curious even though I haven't run into this myself.
  3. @Mark_invisu Hey, sorry to hear you're having trouble. I just uploaded a 30mb file to a ProcessWire install (latest version) and it worked as expected. I think that your host may be a factor in this issue since you did have issues with all of your sites at the same time. Hosting companies can make trouble for anyone on any CMS unfortunately. Here are a few things you can try taking a look at. POST upload size. You did mention setting up .ini to accept larger files, but it would be worth checking off your list if you can confirm that the post_max_size parameter is slightly larger than upload_max_filesize. So for accepting 64mb files, upload_max_filesize=64M and post_max_size=65M. I've missed this detail before. HTTP response code. In your browser developer tools, switch over to the "Network" tab and then attempt to upload a file, then look at the return HTTP response code. Anything other than 200 indicates a problem. Hosting server security. Hosting companies can be overzealous with their security settings. A specific example is ModSecurity which can cause web applications to choke either due to overly strict settings or false positives. Depending on whether the hosting company is using it and how it's configured, your HTTP response may help indicate an issue. A hosting company I've used updated their rules and suddenly some requests from ProcessWire failed with a HTTP 418 response on all sites I had on their server at the same time. Cute, but frustrating. If you see anything like that it could be a good indicator that this may be an issue. It's not a sure thing since security rules can be configured to return any HTTP code. Server logs. If you can access them, check out log files outside of ProcessWire, specifically access_log and error_log. The error_log file may be useful since that is where you'll likely find log entries for server security hits. If you see something similar to this: [Wed Apr 16 19:02:07.918136 2025] [authz_core:error] [pid 3599862:tid 128359658948288] [client X.X.X.X:XXXX] AH01630: client denied by server configuration: /some/path/on/your/server/here then you're seeing something block the action you're trying to take when uploading. ModSecurity also logs to access_log and error_log if I remember correctly. PHP logs. If you can access the logs for PHP itself it might be helpful. Entries in a log like php8.3-fpm.log usually contain errors/exceptions that the application/ProcessWire generally see and log themselves, but checking is a good idea to be thorough. Digging into information outside of ProcessWire will probably be the most helpful. ProcessWire logs errors and exceptions pretty consistently so the fact that you aren't seeing any log entries generated in the PW admin makes me think that this is something failing outside of PHP execution and the result isn't visible to PHP itself. That may or may not be true, but looking at the items above would be the first places I start. If you're coming up short after doing more research, you may need to hop on a chat with the hosting support team so they can take a look at anything that you may not have access to or control over.
  4. I think Ryan mentioned that core is getting 8.4 compatibility fixes so I assumed 8.3 was taken care of. The few issues that I've experienced with 8.x PHP versions are the newer more strict null values being invalid for native PHP functions. I'm running Tracy which has been pretty good catching both errors and warnings so I'm not 100% convinced it's a PHP version issue, however I'm not against trying. I use DDEV and switching PHP versions is cake. I'll give it a shot.
  5. @wbmnfktr I welcome "that guy", thanks for asking haha. PageListCustomChildren is installed but not configured. I'm not familiar with VirtualParents, so gonna be a no on that one. What is odd is that this is happening on some pages but not others. I tried removing modules and hooks but couldn't get any different results. I'm assuming this may be something that's happening in my install rather than some sort of bug, I just don't know where to start looking. ProcessWire 3.0.246 PHP 8.3
  6. Seeing an odd issue when editing pages. The page list under "Children" should have the page currently being edited as the root page. Example- the page list should show pages under "Directory Profiles" rather than all pages under the "Home" page. So this should only show "Arosa". Haven't seen this before and not sure if it's a setting nested somewhere I'm not familiar with. Disabled all custom hooks, no dice...
  7. @bernhard Excellent! It took 6 months and a bot attack to get to that number. We were getting many requests per second so this is probably not something many users experience. I'll call it "accelerated testing" 🀣 Thanks for the fix!
  8. @bernhard Admittedly I just had to run some updates to the server firewall because we were getting hit with serious amounts of malicious traffic, so I don't think these may be numbers most RockMigrations users are going to see haha.
  9. The lastrun log file accumulates a lot of entries and is never automatically pruned/cleared. Production server has a ~50mb file with 1.5 million entries. The log file contents are not written in a way that ProcessWire can parse. Is this log file necessary for RM to function properly? The log entries are accumulating even when migrations are disabled.
  10. @bernhard So glad it helped out! Nice to know that it addressed another challenge. Your modules are so great to work with and really improve the developer and user experiences. The less time you spend fixing things is more time you have for building awesome stuff, so I'm happy to help 😎
  11. @bernhard I really like this direction with adding something next to the languages, it makes a lot of sense and does a good job showing the relationship between the button to what it does. The only concern I have is that on fields with smaller widths a larger tab size will cause some crowding next to the language tabs and cause wrapping. Example would be the description fields for images. Real world example for me: If it could be a little more minimal it would fit in a lot of places, especially if there are many languages. Experimenting with an alternate "X" style icon to differentiate it from the trash icon used to delete blocks, groups, pages, etc. Hover state A popup with a similar message would confirm both the intention and purpose of the button. Perhaps "Delete content in all languages for this field? Cancel/OK". A "delete all" action would prevent having to first manually remove the contents of the default language then click to delete the contents for all other languages. A tooltip would show "Delete content for this field in all languages". With both a tooltip and confirm popup the user would see, understand, and remember its purpose when editing content anywhere in the admin. Thoughts?
  12. Entirely understand, a task not for the faint of heart. I haven't had to implement RRule myself but I've reviewed enough documentation to know that your work is tough, but incredibly appreciated. So I offer a message of support and encouragement πŸ™Œ I have a project in dev right now that I'd be pleased to use for testing if/when you need it.
  13. @bernhard Do you see a feature for viewing and managing existing recurring events as a feature implemented in RC?
  14. @bernhard Sure thing when I can get a chance. Maybe this weekend. In the meantime, if you're importing an svg you may have some success taking a look at the markup and seeing if there's anything extra that may be added by Affinity. I had a graphics program that liked to create a lot of attributes and stuff that wasn't needed. No guarantee that's the cause but it may help. Think the List.svg button in the repo is an example of one that has good markup with no extras. That's the best guess off the top of my head.
  15. Hey @bernhard & @monollonom I didn't forget about you, just hammering out some work. Taking notes from your great input. I appreciate it! Will be back when I escape from programming prison 🀣
  16. @bernhard I wasn't able to provide a more robust response above but I wanted to mention that my concept wasn't an impulsive decision. I think my language in the confirmation popup should be changed. The "clear all" feature is a shortcut to clear all content in all languages including the default language so that it has one purpose. One of the things that I first had to consider was how often the feature gets used. Fluency has been available for over 5 years and this feature absolutely has great value but hasn't been mentioned before. I haven't heard about users/devs expressing a need to clear all content from multilanguage fields, and the general practice has been in my experience that if content changes then it would involve entering new content and re-translating. I thought about weighing how often the feature would be used compared to translation and it seemed like much less often, but I didn't have experience to go on. I also wondered if this was a feature that was use most during the initial build and population of content vs. ongoing content management. I think that was another area where the use of the feature may change over time as far as how often it's used, but again I haven't had the need so my understanding may be limited there. I'm not against the concept of a always-visible button or icon. Throughout the admin UI the trash icon is, as far as I can tell, mainly implemented for block, group, or object deletion rather than field contents. This is where the use of the trash icon without a label to explain the difference between what it means when used specifically for a field could be confusing because it does break from what it signifies elsewhere. The position of the translation action menu to the right as a clickable option felt natural with destructive actions located elsewhere. Placing it under a dedicated language icon menu seemed like it would strongly associate the action exclusively with multilanguage field features. Each field can have translation disabled, so there would have to be a decision whether to include just a trash icon even if there is no translation enabled for consistency when working with multilanguage fields. I think this could be a great convenience enhancement even if it steps outside of Fluency's current purpose and may be even be necessary for consistency. This may present another challenge because only multilanguage fields would provide the ability to delete content from the primary field that is visible where all other fields that only have primary content would need to manually be deleted. It's a step that may push a little further into ProcessWire's core behavior because some fields enable you to delete content for the default language alone, but other fields that are not multi-lingual still require a select-all-then-delete action by the user. If the trash icon is not present on all fields, would it seem like an oversight? Another thing that comes to mind is whether a multilanguage field with translation disabled were next to a single language field. On the left you can delete the primary content without deleting any other language, but on the right you can't delete the primary content with one click. The tabs hint that it's related to language fields, but non-language fields aren't afforded the same convenience even though they are visually similar to the end user. The intention is to have the clear all button clear everything in one action, so if the user is aware of the feature then they wouldn't clear any text to begin with. I think the language I used in my original "confirm" example may not have been as descriptive as it should be. It's an all-or-nothing action. The wording you used: "Are you sure you want to clear content in all languages for this field?" is much better and communicates clearly. So my approach was placing the option under an action menu since it felt natural to group secondary behaviors. The button that opens the translator is secondary and the ability to delete content in all languages is secondary compared to the primary feature of translation. I like the ideas and want to take the best approach, and I'm not against any specific implementation. Thinking through this though when you originally mentioned stepping into "core" behavior may be more impactful than it seemed when putting all different types of fields into the mix.
  17. I sketched my ideas to come back and share them with the people who suggested the feature and I haven't worked on any true implementation yet. I can assure you there's no rush, I wanted to get some feedback before diving in and coding everything. If I had made a decision in private, programmed everything, then come back and announced the new changes it would be far more work to change my approach if it had a negative reception. Luckily the custom header actions are 20 lines of code and aren't a commitment.
  18. I'm adding a header action with something similar to the following: Inputfields.addHeaderAction('title', { label: 'Some custom actions', icon: 'fa-question', menuItems: [ { label: 'Option 1', href: 'https://somedomain.ddev.site/admin/page-to-show/', modal: true, active: true, callback: null, }, { label: 'Option 2', callback: function() { ProcessWire.alert('Shows option 2'); }, active: true, }, { label: 'Option 3', callback: function() { ProcessWire.alert('Shows option 3'); }, active: true, }, ] }); When there is a combination of types of actions then the options that execute a callback will trigger the option that executes a href/modal. When clicking the option that opens a modal, the other options are not triggered. Example that opens the "Logs" page in a modal. Clicking "Option 2" executes both the callback and opens the modal in "Option 1": The same occurs if "Option 3" is clicked. I'm trying to figure out if this is something I'm doing wrong or if there's a bug when mixing option types. I was able to create a workaround by adapting this code by @bernhard that uses a callback to programmatically open a modal: Inputfields.addHeaderAction('title', { label: 'Some custom actions', icon: 'fa-question', menuItems: [ { label: 'Option 1', active: true, callback: function() { const link = document.createElement("a"); const $link = $(link); $link.attr('href', 'https://moduledev.ddev.site/admin/setup/logs/'); $link.addClass('pw-modal'); $link.on('click', pwModalOpenEvent); $link.on('pw-modal-closed', () => $link.remove()); $link.click(); }, }, { label: 'Option 2', callback: function() { ProcessWire.alert('Shows option 2'); }, active: true, }, { label: 'Option 3', callback: function() { ProcessWire.alert('Shows option 3'); }, active: true, }, ] }); This works but doesn't use the native API. Anyone have any insights that could help? Many thanks!
  19. @bernhard I like your thinking 🀝 @Tiberium I'm glad you chimed in as well. Good to know that there are many people that will benefit from a new feature. Here's the UI I'm working towards: Going to create a new header action for translation related features. This will keep the UI tidy, clear all will be enabled by default, and doesn't need an option to enable/disable it on the module config page. @bernhard The icon to show the translator will be moved from the icon next to the translation button to the menu for consistency, since it's hover there won't be extra clicks. It will of course politely ask you if you are sure you want to nuke all of the content... I like this implementation because it will provide a good location for possible future features as well without crowding UI for fields. It will take a little bit to implement, I'm trying to keep up with work and I think I caught a bug with the custom header actions in PW core. I'll tag you both when it's on the dev branch so you can take it out for a test drive.
  20. I like to live dangerously* *please don't live dangerously Thank you for the correction of my oversight @teppo. I've edited my example to include that in case someone doesn't make it further down the comments πŸ‘
  21. @bernhard I was working on some blocks in RPB and noticed that there were some edge cases where changes weren't being detected by RPB. I ran into this with the trash icon on RepeaterMatrix items. Clicking it checks a hidden checkbox programmatically and doesn't emit a change event, so it's pretty much invisible to everything else that isn't RepeaterMatrix code. I added this mutation observer to InputfieldRockPageBuilder.js to watch for elements that have had the 'InputfieldStateChanged' class added. // trigger changed event when InputfieldStateChanged is added to elements $(document).on('ready', function () { const rpbItemsObserver = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.target.classList.contains('InputfieldStateChanged')) { RockPageBuilder.changed(mutation); } }); }); $('.rpb-items').each(function (_, rpbItem) { rpbItemsObserver.observe(rpbItem, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); }); }); In my testing this took care of some edge cases where changes aren't visible to RPB. Could be helpful for handling other sneaky inputs as well πŸ‘
  22. @protro I use this module with htmx and it works nicely. It's pretty easy to do and it can all be done in HTML without handwriting JavaScript or parsing JSON. Here's a simple example. It should work, it may need tweaking but the concept is accurate. <!-- Your search form --> <style> .search-box { position: relative; } .search-indicator { align-items: center; display: flex; inset: 0; justify-content: center; opacity: 0; pointer-events: none; transition: opacity .3s; } /* Style your AJAX indicator as you please */ .htmx-request .search-indicator, .htmx-request.search-indicator { opacity: 1; pointer-events: auto; } </style> <div class="search-box"> <form hx-get="the search URL here" hx-target="#search-results-container" hx-disabled-elt="button[type=submit]" hx-indicator=".search-indicator"> <input type="search" inputmode="search" name="q" placeholder="What would you like to find?"> <input type="submit" value="Search"> <div id="search-results-container"> <!-- Search results will load inside this div --> </div> </form> <div class="search-indicator"> <span>Searching...</span> </div> </div> hx-get tells htmx to request the page from the URL you provide hx-target tells htmx where to put the markup that it receives back from the AJAX request, it accepts any CSS selector hx-disabled-elt directs htmx to disable the submit button during the request to prevent people from clicking the button multiple times, it accepts any CSS selector hx-indicator isn't required, but tells htmx which element to add the .htmx-request class while the request is in flight and then remove it when the results are loaded for a nice "loading" display. It accepts any CSS selector On the search page all you have to do is render the results that will appear inside #search-results-container, just markup. This is a rough example, but just illustrates how simple it can be. You'll have to tailor this to your needs. You can probably use markup that the SearchEngine module generates, but I haven't used that before myself. <div class="search-results"> <?php if ($searchResults->count()): ?> <ul> <?php foreach ($searchResults as $result): ?> <li> <p><?=$result->title?></p> <a href="<?=$result->url?>">View Page</a> </li> <?php endforeach ?> </ul> <?php else: ?> <p>There were no search results for "<?=$sanitizer->entities1($input->get->q)?>"</p> <!-- Thanks to teppo for reminder to sanitize --> <?php endif ?> </div> That's the only markup you need. You'll probably need to do some additional work to make things like paging happen, but it's all doable. I cobbled this together based on some code I've already written so it's just a starting point and probably needs some tinkering. Here's a handy reference of htmx attributes that will let you do anything you need.
Γ—
Γ—
  • Create New...