Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Posts posted by teppo

  1. Probably worth mentioning that since this setting prevents ProcessWire from using unfamiliar hosts in output, it's actually pretty important:

    • Let's say that your server was configured to serve your site with any host that a visitor happens to provide. (I've seen this happen, but admittedly it's a major configuration fumble.)
    • Someone points some-weird-and-perhaps-malicious-domain.tld to your site, and then visits the site using said domain. This could be intentional, or even an accident (again this is something I've seen happen, as weird as it may sound.)
    • Finally some code — your own, or perhaps code from a third party module, or even some core feature — asks ProcessWire for the full hostname, and makes use of it in output.

    Now, if the $config->httpHosts setting didn't exist, ProcessWire would have no way to know which domains are valid, and it would just have to trust that the domain specified by the user is indeed a valid one. Any output using this potentially malicious domain could then get cached, leading to various cache poisoning related issues: redirecting other visitors to this domain, or perhaps making the visitor or ProcessWire itself unknowingly send private data there, thus granting a third party access to it.


    • Like 6

  2. Quote

    So this is where preloading comes into play: it will not only compile source files to opcodes, but also link related classes, traits and interfaces together. It will then keep this "compiled" blob of runnable code — that is: code usable by the PHP interpreter — in memory.

    And from the RFC:


    And also, this approach will not be compatible with servers that host multiple applications, or multiple versions of applications - that would have different implementations for certain classes with the same name - if such classes are preloaded from the codebase of one app, it will conflict with loading the different class implementation from the other app(s).

    While I'd love to give this a try, this limitation is a dealbreaker for me. All the environments I work with host multiple versions of ProcessWire.

    Might be another reason to move to fully containerized environment... 😄

    • Like 2
    • Haha 1

  3. Just checking: are you absolutely sure that this method returns only 50 items? Do you have any hooks or modules that could affect this... and are you checking right after, i.e. there's no possibility that the list of items was filtered before you check the number of returned items?

    $page->children() should return all the children (according to docs too) 🙂

  4. So... this may be a bit of a weird question, but does anyone have brilliant ideas for generating thumbnails for Pagefile (not Pageimage) objects?

    A bit of background: in a recent project I ran into an issue with this in a situation where there's a files field that contains many different types of files, but for image files it needs to display thumbnails. The problem is that those images are Pagefiles, not Pageimages, so they don't have any image handling features built-in.

    Current solution involves creating a new Pageimages object and a new Pageimage object, passing the image file to the Pageimage object... and hooking into the install method of said object to prevent duplicate file detection from actually spitting out an endless stream of duplicates. I did consider duplicating image files into another (hidden) field behind the scenes (did that in an even earlier project), but in the end neither solution seems particularly straightforward.

    What's the state of the art approach for this? I've got this nagging feeling that there's something obvious I've missed 🙂

  5. 16 hours ago, dotnetic said:

    As this is the support forum for the german language files, what are your opinions, about communicating in german here?

    Just an observation from "an outsider": folks who are not competent in German might still need a German language pack for their projects. It'd be a little difficult to figure out what's going on if the discussion related to said language pack was in German as well.

    Also, forum guidelines state that the language here is English — though personally I don't think it's going to be a major issue if you do decide that German would be better (in this specific context, based on a good reason; the key point being that it would be an exception to the rule) 🙂

    • Like 3

  6. 6 hours ago, adrian said:

     I don't really know what Ryan wrote the regex this way, but it means your text field must be HTML and not plain text.

    Ryan might've had other reasons as well, but... this keeps the textformatter from making a mess out of user-generated content where video URLs could be used in links, within regular text, inside table cells, in image captions, etc. 🙂

    That being said, it'd be nice if the module provided a public method for converting known single video URL into an embed code. Currently it looks a little hacky:

    echo $modules->get('TextformatterVideoEmbed')->format('<p>' . $url . '</p>')


    • Like 4

  7. 2 hours ago, spercy16 said:

    I get this error on my page and can't figure out how to fix it:

    : Invalid argument supplied for foreach() in 

    I'm a noob with PHP too and haven't quite figured out the foreach loop yet. I've looked at the PW documentation but haven't (quickly) found anything that explains it in detail. [...] FYI, I'm using the module TextformatterVideoEmbed as well to parse the videos from Youtube. I basically just have them listed in my page's textarea like this:


    Obviously they'll be unique links once the page goes live. The TextformatterVideoEmbed module requires them to be in <p> tags before exporting them to the page or I would just use the <p> or some other tag in the template file.

    If you look at the first post in this thread, you can see that this module requires a specific format in the texarea ("Converts contents of textarea field..." etc.)

    If what you've pasted above is literally the contents of your textarea field, then it won't work with this textformatter. Note, though, that this module and Textformatter Video Embed are probably not compatible out of the box due to different format requirements.

    Depending on your use case you could perhaps use PHP's explode() or preg_split() to split the value of your textarea field into an array (which could then be used in foreach), but it also kind of sounds like a Repeater field would make more sense in this case.

    • Like 1

  8. Needed a really simple solution to embed audio files within page content and couldn't find a module for that, so here we go. Textformatter Audio Embed works a bit like Textformatter Video Embed, converting this:


    Into this:

    <audio controls class="TextformatterAudioEmbed">
        <source src="https://www.domain.tld/path/to/file.mp3" type="audio/mpeg">

    The audio element has pretty good browser support, so quite often this should be enough to get things rolling 🙂

    • Like 14

  9. 3 hours ago, rmenu said:

    Overall, does this mean most of the PW code is not tested?

    In the sense that no automated/programmatic tests are used: most likely yes.

    Third party modules often don't come with any tests, and as for sites — well, I don't really know, but my assumption is that many don't have tests. ProcessWire can be used for a lot of stuff, but the most common use case are still bespoke websites, and for those testing is rarely a key requirement. Hence the gap in testing support compared to pure web application frameworks such as Laravel 🙂

    As for core code, I don't really know. Ryan used to use a set of tests for the Selector engine, but I can't say for sure what the status of that project is.

    • Like 1

  10. 6 hours ago, Jan Romero said:

    I dunno, I also get annoyed when I lose my session. It doesn’t happen every couple of minutes, but sometimes it still happens from one day to the next, even though I set the lifetime to a year.

    It's very likely that your IP will change every now and then. My understanding is that regular ISPs often charge extra for static IP addresses and (at least around here) some don't even offer this sort of service to consumers.

    When your IP changes and session fingerprinting (involving IP address) is enabled, you'll have to renew your login session. This is unrelated to session lifetime limit.

    6 hours ago, Jan Romero said:

    If ignoring IP and user-agent changes is so insecure, how does this forum do it, or pretty much all big websites for that matter?

    That's a valid question!

    In many services that I use the situation is exactly the same as with ProcessWire. if I disconnect from the company VPN (or first log in to the service and only then connect to the VPN) I'm forced to redo the login process, which in turn may involve new 2FA confirmation request. Most likely these services use a similar fingerprinting mechanism as ProcessWire.

    On the other hand I wouldn't be terribly surprised if some big services skipped this step, especially if they happen to have many "consumer users". It can indeed be problematic for some users, and on the other hand session hijacking can also be mitigated using other measures. Storing the cookies securely and so that no one should get easy access to them is the most important step (obviously ProcessWire does that as well.) After that it's more about adding extra layers of security.

    According to Invision Community documentation our forum software has IP address based fingerprinting enabled by default. They recommend keeping it on, unless it causes issues. Just to make sure I just tried "hijacking" my own session — and so far it looks like the forum doesn't really care about which IP I'm using, what my UA string look like, etc. I was able to "transfer" a session to another browser, and it continued to work even after IP address change.

    It's important to keep in mind that lacking session fingerprinting is not a security issue in itself, more like a precaution that could've (and, in my opinion, almost always should've) been taken, yet wasn't. In this particular sense our forum could indeed be considered less secure than a typical ProcessWire site where fingerprinting is enabled 🙂

    • Like 4

  11. 5 hours ago, spercy16 said:

    It's absolutely an issue and not a feature if it logs people out ever two minutes. It also should be adjustable in the admin settings regardless. Requiring users, whether or not their IT professionals, software developers, or noob end-users to edit .php files to adjust these kinds of time-outs, etc. is bad, lazy software engineering.

    I don't want to dismiss your frustration — I get that problems like this one can be really annoying! — but I do want to stress a couple of points about this:

    • This is very much a needed (even required) security feature. I wouldn't recommend disabling it unless it's causing major issues, and even then there's a 99% chance that you should just fall back to one of the "less strict" options (as mentioned earlier). Without session fingerprinting attacks involving session hijacking are a very real possibility.
    • Providing UI way to disable any security feature is something I'd be wary of. Of course it depends on the situation, but generally decisions like these should be a) made by folks who have enough technical know-how to make educated decisions knowing what the consequences will be, and b) disabling any security feature should never, ever be something you can do "on a whim" — it needs to be a decision made after serious consideration.

    Of course technical know-how and well considered decisions don't equal being a developer with access to site's config files or code, but the point is that providing an easy way to decrease the security of the system is definitely not something I'd consider a best practice. Quite the opposite, in fact.

    Also, one more thing to consider is that if someone did somehow gain illegitimate access to the admin panel, providing an UI way to disable security features could potentially allow them to escalate the attack. (This particular setting is not the best example of that, but generally speaking.)

    As for session fingerprinting: I've personally not had real problems with it, but I know others have, so not trying to dismiss this problem. It should, though, only happen if your IP or user agent string changes constantly, which is a pretty rare situation — though I'm not an expert in this subject. For me the only case where I've experienced something similar was while testing the site using developer tools, going between mobile UA string and regular UA string... 🙂

    • Like 5

  12. On 7/15/2020 at 12:45 AM, apeisa said:

    I think @teppo has done some testing with few of his modules if I remember correctly?

    I added tests for two of my modules, VersionControl and ProcessChangelog, back in the day. VersionControlTests is the more recent project, though I haven't touched or used it in years. There's only one test class in that project, and sadly I'm pretty sure it goes against so many best practices that I probably wouldn't consider it a very good starting point 🙂

    While I did use PHPUnit, it wasn't really unit testing — more like integration testing. The test class starts from a blank ProcessWire installation with required module files included, installs the module, sets up language support and adds some languages, makes changes to page(s) and after each one checks what was stored in the database, etc. In the end it attempts to restore the site to its original "untouched" condition, so that new tests can be started.

    In my experience ProcessWire involves so many interconnected parts and processes that creating "good enough" mock data would've been a major pain, and still wouldn't really have answered the question of "does this module work as expected in all supported ProcessWire versions, different operating systems, and different database system(s/ versions)". Of course there's still need for unit testing, but in my case it just didn't seem like the best approach 🙂

    As for current testing best practices with ProcessWire, I'd definitely check out Process Nette Tester. And — this is very opinionated, sorry in advance! — I'd probably steer away from PHPUnit. I mean... I'm sure it's an amazing tool once you really get to know it, but the more I've worked (read: fought) with it, the more frustrated I've become. In my humble opinion it's not particularly developer friendly, and there are too many limitations.

    Again, this might be a result of using it for wrong type of testing, so take it with a grain of salt. I just feel that there are now better options out there.

    • Like 2

  13. On 7/15/2020 at 4:03 AM, gornycreative said:

    I just started tinkering around with this haven't haven't looked under the hood a ton. Is the _auto_desc using a method to generate on the fly or is this being populated in the results somewhere that I can refer to?

    This is generated on the fly when a result is rendered. Behind the scenes Renderer::renderResultDesc() and Renderer::renderResultsJson() both get field values using Renderer::getResultValue(), which in turn calls Renderer::getResultAutoDesc _auto_desc "pseudo field" (as in: not a real field) is requested.

    There's currently no public API for accessing this directly, but if you've got a use case that can be solved by adding one, I wouldn't be against it. Though in that case I'd like to know a bit more about the context 🙂

    16 hours ago, Sevarf2 said:

    I got this error during install (pw 3.0.159 dev)

    Edit: apparently I solved updating to the latest dev version 3.0.160

    Sorry! Accidentally introduced a dependency for ProcessWire 3.0.160 in the Config class.

    This is now fixed: latest module version (0.25.1) provides proper fallbacks for core versions prior to that.

    • Like 1
    • Thanks 1

  14. Regarding a) and b) you might perhaps find some useful bits and pieces from here: https://github.com/teppokoivula/VersionControlTests/blob/master/tests/VersionControlTest.php.

    If I remember correctly, installing language support and adding new languages was indeed relatively simple, though if you want ProcessWire to recognize them right away you need to go through some extra hoops (look for "reloadLanguages" and "LS_init"). In fact reloadLanguages() was initially added for this case.

    That being said, this is some very old code, so I have no idea if it still runs (properly) 🙂

    Edit: looks like you solved it already 😛

    • Like 1

  15. 13 minutes ago, Sevarf2 said:

    Any update? I can't download the module, even from github, it's no longer available?

    Looks like GitHub itself is down right now, so this probably has nothing to do with SettingsFactory 🙂

    • Like 1

  16. Heya folks! Just wanted to say that I finally got a chance to properly test this module, and... wow. Amazing work!

    It looks like you had a bunch of additional stuff planned, but the features that already are there are very useful, and apart from a few minor glitches the module seemed to work like a charm. While the built-in template editing tools we have in the core are not at all bad, at least for me the workflow with Designme is still a huge improvement 🙂

    At this point I'm mostly curious about what else you might've had in store when you said that the module was "far from being good enough for release". @elabx, care to provide some insight on this? I mean... it feels to me like you could've removed some of the "less "critical" features (widgets, perhaps even the code editor, etc.) and just released the module as-is. I might be missing something important, of course, but that's my impression anyway.

    Either way I'm blown away by just how awesome this module is! 🙂

    • Like 7

  17. Quick heads-up: SearchEngine 0.25.0 was just released. This version adds support for the new selector operators added in ProcessWire 3.0.160, and also adds a new details section below the selector operator setting.

    If someone has defined the operator in site config ($config->SearchEngine), that's still a valid option and new operators can be used there as well.

    • Like 1

  18. Quote

    First I have to say: WOW! I took another look at your module because I got again frustrated with my setup and I wanted to build something on my own. Luckily I remembered your module and came back to the docs before developing something on my own 🙂 



    It would be great to have < prev | next > links on each page at the bottom. I almost missed all the other great pages when reaching the bottom of https://wireframe-framework.com/docs/ (the menu is not visible in the sidebar on such long pages)

    Makes sense. I've added this to my todo list, will take care of it soon.


    It would be great to have a simple hello-world walkthrough for setting up a custom wireframe template (instead of providing a full-blown site profile). It's always easier to understand something if you start from scratch than finding your way around several files not knowing which pieces came before and after another.

    Again, makes sense. I'm personally not a huge fan of tutorials — it's just not my thing. I prefer to learn by finding a project to work on, or alternatively by digging into existing implementations. Probably explains why there's no tutorial available for Wireframe either.

    Another item on my todo list 🙂


    As far as I understood one can define a path for every type that Wireframe is based on (views, controllers, components, etc). And as far as I understood it is possible for components to define custom view files via Wireframe::component('foo')::setView('bar'); Is that correct?

    Yes. On a very minor note the API for redefining component view would look like Wireframe::component('foo')->setView('bar'). Also: I typically choose the view in the component, i.e. the constructor picks the most suitable view based on the params it received. Both approaches are fine though, depends on the context! 🙂


    The problem with that approach is that it is not possible to load components from outside of the wireframe folder structure. That's a quite big deal, because if that were possible, we could ship custom components/views/partials (I'm planning on working on styles using RockLESS) directly within our modules and that would just be awesome! [...]

    What if we had a new Wireframe type called "package"? This could be included in any Wireframe layout like this:

    Interesting idea! I can definitely see value in this, but I'd still like to give it a bit more thought. It's easy to add features, but hard to remove (or significantly alter) them, so I prefer not to rush things 🙂

    Out of interest, how do you see this comparing to Markup modules using render method(s)? For an example:

    <!-- RockSearch with partial -->
    <section><?= $packages->RockSearch->partials->searchform() ?></section>
    <!-- SearchEngine -->
    <section><?= $modules->SearchEngine->renderForm() ?></section>

    One benefit would be that if I wanted to use the default search form as a starting point and start building on top of that, I could just copy the file to local partials directory and change the reference in the layout. This would, obviously, mean no more easy updates, so it's a double edged sword.

    In SearchEngine I decided to go with a set of interconnected render methods, each tasked with some specific part of the markup. I felt that this provided the best balance between reusability and customization: one can get pretty far by modifying config settings, but if that isn't enough, it's also possible to make more drastic changes using hooks.

    All in all I really like the idea, but it will require a bit more thought and probably some experimenting to strike the perfect balance 🙂


    PPS: I didn't quite get where the differences between using controllers+views or components+views/partials are?!

    Hopefully I'm answering the right question:

    • Controllers and views are specific to a single template. Controllers' job is to accept arguments, process data, and pass processed data to the View layer. View — which consists of layout(s), view files, and partials — is there to output said data, so it should be as "dumb" as possible. View doesn't need to know anything about what's going on behind the scenes.
    • Partials were originally just "include files" without the ability to accept params or a dedicated approach for processing data. They were great when you had a relatively static block you wanted to repeat in multiple templates, but if you wanted to pass them params, you'd have to define them in the parent context, etc.
    • Components were added to fill this void. There's always a class that can accept arguments and process data, and usually there's at least one view file meant to render output. (Components can also render output directly by implementing the render() method, or they might not produce any markup at all, so technically component views are optional.)

    ... and then things changed a bit when partials also got the ability to accept params. Now the biggest difference between components and partials is the class: I prefer not to mix code with markup, which means that if I need a reusable "thing" that needs to, say, fetch data from an API, it's a component. On the other hand if I just need to reuse a block of HTML and perhaps iterate/output some variables in there, most of the time I go with a partial.

    In my mind controllers + views (and layout(s)) are the typical way to use Wireframe. Components are handy when you need an element that should be reusable across multiple templates. I guess they're sort of "template-agnostic miniature controller + view" bundles 🙂

    Note: how you actually use Wireframe may vary. Your site might not have any controllers, relying on components instead. Or you could produce all the markup in the layout and have no other files (apart from the bootstrap file). What I've described above is just the way I prefer to do things 👌

    • Like 3

  19. 17 hours ago, olafgleba said:

    While accessing subfields as selectors within a $pages-find() works fine, i am having trouble using subfields within PageArray results. Definitely i miss something here. Maybe i should stop working for today, but meanwhile someone maybe have a hint what i am doing wrong...

    I'm not really familiar with this module, but it looks like the formatted output will indeed be a single date. Have you tried $result->getUnformatted('programm_date_advanced') to get the unformatted version?

  20. Check the "Advanced" tab in the Template settings. There you'll find an option to make the createdUser modifiable:


    When checked, pages using this template will have an option to change the 'created by user' (for superusers only). It will also enable the $page->createdUser or $page->created_users_id fields to be saved via the API.


    • Like 6

  21. 3 hours ago, bernhard said:

    If the hook works in ready.php but not in your module it will most likely not get called.

    I could be too tired to wrap my head around this properly, but it seems to me that your module's init/ready is going to be called after the (admin) page::render method is called, which would explain why it has no effect at all. Your module is not autoloaded, so the init/ready should only trigger when this specific inputfield is being rendered, which is likely too late in the process.

    Might be easier to go along the lines of what Adrian suggested and a) split the hook into a separate module that extends Wire, and b) make that separate module autoload (preferably with conditional autoloading, i.e. when the template is admin or something) 🙂

    (Note: making the Inputfield module itself autoloading should probably work too, but this way you'll end up loading some unnecessary baggage even when it's not necessarily needed.)

    • Like 2
  • Create New...