Jump to content

nbcommunication

Members
  • Posts

    286
  • Joined

  • Last visited

  • Days Won

    7

Everything posted by nbcommunication

  1. Hi @Stefanowitsch, I'd start removing layers of complexity - does getMedia() return something outwith the ajax context? Is anything being logged by the module in Logs? Does the default user account appear in the module config? Cheers, Chris
  2. Hi @Stefanowitsch, Are you using the javascript from the README? I think the UIkit ajax() function has changed so that could be the issue. You could try: fetch(window.location.href, { headers: { 'X-Requested-With': 'XMLHttpRequest', }, cache: 'no-store', }) .then(response => { if (response.ok) { return response.json(); } UIkit.util.addClass(instagram.$loading, 'uk-hidden'); console.error(response.statusText); // ERROR return []; }) .then(data => { // Hide spinner UIkit.util.addClass(instagram.$loading, 'uk-hidden'); if (!UIkit.util.isArray(data) || !data.length) return; // If no items do not render const items = []; data.forEach(item => { switch (item.type) { case 'VIDEO': items.push(instagram.renderItem(item.poster, item.alt, item.src)); break; case 'CAROUSEL_ALBUM': // If 4 or greater items, display a grid of the first 4 images with the rest hidden // Otherwise display the main image (no break, moves to default) if (item.children.length >= 4) { let out = ''; for (let i = 0; i < item.children.length; i++) { out += `<div${i < 4 ? '' : ' class=uk-hidden'}> ${instagram.renderItem(item.children[i].src, item.alt)} </div>`; } items.push(`<div class="uk-grid-collapse uk-child-width-1-2" data-uk-grid>${out}</div>`); break; } default: // IMAGE items.push(instagram.renderItem(item.src, item.alt)); break; } }); const count = items.length; if (count) { // Wrap all items with a div let out = ''; for (let i = 0; i < count; i++) { out += `<div id=instagram-item-${instagram.total + i}> ${items[i]} </div>`; } // Append items to the container UIkit.util.append(instagram.$el, out); // Attach scrollspy listener on last item of second last row if (count > 5) { UIkit.util.on(`#instagram-item-${instagram.total + count - 6}`, 'inview', () => instagram.get()); } // Update total instagram.total = instagram.total + count; } }); The next thing to do would be to try and get the full output that the script is returning. I'm not familiar enough with fetch() to know for certain but you could try console.log(response.text()); after the error log to see if that gives you it. My experience with the errors you've mentioned is that the first is caused by HTML being output/echoed before the JSON, and the second is usually caused by a deprecation notice being output. If you've got $config->debug enabled, try switching that off - if that works then check your logs to see what is triggering the notice and see if it can be resolved. Hope that helps, Chris
  3. Hi @bdbdbd, It isn't the way I'd do it but if it is working for you then that's great. I'd probably add something that checks whether a resized version exists already prior to resizing. If it exists, perhaps update the file modified time if that's possible, and then have a bit of a script to remove images that are older that a set time period, could be anywhere from 1 day to 6 months depending on how often the feed is updated. Cheers, Chris
  4. Hi @bdbdbd, The size() method needs to be called on a Pageimage object (an image saves to a Pageimages field) - it can't be called on an image directly. Saving the images to an image field would end up being quite tricky as you'd need to handle checking if the image already exists, and removing old images too. Honestly, I'd recommend just using the images from instagram, add width="300" height="n" to the <img> tag. I say height=n as this will need to be the height that the image would be if it were 300px wide - they aren't all square images. <?php $instagram = $modules->get('InstagramBasicDisplayApi'); // Get 10 images $images = $instagram->getImages(10); $counter = ''; foreach ($images as $image) { $counter = $counter + 1; $width = 300; $height = round(($image->height / $image->width) * $width); echo "<img src=$image->src alt='$image->alt' width=$width height=$height>"; } ?> If you need a 300px x 300px image grid, I'd recommend using a <div> with these dimensions and adding the image as a background-image (background-size: cover). Cheers, Chris
  5. Hi, Now that the page-edit-redirects permission is in the latest master, I've redeveloped this module to list redirects in the system. I've also added a list of redirects present in the htaccess file (that match one of the httpHosts), and a field for filtering the tables. Cheers, Chris
  6. Hi @snck, I'm just doing some testing on the module at the moment and was using this code as an example. Just wanted to let you know that 'allSets' should be set in srcset options alongside 'upscaling'. In this case, you wouldn't need to set upscaling as 'allSets' enables upscaling anyway. Cheers, Chris
  7. Hi @Sanyaissues, It might be that this Textformatter isn't the best fit for your use case, but to hopefully solve your issue: json_decode() can return a stdClass object or an associative array. This module returns a stdClass object. I don't think you can use array_merge() on this (might be wrong, never tried it). To retrieve the field, modify it and save it, this should work: <?php $otherArray = []; $page->of(false); $array = json_decode($page->jsonfield, 1); // associative array $page->jsonfield = json_encode(array_merge($array, $otherArray)); $page>save(); // Or $array = json_decode($page->getUnformatted('jsonfield'), 1); // associative array $page->setAndSave('jsonfield', json_encode(array_merge($array, $otherArray))); Cheers, Chris
  8. 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
  9. 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
  10. 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
  11. Stores a GeoJSON FeatureCollection and its bounds drawn on a MapLibre map. Here's the README.
  12. 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 ?
  13. 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
  14. 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
  15. 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
  16. Hi @Krlos, Can you please post a code example? Are you are just calling render() without providing a markup template? Cheers, Chris
  17. 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
  18. 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
  19. 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
  20. 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.
  21. 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
  22. 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
  23. 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
  24. 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
×
×
  • Create New...