Leaderboard
Popular Content
Showing content with the highest reputation on 07/27/2020 in all areas
-
We relaunched the website of German health insurance broker KLforExpats, who provide a service that is specifically tailored for expatriates in Germany. The website includes very extensive, completely custom-built forms for data entry and multiple custom interfaces for management and handling of requests. Concept, design, branding and development by schwarzdesign. If you are moving to Germany and need health insurance, KLforExpats is the contact for you! Read on below for some technical insights. Features A beautful, streamlined website including an extensive knowledge area (Expert Corner) Custom-built forms for initial contact and data collection A central database of clients / leads An analytics dashboard that displays key performance indicators based on the lead database A client / lead template with multiple workflow-related actions Automatic generation of Trello cards for new leads using the Trello API Notable modules Dashboard TrelloWire ProFields Hanna Code ListerPro Cacheable Placeholders Cache Control Automatically link page titles Unique Image Variations Regular shoutout to Tracy Debugger Building custom forms based on ProcessWire fields The forms on the site are built from scratch, which is a lot of work but opens up a lot of fine-tuning that isn't possible with form builder modules or services. There are a couple of interesting features of the form system we built. In particular, using built-in HTML5 features for form input and constraint validation makes developing simple, cross-browser and mobile-friendly forms a breeze. The forms make heavy use of modern input types and attributes. In particular, all date fields use the date input type, which is supported in all major browsers except Safari. This way, the forms come with good accessibility out of the box. A cleaner solution than using some rickety jQuery UI datepicker. Client-side validation is pure HTML5 as well. Since each form consists of multiple steps, the validation is triggered when the user tries to go to the next step. This is easily done by iterating through the inputs in the current step and calling reportValidity on them. The browser takes care of reporting errors – no need for a popup library. We use ProcessWire's field settings to generate field labels and validation attributes (like the required flag, minimum and maximum length settings etc.). This way, changes to the fields are always kept in sync between the frontend and the backend. For server-side validation, we used an open source library (rakit/validation). We added some custom rules to integrate it with ProcessWire's CSRF protection, a honeypot spam protection, and file uploads using WireUpload. This way, validation and error reporting can be done through a uniform interface. Using custom page classes as data models New leads are represented by ProcessWire pages. We ended up writing a lot of custom functionality for those pages – for example, automatically generating a vCard based on the contact information entered in the form. We used a custom page class as a nice way to group those methods and be able to call them from anywhere. <?php namespace schwarzdesign\Page; use Processwire\Page; class ClientPage extends Page { /*** methods here */ } Since each lead is a regular page, we used the regular page template to display all the data collected for this lead as well as to provide an interface to perform lead-related actions, like create form access keys, generate PDF protocols, etc. Since we use Twig as a templating layer, we ended up with a MVC-like approach, where the PHP-template is only used to call the appropriate methods of the ClientPage based on URL parameters. You can read more on the process and the client-facing functionality on the KLforExpats project showcase on our website (in German).8 points
-
No. It could. Not worth the hassle. Instead, I'd suggest you try one of the 'restore' DB modules or at 'worst', do a manual save state of DB and restore it after each of your import script tests. Some candidates to do this: ProcessDatabaseBackups - https://modules.processwire.com/modules/process-database-backups/ (quick, in out, all or nothing) RockMigrations - https://modules.processwire.com/modules/rock-migrations/ (if you want fine-grained control BUT I am not sure how it deals with pages )3 points
-
Repeaters are pages placed under the admin which users of role "guest" cannot access due to the way access control works. It's a bit confusing because you don't think of repeater elements as pages per se, but since they actually are that, the same rules as for the rest of the pages apply, they are kind of "admin pages" Hope I made myself clear!2 points
-
I played around with multi-instances and found out that we currently (PW 3.0.163) are not able to use multiple instances when more then one site has set $config->useFunctionsAPI (in site/config.php) to true! Then I saw that, (when $config->useFunctionsAPI was set to false) in all instances $config->version returned the same version, that from the master instance. So, first I was a bit confused, but then I thought that this may have to do with the early step when PW processes/build the $config. And indeed, if I set in all site/config.php files the $config->useFunctionsAPI to false, and then in all site/init.php files to true, everything is working fine. Now we can use our sites with the functions API, and we can load as many multiple instances in parallel we want. ? TL;DR site/init.php /** * FOR BETTER SUPPORT OF MULTIINSTANCES, WE ENABLE $config->useFunctionsAPI HERE, * INSTEAD OF THE site/config.php FILE: */ $wire->config->useFunctionsAPI = true; Bootstrapping three different instances, in first step each of them in a single environment: <?php namespace ProcessWire; if(!defined('PW_MASTER_PATH')) define('PW_MASTER_PATH', 'E:/laragon/www/hwm/'); if(!defined('PW_MASTER_HTTPURL')) define('PW_MASTER_HTTPURL', 'https://hwm.local/'); // bootstrap ProcessWire instance site1 (3.0.163) require_once(PW_MASTER_PATH . 'index.php'); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); When running all three in a multi instance environment, they load fine, (no compile error), all with the use for the functions API enabled: <?php namespace ProcessWire; if(!defined('PW_MASTER_PATH')) define('PW_MASTER_PATH', 'E:/laragon/www/hwm/'); if(!defined('PW_MASTER_HTTPURL')) define('PW_MASTER_HTTPURL', 'https://hwm.local/'); if(!defined('PW_SITE2_PATH')) define('PW_SITE2_PATH', 'E:/laragon/www/hwm2/'); if(!defined('PW_SITE2_HTTPURL')) define('PW_SITE2_HTTPURL', 'https://hwm2.local/'); if(!defined('PW_SITE3_PATH')) define('PW_SITE3_PATH', 'E:/laragon/www/hwm3/'); if(!defined('PW_SITE3_HTTPURL')) define('PW_SITE3_HTTPURL', 'https://hwm3.local/'); // bootstrap ProcessWire master instance (3.0.163) require_once(PW_MASTER_PATH . 'index.php'); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); // create a secondary instance from master (3.0.163) $wire = new \ProcessWire\ProcessWire(PW_MASTER_PATH); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); // create instance of a second site (3.0.162) $site2 = new ProcessWire(PW_SITE2_PATH, PW_SITE2_HTTPURL); mvd([ 'httpurl' => $site2->wire('pages')->get(1)->httpURL, 'instanceNum' => $site2->getInstanceNum(), 'config->version' => $site2->wire('config')->version, 'useFunctionsAPI' => $site2->wire('config')->useFunctionsAPI ]); // create instance of a third site (3.0.152) $site3 = new ProcessWire(PW_SITE3_PATH, PW_SITE3_HTTPURL); mvd([ 'httpurl' => $site3->wire('pages')->get(1)->httpURL, 'instanceNum' => $site3->getInstanceNum(), 'config->version' => $site3->wire('config')->version, 'useFunctionsAPI' => $site3->wire('config')->useFunctionsAPI ]);2 points
-
1 point
-
ProcessWire 3.0.163 adds a few new $pages hooks (see PW Weekly #323 for details), adds configurable module upload/install options (ProcessModule), and contains many other minor updates, code refactoring and optimizations. But by far, the majority of updates and commits are related to resolving more than a dozen recent issue reports. That will be the focus next week too, as the goal is to have the next master version out by the end of the month, or the first week of August. Priority focus is on any issues that might be bugs introduced between 3.0.148 (previous master) and 3.0.163, as we want to make sure at minimum we aren’t adding any new bugs from one master version to another. Regarding the new configurable module upload options, the intention here is to add additional safety by having the option of locking down the ability to install modules from the admin. As convenient as it is to be able to install and upgrade modules (during development) directly by URL, file upload or directory; the reality is that—depending on the case—it’s also not the safest thing to have on a client’s production site once development is finished. I think it’s best if module installation and upgrades are left to web developers, who are better equipped to resolve any technical issues that might arise during the process. Though it also depends on the installation, which is why I thought it should be configurable. So now you can specify which install options are available, and they can also depend on whether the site is in debug mode or not: $config->moduleInstall = [ // allow install from ProcessWire modules directory? 'directory' => true, // allow install by module file upload? 'upload' => 'debug', // allow install by download from URL? 'download' => 'debug', ]; Above are the current defaults, which can be changed by specifying your own preferred options in /site/config.php. Boolean true means always allowed, boolean false means never allowed, and string “debug” means: allowed if the site is in debug mode. (I’m currently debating on whether the ‘directory’ option should also be ‘debug’ as well.) In addition to these configuration options, the ProcessModule “New” tab now also provides instructions for manual installation of modules. None of us need it I know, but someone new to ProcessWire might see the prior “New” tab and not realize there’s a really simple and safe way to install modules from the file system. So the instructions just seemed to make sense there for consistency. ProCache 4.0 β released Last week I mentioned a new version of ProCache would be coming out this week and version 4.0 of ProCache was released on Wednesday in beta form. It’s available for download now in the ProCache board download thread. This is one of the biggest upgrades for ProCache yet. If you are upgrading from a previous version, read the upgrade instructions in the README.txt file included with it, as it will guide you through some of the new features, and may save you from having to make an update to your .htaccess file. I mentioned much of this in last week's post, but here’s a summary of what’s new in this version of ProCache relative to the previous version: Major refactor of entire module. Now native to ProcessWire 3.x (ProcessWire 3.0.148+ recommended). New .htaccess rules for static cache. New ability to select .htaccess version (v1 or v2, Tweaks tab). New option to specify how trailing slashes are handled (Tweaks tab). Upgrade SCSS compiler from version 0.7.8 to 1.1.1. Add Wikimedia LESS as additional option to Leafo LESS (select which you want on Tweaks tab). Improved per-template lifespan settings. Improved default and per-template behavior settings. New cache clear behavior: Family (parent, siblings, children). New cache clear behavior: References (page that reference saved page). New cache clear override: No-self (skip clearing page that was saved). Per-template behaviors now supports clearing specific pages by ID or selector. Numerous minor fixes and optimizations throughout. Removed direct .htaccess writing ability, replaced with live example file. Lots of new hookable methods for special cases. New “Tests” tab with the following built-in tests: cache function and performance; cache clear behaviors tests; test http response headers; test for GZIP, LZW, zlib/deflate or Brotli compression; Test for keep-alive connection. Thanks for reading and have a great weekend!1 point
-
1 point
-
1 point
-
@adrian is there a way to let the CSV export to show absolute path to any files/images? I noticed that the exported data only shows the filename itself without any context. Thx Rudy1 point
-
Hi @sodesign , interesting, did your issue is fixed ? if yes, how ? thanks; And to answer the two questions : Yes, but it should only do that if you tell NGINX to do it. About the issue, and based on your post, it look like a cache issue where cookies has been cached. The official statement say that by default, NGINX respects the Cache-Control headers from origin servers. It does not cache responses with Cache-Control set to Private, No-Cache, or No-Store or with Set-Cookie in the response header. This is the current behavior; I will add that before the version 0.8.44, the header was stripped then the request cached. All that to say that theses parameters can be overridden, and you should show us your NGINX config file before we go further.1 point
-
@Zeka I don't think we've got hooks specific to what you are trying to do there, but I've pasted in the list of current hooks that ProCache provides for the static caching side of things. Can you expand on your need with an example? It may be something I can add, though want to make sure I fully understand what you are trying to do. // Is caching allowed for given page? Return true or false // Hooks can modify return value to dictate custom caching rules ProCache::allowCacheForPage(Page $page) // Called when entire cache is being cleared // Returns quantity of items cleared ProCache::clearAll() // Called right before a cache file is written // Hooks can modify $content to adjust what is saved in cache file ProCacheStatic::writeCacheFileReady(Page $page, $content, $file) // Called right before a Page is about to have its cache cleared. // Hooks can make it return false to bypass clearing of page. ProCacheStatic::clearPageReady(Page $page) // Called to execute cache clearing behaviors for given Page // Hooks can modify what behaviors are executed ($behaviors argument) // Returns array indexed by behavior name each with a count of files cleared ProCacheStaticBehaviors::executeCacheClearBehaviors(Page $page, array $behaviors)1 point
-
A demo would be a bit tricky as it would require a valid Snipcart account. No final live project on my side so far ... I'm sure there are some developers here which already have a Snipcart shop to show. ?1 point
-
I would've never expected it to work like that. Good to know.1 point
-
1 point
-
Just happend on PW 3.0.163. Fixed by rebuildAll method available since 3.0.156 $pages->parents()->rebuildAll();1 point
-
In CSV linebreaks are used to separate individual rows, so a linebreak inside a cell may cause problems. Depending on your CSV parser it could result in an error altogether, it may silently discard the newline, or it may handle it fine. As far as I know fgetcsv can handle newlines as long as the cell is quoted properly. Can you post an example of your CSV? Make sure the fields are properly quoted. Regarding the paragraph tags, that problem is the result of bypassing the interface and importing directly to the database. The textarea field doesn't care if it contains HTML or regular text with linebreaks. The HTML structure is created by the CK Editor during editing, so if you don't want to edit all imported pages manually, you will have to convert your body fields programmatically. This involves just using str_replace or a regular expression to replace newlines with paragraph tags. You can do that before the import (by modifying your CSV), during the import (apparently you can hook ImportPagesCSV::importPageValue) or after the import (by using $pages->find to find all imported pages, iterate through them and change the body field). Here's a quick and dirty code sample: $text = $page->body; $textHTML = '<p>' . preg_replace("/[\n\r]+/", "</p><p>", $text) . '<p>'; $page->body = $textHTML; $page->save('body'); You can get very sophisticated with that, like converting single line breaks into <br> tags instead and multiple linebreaks into <p> tags, but it depends on your requirements and source data.1 point
-
Heya folks! Just wanted to say that I finally got a chance to properly test this module, and... wow. Amazing work! It looks like you had a bunch of additional stuff planned, but the features that already are there are very useful, and apart from a few minor glitches the module seemed to work like a charm. While the built-in template editing tools we have in the core are not at all bad, at least for me the workflow with Designme is still a huge improvement ? At this point I'm mostly curious about what else you might've had in store when you said that the module was "far from being good enough for release". @elabx, care to provide some insight on this? I mean... it feels to me like you could've removed some of the "less "critical" features (widgets, perhaps even the code editor, etc.) and just released the module as-is. I might be missing something important, of course, but that's my impression anyway. Either way I'm blown away by just how awesome this module is! ?1 point
-
Ran into this problem today, thanks for asking this question 3,5 years ago @heldercervantes. Would have been hard to debug if you hadn't.1 point
-
Hi guys, I was very excited for this module, but my life took a huge direction change and I no longer have the time to invest in module development. I am gonna leave the files here. You guys can take it and run. Maybe there might be something useful here. Maybe not. I still think it's a good idea to do drag and drop modal building in PW. So hopefully one day something like that can come to light. I love this community and I love ProcessWire. Live long and prosper. - Joshua Designme 2.zip1 point
-
I understand why you are asking for this feature. You're not the first one. But it's not as obvious as it seems. The 'title' field is not the same as all other built-in fields. You can't modify the behavior of the built-in fields per template basis. Which means they all behave the same no matter what template the page has. That's why we have a generic type 'Page' that has all the built-in fields. No matter what template the page we can confidently serve those fields for every page. The 'title' field's behavior could change depending on the template. I understand that it is almost never the case, but semantically it is. For example, you can set different access settings for 'title' field depending on the template. You make it that user can view the 'title' on one template and not on the other. You can change the description of the field for each template and it will appear in the GraphQL documentation. You can also make 'title' field 'not required' for one template and 'required' for others. So, including 'title' field into the Page type will break the semantics. I understand that 'title' field is almost always treated as a built-in field but I just can't overcome this feeling that it is the 'wrong' way to do it. I would like do it only the 'right' way. And the right way brings us to your second question. If we implement it properly and add the ability to get the values of the template fields for generic Page types, then 'title' field should also be solved. For this we will be adding interfaces. It will allow you to get template fields for Page types by providing a template. It will look something like this. { city{ list{ children{ # <== let's say children are the pages with template skyscraper and architect list{ id name ... on SkyscraperPage { # <== you basically say: "for skyscraper pages give me these fields" title images{ url width height } } ... on ArchitectPage { # <== "and for architect pages give me these fields" born email resume{ url filesize } } } } } } } this way you can fetch values for all template fields on Page types. This will work with everything that returns a Page type. Including 'child', 'children', 'parent', 'parents' and Page Reference fields too. And the best part is, it will be semantically correct! ?1 point