Leaderboard
Popular Content
Showing content with the highest reputation on 07/24/2025 in Posts
-
Maybe not useful for everyone, but I find I am often searching for content via Adminer and when the results are from a repeater item page, I need to figure out which is its "forPage". I have just added a new forPage row to the PageInfo section of the RequestInfo panel that lets you view or edit directly from here making things much easier.3 points
-
Hello! I use .env files on every ProcessWire project to manage environment-specific configurations and settings. I've built a ProcessWire specific utility that makes using .env files a breeze. This post isn't intended to debate .env vs. config.php, use what you're comfortable with and prefer. That said, here are a few benefits to using .env files that may make it worth considering: Native support on web servers, including Apache, they are not served via http request by default True environment based secrets and settings management A standard file widely used and accepted as the method for managing secrets and sensitive values Able to store any value whether sensitive or not and access them globally Building a dedicated solution came from a discussion here on the forums where I threw together a rough implementation that needed little polish for real world use. It makes use of phpdotenv. This utility delivers the following: Easy use of and access to .env variables Caching the parsed .env for performance. This is a significant part of this utility and addresses a known need Automatic .env change recognition and re-caching Utilities to make working with environment variables feel ProcessWire native and a few extra nifty things What it isn't: A module. It's not possible to make a module for this need because the information kept in a .env file needs to be available before ProcessWire boots. Adding this to a new or existing project is very easy. It's designed to implement quickly and use immediately in your projects. Full documentation is provided in the Github repository. Here are a few examples of using this tool: <?php namespace ProcessWire; use Env\Env; if(!defined("PROCESSWIRE")) die(); $env = Env::load(__DIR__ . '/../'); // Make env available throughout the application $config->env = $env; $config->dbName = $env->get('DB_NAME'); $config->dbUser = $env->get('DB_USER'); $config->dbPass = $env->get('DB_PASS'); // Env::get() takes a second argument that is the fallback value if for any reason DEBUG doesn't exist $config->debug = $env->get('DEBUG', false); // Conditional values. By default, if the condition is falsey, Env::if() returns null $config->adminEmail = $env->if('APP_ENV', 'production', 'you@youremail.com'); // A fourth argument will be returned if condition is false, truthy/falsey output can be env var names or specific values $config->adminEmail = $env->if('APP_ENV', 'production', 'ADMIN_EMAIL', 'you@youremail.com'); // Conversely, you can also check if a condition is not met. $config->adminEmail = $env->ifNot('APP_ENV', 'development', 'ADMIN_EMAIL'); // Use one env value to set multiple config properties $config->advanced = $env->if('APP_ENV', 'production', false, 'ENABLE_ADVANCED'); // Never in production, change locally in env as needed $config->adminEmail = $env->ifNot('APP_ENV', 'development', 'ADMIN_EMAIL'); // Never send an email in dev, always on staging/production These helper methods make is very straightforward to implement a dynamic config file. This can be useful for using secure .env values while retaining the ability to commit and upload some types of changes to your config.php file without needing to touch .env values on the server. You can also use Env::pushToConfig(). As long as you use the "screaming snake case" naming convention for your environment variable names, type and value recognition are handled automatically. <?php $env->pushToConfig($config, [ 'usePageClasses' => true, 'templateCompile' => 'TEMPLATE_COMPILE', 'debug' => ['DEBUG', false], // Fallback to false 'advanced' => $env->if('APP_ENV', 'production', false, 'ENABLE_ADVANCED'), 'adminEmail' => $env->ifNot('APP_ENV', 'development', 'ADMIN_EMAIL'), 'httpHosts' => [ 'something.com', 'staging.something.com', 'something.ddev.site' ], ]); Using Env in your application files and templates can be very useful. In the above example we assigned the Env object to $config->env. This lets you access your .env variables globally and use some helpful methods. <?php if ($config->env->eq('APP_ENV', 'development')): ?> <script src="/some/development/stuff.js"></script> <?php endif ?> <?php if (!$config->env->exists('GOOGLE_API_KEY')) { $wire->error('A Google API key could not be loaded from the environment file.'); } try { // Do something that could fail } catch (Exception $e) { $message = $config->env->if('APP_ENV', 'production', 'Oh no. Friendly message here', $e->getMessage()); } This utility also automatically casts 'true' and 'false' values in .env files to booleans, and casts numbers to integers. It also includes several configuration options. I have been using this tool in production and have been happy with it. Maybe you might find it helpful in your projects as well. If you like it, throw a star on the repo. If you run into any bugs, file an issue on Github. I may publish it as a composer package at some point. Env utility for ProcessWIre on Github.1 point
-
I'd just add the button as regular html that you then place in ##content## in your mjml file. That way you don't have to recreate the .html from the .mjml - but it depends. If you need complex content like a responsive grid then mjml might be the better choice.1 point
-
@snck yeah that's likely the change detection in RPB not recognising the change. Sounds like it would need a fix in RPB not in fluency. Do you have the latest version of RPB? There have been some changes in change detection, one of them coming from @FireWire himself 🙂1 point
-
@FireWire Thank you so much for your explanation and patience. I got four requests every time I loaded the settings page. I uninstalled the module, reinstalled it, entered the same settings, saved them (2 times) and out of a sudden it worked. I am able to configure the languages and translate. Great experience so far! 👍 One quick observation: I am using @bernhard's RockPageBuilder. In a gallery block that contains multiple images (Pageimages field) I wanted to translate the descriptions. Translating them works as expected (translation is shown in the field), but after saving (clicking Save button or pushing Return key) the field is empty again (translation gone). If I change the field's value (before or after translating), the translation is saved as expected. I noticed that whenever I manually change something in the description field, .InputfieldStateChanged class is added to the inputfield wrapper (#wrap_Inputfield_rpb_gallery_images_repeater1613 in this case), but not if I just click the Translate link. I suspect that the change in the description field is somehow not detected correctly and not saved in consequence? Maybe there is a way for Fluency to trigger the detection of that change?1 point
-
And https://processwire.com/store/form-builder/ has a stripe integration as far as I know1 point
-
What exactly is your question? There are actually multiple ecommerce modules available these days: https://www.baumrock.com/en/processwire/modules/rockcommerce/ https://processwire.com/talk/topic/31317-introducing-processwire-commerce/1 point
-
There's LoginRegisterPro: https://processwire.com/store/login-register-pro/ And the older, free LoginRegister: https://github.com/ryancramerdesign/LoginRegister You can also roll your own, a simple login handler might look like this: <?php namespace ProcessWire; http_response_code(400); header('content-type: text/plain'); $username = input()->post->selectorValue('username'); $potentialUsers = users()->find("roles=my-user, name|email={$username}"); if ($potentialUsers->count != 1) die('Uh-oh.'); try { if (!session()->login($potentialUsers->first(), input()->post->pass)) die("Username or password invalid."); } catch (SessionLoginThrottleException $e) { http_response_code(429); die($e->getMessage()); } http_response_code(200); header('HX-Redirect: '. pages()->request()->getRequestPath()); die('Hello.');1 point
-
In your page reference field’s settings under Input -> Selectable Pages -> Parent, you can select /admin/access/users. If you don’t specify anything else, that should make all users available for selection. You can of course narrow it down more by using the other settings. I’m sure you’re aware that ProcessWire keeps track of which User created an Article page anyway. It may be a viable option for you to just use that (if the default behaviour doesn’t work for you, override $page->createdUser in a hook or enable editing the user through the advanced template options). Using the built-in user field should improve performance since it’s part of a Page’s basic data, not a regular field, and it may be more idiomatic, depending on what exactly you’re doing.1 point
-
@snck The purpose of the requests on the config page are to confirm that your API key works by making an API request to get the available languages. The only time that it will make 4 API calls on the config page is when you are first entering your API credentials. After you have entered valid credentials it will only make 2 API calls when you load the module config page. This hasn't ever been an issue before so I'm very curious why you are seeing a 429 but others haven't. Here's some additional details on why you are seeing 2 or 4 API calls for languages in Fluency when using DeepL: Fluency needs to know what languages a service allows you to translate from and what languages you can translate to. Google Cloud Translate will give you this information in 1 API call. DeepL requires you to make two API calls, one for source languages and one for target languages. Fluency is built with a modular architecture so that new translation services can be added easily. If you're interested you can compare DeepLEngine.php with GoogleCloudTranslationEngine.php. Each have the same methods that return the same data type but how it gets that data is entirely internal. To see what I mean about the 2 API calls vs 1 API call compare the getLanguages() method in each of those. 2 API calls is technically just one execution of the getLanguages() function. You should only see 4 API calls when: You first enter your API credentials and hit save You change translation engines You entered incorrect credentials and have to re-enter them After that it should only be 2 when using DeepL in Fluency. Back to your issue- 4 API calls shouldn't cause a 429. The DeepL team states that API calls should be limited to 50 requests per second. That comment is in an issue in their Node library, but the limits should still apply for all API usage. I just removed my credentials and re-added them without any issues. Are you seeing 4 API calls every time you load or save the module config page? I have to ask the obligatory security question- is there any chance that your credentials are being used by someone else or were compromised? I know that you said that you just created your API key today but you would have to be absolutely hammering the DeepL API to get a 429. I've never seen it during regular usage and it hasn't come up here in the forums by anyone who has been using the module for years. This is a tough issue to crack especially since it's happening for you but not me at the same time. Let me know if there's any additional info you can share.1 point
-
@elabx Same here, once I stumbled across that Github issue with performance I wanted to implement caching. There were a couple of places I needed to access env variables elswhere in my code, so this all grew out of some real world experience. I have my env folder in the root directory. The folders in the repo come with .htaccess files already placed which block access to any assets via http request, no need to make any changes to the ProcessWire .htaccess file. This can be used without any changes to ProcessWire itself.1 point
-
Hello everyone, Some of you may already be working with DDEV, and probably some of you are familiar with Tailscale as well. Just briefly: Tailscale is, and I’ll try to be as sober as possible, a gift from the heavens. It’s a type of mesh VPN and ridiculously easy to install and manage. It's free for up to 100 clients, too. Please just check out a few videos on YouTube about it, it’s a lot of fun to work with. In broad strokes, it works like this: You sign up – for example – with Google Auth at tailscale.com. Then you install – for example – the client for your Mac (it’s available for nearly all operating systems). You also install the client on your home server. (In my case, Tailscale is also running on my Synology, and there are some great guides for that.) A rough outline of the workflow: (For installation details and the necessary steps, Perplexity was a huge help. LLMs are truly a blessing for this kind of thing; there are nice step-by-step guides.) I still had a Dell Optiplex 7050 lying around (these things cost about 100 euros, they’re very quiet and energy-efficient). I also had some extra RAM, and I installed a 1 TB NVMe. I installed Debian 12 netinstall and then added all the necessary packages. Those include: Docker, DDEV, Tailscale (https://tailscale.com/kb/1031/install-linux) After a successful installation, you'll be prompted in the console: To authenticate, visit: https://login.tailscale.com/a/XXXXXXXXXXXXXXX Open the URL in your browser and log in using the same auth method – for me, that’s Google in all cases. And just like that, your server has joined your Tailscale network and gets an IP in the format 100.x.y.z and tailxxxx.ts.net. Docker and DDEV should already be running smoothly before proceeding. To make Docker listen to the Tailscale IP, you'll need to add the following to /etc/docker/daemon.json: { "hosts": ["fd://", "tcp://100.x.y.z:2375"] } This may vary in your case, but the idea should be clear. On my laptop, I use VSCode, and I’ve also installed the "VSCode Remote SSH Extension" to handle everything remotely. My specific workflow now is that I log into the server with the IDE, and for example, under /home/$USER/sites/$project, I start a new DDEV project. You know the drill: ddev config, ddev start, and so on... Now, to access the newly created projects from my client (here, a MacBook) without constantly editing the hosts file, I installed dnsmask via brew. In the default installation, you can edit the dnsmask.conf via nano: nano /opt/homebrew/etc/dnsmasq.conf And there, please add: address=/.ddev.site/100.x.y.z Then run: sudo brew services restart dnsmasq Et voilà, that’s it. Your example.ddev.site is now directly accessible. This might be a bit rough around the edges, but you’re professionals, and the idea should be clear. It has greatly improved my workflow, and I no longer have to worry about securing my server, since it’s only accessible from my Mac, no matter where I am, while my project data is safe on my home server. I hope you'll have as much fun with it as I have! 😀1 point