-
Posts
194 -
Joined
-
Last visited
-
Days Won
6
Everything posted by poljpocket
-
For such cases, even more readability: $wire->addHookAfter('Pages::saveReady(template=news)', function($event) { // [...] } This way, the hook doesn't even get called if template isn't news. Also, I think you can even get rid of the second guard clause like this: $wire->addHookAfter('Pages::saveReady(template=news,day!=)', function($event) { // [...] } If the page doesn't have a day field, the selector doesn't match and the hook isn't called. This is untested though 😊
-
Cool to see a project about my home country but not in my home country! Greetings from Switzerland! A very cool blog you have there. Model trains bring me back to my childhood, we had a ton of Märklin trains and of course, most of them were Swiss trains 😍 I think many of us feel this way. Welcome to the family 😊
-
Thanks @bernhard for that video. This puts a name on the concept I have used a bunch of times and I think is the only real way to solve OPs problem. Most ERP systems and also some well-known e-commerce systems out there (I know of Shopfiy and Shopware which do that) don't let you manage an item's quantity with a simple text field or a simple "number". Instead, the quantity is "event sourced" (as in the video) with a log of changes. This even includes the initial value. The video also says it, but as an example, one could come up with the current item's stock quantity of 8 by looking at this "event log": +10 from incoming shipment -2 from order -1 from order +3 from incoming shipment -1 from order -1 from order In ProcessWire, you could create a repeater to achieve this. Just record all your "incoming" lines with a repeater in your product (remember to add a datetime field) and add hooks to orders which automatically add lines when orders are placed/refunded/cancelled. The only remaining thing is to modify the repeater editor to only allow the user to edit new items. But a combination of limiting edit access to the entire repeater and a "update quantity" field like @bernhard and @da² suggested will get you there.
-
[SOLVED] How to save fields on a Process page of a module?
poljpocket replied to PWaddict's topic in General Support
Indeed, that is also an option. For your exact use case, there is the ConfigModule interface. It allows you to load/save exactly as you are doing but the differenc is, you don't need the getModuleConfigInputfields() method. I am on my phone so can't look up the code as easily. Edit: Here you go https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/core/ConfigurableModule.php#L40 -
[SOLVED] How to save fields on a Process page of a module?
poljpocket replied to PWaddict's topic in General Support
Hi @PWaddict, You are missing any means of dealing with your data. I don't mean to be rude, but you might have misunderstood what the processInput() call does on the form. All it does is take any input provided via GET or POST and fill the form fields with this data. This allows for further processing and re-rendering the same form with the prefilled data (e.g. when there was a validation error). You can find a hint of this in InputfieldWrapper, the parent class of InputfieldForm. Specifically, take a look at it's processInput() method. Any other action you want to take with the data provided is up to you. As an example, the core module ProcessModule does much of the same you are doing in your module when processing config fields for modules. You can find the method which takes care of the edit form here. It builds a form, processes it's input and renders the form exactly like your module does. But the key part is that it does something with the data, it saves it in the modules config right here after checking if there has been any changes to the data. Process doesn't provide any automatic means "configuring the process" like a ConfigurableModule provides in my example above. This is because most Process modules deal with data present in the database by other means. You must create your own database schema and save your data there if that is what you are after. -
You are completely right. Since strftime() is no longer a thing in PHP> 8.1, ProcessWire no longer uses it to format it's dates. Quickly skipping through the code, you can find that Ryan introduced a replacement for strftime() which uses date() and then translates the language-dependent parts using the PW translation system. Here's the section in question: https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/core/WireDateTime.php#L476 Remember, to get gettext-style translations working, you don't need any other modules activated than the LanguageSupport module itself. No need for PageNames and all the others. You can then just add a translation file for the WireDateTime class and translate the months, short months and days to German and you're done.
-
I would advise you to use Docker or DDEV for that. You could use my composition here as a starting point. It uses MariaDB 10.6 and apache+php8.2 (custom image which auto-installs PW). You can then replace the web container with a Litespeed+php container and configure it. You can refer to the Dockerfile of my custom image to get started with that. As for Litespeed, from my very limited experience, any serious hoster should be using the enterprise variant because, as far as I know, only that really offers full drop-in replacement for apache. This makes it hard to run locally without a license.
-
You are right. I also redacted my post to match your wording.
-
Now I feel bad because I thought I got you, but didn't. It's not about the frontend public website but about the edit experience in the backend PW admin area. My bad and I stand corrected: For that, the approach indeed makes a lot of sense!
-
No, I think I got you the first time :) But thanks for the clarification. Please, don't feel like I hate your proposal, I just think that with a watertight architecture, most of the logic in your examples should happen on the backend anyway. So, let me adapt my question to your example to show what I mean: Why not fetch() the "sold out" state from the backend? The backend already knows if an item is sold out or not because the backend must validate the order anyway and thus must have it's own concept of deciding if an item can be sold or not. So I as a module dev have to add a hook in JS to replace the price label in the frontend and additionally in the backend, block an order with a sold-out item in it with another hook in PHP. Even if we simplify your example down to just the currency format you would like to have customizable: What about your PDF invoice generator in the backend? Again, the backend needs to know the currency format and thus, there is no need to duplicate the hooks in JS for the frontend. I am sure there are examples where your proposal makes a lot of sense, like your second example which only changes the presentation of the data. For such things, I guess you should have a look at how the people over at Snipcart are doing their frontend customization, I really love their approach: https://docs.snipcart.com/v3/setup/customization
-
To test selectors, I use TracyDebugger's console panel. It is useful to run a code snippet and see what it's output is. You can use it to test your selector, e.g.: d($pages->find('selector...')); Here is some more info about the console panel: https://adrianbj.github.io/TracyDebugger/#/debug-bar?id=console
-
Just to understand better: For your use case, is there any specific reason not to use: fetch() to load the config from an API, or $config->js() or $config->jsConfig() to hydrate your JS from the backend, or inline JS as config in the <head>?
-
Emptying / resetting all fields for a recently cloned page?
poljpocket replied to theoretic's topic in General Support
Reading this, I am asking myself: A clone followed by a data wipe is nothing more than creating an empty new page with the same template, right? Why don't you disallow clone for these templates (possibly for your client's role only) and instruct your users to use "new" instead? -
As @da² said, you shouldn't rely on page names like that in your code since names can change and also, you shouldn't prevent that (for SEO, localization and other reasons). The next best thing is to use different templates for each of your companies. With that, you get custom page classes for each of them and your challenge solves itself. Doubling down on your code though, why not use a new method in your custom page class, e.g. <?php namespace ProcessWire; class CompanyPage extends Page { // [...] public function tools() { $companyClassName = "ProcessWire\\" . ucfirst(str_replace('-', '', $this->name))."CompanyTools"; if(!class_exists($companyClassName)) return false; $event->return = new $companyClassName(); } // [...] } instead of the hook? You can also go all in on the PW style using hooks: <?php namespace ProcessWire; wire()->addHookProperty('CompanyPage(name=microsoft)::tools', function($event) { $event->return = new MicrosoftCompanyTools(); }); wire()->addHookProperty('CompanyPage(name=google)::tools', function($event) { $event->return = new GoogleCompanyTools(); }); wire()->addHookProperty('CompanyPage(name=apple)::tools', function($event) { $event->return = new AppleCompanyTools(); }); // [...] .. but this removes some of the flexibility of the class_exists call above.
-
Update to my last post. The fix sadly isn't easy enough. At least for the whole function "collapse" it is not. The line itself is fixed but, this code here does unexpected stuff when $r = ''. https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/core/WireTextTools.php#L454-L456 foreach($this->getPunctuationChars() as $c) { if(strpos($str, "$c$r")) $str = str_replace("$c$r", "$c ", $str); } Here, the strpos check actually will match any punctuation character no matter the position because the real issue is that we are losing any reference to the replacement positions when the replacement is nothing.
-
A quick code read gives me this problem. I think you are right, this is a bug! Line 443 of WireTextTools must be the culprit: https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/core/WireTextTools.php#L443 while(strpos($str, "$r$r") !== false) { ... } PHP 8 strpos will always return 0 (zero) for an empty string as needle (which is the case for $r = ''). And thus we get an endless loop. PHP 7 strpos will trigger a warning because the needle is an empty string. Nevertheless, the result is false and the loop breaks. I think your code was generating these on PHP7 but didn't fail and thus, you didn't care about it. This behaviour matches the updated strpos function in PHP 8, see Changelog here: https://www.php.net/manual/en/function.strpos.php @Ferdi Derksen this is your finding. Would you like to post the issue? I can produce a PR for it afterwards if @ryan would like me to. The fix is easy enough.. while($r && strpos($str, "$r$r") !== false) { ... }
-
Sorry for OT, but this isn't true. Maybe it is because the documentation lacks any mention of it, but years ago, @ryan fixed that problem in this commit: Add support for retaining abandoned translations in `__('text')` call… · processwire/processwire@34cc4e9 (github.com) You can pass an array with all alternates (as he calls them) to retain the old translations, e.g.: <?php namespace ProcessWire; $stillWorkingForOldTranslation = __(['new_translation_value', 'old_translation_value']); Like this, you can update your strings and still carry over the old translations to apply to both the old and new versions of the strings. I have to be honest, I believe this isn't generally known. I only know this because I stumbled upon this whilst reading the source code of the ProcessWire Core. This strategy also works for _x() and _n() functions, and also in modules with $this->__(), ->_x() and ->_n().
- 14 replies
-
- 1
-
-
- language
- languagesupport
-
(and 1 more)
Tagged with:
-
Unable to add a language pack to site Modules.
poljpocket replied to zilli's topic in Module/Plugin Development
My *.info.php file was @ryan's suggestion when I contacted him about the exact same problem. Even then, it didn't work. I guess I just never removed the file. Ryan ultimatively added the language pack manually to the directory for me. You should ask him to do the same. -
ProcessWire decides the language displayed based on the URL. I am assuming you didn't configure different root URLs for your languages and thus, ProcessWire doesn't know which language to display and will revert to the default language. A quick test shows this exact behaviour. If you configure your homepage URLs into something like this, your languages will work:
- 14 replies
-
- 1
-
-
- language
- languagesupport
-
(and 1 more)
Tagged with:
-
I made some progress. With debug mode enabled, I tried to just go with what the error messages were saying. Seemingly, headers are being sent before the last ini_set calls were made. So I restructured the install.php a bit and moved the PW initialization in step 5 of the installer in front of the install-head.php include: No more warnings even with debug mode on. @ryan I think this might be worty of a PR? Would you like one?
-
As I mentioned, this happens to me every time. Well, I thought about how I'm installing PW usually: To start a new project and what do always enable for in-development projects? I enable debug mode. So, I am still testing around a bit, but using my docker image (https://hub.docker.com/r/poljpocket/processwire) the errors only are output if I enable debug mode, leaving debug mode disabled I get no warnings.