-
Posts
311 -
Joined
-
Last visited
-
Days Won
8
Everything posted by nbcommunication
-
Thanks @gornycreative, I don't use TracyDebugger (*hangs head in shame*) but I do wonder whether that is why $this->wire()->page isn't available in the init(). The test I ran was on a new install of the dev branch so it does suggest something additional altering things. Regardless, for the purposes of this module the fix I put in place to use $this->wire()->process should work. I would normally have put this logic in ready() but didn't and can't remember why, so I'd prefer to keep it where it is for now at least. Cheers, Chris
-
Hi @snck, Indeed, now I've tested both your and my code on an image of the width you'd specified, I can see I put the fix in the wrong place. The latest version 1.0.7 should hopefully resolve this for you. @gornycreative, How odd - I got this way of checking if it is the admin years ago from someone else's module / a mixture of forum post responses. I've never had a situation where it triggered these warnings. If I log $this->wire()->page in init() I get the Page object. However, I do agree that relying on this in init() isn't the correct implementation. In 1.0.7 I've changed this instead to (string) $this->wire()->process === 'ProcessModule' which works for me and should also hopefully resolve the warnings. Cheers, Chris
-
- 2 replies
-
- 13
-
-
Hi @flydev, Unfortunately we're not there yet with the scaling setup. However this is an interesting thread, this could be potentially related to https://processwire.com/talk/topic/26070-error-exception-unable-to-obtain-lock-for-session/ which we've never been able to figure out. Cheers, Chris
-
Stores a GeoJSON FeatureCollection and its bounds drawn on a MapLibre map. Here's the README.
-
The simplest, quickest, and maybe most useful module I've ever built ? TextformatterJsonDecode: Passes the given text through json_decode(), returning the value (if valid) as a stdClass object. Didn't even bother with a README - does what it says on the tin. Ha need one for the modules repo... This is particularly useful if you are storing JSON from an API in a Page field and want to access it in a similar way to normal Page objects e.g. <?php /* The data { "fieldName": "value" } */ echo $page->api_data->fieldName; // value I'll be using this extensively over the next few weeks, looking forward to it ?
-
Hi @snck, Thanks - I think I found the place where this is failing to generate the 1600x800 variation where it should. I've pushed the potential fix. Can you try it out? I would note that the example implementation I gave above (creating the variation before calling render()) is a better way to implement this as the markup is meant to be a template not a string with actual values, however if the fix I've pushed works, it should work for either implementation. Cheers, Chris
-
Hi @snck, The approach here seems odd to me but I'm probably misunderstanding the use case. I'd do: <?php $img->size(800,400)->render( [ 'picture' => true, 'srcset' => [ 'rules' => ['800x400', '1600x800'], 'options' => [ 'upscaling' => true, ], ], 'allSets' => true, 'sizes' => '(max-width: 900px) 100vw, ((min-width: 901px) and (max-width: 1200px)) 67vw, ((min-width: 1201px) and (min-width: 1201px)) 50vw', 'class' => 'hero-img', 'alt' => "...", 'markup' => "<img src={src} alt='{alt}' class='{class}' width={width} height={height}>", ] ); I'd then switch off upscaling to see what that would do. What would you expect the markup to be in this case? Cheers, Chris
-
Hi @Krlos, Yes, Pageimage::render() is for rendering image markup from a PageImage: https://processwire.com/api/ref/pageimage/render/ In your example above, the correct call would be: <section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;"> Assuming that $page->images is a single Pageimage object and not multiple images. In this case it would be: <section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->first->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;"> This of course doesn't use srcset in any way. Going on @Stefanowitsch's example above you would need to implement Lazysizes and Lazysizes beset and then add something like <section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->first->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;" data-bgset="<?= $page->images->first->srcset ?>"> to your markup. I'm not familiar with Lazysizes though so doubt this is a working example. If you look through this thread you can see how I implemented srcset background images using UIkit's Image component. Cheers, Chris
-
Hi @Krlos, Can you please post a code example? Are you are just calling render() without providing a markup template? Cheers, Chris
-
Hi, We've been looking at using Postmark for some clients and we were delighted to see an existing module WireMailPostmark - https://processwire.com/modules/wire-mail-postmark/. However the note in the initial forum post about it not being used in production by the authors meant that for us we would need to build something a little bit more in line with what we need and can maintain through usage. WireMailPostmarkApp is an implementation of postmark-php, somewhat in line with a previous WireMail module we built WireMailgun - https://processwire.com/modules/wire-mailgun/ - and its usage will be familiar to those who have used that module. Here's the README: https://github.com/nbcommunication/WireMailPostmarkApp/blob/main/README.md Cheers, Chris
-
Hi @snck, This is definitely a bug. The quick solution would be to resize your image before calling render (e.g. $img->size(1600, 534)) but I've pushed a fix which should resolve this. Please download the latest version (1.0.5) and let me know if that hasn't fixed it for you. If not could you please let me know what the values for $img_tag_width and $img_tag_height are in the 'markup' option as I'll need this to debug further. Cheers, Chris
-
Hi @Kiwi Chris, The admin needs the local copy, from what I can see it is mainly for the file size displayed beside the filename in the admin. I did look at hooking InputfieldFile::render() to replace this but I eventually decided that it made sense to keep the original file in place when uploaded, and if it didn't exist to download from the R2 copy. I was thinking here of worst case scenario where Cloudflare Images has a major service outage. In a multi-server environment I could perhaps query each server to see which has the most files and switch off the rest of the servers, and switch off the CF integration on the chosen server. That way a site could continue to function. A very unlikely situation but I'd like that option. What it doesn't do (or shouldn't do, haven't fully tested it yet) is create the size variation image locally. Calls to Pageimage::size() should just create a variant in Cloudflare Images if it doesn't already exist. Unfortunately there is a limit of 100 variants (which can be applied to every image upload, it isn't a limit of 100 actual images), which while sufficient for a single development, means that the service cannot be used for multiple sites, unless they are creating the same variants. I did expect to keep this and the other modules I posted at the start of the week internal as they are somewhat specific to our needs, but after consideration I figured it would make sense for them to get other eyes on them and some differing perspectives - if you do go down the route of Cloudflare Images with your own integration please use this work as reference and please do share any solution you reach! Cheers, Chris
-
It didn't take long for the changes to the Images implementation - it turns out that image options are available for named variants, just not documented. The module now uses named variants instead of flexible variants. More notes etc to be added to the README in the next month or so.
-
Hello, We've recently been researching how to use ProcessWire in a horizontal scaling environment (multiple server instances using a load balanced, read replica databases), and ran an experiment using AWS Elastic Beanstalk. Getting read replica databases up and running was easy - it's built in to the core: https://processwire.com/blog/posts/pw-3.0.175/#how-to-use-it-in-processwire Using multiple server instances throws up one big problem: how to keep the filesystem on multiple instances in sync given that ProcessWire doesn't currently support using an external service (like s3 or EFS) as the filesystem. The solution that we came up with is to use various Cloudflare services (R2, Stream, Images) to serve file assets, and we've built a module to facilitate this: We're not using this in production yet, but our tests on EB were successful, and we're confident this will solve the main part of this problem. However the Cloudflare Images service is still quite new and there's still features to be rolled out (e.g. webP for flexible variants) so it can't be considered a complete solution yet. Additionally, we use ProCache and this presents an additional multi-instance problem - if the cache is cleared on one, how can we clear it on all? Our solution is to log clears in the database and use this to sync up clearing. We built another module: Again this worked well in our test, but isn't yet being used in production. The main purpose of this thread, aside from sharing these potential solutions, is to ask for and discuss other experiences of hosting ProcessWire in a horizontal scaling environment. What solutions did you come up with (if you want to share them) and are there other potential issues we maybe haven't thought about? Cheers, Chris
- 1 reply
-
- 10
-
-
-
Extends Pagefile to use Cloudflare Images, Stream and R2 storage to serve files. https://github.com/nbcommunication/CloudflareAssets The main purpose of this module is to allow ProcessWire to be used in an auto-scaling multi-instance environment. By serving file assets from Cloudflare, it is not necessary to have all file assets copied to all instances and we also get the benefits of serving assets from a CDN. How it works When a Pagefile is added in the admin or via the API, it is uploaded to Cloudflare's R2 storage service. Additionally, if the file is an image, it is uploaded to Cloudflare Images, and if the file is a video it is uploaded to Cloudflare Stream. When a URL for the Pagefile is requested e.g. $pagefile->url(), the appropriate Cloudflare URL is returned. As ProcessWire's admin still requires the file to be available locally, in a multi-instance setup if a file is not available it is downloaded from the 'master' copy in R2. This module is not yet being used in production. There may be changes to how Images work in the coming months as features are still being rolled out to this Cloudflare service. Cheers, Chris
- 7 replies
-
- 15
-
-
-
Synchronises ProCache clearing across a multi-instance environment. https://github.com/nbcommunication/ProCacheSync The main purpose of this module is to allow ProCache to be used in an auto-scaling multi-instance environment. How it works When a page is saved and cache clearing is triggered, the page id(s) associated with that clear are saved to the database. ProCacheSync runs a check every minute via LazyCron to look for records in the database since ProCache was last cleared. If it finds any it processes them as ProCache would. Any records it finds will have been generated by a clear on another server instance, thus enabling multiple instances of ProCache to stay approximately synchronous. This module is not yet being used in production. Cheers, Chris
-
Purge the StackPath CDN cache when ProCache clears. https://github.com/nbcommunication/ProCacheStackPath If you use StackPath's CDN to deliver your website, you need a way to clear its cache when ProCache clears. This module connects with your StackPath stack via the StackPath API and when ProCache clears it requests StackPath clear the cache, attempting to respect the specific rules (Parents, Family, Children etc) set up in ProCache. This module is being using in production but only for a couple of sites that just clear the whole cache when a page is saved. The implementation of the Parents / Family / Children rules haven't been fully tested, and it isn't clear from StackPath's documentation whether their 'recursive' option only works from the root URL or from internal pages too. Hopefully it does and I'll hopefully get it tested soon. Cheers, Chris
-
Note to anyone using potentially using this module: A page-edit-redirects permission has been added to the core - https://github.com/processwire/processwire/commit/dafceffc6f5d2d10c395faa1586ef0993633e6de - and once this hits the master branch I intend to rework this module so that it provided a list of redirects in the system. As the permission can be added to any user role, management of those redirects will happen in the page editor instead of the 'cloned' redirects editor this module currently provides. Cheers, Chris
-
Hi, I've been trying to get the active status of languages to update based on other info on the page, in this case I only want a language to be active if there is a file tagged with its name: <?php // admin.php $pages->addHook('saveReady', function(HookEvent $event) { $page = $event->arguments('page'); foreach($event->wire()->languages->findNonDefault() as $language) { $key = "status$language->id"; if($page->id) { $page->set($key, $page->resource->findTag($language->name)->count ? 1 : 0); } else { $page->setQuietly($key, 0); } } }); I've tried all sorts of approaches but nothing works. It seems as if there is a Page cache issue here. Tried $pages->uncache() but that didn't seem to work either... Anyway, I 'solved' it like so: <?php // admin.php $wire->addHook('InputfieldPageName::render', function(HookEvent $event) { $page = $event->object->editPage; if($page && $page->id) { foreach($event->wire()->languages->findNonDefault() as $language) { $page->setQuietly("status$language->id", $page->resource->findTag($language->name)->count ? 1 : 0); } } }); It does require the user to then save the page, but it is definitely better than having all the languages active when I only need some. Hope this is useful... Cheers, Chris
-
Hi @mel47, This module isn't built to handle art direction I'm afraid, it is to provide a srcset property to a single Pageimage. Art direction will likely require more than one Pageimage (as your example suggests) so this would need to be handled with your own code. However, the module should still be useful for your example; use ->srcset instead of ->url in the <source srcset> attribute. Cheers, Chris
-
Almost every time. I think we're just a bit spoiled with the PW API, but it is always a bit of a shock to work with API data that needs to be wrestled into shape before we can do what we want to do. I'm not sure I could even wrestle it into shape if it wasn't for PW.... On the plus side, at least that API is documented and returning JSON ?
-
Hi @DV-JF, Thanks but no need, I'm always glad to hear that the module is getting used! Cheers, Chris
-
Hi @DV-JF, It happens because Instagram/Facebook invalidates the (authorised) access token if the user changes their password. I guess from the error message (Facebook has changed the session for security reasons) other security issues can lead to it happening too. It isn't in the scope of the module to notify admins, but it should be pretty easy to implement. Try something like: <?php $instagram = $modules->get('InstagramBasicDisplayApi'); $items = $instagram->getMedia(); if(!($items instanceof WireArray) || !$items->count) { $cache->getFor($instagram, 'errorNotifyAdmin', 'daily', function() use ($config, $instagram, $log, $mail) { return $mail->new() ->to($config->adminEmail) ->subject("$instagram error") ->bodyHTML('<p>' . implode('<br>', $log->getLines( $instagram->className(['lowercase' => true]), ['limit' => 10] )) . '</p>') ->send(); }); } This would send the admin an email every day if no media is being returned, with the email being the last 10 log messages. Cheers, Chris
-
Hi @DV-JF, Ah yes, this is a total pain when this happens. We've had this happen on sites where we don't have much contact with the client, as since we need them to re-authorise, the feed is just lying empty. Anyway, going through the authorisation process again should fix this. Cheers, Chris