Leaderboard
Popular Content
Showing content with the highest reputation on 10/29/2024 in all areas
-
There you go, the M4 Mac mini: https://www.apple.com/mac-mini/ Mine will be configured as: Apple M4 chip with 10-core CPU, 10-core GPU, 16-core Neural Engine 16GB unified memory 512GB SSD storage 10 Gigabit Ethernet Three Thunderbolt 4 ports, HDMI port, two USB‑C ports, headphone jack Should you want to install Linux on it: https://asahilinux.org/2024/10/aaa-gaming-on-asahi-linux/ But probably a better option: https://eclecticlight.co/2024/01/01/virtualise-linux-on-apple-silicon-with-liviable-beta-4/2 points
-
WireDatabasePDO's constructur doesn't connect to the database yet. This is either implicitly done when the query or exec(ute) methods are called, or explicitly by invoking $db->pdo(), which will return the underlying plain PDO object.2 points
-
This module won't suit everyone because... It requires what is currently the latest dev version of ProcessWire It requires your server environment have AVIF support Generating AVIF files is slow It offers fewer features than the core provides for WebP It is likely incompatible with the core WebP features so is an either/or prospect ...but it allows for the basic generation and serving of AVIF files until such time as the core provides AVIF features. Auto AVIF Automatically generates AVIF files when image variations are created. The AVIF image format usually provides better compression efficiency than JPG or WebP formats, in many cases producing image files that are significantly smaller in size while also having fewer visible compression artifacts. Requires ProcessWire v3.0.236 or newer. In order to generate AVIF files your environment must have a version of GD or Imagick that supports the AVIF format. If you are using ImageSizerEngineGD (the ProcessWire default) then this means you need PHP 8.1 or newer and an OS that has AVIF support. If you want to use Imagick to generate AVIF files then you must have the core ImageSizerEngineIMagick module installed. The module attempts to detect if your environment supports AVIF and warns you on the module config screen if it finds a problem. Delayed Image Variations Generating AVIF files can be very slow - much slower than creating an equivalent JPG or WebP file. If you want to use this module it's highly recommended that you also install the Delayed Image Variations module so that image variations are created one by one on request rather than all at once before a page renders. Otherwise it's likely that pages with more than a few images will timeout before the AVIF files can be generated. Configuration On the module configuration screen are settings for "Quality (1 – 100)" and "Speed (0 – 9)". These are parameters for the underlying GD and Imagick AVIF generation methods. There is also an option to create AVIF files for existing image variations instead of only new image variations. If you enable this option then all image variations on your site will be recreated the next time they are requested. As per the earlier note, the process of recreating the image variations and the AVIF files is likely to be slow. Usage Just install the module, choose the configuration settings you want, and make the additions to the .htaccess file in the site root described in the next section. How the AVIF files are served The module doesn't have all the features that the ProcessWire core provides for WebP files. It's much simpler and uses .htaccess to serve an AVIF file instead of the original variation file when the visitor's browser supports AVIF and an AVIF file named the same as the variation exists. This may not be compatible with the various approaches the core takes to serving WebP files so you'll want to choose to serve either AVIF files via this module or WebP files via the core but not both. Two additions to the .htaccess file in the site root are needed. 1. Immediately after the RewriteEngine On line: # AutoAvif RewriteCond %{HTTP_ACCEPT} image/avif RewriteCond %{QUERY_STRING} !original=1 RewriteCond %{DOCUMENT_ROOT}/$1.avif -f RewriteRule (.+)\.(jpe?g|png|gif)$ $1.avif [T=image/avif,E=REQUEST_image,L] 2. After the last line: # AutoAvif <IfModule mod_headers.c> Header append Vary Accept env=REQUEST_image </IfModule> <IfModule mod_mime.c> AddType image/avif .avif </IfModule> Opting out of AVIF generation for specific images If you want to prevent an AVIF file being generated and served for a particular image you can hook AutoAvif::allowAvif and set the event return to false. AutoAvif generates an AVIF file when an image variation is being created so the hookable method receives some arguments relating to the resizing of the requested variation. Example: $wire->addHookAfter('AutoAvif::allowAvif', function(HookEvent $event) { $pageimage = $event->arguments(0); // The Pageimage that is being resized $width = $event->arguments(1); // The requested width of the variation $height = $event->arguments(2); // The requested height of the variation $options = $event->arguments(3); // The array of ImageSizer options supplied // You can check things like $pageimage->field, $pageimage->page and $pageimage->ext here... // Don't create an AVIF file if the file extension is PNG if($pageimage->ext === 'png') $event->return = false; }); Deleting an AVIF file If you delete a variation via the "Variations > Delete Checked" option for an image in an Images field then any corresponding AVIF file is also deleted. And if you delete an image then any AVIF files for that image are also deleted. Deleting all AVIF files If needed you can execute this code snippet to delete all AVIF files sitewide. $iterator = new \DirectoryIterator($config->paths->files); foreach($iterator as $dir) { if($dir->isDot() || !$dir->isDir()) continue; $sub_iterator = new \DirectoryIterator($dir->getPathname()); foreach($sub_iterator as $file) { if($file->isDot() || !$file->isFile()) continue; if($file->getExtension() === 'avif') { unlink($file->getPathname()); echo 'Deleted: ' . $file->getFilename() . '<br>'; } } } Saving an original variation file Because requests to images are being rewritten to matching AVIF files where they exist, if you try to save example.500x500.jpg from your browser you will actually save example.500x500.avif. You can prevent the rewrite and load/save the original variation file by adding "original=1" to the query string in the image URL, e.g. example.500x500.jpg?original=1. https://github.com/Toutouwai/AutoAvif https://processwire.com/modules/auto-avif/1 point
-
That was my thought too. Since the machine fits in a pocket (well, you need a large coat for that, but there are such pockets...) if I buy a small keyboard and a small screen, I can easily temporarily relocate my office when I need to. I have no idea which keyboard and small monitor to buy just yet, but I will definitely purchase them in the end. BTW, here is a quick review for those interested: https://www.youtube.com/watch?v=KxgnSiK5qBA1 point
-
Dude! Now you've got me really, I mean really, interested! Aside from the 'marketing' talk (in the announcement), this little guy looks like it packs a powerful punch! All that and managing to keep it cool? Hmm. We are seriously OT-ing, sorry, but are you able to please recommend a 'portable' screen to go with it? Thanks!1 point
-
@wbmnfktr Reminds me of the first model of iPhone where Apple removed the headphone jack and Phil Schiller was up on stage patting himself on the back for everything. When he got to the part telling everyone the headphone jack had been removed, he said: It was the most dramatic and hilarious delivery ever. "The reason to move on..." (dramatic pause) "...courage". Like he just personally cured cancer or something, What you're witnessing right there with that power button? Courage. Apple is blazing towards the future. We're out here stuck in the past where we turn our computers on and off like cavemen and cavewomen with big ugly power buttons on our laptops staring us in the face.1 point
-
1 point
-
*cough*windowsisspyware*cough* Pardon me, must be a cold or something going around.1 point
-
@cpx3 Thanks! It should be fixed now, but let me know if you still can't access.1 point
-
@Ryan, ok thanks! I just would need access to ProCache forum to ask a question... Get healthy, all the best!1 point
-
@cpx3 Sorry about that, I got back two days ago, and I've been battling the flu or something since, so I've not caught up with my messages yet. I'll be getting caught up over the next week and will fix that access issue right now. Thanks.1 point
-
@nurkka, when I test here DelayedImageVariations is sort of working with webp(), although I'm surprised it works at all because I thought it would be a case like the one mentioned in the readme: I thought the webp() method would need an actual resized variation to be available at the time it is called. But I'm testing like this... foreach($page->images as $image) { $image_url = $image->size(250,250)->webp()->url; bd($image_url, "image_url"); echo "<img src='$image_url' alt=''>"; } ...and what I experience is that on the first page load the webp()->url results in a JPG file... ...and on subsequent page loads it results in a WebP file. I don't get any 404s or broken images, and the only effect is slightly larger file sizes on the first page load, which isn't that big of a deal. But if you experience something different then I don't have a solution within DelayedImageVariations, sorry. My suggestion then would be to pursue a different strategy to pre-generate your image variations rather than use DelayedImageVariations. You could generate the variations on page save. See this post for how you could do it without slowing down page saves in the admin:1 point
-
Now tested (I used the module configuration field) and it works perfectly. Thanks again.1 point
-
wire()->addHookBefore("InputfieldFile::renderItem", function(HookEvent $event) { $pagefile = $event->argumentsByName('pagefile'); if ($pagefile->field->name === 'yourFileField') { $pagefile->description = 'Communiqué de presse'; $pagefile->page->save($pagefile->field->name); } }); Try this @TomPich.1 point
-
#@!^$ problem was on my side (forgot that i put it here, yesterday) : <?php // Prüfen, ob der Aufruf per AJAX erfolgt if (!$config->ajax) { http_response_code(403); echo "Forbidden"; exit; } // Beispielantwort echo "Dies ist die Antwort von /ajax/foo"; after deleting the first part, everything works just fine! thank you guys for your support!1 point
-
Another module that was created through the development of RockCommerce 😎 Ever needed a list of all countries of the world? Wanted to show a subset? Needed to translated them to other languages? Check out RockCountries, which can help you with these things: // using tracy debugger's bd() bd(rockcountries()->countries()->get('alpha2=aut')); Download & Docs: baumrock.com/RockCountries1 point
-
I just watched a video about e-mobility and comparison of different energy sources like petrol, e-fules and batteries. Don't want to start a discussion here as it would also violate forum rules, but seeing this picture I thought this look so much like the comparison between a typical WordPress site compared to a typical ProcessWire site 😄1 point
-
In the last couple of weeks I’ve been to several cities in Spain, France and Italy. I’d never been to any of those countries before (or Europe for that matter), so it was an exciting trip. Though the goal was for my kids to broaden their horizons and experience other parts of the world, as well as spend time with my parents and family. We got back this week and have been recovering from jet lag (another thing I’d not experienced before). The 6 hour difference was no problem getting there, but coming back, it’s a little harder to adjust! Next week I turn 50 years old (ugh), and then the following week I’m back in Europe again, except this time in the Netherlands on a bike trip with a client, and without my kids and parents. I’m not sure I’ll be able to do many core updates during the 10 day trip but do expect to have internet access this time, so will at least be online regularly and hope to be here in the forums. After that trip, I won’t be traveling again for a long time, and the focus will be on getting our next main/master version out. I noticed this week that @Robin S is now beating me as our most prolific module developer, with 72 modules! Great job and thanks for all the great modules Robin S.!1 point
-
My pleasure. The hooks and inputfields APIs in ProcessWire make module development an absolute dream. It's very satisfying seeing the results you can get with just a little code, and working on modules provides a motivation to dig into the core code so I learn a lot in the process. Also, another shout out to @adrian's amazing Tracy Debugger, which has been transformative for my coding. I have several more modules in progress so watch this space. 🙂1 point
-
Done! Here is the link for everybody to submit a review 🙂 https://www.softaculous.com/review/ProcessWire If you are short on time: https://www.softaculous.com/rate/ProcessWire Both without registration!1 point
-
I'm not a PHP expert, I use this language since a few years but only intensively since last year. And I just found the spaceship operator <=>. A few days before I implemented an ArrayUtils::floatCompare() because I found bugs in my code where I compared floats like int, because usort callback function return value is an int and I was returning "$float1 - $float2"... followed by the implicit cast to int... not perfect sorting. ? I know I've already read about this 'spaceship.' I remember the name, but probably it wasn't the right time to fully understand its meaning. ^^ Did you know this operator? EDIT : thanks to the moderator who pinned this topic, I owe you a beer! ?1 point
-
Sometimes you need to execute a slow task after some event occurs in the PW admin, and normally you have to wait for this task to finish before you can continue using the admin. This is because PHP is "blocking", meaning that while one thing is executing nothing else can execute. There are potentially lots of different kinds of tasks that could be slow, but just as an example suppose you want to generate resized variations of images on a page, and there are a lot of images. You might have a hook like this so that any non-existing variations are created when the page is saved: $pages->addHookAfter('saveReady', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); // When a gallery page is saved if($page->template == 'gallery') { // Create an image variation for each image foreach($page->images as $image) { $image->size(1200, 1200); } } }); When you save a gallery page in the PW admin, the admin will be unresponsive and will only load again after all the variations have been created. I wanted to find a way for slow tasks to be triggered by events in the PW admin and for the website editor not to have to wait for the task to finish before continuing with other work in the admin. Inspired by this StackOverflow answer I came up with the following solution that seems to work well. Using the image variations task above as an example... First we make use of the URL hooks feature to set up a URL that can trigger tasks to run when it is loaded: // A URL that will trigger tasks when loaded $wire->addHook('/run-task/', function($event) { $input = $event->wire()->input; // A simple check to avoid unauthorised access // You could implement more advanced checks if needed if($input->post('key') !== 'cTdPMBQ7x8b7') return false; // Allow the script to keep running even though we have set a short WireHttp timeout ignore_user_abort(true); // The "create variations" task if($input->post('task') === 'create-variations') { $page_id = (int) $input->post('page'); $p = $event->wire()->pages->get($page_id); // Create an image variation for each image foreach($p->images as $image) { $image->size(1200, 1200); } return true; } return false; }); Then in the Pages::saveReady hook we use WireHttp to load that URL and post parameters that define what task to run and anything else needed for the task (in this case the ID of the page that has been saved). $pages->addHookAfter('saveReady', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); // When a gallery page is saved if($page->template == 'gallery') { // Load the /run-task/ URL using WireHttp $http = new WireHttp(); // Set a short timeout so we don't have to wait until the script finishes // Timeout values shorter than 1 second can be tried once a core issue is fixed // https://github.com/processwire/processwire-issues/issues/1773 $http->setTimeout(1); $url = $event->wire()->config->urls->httpRoot . 'run-task/'; $data = [ 'key' => 'cTdPMBQ7x8b7', 'task' => 'create-variations', 'page' => $page->id, ]; $http->post($url, $data, ['use' => 'curl']); } }); By doing it this way the task runs in a separate request and the website editor doesn't have to wait for it to finish before they can continue working in the PW admin.1 point
-
You can Hook into InputfieldFile::processInputFile. There are other places in that Class you could also hook into, but I think processInputFile works best. Throw the code below in ready.php Please note: Starter code: not much validation going on other than checking if the field the file was uploaded to is 'course_file' You will have to implement other logic yourself. For instance, the code copies the file immediately it is uploaded by ProcessWire Ajax. It doesn't check if the page is actually saved. If a page is not saved and the page is reloaded, as you know, files in file fields are deleted from disk. This code does not delete the corresponding file in your custom directory You might want the Hook to only run if you are in admin. You can add that logic I've purposefully left in verbose and debugging code in there (Tracy stuff) to help you ( maybe and others) understand what's going on. I suggest you test using Tracy Debugger for a better grasp of the file upload process. Delete the debugging stuff when you've got this working as you want :-). wire()->addHookAfter("InputfieldFile::processInputFile", function(HookEvent $event) { // @note: here, events are $input, $pagefile, $n @see: the method // get event we are hooking into // get arguments by index {a bit faster, but less-readable} /* $input = $event->arguments[0]; $pagefile = $event->arguments[1]; $n = $event->arguments[2]; */ // get arguments by name #$input = $event->argumentsByName('input'); $pagefile = $event->argumentsByName('pagefile'); #$n = $event->argumentsByName('n'); // $pagefile->field: The Field object that this file is part of. // limit to a specific field {course_file} if($pagefile->field->name != 'course_files') return; # intercept file // Tracy Debugger calls to see what's going on. Also logs Ajax inputs! #bd($input, 'input'); #bd($n, 'input'); // @see: http://processwire.com/api/ref/pagefile/ // pagefile object bd($pagefile, 'pagefile'); // name of the field uploading to {your 'course_file'} bd($pagefile->field->name, 'field pagefile is part of'); // file-sanitized name of the file we've added, e.g. 'checklist_install.pdf' bd($pagefile->basename, 'name of added file'); // full disk path where the file has been uploaded in this page's files folder... //... in /site/assets/files/1234 where 1234 is this page's ID // ... e.g. "F:/www/mysite/site/assets/files/1234/checklist_install.pdf" bd($pagefile->filename, 'full disk path name of added file'); // $pagefile->page: The Page object that this file is part of bd($pagefile->page->id, 'id of the page file added to'); // full disk path to your custom uploads directory $customDirectory = $this->wire('config')->paths->assets . 'custom_directory/'; bd($customDirectory,'custom directory for files'); # copy file // use ProcessWire's $files API // @see: http://processwire.com/api/ref/files/ $files = $this->wire('files'); // copy the file(s) $files->copy($pagefile->filename,$customDirectory . $pagefile->basename); });1 point
-
Also quite useful: When hooking ProcessPageEdit the edited page is $event->object->getPage();1 point