Leaderboard
Popular Content
Showing content with the highest reputation on 08/21/2021 in all areas
-
This week the dev branch contains about a dozen issue fixes relative to this time last week. (commit log) While these are all relatively minor things, some have been around awhile and it's always nice to get them figured out. Plus it's often a good opportunity to iterate and improve upon related things in the process. While I think we're very close to being ready to merge to the master branch, I'm going to give it a few more days just in case. I want to make sure no new issues arise (no matter how small) as a result of all the commits we've been doing over the last few weeks with GitHub issue resolutions. Most likely there won't be many more commits on the dev branch before the merge, and perhaps by this time next week, we'll have version 3.0.184 as our next master version. Following that, I'll write up a post that documents everything new relative to the previous master version 3.0.165, as there has been quite a lot! But if you want to upgrade now, I do think there's very little risk in upgrading existing master/main installs to the current dev branch, as it is quite stable at this point, in my experience. Thank you for all of your help in testing and/or reporting issues. Have a great weekend!5 points
-
Hello @ all I want to share a new module with you, which makes the creation and validation of forms easy. Take a look at the following example of a simple contact form: // A very simple example of a contactform for demonstration purposes $form = new Form('contactform'); $gender = new Select('gender'); $gender->setLabel('Gender'); $gender->addOption('Mister', '0'); $gender->addOption('Miss', '1'); $form->add($gender); $surname = new InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $form->add($surname); $name = new InputText('name'); $name->setLabel('Name'); $name->setRule('required'); $form->add($name); $email = new InputText('email'); $email->setLabel('E-Mail'); $email->setRule('required'); $form->add($email); $subject = new InputText('subject'); $subject->setLabel('Subject'); $subject->setRule('required'); $form->add($subject); $message = new Textarea('message'); $message->setLabel('Message'); $message->setRule('required'); $form->add($message); $privacy = new InputCheckbox('privacy'); $privacy->setLabel('I accept the privacy policy'); $privacy->setRule('required')->setCustomMessage('You have to accept our privacy policy'); $form->add($privacy); $button = new Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if($form->isValid()){ print_r($form->getValues()); // do what you want } // render the form echo $form->render(); This piece of code creates a simple contact form and validates it according to the validation rules set. Inside the isValid() method you can run your code (fe sending an email) Highlights: 30+ validation types Support for UiKit 3 and Bootstrap 5 CSS framework SPAM protection Highly customizable Hookable methods for further customization Multi-language You can download and find really extensive information on how to use at https://github.com/juergenweb/FrontendForms. Please report errors or suggestions directly in GitHub. Best regards and happy testing ? If you have downloaded the module in the past I recommend you to uninstall the module completely and install the newest version 2.1.14. There are a lot of changes in the new version, so please test carefully.4 points
-
Very well done. Can't wait to give it a try.2 points
-
Yes 100%. I built and run a client-specific CRM/membership system for an arts organisation using Processwire. It started out relatively simple and has grown, but allowed us to build exactly what was needed and cut-out the over-complication of the many off the shelf systems they had already tried. Without PW's baked-in features development of this system would have taken an immeasurable amount of time longer.2 points
-
@netcarver There wasn't no. I did check this. It's now resolved. I dug around for a bit, and then considered whether the person I'd handed the site off to had unpackaged everything properly. After re-uploading the package and connecting it all up on their server for them it's working. Something must have been missed, or perhaps they used FTP to upload and a file got skipped. Thank you for your response though ?1 point
-
@howdytom You can not revoke a single key I am afraid. The reason is in ProcessWire (at least when I coded this, might of changed since then) TFA modules was a setup then your locked from configuration changes. So under the user settings once you enable the TFA it will only let you remove it instead of edit it. Thats out of my control but might of changed since I made this. Will look into it as I know its not great design how it is. As for gaining access if something goes wrong I am pretty sure the best way to regain access would be through the database. As even if you remove the module ProcessWire will still see the user as having TFA enabled. I have not tested this myself I did some googling and found nothing about regaining access after TFA goes wrong bit strange to have no way to recover yourself. When I get time I will look at adding some sort of confirmation messages that show more clearly that a new key has been added. As for a summary/description that should be doable but behind the scenes all the data for all the keys is being saved in one huge text field which is already imposing a limit of keys to about 10 if I recall correctly? (janky I know but at the time the was zero documentation on making custom TFA modules I was the first developer besides Ryan to make a TFA module)1 point
-
Also check the source server doesn't hasn't blocked image hotlinking or downloading of images without a referrer. I had an issue with an import script once along these lines.1 point
-
Try using urlencode() on the image URL to deal with spaces and other potentially problematic characters.1 point
-
Adam, Thank you for this fantastic module. It works great with PW 3.0.165 and Yubiykeys. Some additional thoughts: I added three Yubikeys. In case of loss, how can I revoke one specific Yubikey? It looks like I have to turn off U2F and deactivate all keys. Then re-add all YubiKeys again, right? How can I recover access due to PHP incompatibility or PW version issues? Can I remove TfaU2F from the site/modules directory? Feature Request: You should add some highlighting when a new security key has been added. The confirmation changes so quickly and could be easily missed. A summary with all active keys and description field would be great. Excellent work!1 point
-
I did try it with the updated class names. Sorry for not mentioning that. But that did not help ?1 point
-
Hey @MoritzLost, short question: Following scenario: I'm using FormBuilder with the option "Submit to another URL (bypassing Form Builder processing)" (with "Form Submit Method" POST) to process the input of the form on a dedicated page with a separate template. Is it possible to validate the hCaptcha field on this dedicated page to process only if hCaptcha field is valid. I'm trying to avoid a scenario where visitors (or rather bots) visit the "processing" URL and causing high traffic. Any thoughts are welcome... Many greets Jens alias DV-JF1 point
-
Any difference in PHP versions between these two setups?1 point
-
I've changed that so it only checks for minimum MySQL Version. Still, the module is very much alpha code and work-in-progress. I haven't gotten around to apply and test the field type configuration options, and there are quite a few rough spots in the existing code. FYI, I decided to rename my helper classes as I realized that JsonData and JsonValue may make nice names for core classes. To avoid clashing and hogging names I've prepended "JN", so it's JNJsonData and JNJsonValue now. The new release is still in testing stage and can be found here.1 point
-
I developed the new Geffen Playhouse website over the course of 2018/2019 and launched it in September 2019. It has been perhaps the largest project I have been involved in. The Geffen Playhouse went through an entire re-branding done by Base (including a custom font), and I worked with Teak on the new website. Website https://www.geffenplayhouse.org/ Wikipedia https://en.wikipedia.org/wiki/Geffen_Playhouse Base write-up https://www.basedesign.com/work/geffen-playhouse-always-geffen-playhouse-always-new Teak SF write-up https://teaksf.com/work/geffen-playhouse-ticketing-ecommerce-website-design/ Another write-up: https://www.laurentakayama.com/geffen Their previous website was severely antiquated and it wasn't a responsive website (as of 2019!). Instead, it forwarded mobile users to a "mobile-friendly" website on a different subdomain, which I think was hosted by a third party service. However the data containing all the actors, shows, seasons, news and press articles were all in there. So one major aspect of this website was de-duping and importing their data into ProcessWire, along with some post-import cleaning… that's ~25 years of data. The site is built with UIkit 3 for the most part, and also uses FullCalendar for the large and small calendars. There is a custom integration with AudienceView, their ticketing system, which is used to import all the performance showtimes of their shows into ProcessWire. It's not the easiest API to work with (XML), but I eventually got it working. Repeater Matrix is being heavily used for section-based page building. Building out all the necessary matrix types took a long time as there was quite a bit of thinking what types and layouts we needed as we went along. However the end result has given the editors a lot of flexibility. ProCache is being used as well, including a CDN for all assets. This is crucial because when opening season sales are announced, the site gets slammed, but with caching turned on, it's not a problem anymore. On a deeper level, the site uses my new (well 2 years old now), universal and very opinionated base module that provides a menu builder, a standard set of fields/templates/pages, and a bunch of other tweaks that I tend to use on every site. All the fields, templates and pages are set up in a streamlined and editor friendly way. I wasn't able to access their previous CMS backend for various reasons (I only got the MySQL dump), so when developing the site and data model in ProcessWire, I was able to completely re-envision the editor experience and the data model without bias. A quote from one of the marketing directors at Geffen Playhouse: "We absolutely love ProcessWire." More details on my personal website: https://jonathanlahijani.com/projects/geffen-playhouse/1 point
-
Sure... If you haven't read deeply into htmx, the main premise is that the server is the single source of truth regarding both data and markup, i.e. whole application state. If we need to update either data or markup, the server handles that. We just need to tell it what action to take. Validation has to pass, of course, before the server will oblige ?. Below is a quick example that demonstrates updating the markup using htmx based on user actions. Only 'remove' locations is demonstrated in this example. I wasn't sure whether your app shows the user both their removed and added locations and whether they can reset the session to have all locations reloaded afresh. It doesn't matter much as it wouldn't change much of the logic in the example. Secondly, note that this example makes use of alpine.js and tailwind css just for the pizzaz. These are not required by htmx. To let ProcessWire recognise htmx requests, please refer to this thread. Depending on the approach you take from there, you might not even need a JavaScript file! In the example below, we do have a JavaScript file just because we want to use alpine.js (for notifications) and we need htmx to talk to alpine.js. We also need the JavaScript file to tell htmx to add XMLHttpRequest to its request headers so that ProcessWire's $config->ajax will understand the request. First, let's see a demo then we'll see how easy our work is using htmx. Just for this demo, I have included htmx (and alpine.js and tailwind css via their respective CDNs [in production, you want to purge your tailwind css ?]) in my _main.php. Inside the template I am using for this demo, I have the following code. Here, I have removed the tailwind classes used in the demo so we can focus on htmx. Note that you don't need a dedicated template file for this to work. It will work with any template. As long as htmx is loaded in the page view and your template (in this case, the current page's template) is listening to ajax requests. In the template file, the main htmx magic happens here: <?php namespace ProcessWire; $out = "<a hx-post='./' hx-target='#locations' hx-vals='{\"location_add_id\": \"{$page->id}\"}' hx-include='._post_token' hx-indicator='#locations_spinner_indicator'>Add</a>" . "<a hx-post='./' hx-target='#locations' hx-vals='{\"location_remove_id\": \"{$page->id}\"}' hx-include='._post_token' hx-indicator='#locations_spinner_indicator'>Remove</a>"; echo $out; Let's go through the htmx attributes: hx-post This tells htmx where to send its ajax request. In this case, we are sending it to the same page we are viewing (./) and are using POST. We could have used hx-get if we wanted to (GET). hx-target This tells htmx which markup to replace/swap. The default is to replace the markup of the element from which htmx was called. However, hx-target can be used to specify the element to replace. In this example, we are replacing the whole listing so we target its wrapper element which has the id locations. hx-vals This is optional but we need it in our example. We want to tell the server which location (ID) has been added/removed. If we had a form element, we could have used it for this instead. Since we don't have one, we are telling htmx to process the (JSON) value of hx-vals and send that together with its request. Note: the escape slashes are so we can have raw, valid JSON in the attribute as required by htmx. hx-include This is also optional but important in our case. It tells htmx to include input elements found via the selector in this attribute in its ajax request. In our example, we are telling htmx to include the CSRF token we set on the server together with its request. hx-indicator Also optional. Tells htmx to show/hide this element to show the user that something happened. In this case we use a spinner. We could have used a progress indicator as well, .e.g., if we were uploading a file. That's it really! No event listeners, no handlers! We can add (and I did add one), event listeners on htmx events in order to do something after the event. In this example, htmx fires a custom event which alpine.js is listening to in order to show notifications after the DOM has settled. The notification type (success, error, etc) and the message are all coming back from the server but not as JSON. The markup to update the page is also coming back from the server. htmx receives it and plugs it into the DOM per the hx-target (also see hx-swap) attribute value. In this example, we are updating the whole listing. If we wanted, we could update just the location that was removed, e.g. add it back but with some removed 'indicator', e.g. greyed-out. In this example we use anchor tags as htmx triggers. For htmx, it doesn't matter; button, div, p, li, whatever valid HTML element would work. You already have a backend logic that's working for you but I show an excerpt of mine here, for completeness. Inside my-template-file.php (the template file for the template for the current page, in this example), I have the following code: <?php namespace ProcessWire; if ($config->ajax) { // check CSRF if (!$session->CSRF->hasValidToken()) { // form submission is NOT valid throw new WireException('CSRF check failed!'); } // ................ more code // e.g. check removed locations in the session, etc // get previously removed locations (keeping things in sync) $removedLocations = $session->get('removedLocations'); // REMOVING LOCATION if ((int) $input->post->location_remove_id) { $mode = 'remove'; $notice = "Removed"; $id = (int) $input->post->location_remove_id; } else if ((int) $input->post->location_add_id) { // ADDING LOCATION $mode = 'add'; $notice = 'Added'; $id = (int) $input->post->location_add_id; } // ................ more code // e.g. check if we really have a page by that id, SET $noticeType, $options and update session 'removedLocations' etc // build final content //----------- // @note: buildLocationsCards() is a function that does what it says on the tin. We use it in both the ajax response here and also below, in non-ajax content, when the page loads // the $options array contains a key 'skip_pages_ids' with an array of IDs of locations (pages) that have been removed in this session. We skip these in buildLocationCards(). $out = buildLocationCards($page, $options); // @note - here we always return one input only // we use the values in this input in JS to pass event details to alpine.js to show the correct notification and the notification message. $out .= "<input type='hidden' id='location_notice' name='location_notice' data-notice-type='{$noticeType}' value='{$notice}'>"; echo $out; $this->halt(); } // NON-AJAX CONTENT BELOW.... That's all there is to it ?. I am happy to share the full code if anyone wants to play with this further.1 point
-
Very interesting, although the visualisation doesn't quite demonstrate the fact that the bundled site profiles make up more than half of the total ZIP filesize when you download PW from the repo. I believe this has some negatives so I'm keen to start a discussion about moving most of the profiles to separate repos. For anyone interested, please participate here: https://github.com/processwire/processwire-requests/issues/4151 point
-
Not solved, just bypassed: Fresh PW install into a different root directory on the same machine, moved old /site/ directory to the new install and set config.php to the old database and user salt. After clearing the cache and session folder, everything runs fine now. Fortunately, this very obscure situation appeared on a site that is managed by myself and nobody else. To have this on customer work would probably be a nightmare. I don’t know if it’s possible or rather a security issue, but I would appreciate it very much if an error message would reveal a bit more than 'This request was aborted because it appears to be forged'. The error seems to occur repeatedly at least since 2012 without any systematic debugging strategy beyond guesswork into the blue. To hear that something went wrong is arguably better than complete silence, but a bit more information what the system doesn’t like would be helpful.1 point
-
I guess a curious question will be for Modules developers any of your modules breaking with PHP 8 and great to be back to this forum.1 point
-
I don't want to dismiss your frustration — I get that problems like this one can be really annoying! — but I do want to stress a couple of points about this: This is very much a needed (even required) security feature. I wouldn't recommend disabling it unless it's causing major issues, and even then there's a 99% chance that you should just fall back to one of the "less strict" options (as mentioned earlier). Without session fingerprinting attacks involving session hijacking are a very real possibility. Providing UI way to disable any security feature is something I'd be wary of. Of course it depends on the situation, but generally decisions like these should be a) made by folks who have enough technical know-how to make educated decisions knowing what the consequences will be, and b) disabling any security feature should never, ever be something you can do "on a whim" — it needs to be a decision made after serious consideration. Of course technical know-how and well considered decisions don't equal being a developer with access to site's config files or code, but the point is that providing an easy way to decrease the security of the system is definitely not something I'd consider a best practice. Quite the opposite, in fact. Also, one more thing to consider is that if someone did somehow gain illegitimate access to the admin panel, providing an UI way to disable security features could potentially allow them to escalate the attack. (This particular setting is not the best example of that, but generally speaking.) As for session fingerprinting: I've personally not had real problems with it, but I know others have, so not trying to dismiss this problem. It should, though, only happen if your IP or user agent string changes constantly, which is a pretty rare situation — though I'm not an expert in this subject. For me the only case where I've experienced something similar was while testing the site using developer tools, going between mobile UA string and regular UA string... ?1 point
-
it is worth trying other options before disabling this feature completely * 0 or false: Fingerprint off * 1 or true: Fingerprint on with default/recommended setting (currently 10). * 2: Fingerprint only the remote IP * 4: Fingerprint only the forwarded/client IP (can be spoofed) * 8: Fingerprint only the useragent * 10: Fingerprint the remote IP and useragent (default) * 12: Fingerprint the forwarded/client IP and useragent * 14: Fingerprint the remote IP, forwarded/client IP and useragent (all).1 point
-
@modifiedcontent From /wire/config.php file, to change it you add the config option to /site/config.php /** * Use session fingerprint? * * Should login sessions be tied to IP and user agent? * IP fingerprinting may be problematic on dynamic IPs. * Below are the possible values: * * 0 or false: Fingerprint off * 1 or true: Fingerprint on with default/recommended setting (currently 10). * 2: Fingerprint only the remote IP * 4: Fingerprint only the forwarded/client IP (can be spoofed) * 8: Fingerprint only the useragent * 10: Fingerprint the remote IP and useragent (default) * 12: Fingerprint the forwarded/client IP and useragent * 14: Fingerprint the remote IP, forwarded/client IP and useragent (all). * * If using fingerprint in an environment where the user’s * IP address may change during the session, you should * fingerprint only the useragent, or disable fingerprinting. * * If using fingerprint with an AWS load balancer, you should * use one of the options that uses the “client IP” rather than * the “remote IP”, fingerprint only the useragent, or disable * fingerprinting. * * @var int * */ $config->sessionFingerprint = 1; Session Handler Database, in your PW admin go to modules, install tab and there it is.1 point
-
cool link there is a former used addon linked from a php develloper i tested addon some years ago. Have used this one on a local township site for years now: https://github.com/phpManufaktur/kitEvent It has a lot of thirdparty requirements but repeating events, creates ical links, creates QR-codes on events, reusing "events" for new ones...like presets...but it just a element of a real big CRM application of my former used cms "kit" is called "Keep In Touch"...so events was a part of that app.....just funny to find such a old connection to the past....1 point
-
this thread was helpful in setting up the ical and google calendar feeds. i changed the module a bit to get it to support the time start and end of events, otherwise your events will always appear to be all day, if you use this module. It's a bit hackish, in that it determines whether to use the all-day style, or the actual time style by checking if the time is set to midnight, which it would be if you were not specifying a time; though this could be a problem if you had an event that started at midnight. it might work to have a separate checkbox to indicate "all day" and then use that to conditionally output the date with or without time, if you wanted it more foolproof; here are the relevant changes: $start = $event->getUnformatted($this->itemStartDateField); if( date('His', $start) == "000000" ) { $vevent->setProperty('dtstart', $this->ical_date($event->getUnformatted($this->itemStartDateField)),array("VALUE" => "DATE")); } else { $vevent->setProperty('dtstart', $this->ical_date($event->getUnformatted($this->itemStartDateField))); } if($event->get($this->itemEndDateField)) { $end = $event->getUnformatted($this->itemEndDateField); if( date('His', $end) == "000000" ) { $vevent->setProperty('dtend', $this->ical_date($event->getUnformatted($this->itemEndDateField)),array("VALUE" => "DATE")); } else { $vevent->setProperty('dtend', $this->ical_date($event->getUnformatted($this->itemEndDateField))); } } since this module also includes the full iCalcreator library, it could be extended to support repeating events and other cool things.. might experiment with it this summer; They mention processwire, this module, also, on the main page http://kigkonsult.se/iCalcreator/index.php Another thing that came up was the existence of special characters in the titles of the events. The title field needed to be decoded or you end up with &\; in your feed: $summary = html_entity_decode($event->get($this->itemSummaryField), ENT_QUOTES); $vevent->setProperty('summary',$summary); //$vevent->setProperty('summary',$event->get($this->itemSummaryField));1 point