Jump to content

bernhard

Members
  • Posts

    6,264
  • Joined

  • Last visited

  • Days Won

    313

Everything posted by bernhard

  1. Thx for trying to explain the details. I understand you well. This is why I built RockMigrations. On the last sentence I'm losing you. I'd still be interested in a detailed example of what you are doing and where this is necessary and why. You are explaining extensively the same workflows that I'm using and then you suddenly state that something is missing without going into detail. For example: How to you execute these snippets? Who does it? Did you think of any different approaches? Why do you think this has not been an issue for me so far?
  2. Sounds cool! I understand the need for what you are working on and I'd even be happy to add such features to RockMigrations, if you want and think that could make sense, but more on that later ? That was confusing for me because it's wrong ? Not trying to be know-it-all but it might be interesting for you to know that I tried to put all the method arguments in the order of how the method is named, so add-FIELD-to-TEMPLATE means field first, then template. Using PHP8 with named arguments that not that important any more, though. So back to topic. What you are trying to do have actually been my very first approaches when working with migrations. That's how they work everywhere after all. RockMigrations1 even had downgrade() and upgrade() methods and some version_compare to see if migrations should run or not. The reason why I completely removed that was because it has been so much more productive to use just config-based migrations in my daily work. Rather than writing all the logic around the actual migration to make sure migrations are only executed once I made sure that no matter how often they run they produce the same result. That works great in 99% of my use cases, though there are situations where it does not and I admit it's not terribly beautiful ? So for example if you have fields added via RockMigrations that you don't need any more you'd do this: <?php public function migrate($rm) { // cleanup $rm->deleteField("old_fieldname"); // actual migration } So while this would just work it's really not beautiful and it would log "Field old_fieldname not found" on every run. You can prevent that by adding TRUE as second parameter, but it's still not really beautiful. I've also thought of adding something like this: <?php public function migrate($rm) { // cleanup $rm->once(function($rm) { $rm->deleteField('old_fieldname'); } } The problem here is: How does RM know, what that "once" means? What if it fails? What if inside the once was multiple steps like in your example, for example looping over 100 pages and after 50 it breaks? What do you in your module in such a case? What I've done in such cases was to create an import script based on RockShell that I could run whenever needed. Manually. In the best case only once ? I could also run this script locally as often as I want, try everything out, see the result, and if it's not working I'd just do "rockshell db:restore" and try it again. Once everything works I push to production and run the script there. This is what your script would look like in RockShell: <?php namespace RockShell; use function ProcessWire\rockmigrations; class DemoMigration extends Command { public function handle() { $rm = rockmigrations(); $rm->createField('richtext', [ 'type' => 'FieldtypeTinyMCE', // ... ]); $rm->addFieldToTemplate('richtext', 'basic-page', 'textarea'); $pagesToUpdate = $this->wire()->pages->find('template=basic-page'); foreach ($pagesToUpdate as $pg) { $this->write("Updating page #$pg ..."); $pg->setOutputFormatting(false); $pg->set('richtext', $pg->textarea); $pg->save(); } $rm->removeFieldFromTemplate('textarea', 'basic-page'); $this->success("Hooray - we are done :)"); return self::SUCCESS; } } Put that in /site/assets/RockShell/Commands and you are good to go. I'd also really be interested in how you work with docker. I've seen https://github.com/poljpocket/processwire-docker and your statement sounds very interesting. So I'd love to hear more about that if you find time.
  3. Hey @adrian could tracy show the execution time of the page even when tracy is toggled off? I think it would be nice to see this to get a feeling of how fast the website is for public users. Tracy and all the panels sometimes make sites a little slower, so I sometimes toggle it off completely, but then I don't see the loading time any more. Would that make sense? What do you think?
  4. I've literally yesterday thought of adding this to RockFrontend! I thought I'd add /site/templates/htmx and whatever file you place there would be available as yourdomain.com/htmx/[filename] So for example placing modal.php there you could use hx-get="/htmx/modal" What do you think? Not sure what you mean by JSON api support. Maybe I'm missing something?
  5. This feedback is so great, I have to share it with you ? Thx so much @FireWire and thanks for brilliant fluency module!! Just pushed v5.2 to the main branch!
  6. Yeah, with more complicated things stackoverflow is often still nicer, because you often see that some solutions are outdated and there are better solutions in 2024. You often don't see that in AI, as it just presents you the solution that it thinks is the best. But for things like "oh yes, 644, why did I even ask" it's a lot more efficient to ask the AI inside cursor and not Google. From my first month of using cursor I'm a little shocked how much I am using it and how much I must have been googling before ?
  7. Of course you have to check. It's the same with any source... AI, web, manual, other devs... You always have to think about what they tell you and then you have to decide what you do and take the responsibility for your actions. Cursor gives you the option, it does not fire the command by itself. If it did I wouldn't use it.
  8. It really helps with all the little annoying time consuming tasks. Ever forgot what the chmod command is to set permissions to "-rw-r--r--" ? Or even faster: Just hit CMD+K and type this: It will present you with this terminal command: Hit CMD+Enter and done ✅
  9. bernhard

    CVE-2023-24676

    What would happen if anybody uploaded such a zip to a regular user's file field? It would still be a zip, right? Isn't there a setting to automatically unzip on upload? Would that be a problem? I guess no, right? It would just unzip it and then we'd have a .php file in the field, but I think that would need to be allowed in the field settings. And even if allowed I don't think pw would at any time execute this file?
  10. Using RockFrontend you could also do this, for example inside a saveReady hook: <?php use Wa72\HtmlPageDom\HtmlPageCrawler; $dom = rockfrontend()->dom($page->body); $dom ->filter("a") ->each(function (HtmlPageCrawler $node) { $href = $node->getAttribute("href"); if (!$href) return; if (strpos($href, "http://") === 0) return; if (strpos($href, "https://") === 0) return; $https = rtrim($this->wire->pages->get(1)->httpUrl(true),"/"); $node->setAttribute("href", $https.$href); }); $page->set('body', $dom->html()); I've added docs for it on the dev branch: https://github.com/baumrock/RockFrontend/tree/dev/docs/dom
  11. Hey Ryan, thx for all the updates and congrats on the launch! I am seeing a horizontal scrollbar on screen sizes around 850-900 in chrome, but only when I size the window without devtools!
  12. You can just add a hidden field that is populated on page save from the content of each RepeaterMatrix or RockPageBuilder item. That field can then be queried by any search. In RockPageBuilder you get the benefit that you can simply add a dedicated method to every block: <?php // Text.php public function searchIndex() { return $this->body; } // Accordion.php public function searchIndex() { $index = ""; foreach($this->items as $item) { $index .= $item->headline . ": " . $item->body . "\n"; } return $index; } Thats not a built in feature but as all RockPageBuilder blocks are dedicated PHP files and classes things like this are super easy and clean to implement. This solution would obviously add additional data to the database, so fields are not queried directly. But that adds more options in presenting your search results. See here for some insights:
  13. I don't have much time, but do you think this is related? https://github.com/processwire/processwire-issues/issues/1706
  14. Imagine you want to display an image on your website. Easy. Imagine you want to open the bigger version in a lightbox. Easy when using UIkit (or any other framework). Imagine you only want to add the lightbox link only if there is actually a larger version than the one displayed. Easy when using LATTE ? <div n:if="$img = $page->image" class="uk-background-muted uk-padding-small uk-text-center" uk-lightbox > <a n:tag-if="$img->width > 800 || $img->height > 400" href="{$img->maxSize(1920,1920)->webp->url}" > <img src="{$img->size(800,400)->webp->url}" alt="{$page->title}" /> </a> </div> This takes care of so many things with so little and clean code: the n:if on the outer div makes sure that we don't get any errors if no image is uploaded the n:tag-if makes sure that the anchor wrapper is only added if the original image is larger than the thumbnail Note that you can assign $img directly in the n:if condition. No need for an additional {var $img = $page->image} at the top. For some that might be too short, but I like it ?
  15. v1.5.0 adds support for directly using fontawesome icon markup like <i class="fa-brands fa-youtube"></i> Just download FontAwesome and start using FontAwesome markup in your PDFs right away! ?? Docs: https://www.baumrock.com/en/processwire/modules/rockpdf/docs/fontawesome/
  16. Hey @Jon sorry for the trouble, but I have a little present for you ? v1.5.0 adds support for directly using fontawesome icon markup like <i class="fa-brands fa-youtube"></i> The release is less than 10 minutes young and ready for download at https://www.baumrock.com/en/releases/rockpdf/ Docs are already there as well: https://www.baumrock.com/en/processwire/modules/rockpdf/docs/fontawesome/ Hope that helps you and many others ?
  17. Thx! While I don't agree on everything, this was an interesting read: https://www.nngroup.com/articles/toggle-switch-guidelines/ I've added some opacity to make it even more obvious ?
  18. I'm working on improving the RockPageBuilder config page and added toggle buttons instead of checkboxes as they are a lot more intuitive (especially if you have default=yes toggles, where you'd need to use a negative meaning with checkboxes, eg "dont use the widgets feature" vs. "use widgets feature yes/no" The default toggle looks like this in ProcessWire: There it is not really obvious which value is selected. Is the grey one the active item or the shiny white one? I think this is much better: So I'm wondering if that should be a global default for toggles in AdminStyleRock - what do you think?
  19. Ok... AI did indeed help with this problem again! I told cursor "@[link to this topic] can you help bernhard?" and it gave me instructions what I can do and check. So it told me to place a file in /.well-known/foo.txt to check if my rules work. That was a great "idea" because I was able to check the rules without issuing a cert all the time. I also had a look at PW's .htaccess file and looked how it is done there. Mixing everything together with some trial&error brought me to the working solution: RewriteEngine on # don't proxy requests to the .well-known folder RewriteCond %{REQUEST_URI} ^/\.well-known/.* RewriteRule ^ - [L] # send other requests to uptime kuma RewriteCond %{HTTP:Upgrade} =websocket RewriteRule /(.*) ws://localhost:3001/$1 [P,L] RewriteCond %{HTTP:Upgrade} !=websocket RewriteRule /(.*) http://localhost:3001/$1 [P,L] Maybe it helps someone else ?
  20. I'm hosting uptime-kuma on my server as docker container behind a reverse proxy. The domain is set to redirect http://uptime.example.com to https://uptime.example.com Unfortunately my proxy does not let the letsencrypt request through and fails: [23-Jan-2024 10:19:05] INFO | check domain "example.com' [23-Jan-2024 10:19:05] INFO | certificate is valid until 2024-02-03 16:45:10 (11 days left) [23-Jan-2024 10:19:05] INFO | certificate is in renewal period [23-Jan-2024 10:19:05] INFO | renew cert [23-Jan-2024 10:19:05] INFO | Using certificate authority: "https://acme-v02.api.letsencrypt.org/" (PRODUCTION). [23-Jan-2024 10:19:05] INFO | Getting endpoint URLs. [23-Jan-2024 10:19:05] INFO | Account "foo" already registered. Continue. [23-Jan-2024 10:19:05] INFO | Requesting Key ID. [23-Jan-2024 10:19:05] INFO | Sending signed request to "https://acme-v02.api.letsencrypt.org/acme/new-acct". [23-Jan-2024 10:19:06] INFO | Start certificate generation. [23-Jan-2024 10:19:06] INFO | Token stored at: /home/panel/www/.well-known/acme-challenge/local-check-123456 [23-Jan-2024 10:19:06] INFO | URL: http://example.com/.well-known/acme-challenge/local-check-123456 | HTTP code: 200 | HTTP body (first 100 chars): <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport" conte [23-Jan-2024 10:19:06] ERROR | a Let's Encrypt error occurred: Local resolving checks failed for domain "example.com". Please ensure that your domain is locally resolvable! This is the proxy setup for HTTPS: # dont proxy letsencrypt requests ProxyPass /.well-known ! # uptime kuma directives ProxyPass / http://localhost:3001/ RewriteEngine on RewriteCond %{HTTP:Upgrade} =websocket RewriteRule /(.*) ws://localhost:3001/$1 [P,L] RewriteCond %{HTTP:Upgrade} !=websocket RewriteRule /(.*) http://localhost:3001/$1 [P,L] Any ideas? AI is not smart enough to help me ?
  21. I don't think that this is true any more with HTTP2 because browsers can download multiple files at once. That's why I didn't implement something like this in RockFrontend. But I'm not sure ?
  22. Hey @Juergen got bit by this again. I think the reason why the language is always the default one is because the hook adds to an URL that looks like the default language in PW - which makes sense. My solution today was to add two hooks for two languages: <?php public function init() { wire()->addHook("/create-cv", $this, "createCV"); wire()->addHook("/de/create-cv", $this, "createCV"); } public function createCV(HookEvent $event): void { // more code here $url = $this->wire->user->language->isDefault() ? $pdfs->first()->url : $pdfs->last()->url; $this->wire->session->redirect($url); } I created an issue on github: https://github.com/processwire/processwire-issues/issues/1871
  23. Hey @Jon thx for the purchase and sorry for the trouble. I was confused because you posted your question in the old thread with old code. I'll update this threads title to make it more obvious! Anyways your code looks still strange. Why are you defining your fonts twice? Please have a look at the docs (https://www.baumrock.com/en/processwire/modules/rockpdf/docs/fonts/) and use one of the listed fonts exactly like shown in the examples. Once that works try your own font. If it breaks then, share your code and also your font (if possible) so that I can try to reproduce the problem. Thx PS: Where is that code that you posted? It has an additional bracket at the end...
  24. Hey @aComAdi thx for the report. Are you on the latest dev? See https://github.com/processwire/processwire-issues/issues/1862 I've heard from @Stefanowitsch that the issue is still there so it might be necessary to reopen the issue. But it's gone one my end so we'd need more insights first ?
×
×
  • Create New...