Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 04/17/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!
    18 points
  2. @Mustafa-Online I made nice update today on this module after not having touched it in several weeks. It's now basically complete but before I release it I still need to clean up some old code that's left over, make it work more nicely with SelectizeAll and provide similar overriding capabilities that the UIkit theme has. This module includes Bootstrap Icons and it substitutes Font Awesome icons accordingly (I went through each one and found the equivalents!). It also uses the Bootstrap navbar and dropdowns. A side-effect of this is ajax-loaded dropdown content won't work in the first release. I may backtrack on using Bootstrap dropdowns depending on if that becomes difficult. Anyway, it's looking good overall. If anyone is wondering why use this as opposed to UIkit, it may be beneficial if you are doing a lot of custom admin stuff and want to use pre-made Bootstrap styled components since the Bootstrap ecosystem is much much larger than UIkit. Also, it feels a little more fresh, although my actual reason for creating this was to for a way for me to get a deeper understanding of how admin themes work.
    6 points
  3. It's been talked about elsewhere here in the forums, but an alternate idea would be utilizing .env files. It would satisfy both the installation process and long-term management of values. Some benefits: Widely used across applications, frameworks, and languages running in a web server environment and strongly recommended as a standard practice Secure by default. Web servers do not serve .env files Provides the ability to manage local and production configurations separately Frameworks like Laravel provide a .env file as well as a .env.example file containing all variables used in the application. This is kept up to date, used to document application requirements, and is committed into the repository Values that are not security-critical can be safely stored in the example file Provides a convenient location for additional non-ProcessWire site/app specific values such as API keys, or those required for modules Solves the issue of excluding site/config.php from a repository given that it's a required file containing specific syntax and $config object property assignments If .env was available in ProcessWire I would have my Fluency module look for translation API keys there rather than store them in the database. A benefit there is that different environments like local/ staging/production can mean an environment that is yours and an environment that is a client's. Pulling the latest copy of a database from production wouldn't require manually re-configuring modules that require API keys, or module registration keys. It would be good to eliminate storing security-critical values in PHP files entirely. The .env file could be generated and populated during the ProcessWire install process pre-excluded in the .gitignore file. Example: ENVIRONMENT="development" # ProcessWire PW_DB_HOST=localhost PW_DB_NAME="your_database PW_DB_USER=your_database_user PW_DB_PASS="LowuHeju7[BoI3" PW_DB_PORT=3306 PW_DB_ENGINE=InnoDB PW_DEBUG=true PW_CHMOD_DIR=0755 PW_CHMOD_FILE=0644 PW_USE_PAGE_CLASSES=true PW_USE_FUNCTIONS_API=true PW_PREPEND_TEMPLATE_FILE="_init.php" PW_USER_AUTH_SALT=d5e3ac4beda1e382255bbd8744d7e815 PW_LOCALE="en_US.UTF-8" PW_TIMEZONE="America/Los_Angeles" PW_DEFAULT_ADMIN_THEME=AdminThemeUikit PW_INSTALLED=1580675413 PW_HTTP_HOSTS = "domain.com,www.domain.com" # Some API that is used EXTERNAL_SERVICE_API_URL="https://api.someservice.loc/v2" # Development EXTERNAL_SERVICE_API_KEY=0d41fe1b68244f4ea51ae5e4abd24fab # Mailgun MG_KEY=key-192cde47ab73095e747ebe7556577b2d MG_DOMAIN="mg.somedomain.com" # Forecast.io FORECAST_IO_KEY=c28096383d66bcb1e2cb9ec37153f85c To take the idea further, it could be integrated with the ProcessWire API in a way that would prevent conflicts, keep .env variable naming organized, and make any value added by the developer available. Something like: <?php // An accessor method, this is probably the cleanest and resembles other frameworks $config->env('SOME_ENV_VARIABLE'); // Nested under a property acting as a namespace $config->env->SOME_ENV_VARIABLE; // On ProcessWire projects I implement some extras to easily interact with .env values without needing to access them directly. $config->envIs('production'); // boolean I haven't built a ProcessWire site without implementing this for many years and there's a great widely-used great package that provides .env values to PHP. There are also hosting providers that make environment variables/secrets manageable through their admin UI that eliminates the need for an actual file in production entirely. If ProcessWire were to implement environment variables it could look to values that may already exist and fall back to using a file. Implementation aside, if someone is able to access phpinfo() in production it's a critical issue beyond exposing config values given the totality of information dumped by that function.
    6 points
  4. Thought this might be interesting for the UIkit/Tailwind users, maybe best of both worlds?? https://www.franken-ui.dev/docs/introduction
    4 points
  5. 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>
    4 points
  6. 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.
    4 points
  7. @Christophe Thanks to Christophe for suggestion the PHP Session save path, I set it to my writable folder and now it works, had to do in this in PHP Cpanel settings
    4 points
  8. 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 πŸ™‚
    4 points
  9. @bernhard: Thanks to your forum thread, I finally did the switch from my previously used XAMPP development stack to WSL2/DDEV on my Windows 11 machine. Now I do all my Python, PHP and Node/Html projects within the Linux subsystem on Windows 11 using VS Code as my editor of choice. Only Windows Desktop C# projects (WinForms, WPF) are still done on the Windows side using Visual Studio 2022. Always wanted SSL certificates on my localhost. Installation was easy and my first project was set up within minutes by simply cloning and importing my MySQL dump into my ddev container. Thanks for the inspiration.
    3 points
  10. 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
    3 points
  11. For handling datetime in Processwire, I've come to realize that the best way for me to avoid the most headache is leave EVERYTHING in UTC...the $config file, the ddev settings, etc. Then whenever I need to display times on the front end, I use a helper function I created that formats time in the Timezone of my choosing, at display time. With this method, the production server timezone or my dev environment timezone never matters. The added benefit is that you can have users save a timezone to their profile and then display times in their timezone. Any other way of dealing with timezone besides saving UTC to database has always created a mess for me later down the road. function UtcToCst($timestamp) { if(!$timestamp) return; return (new \DateTime("@" . $timestamp))->setTimezone(new \DateTimeZone("America/Chicago")); //Or use a timezone saved on your $user template. }
    3 points
  12. Checking all 3 of these will probably do what you want, but I actually never use the second two because I make use of the "Enable Guest Dumps" button from the panel selector. Enable that, do what you need to do as a guest in a private window and then reload the PW admin where you are logged in as a superuser and you'll get the dumps recorded by the guest. Another thing is to make sure you have the "Tracy Exceptions" panel enabled so that if a guest user interaction results in an exception, the bluescreen with full stack trace will be made available for easy viewing. I rely on this for all my sites with Tracy's production mode. Hope that helps.
    3 points
  13. Hi @poljpocket, sort (-iname ... ) does not work, because iname_* contain different criteria to sort the images. To have an impression of the site, here's the link: (The new sorting function is not yet implemented completely) http://www.malabu.de But ->reverse(); was the right way, it works! Thanks to you all GΓΌnter
    2 points
  14. You need to expand the parent select and navigate to the assigned parent. When you hover on that, you should see the "unselect" button.
    2 points
  15. If you truly want to make an admin theme from scratch like I'm doing, it's best to just take AdminThemeUikit, since that is the "official" and most supported theme and rip out UIkit and start replacing it with your own approach and just hack away at it. Keep in mind that ProcessWire makes heavy use of jQuery UI and a few other libraries so you'll have to play nicely with them unless you want to replace them too, but that takes it to another level. With Bootstrap, it's straight-forward enough given the similarities with UIkit, although this is turning out to be more work than I anticipated. But that was the point since I want it to force me into looking at how everything is interconnected. One idea for an admin theme is to do it with pure, modern CSS and as little JS as possible and as accessible as possible (good reason why here).
    2 points
  16. @Jonathan Lahijani It's great you still working on this, can't wait to try it. I wish one day you make a tutorial on how to create an admin theme from scratch, as all forum's related content is outdated.
    2 points
  17. This week we have some updates for the ProFields table field (FieldtypeTable). These updates are primarily focused on adding new tools for the editor to facilitate input and management of content in a table field. All the details can be found in the new blog post with an accompanying screencast videoβ€” https://processwire.com/blog/posts/table-field-with-actions-support/
    2 points
  18. 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.)
    2 points
  19. I don't know anything about the history of `strtr` in PHP, but my guess would be that the reason it has the ability to replace strings in the first place is simply an extension of its original purpose from single-byte characters to multi-byte. It just so happens that in PHP multi-byte characters are represented as strings… I don't know if that's right, but I've seen it in other languages, so it certainly seems plausible. And when you have that in your head using it to just replace arbitrary strings feels, you know, funny. πŸ™‚
    2 points
  20. 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.
    2 points
  21. Hello, on PW v3.0.229 when setting $config->pagefileSecure, files (PDF inmy case) are still offered for download, even if the pages for those files reside in the trash. Can anyone confirm that behaviour? IMO assets of trashed pages should not be publicly available and $config->pagefileSecure should take care of that like it does for unpublished pages. Many editors without superuser priviliges aren't even aware of pages in the trash, unless we allow them to see the trash. So they would think that a trashed page is gone for good. In my case I now made the trash visible to those editors. But I also needed to instruct them to unpublish pages before moving them to the trash or delete them from the trash in order to make the files not appear publicly anymore
    2 points
  22. 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
    2 points
  23. Depending on your requirements, the Stripe payment processor for FormBuilder might be worth investigating. You can set Paypal to be a payment option in Stripe so that users can pay using PayPal but you can keep all your transactions on the same plaform. Out of the box FormBuilder might not do everything you need (if you need a basket etc) but it is possible to hook into the module to update line items / prices etc. We recently built a basket system for a site that we'd wired directly into Stripe but then shifted over to hook into Formbuilder instead because it already did a lot of the heavy lifting in using the Stripe API.
    2 points
  24. I've only just spotted this but, in my ddev environment, if I modified a page the modified date was always recorded as one hour earlier. So appears on the settings tab immediately after doing a modification (at 14:55). The production environment was OK. I have $config->timezone = 'Europe/London'; throughout in config.php. It seems that you also need to set the timezone (in my case 'timezone: Europe/London') in the ddev config.yaml
    2 points
  25. 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.
    2 points
  26. 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.
    2 points
  27. Hey @Neue Rituale. Yes, Padloper is very much still being developed. Version 009 is due for a release this week (I have been dealing with a number of issues, including this one).
    2 points
  28. 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).
    2 points
  29. The Download page says that 229 is the current master version: Composer and GitHub say that 227 is the current master version: The difference between .227 and .229 is ~8-10 fixes of various kinds.
    1 point
  30. Hi @Christophe Unfortunately we don't have Code Intellisense or autocomplete in latte files at the moment 😞 See https://github.com/smuuf/vscode-latte-lang/issues/5 You are adding the method "listchildren()" to your ParentPagePage, nowhere else. That means you can all this method only on pages that have the template "parent-page". Why should it do that? You are calling a method of an object. If that does not exist it is expected to throw an error. You CAN do what you describe though. Sometimes it is useful and I'm doing that as well. You could add that method to your DefaultPage.php and there return an empty sting. That would make $page->listchildren() return "" by default, which means it does not throw an error. For some page types you can then implement a different logic: DefaultPage.php --> listchildren() { return ""; } FooPage.php extends DefaultPage --> listchildren() { return "foo!"; } BarPage.php extends DefaultPage --> listchildren() { return "BAR"; } // in any template echo $page->listchildren(); That it totally up to you. Same with regular ProcessWire templates. It's up to us devs how we organise things and everybody does it differently. I can only say what I came up with and what works great for all kings of projects (from very simple to very complex ones): layout.latte for main markup /site/templates/sections/... for all sections /site/templates/partials/... for all partials Details: layout.latte --> holds the html markup skeleton of the page, eg: <html> <head>...</head> <body> <header>...</header> <main>...</main> <footer>...</footer> </body> </html> Then all my template files are usually empty (like home.php, basic-page.php, foo.php, bar.php). Next, I divide my design into sections. A section is a portion of the page that goes from the very left to the very right and has an undefined height/content. You can then add those sections to your main markup file like this: <html> <head>...</head> <body> <header> {include "sections/topbar.latte"} {include "sections/navbar.latte"} </header> <main> {include "sections/breadcrumbs.latte"} {include "sections/content.latte"} {include "sections/content-footer.latte"} </main> <footer> {include "sections/footer.latte"} </footer> </body> </html> This is often all I need, because I build all the available sections in RockPageBuilder and then I can simply add them to the pages as I need them. But it works without RockPageBuilder as well. You then just need to code all your page layouts depending on the page template. If all those pages share the same breadcrumbs and content-footer it could look like this: <html> <head>...</head> <body> <header> {include "sections/topbar.latte"} {include "sections/navbar.latte"} </header> <main> {include "sections/breadcrumbs.latte"} {if $page->template == 'foo'} {include "sections/content-foo.latte"} {elseif $page->template == 'bar'} {include "sections/content-bar.latte"} {else} {include "sections/content.latte"} {/if} {include "sections/content-footer.latte"} </main> <footer> {include "sections/footer.latte"} </footer> </body> </html> You could also use a dynamic approach: <html> <head>...</head> <body> <header> {include "sections/topbar.latte"} {include "sections/navbar.latte"} </header> <main> {include "sections/breadcrumbs.latte"} {include "content/" . $page->template . ".latte"} {include "sections/content-footer.latte"} </main> <footer> {include "sections/footer.latte"} </footer> </body> </html> It's just regular PHP inside the latte tags, so you could also do is_file() checks etc: <html> <head>...</head> <body> <header> {include "sections/topbar.latte"} {include "sections/navbar.latte"} </header> <main> {include "sections/breadcrumbs.latte"} {var $file = "content/" . $page->template . ".latte"} {if is_file($file)}{include $file}{/if} {include "sections/content-footer.latte"} </main> <footer> {include "sections/footer.latte"} </footer> </body> </html> Obviously you'd need to create those files. Here I'm placing them into a new folder called "content", which would be /site/templates/content/foo.latte for example. Next, partials: If you have repeating markup inside your sections you can outsource them into the partials folder. For example let's say you want to show a blog overview page that shows all single blog items as cards. You'd have a section like "blog-overview.latte" like this: // blog-overview.latte <div uk-grid> <div n:foreach="$page->children() as $item"> <div class="uk-card"> <h3>{$item->title}</h3> <p>{$item->teaser()}</p> </div> </div> </div> This example is very simple and if you only use your cards here, then it's easier to leave them here. If you are using the exact same cards on two or three places then you can create partials for them: // blog-overview.latte <div uk-grid> {foreach $page->children() as $item} {include "partials/card.latte", item: $item} {/foreach} </div> // /site/templates/partials/card.latte <div> <div class="uk-card"> <h3>{$item->title}</h3> <p>{$item->teaser()}</p> </div> </div>
    1 point
  31. Sorry, I should explain a bit more! `strtr` can work in two modes, and in one mode it can replace substrings. But that isn't its purpose, and I think it would be confusing to use it for that. (It would be especially confusing if, like me, you happen to know about `tr`.) Even more, though: like `str_replace`, `strtr` replaces all matching strings, not just the first. So it can't actually solve the original problem anyway.
    1 point
  32. 1 point
  33. Problem solved. Ryan mentioned in the issue report that only files are protected that are uploaded after the $config->pagefileSecure setting is in place. I was not aware of that and I couldn't find that requirement documented anywhere when doing a search prior to posting this issue. Done a search again which pulled up this forum thread I suggest to add that information to the entry for `$config->pagefileSecure` at https://processwire.com/api/ref/config/
    1 point
  34. Loading a website after updating to PHP 8.x failed. The connection to the server was reset while the page was being loaded. NS_ERROR_NET_RESET PHP error was not catched, nothing displayed, nothing logged. After a long search, it turned out that the Gettext extension was responsible for the fatal error. Code example to reproduce: $locale = 'de_DE'; setlocale(LC_ALL, $locale); echo gettext("foo bar"); // NS_ERROR_NET_RESET After adding the environment variable LANG it worked as expected. $locale = 'de_DE'; setlocale(LC_ALL, $locale); putenv("LANG=$locale"); echo gettext("foo bar"); // foo bar Same behaviour with ngettext() and maybe other Gettext functions. Alternatively, the problem could also be solved with putenv("LC_ALL=$locale"); Possibly affected: ProcessWire\Languages::setLocale() I found little information about this behavior on the Internet.
    1 point
  35. Issue submitted: https://github.com/processwire/processwire-issues/issues/1911
    1 point
  36. There are several modules that might help. Most by Macrura here in the forums.
    1 point
  37. You can use https://processwire.com/modules/fieldtype-runtime-markup/ for that.
    1 point
  38. Maybe open an issue in the issue tracker if not yet done?
    1 point
  39. If anyone is using wire-cli, and you find you're getting a lot of PHP warnings about not being able to set session parameters after headers have been sent, this may help. You may need to add a custom session function to site/config.php to prevent ProcessWire attempting to setup session handling when it's bootstrapped by wire-cli from the command line. YMMV, but this seems to be working for me. NOTES: Adjust the path if your admin interface is not at /processwire/. If you need sessions on the public (non-admin) paths of your site, remove the "ADJUST THIS PATH..." line and change the final line to "return true;". /** * Custom Session Control * * - Keeps non-admin pages free of cookies/sessions * - Unless there is already a session cookie * - Prevents session start on CLI invocation (wire-cli etc.) * - Allows admin pages to use sessions */ $config->sessionAllow = function($session) { if ($session->hasCookie()) return true; $req_uri = $_SERVER['REQUEST_URI'] ?? false; if (false === $req_uri) return false; // CLI invocation? if (0 === strpos($req_uri, '/processwire/')) return true; // ADJUST THIS PATH IF NEEDED return false; };
    1 point
  40. @ryan @Pete Can we get this fixed? Or if you'd like, I can help maintain this site.
    1 point
  41. 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
  42. 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
  43. Published to GitHub and pending approval in the module directory.
    1 point
  44. 🚨 [[ UPDATE December 6, 2022 ]] 🚨 I prepared a small landing page to validate how many of you would be willing to take the course, so that we would have a rough estimate of how many people would be willing to take the course. πŸ”— Show me your interest here πŸ”— ------------------------------------------------------- Hello to the entire wonderful Processwire community! I am here to announce my willingness to create a video course for beginner/mid-level developers interested in learning more about the main aspects of our beloved CMS. I have been working with Processwire continuously for years now, so I feel confident that I can share what I have learned to other developers interested in becoming faster and more efficient in their day-to-day work. I have noticed that lately many people here in the forum have complained about a lack of material and tutorials for taking the first steps, and although so many resources are already present within the board, I understand how complicated it can be to be able to connect the dots and have a clear reference on how to get started or how to find clear answers in a short time. As you know Processwire is a very broad tool, very flexible and able to be adapted to any need, so it will not be possible to dissect every aspect in this course, especially the more advanced ones that can help in rarer cases (at least in my personal experience). πŸŽ‰ But don't worry, I plan to explain with many practical examples many tips and tricks that can help you in developing sites, even particularly structured ones! πŸŽ‰ So I am here to test your interest and ask you what aspects you would be most interested in me covering, even those related to design (css, scss, postcss, tailwind) or javascript libraries/frameworks integrations (vue, alpine.js, greensock for animations,etc.). My idea would be to create together a magazine with a restricted area for users, newsletter integration, catalog filtering according to different parameters (year, author, topics, etc.) and much more.πŸ’£ It will be a paid course, I have not yet decided what the price will be, but it will be affordable for everyone πŸ‘. For a small period of time, I would be pleased if you would give me pointers and ideas, so I can see what your real interest is (if any!) and also motivate me πŸ™‚ Let me know! Thanks! πŸ™
    1 point
  45. Source: https://processwire.com/blog/posts/processwire-3.0.107-core-updates/#trash-for-all
    1 point
  46. SOLVED: So I added in the whitelisting just after the $input get. if($input->get->channel){ $channel = $input->get->text('channel'); $input->whitelist('channel', $channel);// This is what I was missing. $chanArray = explode("_", $channel); $chan = $channel = str_replace('_', '|', $channel); $selector = $selector .= ",ab_channels=$chan"; } I had the whitelist but needed to add it after the $input->get. I also added $input->get->text('') to help sanitize according to the docs.
    1 point
  47. 1 point
  48. 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
  49. @MarkE - just be aware that hook doesn't prevent a user getting access to the pages via Pages > Find and also via the Live Search in the menu bar. There are some hooks in the Admin Restrict Branch module that will help you with that though.
    1 point
  50. 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...