Leaderboard
Popular Content
Showing content with the highest reputation on 03/24/2023 in all areas
-
We've got just a few core updates on the dev branch this week, but next week we're looking at finally merging in the InputfieldTinyMCE module! This week I also wrapped up the WireRequestBlocker module that was mentioned in last week post, and the v1 beta is now posted in the ProDevTools download thread. I've been running it here on processwire.com this week and it's been doing a good job of keeping out the vulnerability scanners and bots. For more details on this new module please see the new Wire Request Blocker page that I just posted. Thanks and have a great weekend!12 points
-
I was wondering: when I use the same hooks on different pages, is it better to only use that hook once and divide with if statements or is it ok to call a hook multiple times. Like: $wire->addHookBefore('Pages::saveReady', function(HookEvent $event){ $page = $event->arguments(0); if($page->hasField("field1")) { //do something } if($page->hasField("field2")) { //do something else } }); $wire->addHookAfter('Pages::unpublishReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->hasField("field1")) { //do something } if($page->hasField("field2")) { //do something else } }); or //Things regarding pages with Field 1 //###################### $wire->addHookBefore('Pages::saveReady', function(HookEvent $event){ $page = $event->arguments(0); if($page->hasField("field1")) { //do something } }); $wire->addHookAfter('Pages::unpublishReady', function(HookEvent $event) { if($page->hasField("field1")) { //do something else } }); //###################### //Things regarding pages with Field 2 //###################### $wire->addHookBefore('Pages::saveReady', function(HookEvent $event){ $page = $event->arguments(0); if($page->hasField("field2")) { //do something else } }); $wire->addHookAfter('Pages::unpublishReady', function(HookEvent $event) { if($page->hasField("field2")) { //do something else } }); //###################### Of course the first version looks nicer, but if you have a lot of functions it becomes increasingly confusing to keep track of those functions. The second version makes it much easier to keep logic together but I'm concerned if that will raise trouble with performance.3 points
-
Hey @eydun The module uses PHP8 syntax/features on several spots. All my modules do, as PHP7.4 is end of life and updating should be very easy. There will definitely be some challenges. Most likely a lot more than upgrading your site to PHP8.1 or 8.2 which would be the best thing to do anyhow ?2 points
-
Not sure if this has been mentioned?? https://github.com/uiii/processwire Not sure who the user is though to quote, but I guess this is an approach using plugins instead of post-install-cmd?? The actual composer plugin: https://github.com/uiii/pw-core2 points
-
I'm creating a new topic in response to @cst989's question in the RM thread as I think this is a common question and misunderstanding when evaluating RockMigrations. It's also easier to communicate in separate threads than in one huge multi-page-thread... Hi @cst989 thx for your question and interest in RockMigrations. This sounds like you have a misconception in your head which is quite common I guess. Did you watch my latest video on RM, especially this part? https://www.youtube.com/watch?v=o6O859d3cFA&t=576s So why do you think it is a good thing to have one file per migration? I know that this is the way migrations usually work. But I don't think that this is the best way to do it. I'm not saying one way is right and the other is not. I'm just saying I'm having a really, really good time with RockMigrations and it makes working with PW in a more professional setup (meaning either working in a team and/or deploying PW to multiple locations and of course managing everything with GIT) a lot more fun an a lot faster and more efficient. If we look at how migrations usually work we can have a look at the other PW migrations module, which works just like usual migration modules work: You create one file per migration and you end up with a list of migrations that get executed one after another. See this screenshot from the modue's docs: In my opinion that screenshot perfectly shows one huge disadvantage of that approach: You don't see what's going on. You end up with a huge list of migrations that you can't understand on first sight. In RockMigrations this is totally different. You don't create one file per migration. You put all the necessary migrations where they belong and - in my opinion - make the most sense. An example: Let's say we want to add 2 fields to the homepage: "foo" and "bar". Ideally you are already using Custom Page Classes (see my video here https://www.youtube.com/watch?v=D651-w95M0A). They are not only a good idea for organizing your hooks but also your migrations! Just like adding all your HomePage-related hooks into the HomePage pageclass init() or ready() method, you'd add the migrations for your 3 fields into the HomePage pageclasses migrate() method. This could look something like this: Now let's say we develop things further and realise we also need a "bar" field: Do so see what we changed? I guess yes ? Now one big difference to a regular migration approach is that you don't write downgrade() or reversion migrations - unless you don't want to revert the changes! In real life I've almost never ever needed to revert changes. Why? Because you develop things locally and only push changes you really want to have on your production system. If you happen to have to remove some changes that you applied on your dev it's easy to do, though: You see what we did? Nice! So does everybody else that has access to the project's GIT repo! So all your team mates will instantly see and understand what you did. Pro-tip: You don't even need lies 43-45 if you didn't push those changes to production! If you only created those fields on your local dev you can simply restore the staging database on your local dev environment and remove the migrations that create the fields. Pro-tip 2: Also have a look at RockShell, then restoring staging or production data is as easy as "php rockshell db-pull staging" Pro-tip 3: When restoring a DB dump from the staging system it can easily happen that you have data in your database that was created only on the remote and you don't have on your dev system (like new blog posts for example). If you then open those new blog posts on your dev system processwire and the blog post contains images processwire will not be able to show those images (as only the file path is stored in the DB and not the whole image!). Just add $config->filesOnDemand = "http://yourstagingsite.example.com" to your config.php file and RockMigrations will download those files once PW requests the file (either on the frontend or also on the backend)! Having all your changes now in your git history you can even jump back and forth in time with your IDE: You could. I thought about that as well. But I think it does not really make sense and I hope my examples above show why. I'm always open to input though and happy to try to think about it from other perspectives. One final note: I'm not sure if what you say about $rm->watch() makes sense here. If you watch() a file that means that RM checks it's modified timestamp. If that timestamp is later than the last migration that RM ran, then RM will automatically execute the migrations that are in that file. All other files and migrations will be ignored. That makes it a lot more efficient when working on projects that have many migration files in many different places. When triggered from the CLI though or if you do a modules refresh then it will always trigger all migrations in all watched files. I hope that makes sense! --- Ok, now really a final note ? One HUGE benefit of how RockMigrations works (meaning that you write migrations in page classes or in modules) is that you create reusable pieces of work/code. For example let's say you work on a website that needs a blog. So you create a blog module and in that module you have some migrations like this: <?php $rm->createTemplate('blogparent'); $rm->createTemplate('blogitem'); $rm->setParentChild('blogparent', 'blogitem'); $rm->migrate([ 'fields' => [...], // create fields headline, date, body 'templates' => [...], // add those fields to the blogitem template ]); You'd typically have those lines in Blog.module.php::migrate() What if you need a blog in another project? Yep --> just git clone that module into the new project and execute migrations! For example in migrate.php this: <?php $rm->installModule('Blog'); If you follow a regular migrations concept where all project-migrations are stored in a central folder you can't do that! Of course you don't have to work like this. You can still write all your migrations in the project's migrate.php file. Because I have to admit that it is a lot harder to build a blog module that can be reused across different projects than just creating one for one single project! It always depends on the situation. But - and now I'll really leave it for today ? - you could also make your Blog-Module's migrate() method hookable and that would make it possible that you build a generic blog for all projects and then you add field "foo" to your blog in project-a and you add field "bar" to your blog of project-b. Have fun discovering RockMigrations. I understand it can look frightening at first, but it is an extremely rewarding investment! Ask @dotnetic if you don't believe me ?1 point
-
Just took a moment to play a bit more with ChatGPT (v3.5) and built a simple module with it. While it was pretty easy, ChatGPT needs a lot of assistance to make things work out as expected. Adding the Processwire namespace? Nope. Taking care of user input and sanitizing? Nope. But that's totally fine for me. It took about 30-40 minutes from start to published on Github. See: TextformatterAsciiEmoji The README.md was also written by ChatGPT.1 point
-
Hello @all I have a configurable module and for better overview i have created a lot of fieldsets where I have placed configuration fields inside. By default all fieldsets are closed. So if an error occurs in one field after saving the module, I get the error message at the top, but the fieldset which includes the field with the error keeps closed. This is not very userfriendly, because you will not know in which of the fieldsets is the field which causes the error (I know, where to look, but someon who does not know my module will not...) So it would be great if the fieldset with the error field inside will be opened, after the form processing. Is there an inbuilt way to achive this or has someone struggled with the same problem and has found a working solution and will be so kind to post it here? Thanks in advance1 point
-
I think that the first example would be more performant as every declaration of the hook creates an additional WireHook object that should be processed. While I think that difference in performance impact would be hard to measure in a typical PW site, I would stick with the first way not from the performance side, but from the side of structure, clarity, and repetition of the code, but it still depends on actual hook and what it is doing etc1 point
-
Hi @Juergen Just tested and in my setup, if there are any nested fields in the fieldset with an error the parent fieldset is get automatically opened. From what I see in the code it is the intended behavior https://github.com/processwire/processwire/blob/master/wire/core/InputfieldWrapper.php#L777 In any case you can manually set collapsed state of inputfields inside the getModuleConfigInputfields public function getModuleConfigInputfields(array $data) { .... foreach ($inputfields->getErrorInputfields() as $inputfield) { $inputfield->collapsed = Inputfield::collapsedNo; } return $inputfields; } or even like this public function getModuleConfigInputfields(array $data) { .... foreach ($inputfields->getErrorInputfields() as $inputfield) { $inputfield->collapsed = Inputfield::collapsedNo; $parents = $inputfield->getParents(); foreach ($parents as $parent) { $parent->collapsed = Inputfield::collapsedNo; } } return $inputfields; }1 point
-
If I’m not mistaken that should be 47,672,401,706,823,533,450,263,330,816 combinations, so… seems sufficient? GUIDs are 128 bit tokens and they’re used for computer things, so for something like this that only needs to work on a human scale it shouldn’t be a problem to go a couple of billion times smaller. Especially if you rate limit against guessing. I wouldn’t ask for the phone number since anyone who intercepted the SMS would know that anyway. Shipment tracking things usually ask for my post code before showing my address, maybe that’s worth considering?1 point
-
Ok great, I thought I might be missing something, which can easily happen if you don't use the "regular" approach any more ? For me the runtime approach in general is a huge benefit. Once you start defining things in code all the little details that you would usually avoid because the GUI does not support it suddenly become a no-brainer and very easy to add. All the little customisations that you'd usually need a hook or a module for. They are simply there in your pageclass and you start to develop the backend (page editor) similar to how you'd develop your frontend. <?php public function editForm($form) { if ($f = $form->get('title')) { $f->appendMarkup(" <div>Custom field markup without any hooks...</div> <style>#wrap_Inputfield_title {border: 5px solid red;z-index:1;}</style> <script>console.log('js-demo');</script> "); } } PS: Note that this code will only be added on the page editor of pages having the pageclass where you defined your editForm() method! So if you added that in HomePage.php you'll only get the red border on the "home" page ?1 point
-
Hey @gebeer working with fieldsets in migrations has always been a bit of a pain for me. That's why I'm using them only at runtime in all of my projects. I don't see any drawback with this. Using MagicPages it is as simple as doing this: <?php ... public function editForm($form) { ... $rm->wrapFields( // current form wrapper $form, // fields inside the fieldset [ 'foo' => ['columnWidth'=>33], 'bar' => ['columnWidth'=>33], 'baz' => ['columnWidth'=>33], ], // fieldset settings [ 'label' => 'Your Runtime Fieldset', 'icon' => 'bolt', ] ); } This is a lot quicker than messing around with fields, field order, moving the ending field to the correct place etc. I only place the fields on the correct template, which is necessary for the fields to be queryable by selectors etc and all the rest is done in code in the pageclass. That also makes it possible to switch layouts based on the user's role for example. So the approach is very powerful. I don't see that as a limitation. Or are there any things that I'm missing?1 point
-
Did you add the textformatter to the field where the video content is stored in? I have the module running latest version and everything is fine.. PW 3.0.214, module version 2.0.2 PHP 8.0.121 point
-
https://processwire.com/talk/profile/2312-richard-jedlička/1 point
-
Hi, just a little idea i often think about, when you create a fieldset field and you give it one or more tags in the advanced tab, it may be a good idea that the fieldset_END gets the same tag(s) by default instead of ending in the fields with no tags list ? have a nice day1 point
-
I’m actually offended that it left out the one key attribute: “…, and good looking.”1 point