Jump to content

teppo

PW-Moderators
  • Posts

    3,208
  • Joined

  • Last visited

  • Days Won

    107

Everything posted by teppo

  1. Another example of creating fields/templates during module install: https://github.com/apeisa/Discussions/blob/master/Discussions.module#L280. That code is 10+ years old and a bit verbose, but that's exactly why it's (in my opinion) a good example. No abstraction layers, no potentially confusing shortcuts, etc. ?
  2. This is why I always prefer the inline mode for CKEditor: very little is done until needed, which speeds things up nicely, yet setting up a new RTE field (when it is needed) takes maybe a few hundred milliseconds (assuming scripts and/or styles need to be loaded, otherwise it's nearly instantaneous). No matter how you do it, adding elements to DOM tends to slow things down. The more you add, slower things get. That is why Ajax loading is great for things that are needed rarely, while things that are needed most of the time can and should be loaded right away ?
  3. Article looks great, but their licensing model is indeed problematic. Folks at Bolt likely got a custom license (or perhaps paid OEM license) to use it, but on what terms is hard to say — I couldn't find specifics about their licensing terms. Only thing they do say is that it's available for use "in Bolt itself", which is a bit vague. It's up to Ryan whether he finds this interesting enough to contact Imperavi and query about license ? Either way, I wouldn't count CKEditor 5 out of the race quite yet. To me personally it looks UI/UX wise like a solid upgrade over CKEditor 4. I do remember that it seemed potentially "too different", and there were some relatively basic features (which I can't for the life of me remember anymore) from v4 that the devs originally said would be very difficult or nearly impossible to implement in v5, but that was a long time ago so perhaps things have changed. First of all, CKEditor 4 being EOL'd in 2023 is a huge reason to move on. There's no guarantee of updates after the EOL date, which includes potential security updates. ProcessWire is relatively safe since most of the time CKEditor is used by trusted users, but there are cases where that isn't necessarily true. And even if it was, there could still be vulnerabilities that third parties can abuse. In my opinion it's painfully obvious that we must drop CKEditor 4 support from the core at some point in the future. If some prefer to keep using EOL'd software (which I would personally recommend against), there's always the possibility of stripping it from the core and converting into a separate, possibly community-supported module. For me personally CKEditor 5 seems like a logical next step, but admittedly I've not used it enough to know if it's really going to be feasible, let alone how much work it will require. It's a good idea to check out what else there is, but CKEditor has quite a few things going for it as well: plenty of features, solid UI/UX, longevity of the project, active community, being open source with no costs or limiting licensing rules, etc. As for ease of use, I absolutely agree that this is vital. And in this regard CKEditor 5 feels like a big step up — if anything it feels less confusing and more streamlined than earlier versions. I would not expect my/our clients to have any trouble with it. Give it a try and see for yourself, and do keep in mind that CKEditor 5 is configurable: features you don't need can be disabled ? Just my two cents. 100%.
  4. No worries, this is always an interesting topic to discuss, as off-topic as it may be. My answer will be a bit lengthy, so I'll wrap it in a spoiler tag (feels overkill to split this into new topic) ?
  5. This module has been superseded by SearchEngineFileIndexer and there will be no further development for it. --- This module is an optional — and experimental — add-on for SearchEngine. It adds support for indexing PDF file contents. While SearchEngine is technically able to index file fields and contained Pagefile(s), it will natively only store the name and description of each file (and hopefully soon custom field values as well). This module hooks into Pagefile indexing and, if said Pagefile looks like a valid PDF document, attempts to extract human-readable text from the file itself. Getting started is straightforward: install and configure SearchEngine, install SearchEngine PDF Indexer, and choose which PDF parser library you'd like to use. The rest should happen automagically behind the scenes. GitHub: https://github.com/teppokoivula/SearchEnginePdfIndexer Composer: composer require teppokoivula/search-engine-pdf-indexer --- Now, as you may or may not know, PDF files are notoriously difficult to process programmatically. For this reason a) we're going to rely on third party libraries to handle parsing them, and b) things can still go wrong, so please consider this module an early beta release. It did work in my early tests, but there's little guarantee that it will work in real life use cases, and as such I'd recommend backing up your site before installing/enabling this module ? Also: while this module can be installed via the admin or by cloning/downloading module from the GitHub repository, please note that you need to run composer install in the module's directory — or preferably install the whole module via Composer. This is mainly because I really don't like bundling dependencies with the module, especially when there's a bunch of them. (... although if you dislike Composer or for whatever reason can't use it, feel free to load either smalot/pdfparser or spatie/pdf-to-text manually. Just make sure that they're available by the time the module's class file is constructed.) -- If you get a chance to use this module, please let me know how it went ?
  6. Just to be clear: CKEditor 5 is licensed under GPL, unless I'm mistaken. LGPL would likely be less of an issue (if not a non-issue), since it's relatively permissive (no strong copyleft, dynamic linking with proprietary code allowed, etc.) Anywho — very interesting to hear that there's a (likely) roadmap to 5 in the future ?
  7. Generally speaking I second what Bernhard said above. Custom tables are rarely a good idea — though there are some exceptions ? Now, as for your error: As the error states, the problem is not that you don't have access to $database — that part works just fine. The issue is that in this case $database does not provide a method called "getIndexes". This method was added in ProcessWire 3.0.182, so the first thing to check is your ProcessWire version. If it's earlier than 3.0.182, this error is expected. If it's a later one, then we can continue debugging from there. Also, as a loosely related note, the use of getIndexes() seems a bit odd here. Usually one would use $database->getColumns() (which, just for the record, was added in ProcessWire 3.0.180) to display column names/labels ?
  8. Sorry for the delay — Combo field is now supported in SearchEngine 0.31.0. The end result should be very similar to that generated by @xportde modification to Indexer, but I decided to implement it in a slightly different way. Let me know if you run into any issues with this solution, though. Just trying to figure out an approach that would/could work for other, yet unforeseen fieldtypes in the future ?
  9. Good day, Ivan. Glad to hear that you're enjoying Wireframe ? Could you clarify how you're calling such methods in case of regular views? You should be already able to access component class methods from a component view with $this->method_name, similar to they way you access controller class methods from regular views. Both Controller and Component base classes implement MethodPropsTrait, which enables this behaviour. But if you're looking for something along the lines of View::getController(), ComponentView didn't have a direct method for that. Pretty sure this was originally by design (to keep component views from becoming too complex), but I've added a similar method in latest version (0.26.0) just in case: ComponentView::getComponent().
  10. Modules directory: https://processwire.com/modules/page-render-find-replace/ GitHub: https://github.com/teppokoivula/PageRenderFindReplace This module applies replacement patterns defined via TextformatterFindReplace globally to page rendering. All the heavy lifting is done by TextformatterFindReplace (thanks, Ryan!) so this module is just a wrapper around said module plus a bunch of config settings — a few options for selecting matching pages, an option to log replacements as they happen, etc. Long story short, on recent projects I've been running into issues with temporary (development) domain creeping into URLs here and there. While not a major issue, this is annoying and takes some time to correct. Originally I was thinking of building a module that would handle text replacements and log them so that they can be manually fixed later, but TextformatterFindReplace already handles the replacement part quite nicely, so I figured I'd just make use of it, apply replacements to rendered page content instead of individual fields (works better for my use cases, where content is often rather dynamic), and add some logging. Hope someone will find this useful. Please note, though, that this module is not well tested yet so there may be bugs etc. ?
  11. One option is to put them in a single directory. Some may see this as being less elegant, of course. Personally I don't mind, and have done that on multiple occasions ? That being said, I would assume the modules directory to be fine with it as long as there's a module file and/or separate info file for the main module in the root directory, with any "additional modules" in their own subdirectories. Though this is largely guesswork, as I'm not familiar with the way the GitHub parser in modules directory actually works. I've seen quite a few cases where the repository name doesn't match the module name (or has a prefix, such as processwire-[module name]) so I'd be surprised if that's the issue.
  12. Personally I'm a big fan of Form Builder and there are very few cases where I wouldn't use it. The builder and built-in actions are super flexible, it's often a requirement (or at least preferable) for site admins (content editors) to be able to customize the form, and by adding some hooks one can achieve pretty much anything with it. As it happens, I've also built a few e-commerce checkout forms with it, and would definitely do it again ?‍♂️ Cases where I usually go with a custom form are one-off cases with heavy focus on accessibility, super specific layout requirements, mostly custom inputs (which are of course possible to handle with Form Builder, but not exactly straightforward), or loads of custom JavaScript logic. I'll admit that this is quite opinionated, but I've never found the API way of generating forms particularly useful: for me at least markup is both easier and faster to generate without it (particularly if there are specific requirements), validation is in most cases a relatively minor issue — unless it's a very complex setup, in which case there are brilliant third party tools available — and core features such as $session->CSRF->renderInput() and $session->CSRF->hasValidToken() work just fine without it. Long story short: it's either Form Builder or custom form implementation for me ?
  13. "Allowed memory size exhausted" is often a sign of a loop somewhere, but in this case it's more likely just an issue with your hosting environment or PHP configuration: 16777216 bytes = 16 megabytes, which is quite a small amount of memory. It's not surprising that it keeps running out. Is this an actual limit of your hosting package, or have you configured PHP to only use 16M? Either way I would recommend raising the limit to at least 64M, or preferably 128M.
  14. Thanks for the heads-up — docs were out of sync with current structure. Updated now! Just for the record, layouts used to live in /site/templates/views/layouts/, but based on user feedback the "views" part was removed and now it's just /site/templates/layouts/.
  15. Very nice addition, thanks Ryan! ? This is actually one of the features of a general purpose utility module we install on all our client sites, so will definitely be using this option in the future.
  16. The gist of this issue is that $sanitizer->email() is a just a very thin wrapper around PHP's filter_var() with FILTER_SANITIZE_EMAIL. Since FILTER_SANITIZE_EMAIL doesn't, at least as far as I know, support non-ASCII letters, neither does $sanitizer->email(). In my opinion it would make sense to handle this at core level, but in the short term your best bet might be writing your own function for sanitizing these addresses, or alternatively using some existing library. One relatively straightforward solution might be converting the address to ASCII (PHP has idn_to_ascii() for this), validating that, and if it's valid then assuming that the original address is valid as well. (By the way: feel free to open a feature request for this at https://github.com/processwire/processwire-requests. Or alternatively an issue at https://github.com/processwire/processwire-issues, though technically current implementation "works" — it just doesn't support international characters, which are a later addition to the spec.)
  17. I know this is not exactly what you were asking for, and it's based on an older version of PrivacyWire so there may be an easier way to do it now, but here's how I handled a similar need (just in case it's of use to you or someone else here): <script> window.cookieConsentUpdate = function(do_update) { do_update = typeof do_update === 'boolean' ? do_update : true; let privacywire_data = window.localStorage.getItem('privacywire') ? JSON.parse(window.localStorage.getItem('privacywire')) : ''; window.cookie_consent = { 'necessary': privacywire_data ? (Boolean(privacywire_data.necessary) ?? true) : true, 'functional': Boolean(privacywire_data.functional) ?? false, 'statistics': Boolean(privacywire_data.statistics) ?? false, 'marketing': Boolean(privacywire_data.marketing) ?? false, 'external_media': Boolean(privacywire_data.external_media) ?? false }; if (do_update) { // this is where you could send data to GA etc. } } window.cookieConsentUpdate(false); </script> Now just have this function run when cookie settings are changed; do_update will default to true, and any custom code in the if block will be triggered.
  18. Also curious about this one. Is lazy-loading enough to make number of fields a non-issue? Mostly just thinking out loud here, but I do see at least one benefit in sticking with fewer fields: your fields may remain more manageable, especially if the alternative is to have a lot of very specific fields. Consider having to make the same change to settings of 50 fields compared to 5 fields, for an example. (Of course assuming that they are identical enough for this to make sense in the first place.) On the other hand I guess that under some circumstances more fields could even be good for performance, considering that each field has a separate table. This seems unlikely to cause noticeable difference, though, unless we're talking about an absolutely massive scale ?
  19. Thanks, glad to hear you like it ? Did you add the "outer" Repeater Matrix field to indexed fields as well? SearchEngine goes through all indexable fields (supported and configured to be indexed), and it should work fine with nested Repeater or Repeater Matrix fields, as long as every containing field is also set to be indexed. Thus if you have field rm_1 with another matrix field rm_2, you need to add both rm_1 and rm_2 to indexed fields. Anyway, let me know if it still doesn't work and I can take a closer look!
  20. Quick note on this: I can definitely see how this could be an issue, and if you require full control over error messages then shutting down browser errors and relying on PHP defined ones instead is a good option. That being said, personally I tend to keep browser level validation enabled due to a few reasons: Although these errors are "defaults" and it's difficult to alter them (constraint validation API is an option, but at least in my experience it's a bit heavy to use), these messages should be in the language chosen by the user. Not the language they're browsing the site in, but the language they're using at OS / browser level. Thus translating to the language of the site may, in some cases, have negative consequences. Personally I like to get feedback early, and thus it feels more intuitive when errors can be displayed before sending and processing the form. Finally I prefer to rely on HTML validation if/when possible for accessibility. PHP generated errors can be added in a way that makes them properly accessible, but it takes a bit of extra work, and typically requires some JS as well. At least in theory HTML level validation features should have the widest possible support ? Anyway, just saying that there are valid reasons for both approaches — combining front-end and backend validation, vs. backend validation only.
  21. Hey @bbeer, Is this related to a specific module, or are you generating PDF with custom code? Asking because a) if it's related to a specific module I can merge this topic with the support thread for that module, and b) if it's custom code, we would have to know a bit more about how you're generating those PDF files. NSURLErrorDomain:-1017 is an error code that apparently means the browser was unable to parse response. If it works on other browsers it could be a browser bug, or some sort of incompatibility between your PDF generation method / its result and the PDF parser in Safari.
  22. If possible, I would check if it works with latest dev version. There have been some selector related fixes, including one that affects strtotime and created/modified/published.
  23. Hey @Ivan Gretsky, I don't see anything wrong with your approach. This is not something I had specifically planned for, but as you've noted above, it works thanks to the autoloader setup ? Only "issue" — and it's not much of an issue to be honest — would be that technically /components/Blocks/ should be the "view path" for a component called "Blocks". I can't really think of any real world situation where this would cause problems, though. The approach Zeka took in earlier posts effectively created a whole new type of components, in some ways more strictly separated from the built-in component structure. I'd say that it's largely a matter of preference.
  24. Hey @Ivan Gretsky Good question, and sorry for taking a while to respond ? In this case the first example was, simply put, a mistake — it didn't work at all. Thanks for spotting that, it's fixed now in the docs ?? As for a best practice of sorts, in my opinion in Controller context one should preferably refer to view as $this->view. Referring to it as $this->wire('view') or $this->wire()->view etc. will work as well, but there's a slight chance that it's a different view. To be honest the "different view" situation is a bit of a border case, and something you're unlikely to run into, so usually this won't really matter. It could, though, happen if a) someone has intentionally provided a new View object to a Controller or overridden the $view API variable (in site/template level code or a module), or b) while using ProcessWire's multi-instance support and rendering content from two instances simultaneously. Personally I also prefer $this->view because it makes sense to me and is (IMHO) syntax wise cleaner than the alternatives. Components are indeed a bit different. First a little dive into the technical background: The Component base class extends ProcessWire's WireData class, and thus when we set $this->title in the example above, what actually happens is that the value gets stored in a local data array, so that $this->data['title'] now contains the value we set for title. When the component is rendered (Component::render() is called), everything stored in that local data array is passed to an instance of the ComponentView class, which makes it available in the view file. In other words the View object doesn't come into play at all. ComponentView has certain similar qualities to View, but it's more limited (in both features and scope). And when I say scope, what I mostly mean is that components are intended to be their own "sandbox", so that what happens in them doesn't directly affect the "outside context", i.e. Page specific view(s), or the layout. What happens in your last example is that you are storing a value in the "global view" instead of the local context of the component in question. This does make it available in the component, since ComponentView extends ProcessWire's TemplateFile which in turn makes it work, but I would say that this working (in some situations) is more a side effect than an intended result ? The reason it won't work when rendering components outside of templates fully handled by Wireframe is, as far as I can tell, that in this situation only the necessary parts of Wireframe are initialized. Global View API variable is not one of these. (Honestly this is somewhat fuzzy area for me, and I would've expected $this->view->headline to throw some sort of notice/error.) Reading your post does make me wonder if components should actually provide a "fake view" to make passing variables to their own view layer more in line with controllers, but at this time I'm unsure if this is a good idea. Technically speaking it would be a backwards compatibility break, since someone might currently rely on having access to the "real view". Anyway, this is probably a bit off-topic; the long story short is that "yes, data is passed from components to their views in a slightly different way" ?
×
×
  • Create New...