-
Posts
1,489 -
Joined
-
Last visited
-
Days Won
43
gebeer last won the day on December 5 2024
gebeer had the most liked content!
Profile Information
-
Gender
Male
-
Location
Thailand
Recent Profile Visitors
14,842 profile views
gebeer's Achievements
-
gebeer started following Backup DB before migration , Unexpected Order with Markup Regions pw-append , RockCommerce gross prices by default - my implementation and 4 others
-
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): <html> <head> </head> <body> <main id="maincontent" class="content"> </main> </body> </html> site/templates/products.php: <div class="bg productsintrobg" pw-append="maincontent"> <!-- Products Intro Section --> <div class="container"> <!-- Products Intro Content --> </div> </div> <div class="bg productcatsbg" pw-append="maincontent"> <!-- Product Categories Section --> <div class="container"> <section class="productCats teasers row"> <!-- Product categories content --> </section> </div> </div> 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: <div class="bg productsintrobg" pw-prepend="maincontent"> <!-- Products Intro Section --> </div> <div class="bg productcatsbg" pw-append="maincontent"> <!-- Product Categories Section --> </div> MarkupRegions Debug Output (shows wrong order of processing): • APPEND #maincontent with <div class="bg productcatsbg" ... +24 bytes><div class="container"> <section class="productCats teasers row"> … 14986 bytes</div> • APPEND #maincontent with <div class="bg productsintrobg... +26 bytes><div class="container"> <article class='intro row'> … 1264 bytes</div> • 0.0014 seconds 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
-
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 :-)
-
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
-
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. 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 :-)
-
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.
-
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 :-)
-
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 reply
-
- 2
-
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
-
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. 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.
-
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?