-
Posts
194 -
Joined
-
Last visited
-
Days Won
6
Everything posted by poljpocket
-
How can i limit the form request according to ip of the user?
poljpocket replied to kkalgidim's topic in Getting Started
Here's a good stack overflow article discussing exactly what I am trying to say: Is it reliable to use the IP address to identify a user on your website? - Stack Overflow -
How can i limit the form request according to ip of the user?
poljpocket replied to kkalgidim's topic in Getting Started
Good approach. Didn't know if you actually used PW pages for the submissions, so I stuck to a direct SQL query. But of course that works this way. May I ask why you are limiting this by IP address? First of all, like that you are locking out all users behind one IP address. Means, that if a large number of your visitors is working from a private network with NAT, they will all have the same public IP and thus combined, they all can only post five trades per day. Second, if you want to really limit the trades one single user can do, the IP doesn't help you. I can simply spin up my VPN and have 5000+ IP addresses a click away. All of a sudden, I can post 25000 trades per day and you wouldn't even know! And then, if another user using the same VPN provider tries to post his own legitimate trade, they can't because the IP has been used up already. That's why I added the bracket with bad idea in my last post. You should use user accounts with logins and email verification to really get closer to managing maximum trades per user per day. Luckily, ProcessWire has you covered with that. -
How can i limit the form request according to ip of the user?
poljpocket replied to kkalgidim's topic in Getting Started
Hi, if you really just want to limit by the IP address (off-topic but this is a bad idea!) of your visitors, I guess a simple approach would be to add the IP address alongside a timestamp of the form submission to your database table. Before you're adding submissions, you can then do something like this: SELECT COUNT(*) FROM form_submissions WHERE date_created >= DATE_SUB(NOW(), INTERVAL 1 DAY) AND remote_ip = ':ip'; Whenever that result is 2 or higher, block the submission. Does that help? -
Me too. You can solve this (from a technical point of view at least) by using language-alternate fields. Combine that with @bernhard's great suggestion to sync settings between your language fields and you should be all set. The only thing you're not getting from that is the cool tabs system LanguageTabs provides. I am always extensively tagging both templates and fields. With the tags, you can even have some of them be collapsed by default. This retains all the overview I need.
-
Thanks @Tiberium. Good to know I'm on the right track. Seemingly, crawlers mostly don't send the header in question and thus won't be affected by my implementation anyway. Also, I'm always sending hreflinks for all languages available and thus, crawlers shouldn't be blocked. @HMCB you have to decide your strategy based on what your site will do. If language is location-agnostic, just use two-letter language codes and just respect the language headers sent (e.g. with my snippet). If you are more region-oriented, go with your suggestion. Also, ProcessWire allows you to serve the default language on a path other than / (e.g. /en-us/). For this, just change the name of the homepage. Here is an example of a German page's settings tab for the homepage. The German version gets served at / and the French version at /fr/: Here is the same page with settings changed. German is at /de/ and French is at /fr/. With this, ProcessWire will issue an automatic 301-redirect to /de/ when the root (/) is requested: Remember these settings aren't set in stone once you started your project. You can change them at any point if you want.
-
@Tiberium how are you detecting the languages exactly? I am using the Accept-Language header because it's simple and works almost every time. Here is the snippet I am using which is in readySite.php because this should only run on the frontend. Note that this requires the Language template to have the custom field 'iso_code' which I am always creating no matter if the site is multilingual or not. <?php namespace ProcessWire; /** * @var ProcessWire $wire * @var Session $session * @var User $user * @var Page $page * @var Sanitizer $sanitizer * @var Languages $languages */ // language detection, also make sure language detection only runs once if ($languageHeader = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? false) { // see if we have run detection before if (!($session->get('http_language_detection_done'))) { // in any case, we got a header and can indicate we did run detection (even if it's not successful) $session->set('http_language_detection_done', 1); if ($languageInHeader = Locale::acceptFromHttp($languageHeader)) { // map the value to available codes $isoCodes = $languages->getAll()->each('iso_code'); $preferredLanguageCode = $sanitizer->selectorValue(Locale::lookup($isoCodes, $languageInHeader, false, $languages->default->iso_code)); if ($preferredLanguageCode && $user->language->iso_code !== $preferredLanguageCode) { $requestedLanguage = $languages->get("iso_code=$preferredLanguageCode"); $session->redirect($page->localUrl($requestedLanguage), false); } } } } Do you have a better approach? Without JavaScript that is. I don't like that at all.
-
Remember that if you have all your country sites in one installation (without my inputs below), you are stuck with one set of Templates, one set of Fields and one set Languages (PW's term for localizations). From experience I can tell you that the more sites you have and the more different markets have to be reached, the more you will run into problems. Mostly, these will manifest in content only to be available in select regions and not others. I am from Switzerland and you could think, a site here should be in German and then offer a carbon-copy for French and Italian. Sometimes this is fine. For sites with multiple regional target audiences, I was immediately proven wrong though: The french want a banner for their super discount only the store in some location gets and the italians want a blog post which must only be available in their region. Remember, that a ProcessWire instance has one and exactly one default language/localization and all content must be available in this one language in order for the others to work. Now this is one country. You have multiple! Simply because of that, I would most likely use completely indepentent installations for every country. But PW has you covered! Here are some ideas: Building on @wbmnfktr's answer, there is also multi-site support in ProcessWire. This is where you have separate site folders with separate databases but all under one roof. More info here: Multiple site support in ProcessWire CMS. There is also multi-instance support which would allow you to e.g. fetch data from other installations (e.g. other countries for you). More info about this is here: How to use multi-instance in PW 3.x (processwire.com). You can use the multiple-site approach for your country pages. With this, every country has it's own set of Templates, Fields and Languages. They can mostly be the same but don't have to be the same at all. This allows for flexibility and sites to diverge from the "standard" as needed. On top of that, multi-instance would allow you to for example have a central newsroom section which gets displayed on all your sites somewhere.
-
Very interesting and reading through it, I was also instantly reminded of Mystique. And also, why I am almost never using fields like it. That is because of it's almost complete lack of support for selectors. Looking at your example, I am immediately thinking of problems like this one (people which have an email set, e.g. to filter contacts for a mail send operation): <?php $emailContacts = $pages->find('template=person,contact.email!='); Does your implementation support this? Mystique doesn't and you are stuck with loading everything and then filtering manually once the JSON is decoded.
-
I think ProcessWire has a well-estabilshed versioning plan: Ryan is increasing the version every few commits whenever some notable new feature was introduced. And the master version then just follows suit. I think a set release schedule with fixed time intervals is a very bad idea. I have been working with WordPress in the past and they have been notoriously bad at using their fixed minor release schedule. Sometimes a version introduced very important and big features and other times, there was barely anything new but both were minor releases just because the schedule said so. I have only been in the ProcessWire game for almost three years and thus have started out around where version 200 was released. At that time, I didn't look at GitHub too much though. I didn't notice the "slow releases" at all and was mostly influcenced by the forum and the website. For me, they did a good job. As many before me have mentioned, community activity is very important especially for new potential users (and even more to the target audience: fellow developers). This could also be reflected in more activity on the master branch. Finding a good solution might not be the easiest endeavour though. Has there ever been a situation where old versions needed to be patched for some bugs or security vulnerabilities? I haven't seen one yet. I think this mostly stems from the slow master releases which only ever get done when high stability has been reached. So for me, every master release is a "LTS" version, which is a big strength of ProcessWire: I have no reason to ever update a PW website I did years ago. As long as it doesn't get outdated because of external influences (PHP EOL comes to mind). I think using time-based releases like Ubuntu or Windows don't make much sense for ProcessWire. Years give a feeling of outdatedness. This directly contradicts ProcessWire's strengths: It does away with the stability and ease of upkeep arguments. How do you explain to a client that PW 2016.3 is still completely fine in 2024 and doesn't need any updates whatsoever? With operating systems, you want a sense of outdatedness simply because there is much more incentive to update to never versions, e.g. for hardware compatibility or platform support. Why not stick with semver with a few adjustments? One idea is to keep the patch part of the current versions as sort of like a build number which would primarily be used on the dev branch to indicate new features and fixes. And then every master version gets a minor version bump which corresponds to a dev version (indirectly that is). This would then allow for security fix updates down the road. Not that this would be needed much :).
- 127 replies
-
- 11
-
-
-
@wbmnfktr was just a minute faster, but I feel exactly the same way: I have to say I am using ProcessWire exactly because it doesn't force me into a direction and/or into a form of "best practice". But nevertheless I think there is already a lot of controller in the ProcessWire core. What you @szabesz want I think is a way to create your own controller manifested as a class and tightly integrated in the request lifecycle. But can't you already do that? That is the beauty of ProcessWire. You can alter anything I can think of with hooks. They will allow you to create a fully-fledged controller system if you want to. But again, I feel like ProcessWire handles most of the controller stuff one would ever need.
-
Hi all. Reading through the discussion about page classes, I have to add my two cents. I feel like we are mixing concepts here. We are talking about OOP concepts where the request arises to extend page classes' capabilities to better allow for separation of concerns. Many OOP concepts stem from or are just a fancy form of the MVC pattern. I strongly believe ProcessWire follows such a form too. Whereas the core handles MC and it's API provides endpoints for the V in Model-View-Controller and hooks for extending and altering the C part. So to really allow for separation of concerns, page classes aren't the right place to start off. A page is just the representation of an entity, a line in the database. Instances of said class that is. And thus Page and page classes belong to the Model part of ProcessWire. And this is exactly where my motivation to side with @ryan and his general scepticism of page class init and ready methods comes from. So it makes sense to add virtual properties or basic relationships to the page class. But the model should never contain business logic which acts outside of the lifecycle of the entity. Having made my point so far, I think Ryan's second to add a new class file to act as a controller (by using the ProcessWire's hooks) makes a lot of sense. And exactly that is why I believe, ProcessWire already offers a very good way to enforce MVC patterns and true separation of concerns. It offers a good API without forcing everyone to use the same architectural patterns so many other systems do.
- 127 replies
-
- 10
-
-
Hi everyone ? I have just updated and streamlined my own local development experience. Most importantly, I used to have a custom Dockerfile which resulted in a custom image for every project I ran locally. This has now changed! There is now a GitHub template repository tailored to local development: https://github.com/poljpocket/processwire-docker. This has everything you need to start developing locally on Docker. Some of the features: The composition is set up so that the site folder is fully accessible on the host. You can use any site profile upon first installation. The actual install of ProcessWire is still manual though. I found that there is little benefit in automating this. You can export the database to commit it into your repo and can also import it after pulling changes from upstream. The comp uses my new image for ProcessWire which I just published to Docker Hub: https://hub.docker.com/r/poljpocket/processwire. It uses PHP8.2 via Apache and includes all the PHP extensions needed for ProcessWire. You can find the GitHub repo for it here: https://github.com/poljpocket/processwire-docker-image. There are images for the three most recent stable versions of ProcessWire (210, 227 and 229). Important: I didn't care about security and hardening of the image. It is really only meant for local development. Have fun with it! Any requests and reports are welcome ?, thank you.
-
- 4
-
-
-
[SOLVED] $page->render can't render the current page twice
poljpocket replied to nurkka's topic in General Support
Another idea is to use ProcessWire's caching API and accomplish the JSON completely without the filesystem: use URL endpoints and cache the results until a page is saved. Ryan has used exactly your situation as an example of the (at the time) new feature "URL hooks". You can find that here: https://processwire.com/blog/posts/pw-3.0.173/#outputting-json-data-about-any-page-when-the-last-part-of-the-url-is-json. It is very easy to use a cached result in these hooks. You can find the API here: https://processwire.com/api/ref/wire-cache/. You can then use the Page::saved hook to clear the cache for a page's JSON. -
[SOLVED] LazyCron possible on every page load, or other technique?
poljpocket replied to nurkka's topic in General Support
Why unfortunately? You are not blocking any requests this way and so you can just let the task run for as long as it needs. If you have a task which should run every 10 seconds but takes more than 10 seconds, you have a completely different type of problem ? -
That is your "block editor"? Do you mean PageFrontEdit from the core?
-
[SOLVED] LazyCron possible on every page load, or other technique?
poljpocket replied to nurkka's topic in General Support
If you are in need of something which runs periodically and the 30s interval is too long, using LazyCron isn't the right way to go. That is not really what it's designed to do. Remember, 30s is the minimum time in between runs. If your website doesn't see traffic for minutes, the next call to LazyCron will also only be minutes later. This will possibly lengthen your task when you don't see regular traffic (meaning more than one request at least every 30s) and you are splitting it up into small chunks. For what you are trying to do, you should use the crontab of your server or use an external server which will trigger a Webhook also using it's crontab. But anyway: Is there any harm in just letting your "long task" do it's thing? Not with LazyCron obviously. I get that this would block one of your visitors every once in a while. -
[SOLVED] $page->render can't render the current page twice
poljpocket replied to nurkka's topic in General Support
For me this sounds like a recursion loop. Why would you need to recursively call the render method again in the hook for said exact method? You can solve this for example by using an "after hook": <?php namespace ProcessWire; /** @var ProcessWire $wire */ $wire->addHookAfter('Page::render', function(HookEvent $event) { /** @var Page $page the page in question */ $page = $event->object; /** @var string $renderedMarkup the "after hook"'s return will contain the rendered page */ $renderedMarkup = $event->return; // ... do your stuff and use $renderedMarkup instead of a second call to render() as this would end up in a loop }); You can see something very similar in the PageRender docs here. To be completely honest, you should actually use the hook for when pages get saved because this is actually where the contents change. Using render for this sort of thing you are only wasting resources and re-writing the same markup again and again. Also, remember you don't need to reinvent caching. ProcessWire already has a full API for that! -
Indeed there was no optimization yet. This is fixed! Thanks for the input!
-
Thanks for pointing that out. A lot of videos on that page which still need optimization. The staff images are actually also videos which should have poster images as placeholders. I just saw that my colleagues didn't put the poster images everywhere. We will have to improve that.
-
Thanks everyone for the feedback. You know how it is with your own websites... they get neglected in favor of everything that can make you money and thus, image optimization wasn't the most important thing to finish because we are only targeting the Swiss market anyway. In Switzerland, load times much better. Nevertheless, I did now finish the optimizations and enabled webp everywhere and so most images are <100k now. The videos remain untouched but will be done at some point.
-
Fruitcake has been using ProcessWire for a while now but I didn't get around to posting any of the around 30 sites we did so far. But let me start off with our own new website which launched earlier this year. Our new brand website had the goal to be modern and simple and uses a minimalistic approach. The centerpiece of the page of course is our portfolio which most of the effort went into. It uses a playful and seemingly random (it's not!) layout. The portfolio detail page uses a vertical slider which from a technical point of view was the most challenging part. As for modules we are using, we like to do most of the stuff ourselves so it really only boils down to the Repeater Matrix Fieldtype from @ryan's ProFields package and SEO is done using SeoMaestro by @Wanze. Here you can have a look yourself: Die Kommunikationsagentur | fruitcake.ch Here is a preview of the masthead: Let me know what you think ?
- 9 replies
-
- 11
-
-
As you might expect for a paid module, your support has ended and so most likely, your old version doesn't fully support PHP 8.1. You will not get support for paid modules outside the respective support forum. The only solution will be to renew your license and get access to the newest version and the support forum.
-
For further reference, this is the hook to accomplish this with UTF8 mode for page names: <?php namespace ProcessWire; // we are in ready.php $wire->addHook('/post/{post_slug}/?', function(HookEvent $hookEvent) { // find post to use, fallback 404: $post = $hookEvent->arguments('post_slug'); $postTranslated = $hookEvent->sanitizer->pageNameTranslate($post); $requestedPage = $hookEvent->pages->get('name=' . $hookEvent->sanitizer->selectorValue([$postTranslated, $post])); if ($requestedPage->id) { $hookEvent->session->redirect($requestedPage->url); $hookEvent->return = true; } else { $hookEvent->return = false; } }); Changes to above hook: it is using a simple named path argument and accepts both the non-translated and the translated version of the post slug (e.g. when the UTF8 mode was enabled after a few pages have been created already and have translated names).