Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/20/2024 in all areas

  1. This week we have ProcessWire 3.0.238 on the dev branch. This version contains 17 commits containing new features (some via feature requests) as well as issue fixes. Recent updates have been nicely covered in ProcessWire weekly issues #517 and #518. Also added this week are the following: Improvements to ProcessPageClone, which now supports some new options such as the ability to configure it to always use the full clone form (a requested feature), and an option to specify whether cloned children should be unpublished or not. New $datetime->strtodate($date, $format) method that accepts any PHP recognized date string and reformats it using the given format. It also supports date strings that PHP doesn't recognize if you give it a 3rd argument ($options array) with an `inputFormat`. The existing $datetime->strtotime() method now supports an `inputFormat` option as well. The Inputfield class now has new methods: $inputfield->setLanguageValue($language, $value) and $inputfield->getLanguageValue($language), added by the LanguageSupport module. Previously there were no dedicated methods for this, so you had to manage them with custom keys containing language IDs if you wanted to programmatically use an Inputfield in multi-language mode. The ProcessWire.alert() JS method has been updated with an auto-close option (`expire` argument) that automatically closes the alert box after a specified number of seconds. InputfieldDatetime has been updated with 7 new interactively configurable settings for the jQuery UI date picker. See the screenshot below for an example of a few. Plus, its API has been updated with the ability for you to specify or override any jQuery UI datepicker option, either from PHP or JS, as requested by Toutouwai/Robin S. See the new datepickerOptions() method and phpdoc for details. Next week we've also got some more updates to InputfieldTable that take the newly added actions even further and make them easier to use. Thanks for reading and have a great weekend!
    6 points
  2. Following the advice of some PW-forum members @gebeer @dotnetic @bernhard @sebibu, I would like to share my first Processwire module with all members. QuickSave: My first attempt at developing a PW module to quickly save a page. What can the module QuickSave do: Quickly save a page edit in the admin and return to the last activity. Adds an extra save button AND shortcuts CMD+s and CTRL+s. QuickSave includes an additional plugin for TinyMCE. The plugin for TinyMCE must be assigned and activated specifically for these textarea fields. (Keyboard input shortcut does not yet work in an iFrame - RTE/iFrame, CKE, etc.) PW-QuickSave-1024-v16.mp4 Installation: To install the module, it simply needs to be copied into the Processwire module directory and then activated in the Processwire admin. Optional: Anyone who uses TinyMCE can activate the keyboard input shortcuts via the configuration as a plugin for TinyMCE. Afterwards it has to be activated for the field (e.g. body). This is the path for the configuration in TinyMCE: /site/modules/QuickSave/tinymce/quicksavetinymce.js QuickSave-TinyMCE-inst.mp4 I have been using the module only as a save button version for some time in a long Processwire page with a strong content and a four-fold nested repeater matrix and it works. The keyboard shortcuts were added because of a request. I was only able to test these on the Mac and hope they also work with Windows browsers. Due to another request, the short notification after saving was added. I hope you like the module and that it helps the moderators to keep a better eye on the areas they are currently working on. Especially with long pages and, for example, a table with many rows, it is very helpful for me not to lose the row when saving. (see the video) Note: The module does not intervene in the Processwire saving process, only the original saving button function is triggered. Please note that the keyborad shortcodes do not work in iframes or CKEditor. UPDATE: New version 0.1.7 added on April 13, 2024. A new combined version without jQuery has been created. Thanks to @dotnetic and all others ?. It is now more optimized and further optimizations are planned. Module 0.1.7 Download: QuickSave.zip Feedback on whether the keyboard shortcuts ctrl+s work under MS Windows would be great... ? Thanks and Greetings Chris
    2 points
  3. I had to do this just the other week. We had an old CMSMS site that we'd moved to PW. We had a db table with the old user names and passwords in which we stuck on the new site, and then just created our own login page which first checked to see if we had the user in PW already. If the user isn't already in PW then check the password against the old table; If it matches then use that information to add a new user to PW. The users don't really notice that anything has changed. Here's the code I used for that - you'll have to adapt to your circumstances of course but it worked well for our move. if ($input->post('ml_name')) { // when processing form (POST request), check to see if token is present // (we have a CSRF field on our login form) if ($session->CSRF->hasValidToken()) { // form submission is valid // okay to process } else { // form submission is NOT valid throw new WireException('CSRF check failed!'); } $ml_name = $sanitizer->name($input->post('ml_name')); $ml_pass = $input->post('ml_pass'); // dont allow the guest username if ($ml_name === 'guest') { throw new WireException('Invalid username'); }; // do we have this user in PW already? $u_exists = $users->get("$ml_name"); if ($u_exists->id) { // user exists // lets try and log them in try { if ($session->login($ml_name, $ml_pass)) { $session->redirect('/'); } else { $ml_feedback = 'Unknown details.'; } } catch (WireException $e) { // show some error messages: // $e->getMessage(); } } else { // ok - well do we have this user in the old CMS table? $query = $this->database->prepare("SELECT * FROM `cms_module_feusers_users` WHERE username = :login_name LIMIT 1;"); try { $query->execute(['login_name' => $ml_name]); } catch (PDOException $e) { die ('Error querying table : ' . $e->getMessage()); } // we've got a user from the old table if($query && $row=$query->fetch()) { $ml_feedback='Is in old table'; $hash=$row['password']; // handily the old auth just uses password_verify if(password_verify($ml_pass, $hash)){ // Add this user to the PW users $new_user=$users->add($ml_name); if($new_user){ $new_user->pass=$ml_pass; $new_user->addRole('members'); $new_user->save(); $log->save("new_members_site", $ml_name . " added as user"); $u = $session->login($ml_name, $ml_pass); if($u) { $session->redirect('/'); } else { die("Error in logging in. Please contact admin."); } $ml_feedback='new user added to PW'; }else{ $ml_feedback='Unable to add new user. Please let admin know'; } }else{ $ml_feedback='No matching records found.'; } }else{ $ml_feedback='No record found.'; } } } and this is the login form that the we had on our new login page - this and the above was all in a single template. <form id="ml_login_form" class="ml_login_form" method="POST"> <?php echo $session->CSRF->renderInput(); ?> <label for="ml_name">Username</label> <input id="ml_name" name="ml_name" type="text" value="<?= $ml_name ?>" required> <label for="ml_pass">Password</label> <input id="ml_pass" name="ml_pass" type="password" value="<?= $ml_pass ?>" required> <div style="display: none;"> <label for="ml_pass_bear">Password</label> <input id="ml_pass_bear" name="ml_pass_bear" type="text" value=""> </div> <button type="submit" name="ml_submit" class="butt">Submit</button> <div class="ml_feedback"><?= $ml_feedback ?></div> </form>
    2 points
  4. Hi @DrQuincy I think you can do this by hooking in to PW's login flow. Here's how I'd attempt to do this - untested - just to give you some inspiration... Create a new field on the User template for their hashed password from your old system. Write a script to populate this field where there's an email match between the old system and the new one. If the new system doesn't have users in it yet, then great, you'll be creating user records for everyone from the old system. Make sure you create a long, random, password for the initial processwire password on any new users you create and leave existing user passwords untouched. Store the hash from your system in the new field on the matching user and save any changes. You need a before hook on the session::login method. Use the name param (in $event->argument(0)) to match on emails if that's how you did it in the old system, if you have exactly one match, and this user has a non-empty value for your old password hash, use your existing pwd checking algorithm to authenticate them from the pass ($event->arguments(1)) parameter. If that works, the plaintext password they submitted to you is the correct password. Now set the PW password on that account using the plaintext password you just verified is correct AND delete the old password hash value. Now the correct password has been stored in the User's PW pass field, just exit the hook and PW should process the login as normal, or call the forceLogin method to log them in and do your own redirect. Basically, as people log in, they will auto-convert their accounts over to PWs way of doing things. Once they convert, the login process just reverts to using PWs method. Potential gotcha: more than one account in the PW system with the same email (if there are already accounts in there.) After a reasonable period has elapsed, you could then deal with seemingly dormant accounts by emailing non-converted users and asking them to login (or otherwise handle them as appropriate.) Hope that helps.
    2 points
  5. --- Module Directory: https://modules.processwire.com/modules/privacy-wire/ Github: https://github.com/blaueQuelle/privacywire/ Packagist:https://packagist.org/packages/blauequelle/privacywire Module Class Name: PrivacyWire Changelog: https://github.com/blaueQuelle/privacywire/blob/master/Changelog.md --- This module is (yet another) way for implementing a cookie management solution. Of course there are several other possibilities: - https://processwire.com/talk/topic/22920-klaro-cookie-consent-manager/ - https://github.com/webmanufaktur/CookieManagementBanner - https://github.com/johannesdachsel/cookiemonster - https://www.oiljs.org/ - ... and so on ... In this module you can configure which kind of cookie categories you want to manage: You can also enable the support for respecting the Do-Not-Track (DNT) header to don't annoy users, who already decided for all their browsing experience. Currently there are four possible cookie groups: - Necessary (always enabled) - Functional - Statistics - Marketing - External Media All groups can be renamed, so feel free to use other cookie group names. I just haven't found a way to implement a "repeater like" field as configurable module field ... When you want to load specific scripts ( like Google Analytics, Google Maps, ...) only after the user's content to this specific category of cookies, just use the following script syntax: <script type="text/plain" data-type="text/javascript" data-category="statistics" data-src="/path/to/your/statistic/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing" data-src="/path/to/your/mareketing/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="external_media" data-src="/path/to/your/external-media/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing">console.log("Inline scripts are also working!");</script> The data-attributes (data-type and data-category) are required to get recognized by PrivacyWire. the data-attributes are giving hints, how the script shall be loaded, if the data-category is within the cookie consents of the user. These scripts are loaded asynchronously after the user made the decision. If you want to give the users the possibility to change their consent, you can use the following Textformatter: [[privacywire-choose-cookies]] It's planned to add also other Textformatters to opt-out of specific cookie groups or delete the whole consent cookie. You can also add a custom link to output the banner again with a link / button with following class: <a href="#" class="privacywire-show-options">Show Cookie Options</a> <button class="privacywire-show-options">Show Cookie Options</button> I would love to hear your feedback ? CHANGELOG You can find the always up-to-date changelog file here.
    1 point
  6. Just reporting this to save other people some debugging time: Hanna Codes unintentionally "memoize" results. Here's a rough example of what I mean. Imagine a stateful Hanna Code. For example, imagine a Hanna Code that maintains a count, and increases the count each time it's used: [[count]] [[count]] [[count]] You'd expect this: 1 2 3 But you'll get this instead: 1 1 1 Here's where it gets very odd though: your Hanna Code will in fact be called three times, and the counter will in fact end up at "3"! It took me a bit to figure out what was going on. The problem is that all Hanna Codes are extracted up front, here. Then they're processed one by one, here. As each Hanna Code is processed, it gets replaced here. And that's the problem: the replacement is global; all matches get replaced, not just the first. So in this example all three `[[count]]`s will be extracted, and the loop will iterate three times, but the first iteration will replace all occurrences of `[[count]]`, leaving nothing for the next two iterations to replace. (I'm calling this "unintentional memoization" because typically you memoize to avoid work. In this case work isn't avoided, the result of the work simply isn't used.)
    1 point
  7. Here is Laravel's implementation of `replaceFirst`; it uses `strpos` and `substr_replace`. I think the current behaviour is unintentional; I don't know if Ryan would consider it a bug? I suppose I should report it so that he can decide.
    1 point
  8. @Chris-PW Many thanks for contributing this module. That was really a much needed missing feature. I am using the module with Chrome (Iron) under Windows 11, where in TinyMCE fields, pressing CTRL-S saved the page twice. It seems, that Chrome/Windows reacts also to "meta-s". I then went to quicksavetinymce.js and commented out the block for "ctrl+s". Now, pressing CTRL-S within a TinyMCE field saves the page only once. Thanks again for this great module! P.S.: This also works with Firefox/Windows
    1 point
  9. Agreed, because I read alot of forums and realized that it could allude to a myriad of reasons, only reason I was able to sort this was looking at the source and getting help from @Christophe
    1 point
  10. Thx @Christophe that's some good questions ? I've updated the profile to hopefully answer all of them: https://github.com/baumrock/site-rockfrontend/commit/be55adae28ffe6a7aac83944284820f17afdaabf You don't need to use tailwind. If you don't want to use it just remove the _tailwind.css file. If you find anything happening that should not be let me know and I'll fix it.
    1 point
  11. Someone could create a topic in the forum, maybe in the tutorials section, eg "how to fix request appears to be forged". And we could then simply add a link to that topic to the error message.
    1 point
  12. It would be nice to have a documentation page that lists all possible causes and fixes for this general error message. The forum is littered with requests for help regarding this issue, but I think in development mode there could be a link to a ProcessWire documentation page that actually helps to resolve it. There isn't an infinite number of things that can go wrong, and I think it would be possible to list them all, or at least almost all.
    1 point
  13. Hi @HarryWilliam and welcome to the forum! E-Commerce is a huge topic and there are many ways how to do it - unfortunately or luckily ... Option 1: Payment Buttons or Links Very simple solutions are payment buttons that Platforms like Paypal offer. You can see an example here: https://www.boukal.at/work/catalogues/catalogue-do-you-also-have-pretty-motifs/ Another option would be payment links that payment providers like stripe or mollie offer: https://www.mollie.com/gb/products/payment-links Pro: Very easy to implement Con: You have to manage different buttons/links for different products on your own, place them in your markup (for example with a textformatter), keep them up do date and you have very limited possibilities for customisations (like different options etc). Option 2: SaaS Shop integration The next option would be to add one of the SaaS solutions to your PW site. One option would be to use Snipcart, which is very simple to add to your site, at least in theory: https://snipcart.com/blog/processwire-ecommerce-tutorial Pro: Easy setup, working shop out of the box, they maintain and develop the product continuously and long term (hopefully) Con: You usually pay for it per purchase and/or you have a monthly fee. Snipcart for example costs at least 20$ per month if your sales are < 1000$. That's 240$ each year. https://snipcart.com/pricing Con: You need to add products to your SaaS shop. That means you can either not manage products directly from within your ProcessWire backend or you need to develop a bridge that keeps products in sync. Con: Using a SaaS Shop means you are locked to the features that this shop provides. In PW we have this module, but I'm not sure whether it's still maintained or will see any updates in the near future. Option 3: A custom PW shop This is maybe the most advanced solution. The benefits are that you get a fully integrated solution. You can manage all your products, all your users, all your orders etc. directly from within your PW backend. You can add hooks wherever you want and you can customise everything to make it work 100% the way you or your client wants. Imagination and your skills are the limit. The con is that it will likely be a more complex setup, as you need to understand the basic workflows of E-Commerce and you need to setup everything the way you want. As far as I know we only have Padloper 2 by @kongondo at the moment. I don't know the price, though, because the shop is down at the moment. I'm developing RockCommerce at the moment and it will hopefully be released during this year. The basic version is already done and you can see it in action on my website baumrock.com where I use it to sell my commercial modules, for example RockForms. As you can see on my website it can already be used to sell single products. It comes with a checkout (live example) but it has no cart functionality at the moment. But it already has a nice Dashboard with filters and charts, at least ? Also, it can already create fully automated and 100% customisable invoices directly from within PW/PHP (using RockPdf) - which is something that not all shopping carts do for you, keep that in mind when evaluating those products! Thanks to the integration into the PW system it can send 100% custom emails to your customers, where you can make sure that you comply to your local legislation (for example in Austria we need to attach terms of service to that email): In this example it's a nice looking mail because I use RockMails, which is another module in the pipeline ? But as it is 100% ProcessWire you can simply send an email with some lines of code as well: $m = new WireMail(); $m->from('office@your-company.com'); $m->to('your@client.at'); $m->subject('Thank you for your oder!'); $m->body('Congrats, you are now a ProcessWire hero!'); $m->send(); So while it is not yet 100% it can already be already a great option! If you want to get notified about the release you can subscribe to my monthly developer newsletter: https://www.baumrock.com/en/rock-monthly/ I'm quite sure there are 100 more options, but I tried to give an overview ?
    1 point
  14. Same behaviour for me on Linux Firefox/Chromium. Need to activate the TinyMCE plugin. Used latest version 0.1.7. of your module
    1 point
  15. It now also works on Mac with Firefox. Some other changes are also included. The new optimized and vanilla-js QuickSave version 0.1.7 is available as a new download in the first post.
    1 point
  16. Great module. This really improves UX a lot, especially on larger page edit screens. I can confirm that Ctrl+s is working on Linux Firefox & Chromium (with improved JS version from @dotnetic).
    1 point
  17. Please find attached an improved version in vanilla javascript which is much smaller 2.4 kb instead of 6.75 kb and more efficient without using a scroll listener. Tested in Firefox and chromium based browsers on windows. Please report if it does not work somewhere else. I didn't change the TinyMCE plugin, so I don't now if it still works. QuickSave.zip
    1 point
  18. I haven't bothered with Github yet other than downloading a zip there. But as soon as I find time for it, I will gladly publish the module there.
    1 point
  19. Works fine on Windows in Chromium-based browsers and Firefox. I didn't even have to use the plugin for TinyMCE, it just works out of the box.
    1 point
  20. @Chris-PW Welcome to the plugin-author's club :) Would you be able to create a github account and create a repository for this? It's the next step to getting this published in the PW modules DB.
    1 point
  21. Published to GitHub and pending approval in the module directory.
    1 point
  22. Ok, sorry, clickbait ? Hooks are great! But sometimes, there are even better solutions: I'm cleaning up RockForms to finally release it ? I have some pages that are only for storing data (like form entries and such), so I don't want them to be editable, not even for superusers, as I control them solely via code in my module. -- Solution 1 -- With a regular hook that would look like this: <?php // site/ready.php $wire->addHookAfter("Page::editable", function($event) { $page = $event->object; if($page instanceof \RockForms\Root) $event->return = false; }); That's quite nice, but this approach has some drawbacks: First, sooner or later you might end up with hook-hell in ready.php; That's not ideal and really hard to debug on more complex projects. Second, as we are defining the hook with a callback in a non-OOP style these hooks get a LOT harder to debug! Have a look at tracy's debug panel: The second highlighted hook is the one coming from ready.php and it does not show any helpful information whereas the first one does show clearly that the hook is attached in RockForms\Root in the method "hookUneditEntries" (it should be hookUneditRoot, but I made a mistake when copy-pasting, sorry ? ). -- Solution 2 -- So the next best solution IMHO is using custom page classes! Then you get OOP style and a lot better structure for your project with really very little effort! Just create a file in /site/classes and that's it. Now to attach hooks directly in custom page classes you have to do one additional step. You can watch my video about this if you are interested. If not, head over to solution number 3 which is even simpler ? This solution might look something like this: <?php namespace RockForms; use ProcessWire\HookEvent; use ProcessWire\Page; use RockMigrations\MagicPage; use function ProcessWire\wire; class Root extends Page { use MagicPage; public function init() { wire()->addHookAfter("Page::editable", $this, "hookUneditRoot"); } protected function hookUneditRoot(HookEvent $event): void { $page = $event->object; if (!$page instanceof self) return; $event->return = false; } } This might look like a lot more code, but it's a lot better in the long run in my opinion as things that are related solely to the root page are inside the Root.php file of my module/project. -- Solution 3 -- But then I remembered: As our "Root"-page is a custom page class and PW checks if the page is editable or not by calling $page->editable() we can simply override this method like so: <?php namespace RockForms; use ProcessWire\Page; class Root extends Page { public function editable() { return false; } } You don't even need to make it a "MagicPage" because you don't need an init() method to attach any hooks. Now it's only very little additional code compared to a hook in ready.php but with a lot cleaner setup ? It's not a new invention, but I thought I'd share it nevertheless. Maybe it's helpful for some and maybe it's a good reminder for others, that even hooks are sometimes "overkill" ?
    1 point
  23. 1 point
  24. Thank you for this module. I like it. Is there a posibility to notice them who saves the cookie. To make a documentation of it. So far I know, the privacy policy says, you have to do that. Its very strange and nonsensical in my opinion. Perhaps it ist possible to make a entry in logs. This would be very great. Perhaps others know, what is realy necessary.
    1 point
  25. The error is saying everything. It's not supported, but there's a workaround posted by Ryan here: https://github.com/ryancramerdesign/ProcessWire/issues/1210
    1 point
×
×
  • Create New...