Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/31/2020 in all areas

  1. In preparation for the next master version, this week no new features were added, but just like last week, more than a dozen issue reports were resolved. Having focused largely on fixing various issues over the last month, I feel pretty confident that the current dev branch is significantly more solid than the 3.0.148 master version. It adds and improves a whole lot, and also fixes a lot. And to the best of my knowledge, there aren’t any new issues between 3.0.146 and 3.0.164 that haven’t already been fixed. Basically, I don’t think it makes any sense to keep all these updates exclusive to the dev branch any longer, so have merged it to master, today. Consider it a soft launch, as I haven’t made it an official tagged version yet. Maybe I’m shy, but wanted to wait till Monday before Git tagging it and making it official. The master branch has a different audience than the dev branch, and so there’s always that possibility that some new issue will appear that hasn’t on the dev branch, and wouldn’t have. So we’ll let it marinate on the master branch for the weekend before broadcasting it very far. By this time next week, I should have a blog post ready that covers all that’s new in this version, which is 226 commits ahead of the previous master (3.0.148), so there’s a lot to cover. I want to thank you all that have been helping to identify and report issues on GitHub as they come up. Having covered a lot of issue reports over the last month, I can see a lot of effort goes into preparing many of the reports. Your work is appreciated. This month I focused primarily on the reports that I thought were likely to make the most difference to the most people. I also focused on issues that I thought could be accommodated without introducing potentially new issues or new code to test. Of course, not every report could be covered, and there’s always more to do, so I’ll be getting back to it on the dev branch here soon. In addition, I’ve held off on some new things I’ve wanted to add for awhile (a feature freeze of sorts) in preparation for an end-of-month master version. I’m looking forward to outlining all that’s new in next week’s blog post. Until then, thanks for reading and if you get a chance to test out the new 3.0.164 version, please do and let me know how it goes (both master and dev branches are identical right now). I hope you have a great weekend!
    18 points
  2. Where exactly are you stuck? Differentiating between normal and AJAX requests, rendering content (are you doing that server- or client-side?), encoding the content for the AJAX response? An example of your current code and what's not working about it would be helpful. A couple of observations, in no particular order: The first thing I notice is that the infinite scroll library you linked seems to employ a non-standard way of doing "load more" buttons. Instead of requesting only the new items, it works with an existing classic pagination and just loads the entire next page, throws away everything but the new items and adds them to the existing container. While this does work, it's incredibly wasteful, loading entire pages just to discard most of them immediately. So don't let that library trip you up if you want to build "real" AJAX-powered pagination. What endpoint are you calling in your AJAX request? I remember some tutorials around here recommending to hit the same URL as a regular page view, and differentiating between normal page views and AJAX calls by checking the X-Requested-With header – in my opinion, that's not a good approach. It doesn't even work properly if you use the Fetch API (the modern alternative to XMLHttpRequest). Depending on how much side-loaded content you need on your site, I would either use a URL parameter (?ajax=1) or build an entirely separate endpoint (/api/events/...). The latter approach scales much better. Are you returning HTML or structured data from your endpoint? Depending on that: Returning structured data, i.e. a JSON-encoded object with information about the events is the cleaner way to go about this. But since the first five elements are already rendered server-side, that means you have to replicate your template-logic in JavaScript to create the same HTML structure that the server-rendered events have. Not ideal. In general, I only use this approach if the entire app is client-side rendered (like the Architekturführer Köln). Returning server-rendered HTML is not great, because it makes your API non-reusable (for example, if you want to display side-loaded events in different places with slightly different layouts, you'll need separate endpoints or parameters). It's also just not very clean to insert raw HTML into your page. Though it is a bit easier for simple use cases. I need to mention this: Do you really need to side-load your events? It's one of those features that clients go crazy about because it's "cool and modern", but why not use a regular pagination, which works out of the box and is also better for SEO? If the reason is that your visitors need to load too many pages this way, is there any reason why you can't just show 25 events per page instead of 5?
    8 points
  3. Probably worth mentioning that since this setting prevents ProcessWire from using unfamiliar hosts in output, it's actually pretty important: Let's say that your server was configured to serve your site with any host that a visitor happens to provide. (I've seen this happen, but admittedly it's a major configuration fumble.) Someone points some-weird-and-perhaps-malicious-domain.tld to your site, and then visits the site using said domain. This could be intentional, or even an accident (again this is something I've seen happen, as weird as it may sound.) Finally some code — your own, or perhaps code from a third party module, or even some core feature — asks ProcessWire for the full hostname, and makes use of it in output. Now, if the $config->httpHosts setting didn't exist, ProcessWire would have no way to know which domains are valid, and it would just have to trust that the domain specified by the user is indeed a valid one. Any output using this potentially malicious domain could then get cached, leading to various cache poisoning related issues: redirecting other visitors to this domain, or perhaps making the visitor or ProcessWire itself unknowingly send private data there, thus granting a third party access to it.
    4 points
  4. And from the RFC: While I'd love to give this a try, this limitation is a dealbreaker for me. All the environments I work with host multiple versions of ProcessWire. Might be another reason to move to fully containerized environment... ?
    3 points
  5. If you need redirecting to the final domain name, you may have a look to this snippet. But you have to add it manually somewhere in the top of your root .htaccess file. ################################################################################ # Domain-Namen erzwingen # <IfModule mod_rewrite.c> RewriteEngine On AddDefaultCharset UTF-8 RewriteCond %{HTTP_HOST} ^example\.com [OR] RewriteCond %{HTTP_HOST} ^example-variation\.com [OR] RewriteCond %{HTTP_HOST} ^www\.example-variation\.com RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301] RewriteCond %{HTTPS} !=on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </IfModule> # ################################################################################
    2 points
  6. Small remarks. You should break the loop when work is done: foreach ($page->fields as $field) { if ( $field->type instanceof FieldtypePageTableExtendedGrid ) { // ... break; } } Another approach without loop. Fields is an instance of WireSaveableItems providing a find($selector) function: $selector = implode('|',$fields->find('type=FieldtypePageTableExtendedGrid')->each('name')); if ($page->hasField($selector)) { // ... do something }
    2 points
  7. Needed a really simple solution to embed audio files within page content and couldn't find a module for that, so here we go. Textformatter Audio Embed works a bit like Textformatter Video Embed, converting this: <p>https://www.domain.tld/path/to/file.mp3</p> Into this: <audio controls class="TextformatterAudioEmbed"> <source src="https://www.domain.tld/path/to/file.mp3" type="audio/mpeg"> </audio> The audio element has pretty good browser support, so quite often this should be enough to get things rolling ? GitHub repository: https://github.com/teppokoivula/TextformatterAudioEmbed Modules directory: https://modules.processwire.com/modules/textformatter-audio-embed/
    1 point
  8. Hello, I would like to present you a new module which aim to facilitate the productivity of your editors/publishers when working on ProcessWire. The idea begun when my co-worker told me that when typing in ProcessWire CkEditor field he was feeling "loosing motivation" when writing big wall of text and/or inspiration. So he opened his web-browser and show me a site looking to Wordpress - feel free to put your preferred emoji here - then he opened Gutenberg... typed some text and moving some "blocks". I understood immediately why he got this feeling with CkEditor. If you or your client feel like this guy, then you will love this module ! What is currently supported ? Features Auto-save Medias upload support HannaCode support Blocks Implemented Heading Image Paragraph Embed Quote Code Link Table (beta) Block Delimiter Raw HTML Note (custom block markup) Feature Request Frontend Edition And there you go for the preview - sorry I am to lazy and bad at typing text so I had a copy/pasta moment : Module featured in the ProcessWire Weekly #317 - Thanks @teppo
    1 point
  9. Thanks, @ryan! Sometimes I think that ProcessWire is so mature and feature rich that only fixing the issues at hand can make it stand out even more than adding the new stuff (until the the stuff is added and I start thinking that I could not live without the features just added))) Thank you so much for keeping the right balance.
    1 point
  10. Wow @MoritzLost, that's quite a response. Thanks so much! I will post a few examples here of my code but reading all your point made me realise a few things. Let's start from back: We don't need to load the events, but eventually there is going to be many of them in the archive. My idea was to display the most recent ones and if you want you can pull the next most recent, etc. With pagination maybe it will work the best as I can render everything on the server and just display what I need. My idea was to render everything at the server side as it is easier for me. But I completely get your point why this is not scalable. The Infinite scroll was also too complicated for the same reason, I didn't know what's going on in the back scenes. Right now: let postData = { "ajax:": true, "itemOffset": itemOffset, }; $.ajax({ type: "POST", url: url, data: postData, beforeSend: function (xhr) { xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded") }, success: function (data, status) { pageData = data; itemOffset += itemsToLoad; } }).done(function () { // when finished and successful container.insertAdjacentHTML("afterbegin", 'loaded: ' + pageData + ' (by jquery ajax)'); }); and then I wanted to execute that with my load_events.php template: $num_new_events = $_POST['itemOffset']; $events = $pages->find('template=nk-event, limit=$num_new_events'); // Render something about these events title, images, etc... foreach ($events as $event) { $event_title = $event->title; //etc... $events_output+= '<div class='event'>'. $event_title .'</div>'; //etc... } return $events_output; and then my JS will take it again from there. Of course, this didn't work last week, now it works but only from the home page, because it cannot find my load_events.php file or CORS policy issues. So at the end, I thought it's a bit more straight-forward but it seems like I need to rethink my approach. I have spent a lot of time on this project, so maybe I will try to make what I have until now work or switch to pagination. Thanks for the feedback!
    1 point
  11. Of course, you are right. I should have read the requirements more carefully :-).
    1 point
  12. @fruid never touch the core (wire folder). If you need another Uikit version for the frontend. Install in your site/template folder.
    1 point
  13. If minimum one field is present in the template the other field should be created/ added. No need to go on with the loop.
    1 point
  14. Has anybody tried PHP Preloading in PHP 7.4 with Processwire yet? https://stitcher.io/blog/preloading-in-php-74 Sounds interessting... I would Preload all files in /vendor/ and /wire/. What do you think?
    1 point
  15. Absolutely you can! You just need to get the page the repeater items are on, then you can access the repeater items on it. Based on your code above it should be simple: $id = 1234; // replace with desired page ID $alertspage = $pages->get(id); // replace "alerts" with your repeater field name foreach ($alertspage->alerts as $alert) { // do something with the repeater items ... }
    1 point
  16. This assumes only one field of type FieltypePageTableExtendedGrid is present on the page, no? ?
    1 point
  17. @teppo You already got setup by Kixe and Robin. So, only thing that I can contribute is, if you are using this in an environment that allows overwriting existing files with same filename, you should bind a check of last modified timestamps into your program logic: If fileFieldItem is image and not thumbnail exists: create a thumbnail If fileFieldItem is image and not thumbnail exists OR if origTimestamp is newer than thumbnailTimestamp: create a (new) thumbnail
    1 point
  18. Awesome, thanks @Robin S and @kixe! Manually copying the file and using ImageSizer on it seems like a really nice approach. Don't think I've ever done that myself; in some cases I've accessed Imagick or GD directly, but this is definitely cleaner ?
    1 point
  19. Maybe useful for you @teppo. In one of my last projects I integrated a lightbox gallery that outputs both videos and pictures. The data source for the videos and images was a PageFile field. Here is an excerpt from the template in which the gallery was integrated via Javascript. Resizing works similarly as suggested by @Robin S // galleries $page->_galleriesJS = ''; $galleriePages = $pages->find('template=gallery'); // 16:9 inline video $markup = '<div class="mfp-video-wrapper"><div class="mfp-video-inner"><video width="854" height="480" controls autoplay preload> <source src="{src}" type="video/mp4"> Leider wird dieses Video von ihrem Browser nicht unterstützt. </video></div></div>'; if ($galleriePages->count) { $galleries = ''; foreach ($galleriePages as $gp) { if ($gp->files->count == 0) continue; $items = []; $filesDirPath = $gp->files->path; foreach ($gp->files as $gi) { if (!fileExists($gi->url)) continue; // inline video if (in_array($gi->ext, array('mp4','m4v','ogg','ogv','mpg'))) { $src = str_replace('{src}', $gi->url, $markup); $items[] = ['type' => 'inline', 'src' => $src]; } // wrong file type else if (!in_array($gi->ext, array('png','jpg','jpeg'))) throw new WireException("Unallowed Fileformat $gi->ext for magnificPopup Gallery"); // any image with youtube video source in description else if (strpos($gi->description, 'youtube')) { $oembed = getVideo($gi->description); if ($oembed) { // nocookie source used $items[] = ['type' => 'iframe', 'src' => $oembed->frameUrl]; } } // image else { $src = $gi->url; $copyFileName = strstr($gi->filename, $gi->ext, true) . '1200x0.' . $gi->ext; list($width, $height) = getimagesize($gi->filename); if ($width > 1200) { if (!file_exists($copyFileName)) { $files->copy($gi->filename, $copyFileName, ['limitPath' => true]); $imageSizer = new ImageSizer($copyFileName); $imageSizer->resize(1200, 0); } $src = str_replace($config->paths->root, '', $copyFileName); } $items[] = ['title' => $gi->description, 'src' => $src]; } } $gallery = [ 'gallery' => ['enabled' => true], 'type' => 'image', 'midClick' => true, 'mainClass' => 'mfp-lightbox-wrapper', 'items' => $items, 'tClose' => 'Schließen (esc)' ]; $gallery = json_encode($gallery); $galleries .= "$('.mfp-open-$gp->id').magnificPopup({$gallery})\n"; } $page->_galleriesJS = "<script> $galleries</script> "; }
    1 point
  20. I'm not quite sure if you mean thumbnails within the Files inputfield in the PW admin, or if you mean you want to resize the image file for the front-end. If it's the latter you could use a function or module method along these lines: function getResizedImageUrl(Pagefile $pagefile, $width, $height) { $variation_basename = $pagefile->basename(false) . ".{$width}x{$height}." . $pagefile->ext(); $variation_filename = $pagefile->pagefiles->path . $variation_basename; if(!is_file($variation_filename)) { copy($pagefile->filename, $variation_filename); $sizer = new ImageSizer($variation_filename); $sizer->resize($width, $height); } return $pagefile->pagefiles->url . $variation_basename; } $file = $page->files->first(); $resized_url = getResizedImageUrl($file, 400, 300);
    1 point
  21. Well this was a great one to do. The Beyond Banglatown site is the public facing site for a report conducted by researchers at the London School of Economics and the University of Manchester, and published by the Runnymede Trust. The aim is to present the findingsof the report in a publically accessible way that can be used by teachers and students and well as the general public. It covers the changing face of the neighbourhood around Brick Lane in East London. https://beyondbanglatown.org.uk/ Technically this was the first project we used ProcessWire on - although what with one thing and another it's taken 18 months to get the site launched, so we've managed to get a few others out before this one. It was certainly jumping in at the deep end though and we learned a lot. The site involves a fair amount of ajax driven content and we had to get to grips with importing the data used for the maps and graphs as well as sorting out how best to manage templates and assets. As far as modules that we used there's nothing too exciting, but certainly we made good use of TracyDebugger as we fumbled about. A special mention also needs to go to the PW documentation, the API references and of course this forum which provided a great deal of help. Anyway - we're really pleased with the site and it's already been getting very good coverage. Hopefully the first of many PW sites. s.
    1 point
  22. 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
  23. 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).
    1 point
  24. Hello fellow ProcessWire people! I published an article explaining how I migrated three years worth of running data from Garmin to ProcessWire: https://francescoschwarz.com/articles/running-on-my-own/ Have a great day! Cheers.
    1 point
  25. Yeah.... if(rtrim(floor(( $config->permissionTemplateID * $config->guestUserPageID ) / $config->http404PageID ) + $config->trashPageID, 4) == 1 ) { echo "you are at home"; }
    1 point
×
×
  • Create New...