Jump to content

teppo

PW-Moderators
  • Posts

    3,208
  • Joined

  • Last visited

  • Days Won

    107

Everything posted by teppo

  1. teppo

    Wireframe

    Hey @Mats! The error itself is not visible there, just the trace, but first things first: did you follow the instructions in the Functional Fields README? Asking because I just tried this fieldtype for the first time, and was a bit confused at first: I was too hasty and jumped directly to the "using" part of the blog post, where it seemed to suggest that you can just start using __text() etc. in your template files, while in reality you'll need to create a functional field before that or the functions won't work at all. Without a field the fieldtype file won't be loaded, which also means that the functions.php file won't be loaded, and thus __text() etc. will be undefined. Anyway, let me know if this wasn't the issue. In my quick test the fieldtype seemed to render at least, but I don't have much experience with it otherwise ?
  2. teppo

    Snippets

    Priority numbers and PHP code support / Hanna Code integration are now logged as enhancements in the GitHub repository. I've got another project on my desk right now, but should have some time to work on these soon(ish) ?
  3. teppo

    Snippets

    Seems like it would be worthwhile to add priorities to snippets ? I have considered allowing the use of Hanna Code tags in snippets. Would that make sense for your use case? I'm not against other approaches, but this would be one way to keep Snippets relatively simple, while still allowing for more advanced use cases. Maybe ?
  4. No, not under normal circumstances it won't. $session->CSRF->validate() will only ever reset the token in case an invalid token was provided, or if the token was initially created as a single use token (via $session->CSRF->getSingleUseToken()).
  5. teppo

    Wireframe

    Following up on this: after taking a look at that example I've realized that... it doesn't work. Thanks for pointing this out — I should probably fix it to avoid any further confusion ? In this case the search method of the controller class disables layout and attempts to change the view. First one is doable (layout is rendered after the view), but the second one isn't, since at this point we've already rendered the view (search method is called in the view, after all). Instead this should be done in the init method (triggered as soon as a controller class is loaded) or the render method (triggered when a page using that controller gets rendered). The distinction between init and render usually doesn't matter ?
  6. Sorry, my post was vague on this part (updated now): CSRF token is only reset if/when a reset was specifically requested while validating the token. Page save won't do this, but a custom CSRF check could do it. Only core feature (that I'm aware of) that resets the token is logging in... which is unlikely to occur multiple times during single browsing session ?
  7. Token is stored in session data and thus indeed automatically invalidated if session expires. It can also be invalidated if another CSRF check runs meanwhile (but only if that check specifically requests that the token be regenerated, which is not the case with most core features), so technically user doing something else on the site that triggers a CSRF check could result in such an issue. (It's possible to provide an ID argument for getTokenName(), validate(), etc. which may help with this, although it is likely quite a rare occurrence.) In my experience an issue like this would most commonly be a result of something in the user's environment changing, i.e. IP or some other value used for session fingerprinting has changed and thus session gets invalidated. This behaviour can be tweaked via the $config->sessionFingerprint setting. In my opinion a background process is rarely needed / useful. I wouldn't bother with it, unless this is a critical feature that definitely should never cause errors and where users are likely to spend loads of time. Also: session_start() would not remove the fingerprint issue, so this will likely have limited applicability. You could probably build a setup where the token is checked and/or regenerated periodically, but this is most likely overengineering. By the way: you can use echo $session->CSRF->renderInput() and use if ($session->CSRF->hasValidToken()) { ... } instead of custom markup and try-catch. Not a big deal, they just make things sightly more convenient ?
  8. teppo

    Wireframe

    Hey @Mats! Just gave this a try by dropping your code into Search template controller class init method (SearchController::init()) and in my case it worked right out of the box. Where did you place the code? And, just in case, which versions of Wireframe and SearchEngine do you have installed? In case requested view doesn't exist Wireframe should fall back to the default one (a behaviour I'm no longer entirely sure makes sense, but it's been like that since beginning, so not sure I want to change it either...) so you should also make sure that there definitely is a json.php view file for this template.
  9. teppo

    Snippets

    Glad to hear that the module is useful ? Reported SQL issue should be fixed in version 1.0.1.
  10. @erikvanberkum, I've merged your question from general support to the support thread of the FieldtypePDF module. You may also want to open an issue about this in the FieldtypePDF GitHub repository. Also, please make sure that you're running the latest version of the module ?
  11. The problem here is that it depends a lot on your setup, i.e. which output strategy you're using and how your site is set up etc. ? If you're using simple direct output (templates/template_name.php directly renders output) then you could do something as simple as this: <?php namespace ProcessWire; // finding results goes here if ($config->ajax) { // render results without page "frames", i.e. just the list of cards // ... and when done, halt the rendering process: $this->halt(); } // normal page output Now you just need to trigger an AJAX request to the same page, read the output, and then replace the part of the page content that you wish to be "dynamically filtered" with new content. Note that for $config->ajax to work, your AJAX request needs to include the "X-Requested-With: XMLHttpRequest" header; jQuery adds this automatically, but if you're using raw XMLHttpRequest, Fetch API, or any other approach to trigger the request then you'll likely have to add that header yourself. More examples for AJAX loading content (including alternative approach, where instead of content you return JSON and then render output in JavaScript) can be found from this thread: Loosely related, but a couple of issues I spotted in your sample code: You're passing $chan and $cont values to the selector string unfiltered. This is not a good idea: visitors could pass in characters that break the query, or even rewrite the query. Always run user-provided values through Sanitizer methods ($sanitizer->selectorValue()) is a good default, but if you're expecting integers then use $sanitizer->int(), etc. Since you're first finding all results and then limiting them, you will run into performance issues if there's a lot of data. As a general rule of thumb always include a limit in your initial selector — this way the limit is applied in the database, which is much more efficient.
  12. Currently you could get this from the versionControlRevisions() method of the page. The value of said property is an array of all existing revisions, or null if none were found, so passing it to count() will tell you how many of those there were: echo count($page->versionControlRevisions());
  13. I can't say that I have a strong opinion here either. Also not sure if I grasp the whole context — when you say "routing" and mention URL segments, does that mean that you create routes automatically based on page structure (I assume so but...) or that there's a separate routing setup for front-end and page structure is only reflected in the data? Or do you mean something different with this? ? This may or may not be related, but one thing to consider is whether you want Symprowire to be "all in", or rather something that can be used only for some parts of the site. Couple of examples from other MVC(ish) solutions: Template Engine Factory hooks before Page::render and replaces the response, but also provides hookable method (TemplateEngineFactory::shouldRenderPage) for preventing it from rendering the page, in which case the site will fall back to the regular rendering flow (whatever that happens to be). Wireframe takes an entirely different approach: instead of a hook ("enabled by default") you need to point templates that you want to render via it to the front controller file via Alternate Template Filename setting (more details in the docs). Essentially it's disabled by default. Wireframe is my pet project and something we've used for our production sites for a while now, so that's what I'm mostly familiar with. I intentionally decided not to use hooks, since I felt it was best to let the developer decide if they want to use Wireframe for everything, just a small part of the site, or something in between. In fact it's possible to skip the MVC structure entirely, and just use Wireframe for its partials and/or components ?‍♂️ Template Engine Factory may be a bit closer to Symprowire feature wise, although Symprowire clearly has a much larger scope (and is more opinionated). So not sure if any of what I've said here applies as-is ?
  14. Depends on where and how you want to use this ? The query object has "pager" property that returns a rendered pager, and Renderer has public method (Renderer::renderPager(array $args, Query $query)) that does the same. Whether or not these will be useful depends, again, largely on your context.
  15. I must admit that I'm not really following your logic here: <?php foreach ($page->find('template=uporabnik, sort=random') as $single ):?> <!-- MY Attempt, but not working --> <?php if ($single->count('template=uporabnik, objekt_select=$single') < 1) : ?> First you're iterating over all the children of current page that use the uporabnik template. It's a bit unclear what exactly that "current page" is, but assuming that it has visible "uporabnik" pages below it, this should find them. In the next step you're checking if individual uporabnik pages also have children using the uporabnik template... but these children must refer to their parent page via the objekt_select field. I'm pretty sure that there's some sort of confusion here (that latter selector doesn't seem to make much sense), but since I don't know what your page tree looks like, I'm just guessing here. Could you provide an example of how these pages are structured in the page tree, which templates are used where, and where in that structure are we now (in this example)? That would be helpful in figuring out what exactly is going on ?
  16. @PWaddict, the issue you reported earlier should now be fixed. Sorry for the delay.
  17. @mlfct, the issue mentioned above should now be fixed in SearchEngine version 0.30.2. Thanks for letting me know about this and sorry for taking so long to solve it ?
  18. This seems like a bug. So far I've traced it back to version 0.29.0, but will have to dig in further to see what's causing it. This version introduced major changes behind the scenes, so I'm not entirely surprised that something went wrong. I'll get back to you once I figure this out.
  19. This seems like an issue with ProcessWire itself, not SearchEngine. If you have a chance you might want to give the latest dev version of ProcessWire a try, though if it's a live site then I'd recommend doing it locally / in a development environment first, or alternatively backing your site up before the update (just in case). If that doesn't solve it, you may want to open an issue for this at https://github.com/processwire/processwire-issues. "Internal Server error" alone isn't very informative, so you may also want to dig into your log files etc. to see if there's anything more specific there.
  20. Done — https://processwire.com/talk/topic/25815-custom-notes/. Moved the two posts introducing Custom Notes and placed them in the Modules forum section instead of module development (it's a proper module after all), hope that's fine ?
  21. Hey @Cybermano, Just letting you know that I opened an issue for the module here: https://github.com/cybermano/CustomNotes/issues/5. Minor things, but they are kind of showstoppers for the module right now. After fixing those, things seemed to work pretty nicely ? That would make sense in my opinion. Or if you prefer to, I can split the thread starting from that message (https://processwire.com/talk/topic/25435-custom-notes-former-list-of-allergens/?do=findComment&comment=213864) into a new thread — just let me know.
  22. teppo

    Snippets

    A few days ago I stumbled upon this old module, which had been laying in the modules directory of one of my sites since 2017 in a half-finished state. I have no recollection why I left it like that, but figured it might be useful for someone, so here we go: https://github.com/teppokoivula/Snippets https://processwire.com/modules/snippets/ Snippets is a tool for injecting front-end code snippets (HTML/JS/CSS) into page content. The way it works is that you create a snippet — say, a Google Analytics tag — and then choose... which element it should be tied to (there are some pre-populated choices and custom regex option), whether it should be placed before/after said element or replace it entirely, and which pages the snippet should apply to. The "apply to" option also has some ready to use options (such as "all pages" and "all non-admin pages") or you can select specific pages... or use a selector. Snippets are regular markup, with the exception that you can use values from current page (behind the scenes the module makes use of wirePopulateStringTags()). Available hooks: Snippets::isApplicable, which receives the snippet object and current Page object as arguments and returns a boolean (true/false). Snippets::applySnippet, which receives the snippet object, page content (string), variables (an object derived from WireData), and an array of options for wirePopulateStringTags() as arguments and returns the modified page content string. That's just about it. It's a pretty simple module, but perhaps someone will find this useful ?
  23. teppo

    Wireframe

    To be honest I've never attempted anything like that ? Just did a quick test and something along these lines might work — though I'd highly recommend testing first in a non-production environment: if ($user->isSuperuser()) { $wire->addHookBefore('ProcessPageView::execute', function(HookEvent $event) { foreach ($event->templates->find('name!=admin') as $template) { $template->filename = 'wireframe.php'; } $event->removeHook(null); }); } Note: you don't want to set altFilename specifically. I'm not too familiar with how this actually works, but I just tried that, and it seems that ProcessWire is quite keen to save said value (persistently). Managed to break one of my local test sites ? (Based on a quick test setting filename seems less problematic.)
  24. I'm posting this as an update to an earlier post created by @Hari KT: https://processwire.com/talk/topic/4958-composer-support-for-processwire/. Though that approach still (kind of) works (as does the one detailed in https://github.com/wireframe-framework/processwire-composer-installer), thanks to @d'Hinnisdaël there's now a better alternative: the official composer/installers project ? An example repository implementing the things detailed in this post: GitHub repository: https://github.com/teppokoivula/HelloWorld Packagist entry: https://packagist.org/packages/teppokoivula/hello-world As a module author, how do I make my module installable via Composer? 1) Add a composer.json file to your module's directory. Here's an example: { "name": "vendor-name/module-name", "type": "processwire-module", "license": "MIT", "extra": { "installer-name": "ModuleName" }, "require": { "composer/installers": "~1.0" } } The composer.json file explained: "name" consists of two parts: your vendor (author) name, and the name of the package (module). These can (but don't have to) be the same as your GitHub or BitBucket user and repository names. Please note that this value should be all lowercase! That's the syntax expected by both Packagist and Composer. "type" should be "processwire-module". You may have seen "pw-module" used by other packages; that's the value used by third party installers, you don't need to worry about that now. "license" should specify the license your module is published under. See Composer help for expected syntax. It's technically fine to leave this out, but it's always a good idea to let users know how they're allowed to use your code. "installer-name" under "extra" should specify the expected directory name for your module. Usually this is the same as your module's name. If you leave this out, the package part of the "name" value will be used instead (which may be just fine, though I'd recommend always filling in this value). "require" includes Composer dependencies of your module. The key part here is "composer/installers" — without this Composer won't know that your module requires said installer, and it may not be installable at all, so be sure to add this row. 2) Submit your project to Packagist: https://packagist.org/packages/submit. You will need an account for this step. It's free and very easy to register, and you can automatically connect it with your GitHub account. Connecting with GitHub also makes it easier to auto-update package versions from GitHub repository. 3) Recommended but not absolutely necessary: add tags to your module's Git repository. It's recommended that when you push a new version of your module to GitHub or BitBucket, you also add a matching tag: if you push version 0.0.3 (or version "3", following the old school ProcessWire version number format), you should also add tag 0.0.3 (or "v0.0.3" if you want to be verbose) to GitHub/BitBucket. (This step is not strictly speaking necessary, but it does make things easier for users installing your module, and makes much easier to track which version of the module is currently installed via Composer. It requires additional step when publishing a new version of the module, but please consider doing it anyway!) 4) Also recommended but not absolutely necessary: configure Packagist to auto-update based on GitHub/BitBucket. Follow the instructions here: https://packagist.org/about#how-to-update-packages. This step ensures that once you push a new version of your module, Packagist automatically updates stored information without you logging in and hitting the "update" button manually. (This step may not be necessary if you've already allowed Packagist access to your GitHub account.) ... and that's it. Congratulations, your module is now installable via Composer! As a module user, how do install a module via Composer? Go to your site's root directory and type on the command-line "composer install vendor-name/module-name". You can look up the correct details from Packagist, or the module author may have included them in the support forum thread. Obviously this only works for those modules that have implemented Composer installer support as outlined in this tutorial. Note: if you're using a "non-standard" directory structure for ProcessWire — you've moved the root of the project outside the public web root, or something along those lines — check out the custom install paths part of the composer/installers README. The "installer-paths" setting allows you to manually specify a custom install path for the "processwire-module" package type.
  25. Could you explain what your goal is? I mean — you're already handling dependencies via Composer, so that's a good start at least ? If you want the module itself to be installable via Composer, the approach I'd currently recommend is detailed here: https://github.com/wireframe-framework/processwire-composer-installer. Change the "type" in your composer.json to "pw-module" and add wireframe-framework/processwire-composer-installer to your requires and that's just about it. In case you were wondering, ProcessWire doesn't currently have a way to handle Composer dependencies when a module is installed via Admin. Module with dependencies will either a) need to be installed the regular way and then the user has to run composer install manually, or b) installed via Composer (see processwire-composer-installer) in which case dependencies are automatically handled. ... or you could bundle all dependencies in the Git repository itself. Somewhat crude approach perhaps, but also the easiest one for most users of your module.
×
×
  • Create New...