-
Posts
1,489 -
Joined
-
Last visited
-
Days Won
43
Posts posted by gebeer
-
-
I just managed to get the Blade Formatter extension (https://open-vsx.org/extension/shufo/vscode-blade-formatter) working with Latte files :-)
I needed to use the Blade Formatter from the actions menu:
Although I have it defined as a default formatter for latte files in settings.json, the default formatting command always asks for a formatter.
"[latte]": { "editor.defaultFormatter": "shufo.vscode-blade-formatter" },
But pressing Shift+P and enter to trigger the Blade formatter from the list is still much better than manual formatting :-)
- 2
-
Hi @bernhard,
in the docs-old folder of the module there is a nice section about prices. It says that we can switch to gross prices with a config setting.
I was not so sure whether that still applies and how it works with the cart calculations. So I just wanted to share my custom implementation, so that editors can enter gross price and net price will be calculated.
I added a field (type RockMoney) "price_gross" in addition to the "rockcommerce_net" field to my product template. And in my ProductPage class, I have a saveReady hook that calculates the net price from the gross price and the vat for that product.
/** * Calculates the taxrate of the product * based on the taxrate field of the product * if no custom taxrate is set, the global taxrate is used * * @return float */ public function getTaxrate(): float { return (float) $this->rockcommerce_taxrate ? $this->rockcommerce_taxrate/100 : $this->taxrate(); } /** * Executes when the page is ready to be saved. * * Only executes if price_gross is given and field rockcommerce_net is present. * Calculates the net price and VAT based on the gross price * and tax rate, if a gross price is provided. * It saves the net price to rockcommerce_net. * * @return void */ public function onSaveReady(): void { // only execute if we have price_gross if ($this->price_gross && $this->template->hasField('rockcommerce_net')) { // take price_gross and calculate vat and net price from it using taxrate $taxrate = $this->getTaxrate(); $vat = rockmoney()->parse($this->price_gross)->times($taxrate / (1 + $taxrate)); /** @var \RockMoney\Money */ $priceNet = rockmoney()->parse($this->price_gross)->minus($vat); $this->rockcommerce_net = $priceNet->getFloat(); } }
I also use a custom getTaxrate() method from my page class, in case a custom rate is set for that product.
Page edit screen
- 2
- 1
-
Thank you so much for the quick reply @bernhard and for adding stuff to the docs so quickly!
Now the docs are coming together very nicely. I really appreciate that.
54 minutes ago, bernhard said:As you can see in the old docs I thought about adding that, but I decided against it. The goal was to make the experience of setting up a simple shop as simple as possible. Obviously that comes with some limitations.
I think it would not be too hard to add support for different taxrates per product. But it would also not be trivial. Different taxrates per product means the VAT of the cart is not anymore a simple "net times taxrate" calculation.
That is totally fine. If we know these limitations as developers, we can maybe implement custom solutions if the existing cart hooks are sufficient and allow us to do those calculations and display them in the cart.
I have a rather simple shop atm with single tax rate. Just wanted to know how to handle things when tax rates are needed per product. My experence with other shops shows that this will eventually come up at some point in time :-)
- 2
-
To expand on this, imo these are the minimum points that should be covered by the docs:
- defining tax rates
- setting default tax rate
- apply tax rate different from default to product
- explain how prices are calculated:
- does RC always calculate with default rate if no other rate is set for a product?
- do we need to implement those calculations ourselves?
If you can add those, that would be awesome. Thank you.
-
Hi @bernhard,
I'm just getting started with setting up my first project using your RockCommerce module.
Installation on a new site went fine. Also basic product setup.
But now I'm stuck on setting up and applying tax rates. I figured out that I can add child pages
And I can set a default tax rate on the "Taxrates" page.
But how are non-default rates handled per product? Do I use the field rockcommerce_defaulttaxrate on my product template?
When I add the field rockcommerce_vat to my product template, I get a non-editable field
When I add rockcommerce_taxrate, I get an input for the tax rate
When I enter a value here, will this be picked up automatically for the price calculations?
And I think it would be better to have a page select field where we can choose from the tax rates that we added as children of the "Taxrates" page.Is this the correct way to set this up?
Unfortunately I couldn't find anything in the docs. Would be much appreciated if you added a section about tax handling there. The quickstart docs are great, but I think tax handling is a very essential thing in every shop. So this should definitely be covered by the docs.
EDIT (1h later): I just realized that in the readme.md inside the docs-old/taxes folder of the module there is a section about taxes that answers some of my questions. I was relying on the documentation at https://www.baumrock.com/en/processwire/modules/rockcommerce/docs/ The information in the readme.md is not contained there and I am not sure if it still applies since it is in the docs-old folder? Imo it would be great to have everything in one place.
-
3 minutes ago, bernhard said:
I also have no auto-formatter for latte + vscode, which is a shame. But I try to see that positive and take it as a reminder to keep my template files as simple as possible. Anything more complicated than $page->title is handed over to PHP where I have auto code formatting + intellisense.
I can kind of understand that. But imagine some html structure with more than 3 levels of depth. Then you remove some wrapper deep in the structure and now you have to manually mark the relevant section and move it back 1 tab. That is just a waste of time imo. I prefer to just hit my short key for Format Document and done. It really is a shame that there are no formatters out there for latte. Guess it is too much of a niche template engine.
I even tried to use the blade formatter. But didn't work for me.
Honestly, little things like that have kept me from using Latte at all in the past. Now I took another try and hitting the wall again. Guess, I will just revert to pure PHP and be happy with that :-)
-
On 3/5/2024 at 2:40 AM, fliwire said:
How format .latte files in vs code ?
Currently there is no formatter for "latte".Having the same issue here. VsCode (Windsurf) always asks for a formatter.
I tried in .prettierrc:
Still no luck.
I also have this in my user settings.json:
"[latte]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
Doesn't help either.
So for the moment I'm stuck. A solution would be much appreciated.
-
Hi there,
why the heck would you want to migrate your migrations?
Since v6 of RockMigrations there's a new feature called "config migrations" which you can read more about here.
In a nutshell: instead of having an often lengthy migration function like
$rm->migrate([ 'fields' => [...], 'templates' => [...] ])
with hundreds of lines in either site/migrations.php or site/modules/Site.module.php or other places, we can neatly organize our migration definitions into single files inside site/RockMigrations/fields and site/RockMigrations/templates (...roles, ...permissions). Where each file has the name of the field/template/role/permission and returns an array of settings. If you have module specific migrations, they go under /site/modules/MyModule/RockMigrations/(fields/templates/etc)
This is absolutely wonderful for several reasons. Here's just a few that come to mind:
- clean structure
- smaller migration files
- easy to discover in explorer panel
- faster migrations because only migrations for changed files will fire
- portability across projects
Because I immediately fell in love with this concept, I am currently updating migrations for all projects to the new structure. This can be a very tedious task. We could write a script (and maybe this is the ultimate solution). BUT since I'm lazy, I just commanded my favorite AI assistant to do the job for me. I did this in windsurf editor Write mode (Cascade), but you can also use cursor's composer for this. Let me share how I approached it.
I created the directories "fields" and "templates" under site/RockMigrations. And one migration file each for a field and a template to have examples to pass to the AI.
Then I copied the 'fields' array from above mentioned $rm->migrate(['fields => []]) (that was originally in my Site.module.php) and pasted it into the windsurf Cascade (or cursor composer) chat. Along with these instructions:For each item in this array do the following operations: 1. create file site/RockMigrations/fields/{array_key}.php 2. add namespace ProcessWire and return the array found under this {array_key} Mirror structure of @seo_fieldset.php
Where @seo_fieldset.php is passing the contents of site/RockMigrations/fields/seo_fieldset.php as context to the AI.
And here's what happened:
windsurf Cascade decided to do the operation in batches. It would let me check the results after every 4 files or so and asked me if I wanted to continue with the next batch. After about 10 minutes all my 31 field migrations where refactored into the new structure and I was very happy following along while sipping away at my coffee :-)
After that I did the same for the 'templates' array.
Some considerations on why I chose this exact approach:
- I could have given the whole Site.module.php file as context and asked the AI to read the fields array from there. But that file is pretty large and the fields array alone was about 400 lines of code. And that might have exceeded the context window or at least confused the AI.
- I used the phrase "Mirror structure of ..." because I found that to be a very effective prompt whenever you want the assistant to write code based on an example. Actually I did not find that out by myself (I'm not that great of a prompt engineering genius). Got it from IndyDevDan over at YT. Highly recommended channel btw.
To wrap things up, I can highly recommend switching to the new config migrations structure. So much cleaner. So much better. A big praise to @bernhard for coming up with this. Also praises to the developers over at cursor and codeium (windsurf) for these amazing tools. And, not to forget: Hail Claude!
- 1
- 1
-
3 hours ago, adrian said:
Hi @gebeer - please try the latest version. I have modified to use $_SERVER['REQUEST_URI'] which I hope should solve things when you guys have these unusual redirects in place and well as @Jonathan Lahijani's issue from here: https://github.com/adrianbj/TracyDebugger/issues/96
Please let me know if you can now work without that modification to your hook.
Thank you very much for the fix. I can confirm that Tracy s now working without the modification.
I think, for larger corporate sites redirects that route from root to a specific language/market URI are not that unusual. So it is great that you made things work for those use cases.
- 1
-
1 hour ago, bernhard said:
Actually the name of this module is totally wrong, because you can not only use it to pick colours, you can also use it for example to pick layout positions - here as an example in a RockPageBuilder block:
Awesome! What about RockMPP (RockMultiPurposePicker) or RockPickAnything?
Or just RockPicker.
- 1
- 1
-
On 11/20/2024 at 5:08 AM, nurkka said:
/panels/ConsolePanel.php:
# /panels/ConsolePanel.php line 406 xmlhttp.open("POST", "/", true);
When I change the line to it's previous version, it works for me:
xmlhttp.open("POST", "./", true);
We were experiencing a similar issues because the POST request now goes to / root instead of the current page loaded like before with ./
In our case the console result frame would load the homepage of the frontend instead of the actual results.I solved it for our case (a hook to PageView::execute on /) by returning if it is a tracy request
$wire->addHookBefore("ProcessPageView::execute", function (HookEvent $event) { // do not redirect if tracy request if(isset($_POST['tracyConsole']) && $_POST['tracyConsole'] == 1) return; // alternative // if (isset($_SERVER['HTTP_X_TRACY_AJAX']) && $_SERVER['HTTP_X_TRACY_AJAX']) return; if ($_SERVER['REQUEST_URI'] === '/') { ... session()->redirect("{$lang}{$marketName}"); }
We need that redirect to determine language and market based on a request to GeoApify API.
I think that others might potentially run into this as well. So if the change of xmlhttp.open("POST", "./", true); to root / is not strictly necessary for Tracy to work, it might be better to revert that? @adrian
- 1
-
6 minutes ago, bernhard said:
Any sources for that? PW definitely uses camelcase constants like Inputfield::collapsedHidden which I think looks nicer than Inputfield::COLLAPSEDHIDDEN. But I'd be happy to get some links to read.
https://www.perplexity.ai/search/php-constants-naming-conventio-g4mLG8sbQyu34r4mGXmx6w
Although the source for this is not php.net directly. I wanted to read up on that over there but php.net currently throws a 502 error.
Anyways, that was just a side note.
8 minutes ago, bernhard said:Yes I always use underscores
That explains why you never saw that error. But imo you should not assume that everybody uses underscores so I think, the renaming logic in my PR at https://github.com/baumrock/RockMigrations/pull/70/commits/a06c6062c61b5264932a8044cf25bac0c689f8cf should be implemented.
Otherwise people who use hyphens in their template names would have to rename all their templates just to be able to use the RockMigrationsConstants magic. -
7 minutes ago, bernhard said:
I'm not sure about this. That should only be the case on regular runtime migrations, but when doing a modules refresh all migrations should fire.
Ah, thank you. That make sense. Will prioritize my Site module migration so that the backup is created before the config migrations kick in.
-
Hi @bernhard,
I usually have a line in my Site module that does a DB backup before the migrations are running
public function migrate() { // backup before migrations (not on ddev) if (strpos($this->config->httpHost, 'ddev') === false) $this->wire->database->backups()->backup(); ...
I moved my migrations from the migrate method to the new phantastic config migration structure in site/RockMigrations. So much cleaner to have each field/template migration defined in a separate file :-)
But: since the migrations now do not live in Site module, the DB backup is not being triggered because there are no changes to that file anymore.
Long story short: Is there a setting in $config->rockmigrations that will do automatic backups befor each migration on the live server? Couldn't find anything related in the docs, the GH wiki or even searching the string "backup" in the RockMigrations module folder.
Could this feature be added or how do handle this?
-
7 hours ago, bernhard said:
hen I'd appreciate if you could try to create the file /site/modules/Site/RockMigrationsConstants.php and see if that maybe fixes some other of your mentioned issues?
This solves only the first problem that I described.
The error caused by hyphens in constant names still persists, even after switching to PHP8.3. Do you name all your templates with underscores like "basic_page" to avoid that?
On a side note, after reading up on PHP constants, there seems to be a convention to name them in capital letters.
-
Hi @bernhard,
I already fell in love with the new config migrations feature in RockMigrations > 6.0.0. I am currently on v6.0.1
So much cleaner to have migrations organized in this way.
I just tried to implement the part about the constant traits, described at https://www.baumrock.com/en/processwire/modules/rockmigrations/docs/config-migrations/#class-constant-traits
First it would not work at all as described in the docs. I noticed that my file at site/modules/Site/RockMigrations/RockMigrationsConstants.php never got picked up because of searching for those files did not recurse into module subdirectries. Fixed in PR#70 commit https://github.com/baumrock/RockMigrations/pull/70/commits/faba5475a008ab14415c0e35f2c5c78d2e91f0b1.
First problem:
After fixing that, I get the Compile Error
Traits cannot have constantsActually, constants are only allowed in Traits since PHP 8.2.
So this would change the module dependencies from PHP>=8.0 to PHP>=8.2
I don't think this was intended. But it should be updated or at least documented that the automated constants thingy requires PHP>=8.2.
Second problem:
After upgrading to PHP8.2 I ran into the next issue:
This is caused by the constant name "template_basic-page" containing a hyphen. As it seems, they are not allowed in constant names in PHP at all (https://www.php.net/manual/en/language.constants.php):
QuoteThe name of a constant follows the same rules as any label in PHP. A valid constant name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thusly: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$
For years I have naming conventions for templates and fields in PW. Template names always contain hyphens like in "basic-page". Field names always contain underscores like in "my_field". This is also helpful when looking at code to discern templates from fields on the first glance.
I fixed this by replacing - with _ in constant names. See https://github.com/baumrock/RockMigrations/pull/70/commits/a06c6062c61b5264932a8044cf25bac0c689f8cf
The issue with PHP8.2 still remains to be resolved. I suggest adding the requirement only to docs about RockMigrationsConstants.php because other than that RockMigrations seemed to work fine on 8.1 in my tests.
- 1
-
On 11/18/2024 at 8:08 PM, joe_g said:
@gebeer Is what you describe some native setting or is it part of your module?
This is not native. It is a field definition for a custom field 'langs' that lets you choose one or more language. The array format of the field definition that I posted is used in the @bernhard's fabulous RokMigrations module but you can define the field manually via GUI, too, if you prefer so.
- 1
-
In one of my projects I have a separate field 'langs' that editors can check. Definition (for RockMigrations):
'langs' => [ 'label' => 'Languages', 'tags' => 'general', 'flags' => 0, 'type' => 'FieldtypePage', 'derefAsPage' => 0, 'inputfield' => 'InputfieldCheckboxes', 'parent_id' => '', 'labelFieldName' => 'title', 'optionColumns' => 1, 'template_id' => 'language', ],
So it is a page reference field that gives you checkboxes for each language.
You could then use the value of this field in your logic for the language switch.
- 1
-
Solved. It was indeed a problem with our setup, not with renderLayout().
- 1
-
Hi @bernhard we just updated RockFrontend on a site from 3.20.0 to 3.23.3 and the site stopped working.
I fixed it by changing templates/_main.php
<?= $rockfrontend->renderLayout($page); // worked before update ?> <?= $rockfrontend->render($page); // works after update ?>
We use RockPageBuilder and in templates/sections/main.latte
<div sortable x-ref="additional-sections"> {$page->get('rockpagebuilder_blocks')->render()|noescape} </div>
Now after the update that threw an error on our home page because template home has no field rockpagebuilder_blocks
I am wondering why this is. Do you have any idea?
I looked at the function signature for render() and the examples in the PHPDoc do not mention that we can pass a Page object as $path argument. So I thought we could not call render($page) at all. But it works. I guess because $page is then overwritten with $this->wire->page.
So renderLayout($page) would be the correct method to use. But something in the inner workings of renderLayout must have changed and stopped the site from working.
I suspect that the way we have setup rendering with RockPageBuilder, RockFrontend and Latte is fundamentally wrong.
-
@FireWiresorry, I totally did not see AsmSelect in the list albeit it being the very first item. Strange things happen sometimes...
- 1
-
If you leave active checked, it will automatically fall back to the default language. This behavior is the default behavior.
You can change that behavior per language field in the Details tab
-
The list of currently supported inputfield types under heading "Possible values for “type”" at https://processwire.com/blog/posts/custom-fields-module/ does not list AsmSelect which you chose for your page field (multiple) based on the screenshots. Maybe this is the issue? Have you tried field type SelectMultiple instead of AsmSelect?
- 1
-
5 hours ago, wbmnfktr said:
Supermaven Joins Cursor 🤯
That is great news. I've been using Supermaven in Cursor for the past 4 months with deactivated Cursor Tab feature. IMO Supermaven works way faster and more intelligent than Cursor Tab. So I really appreciate them integrating it into Cursor.
- 1
Unexpected Order with Markup Regions pw-append
in API & Templates
Posted
Hi there,
I'm experiencing unexpected behavior with markup regions where multiple pw-append actions are being processed in reverse order. I have been using markup regions for several years in multiple projects and never came across this. There are no project specific potential causes for my problem that I could identify. Involved HTML markup syntax is correct.
Setup
Delayed output strategy with site/templates/_main.php (simplified):
site/templates/products.php:
Expected Behavior
Since products.php executes before _main.php and contains region actions (pw-append) that should be processed in order, the final output should show:
Products Intro Section
Product Categories Section
Actual Behavior
The sections are rendered in reverse order:
Product Categories Section
Products Intro Section
Technical Context
According to the Markup Regions documentation:
Since products.php is processed before _main.php (using $config->appendTemplateFile = '_main.php'), the region actions in products.php are technically output "before" the <html> tag and region definitions in _main.php. Therefore, the implementation follows the documentation correctly, but the output order is reversed.
Current Workaround
Changed first section from pw-append to pw-prepend to achieve desired order:
MarkupRegions Debug Output (shows wrong order of processing):
Environment
ProcessWire version: .3.0.243
PHP version: 8.1 (same behavior with 8.2)
Has anyone experienced this before? Couldn't find related forum posts or github issues