Jump to content

Robin S

Members
  • Posts

    4,928
  • Joined

  • Days Won

    321

Everything posted by Robin S

  1. No, not unless the core image field supported avif format at some point in the future. This module doesn't change which file formats are supported by an images field.
  2. I like to do that too - show the page ID and also the template name in the page list. I do that via a private module which isn't installed here as it would just confuse things for this demo. But when I'm entering an ID into some API code I feel safer if I'm copying and pasting rather than memorising and typing the ID in manually, particularly on larger sites where the IDs are getting up into 6 digits and it's easy to misread or transpose the digits.
  3. InputfieldFile has several settings that don't have config fields in the admin. See here: https://github.com/processwire/processwire/blob/5609935e4ee96611965550e57d3139200de95c35/wire/modules/Inputfield/InputfieldFile/InputfieldFile.module#L20-L26 I'm not sure of the reasons why but perhaps the thinking is that they would only needed for specialised uses of the inputfield. You could use a hook in /site/ready.php to add a config field for that setting to all files fields if you want to set it per field: $wire->addHookAfter('InputfieldFile::getConfigInputfields', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->object; /** @var InputfieldWrapper $wrapper */ $wrapper = $event->return; /** @var InputfieldCheckbox $f */ $f = $event->wire()->modules->get('InputfieldCheckbox'); $f->name = 'noShortName'; $f->label = 'Disable abbreviated filenames'; $f->label2 = 'Disable abbreviated filenames in inputfield'; $f->collapsed = Inputfield::collapsedBlank; $f->checked($inputfield->noShortName); $wrapper->add($f); }); Or if you want to disable it for all file fields: $wire->addHookAfter('InputfieldFile::renderReadyHook', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->object; $inputfield->noShortName = true; });
  4. When writing API code I often refer to the PW admin to get particular page IDs or field names. And when I'm writing client instructions I often need to insert the labels of particular fields. To make this quicker and more convenient I added some custom JavaScript to the PW admin that copies these things to the clipboard on Alt + click and Ctrl + click. The Page List item and inputfield header are briefly highlighted in yellow to signify that the copying has occurred. This is tested in Windows and I'm not sure if the Alt key / Ctrl key detection is the same for other operating systems but you could adjust the key detection as needed. In /site/ready.php // Add custom JS file to $config->scripts FilenameArray // This adds the custom JS fairly early in the FilenameArray which allows for stopping // event propagation so clicks on InputfieldHeader do not also expand/collapse InputfieldContent $wire->addHookBefore('ProcessController::execute', function(HookEvent $event) { // Optional: for superuser only if(!$event->wire()->user->isSuperuser()) return; $config = $event->wire()->config; $modified = filemtime($config->paths->templates . 'admin-assets/copy-on-click.js'); $js_url = $config->urls->templates . "admin-assets/copy-on-click.js?m=$modified"; $config->scripts->add($js_url); }); In /site/templates/admin-assets/copy-on-click.js $(document).ready(function() { // Copy a string to the clipboard function copyToClipboard(string) { const $temp = $('<input type="text" value="' + string + '">'); $('body').append($temp); $temp.select(); document.execCommand('copy'); $temp.remove(); } // Copy page ID when Page List row is Alt + clicked $(document).on('click', '.PageListItem', function(event) { if(event.altKey) { const classes = $(this).attr('class').split(' '); for(const item of classes) { if(item.startsWith('PageListID')) { const id = item.replace('PageListID', ''); copyToClipboard(id); $(this).effect('highlight', {}, 500); break; } } } }); // When InputfieldHeader is clicked $(document).on('click', '.InputfieldHeader', function(event) { let text = ''; // If Alt + clicked then copy the input name the label is for, or the ID as a fallback if(event.altKey) { event.preventDefault(); event.stopImmediatePropagation(); text = $(this).attr('for'); if(!text) text = $(this).parent().attr('id'); text = text.replace(/^Inputfield_|wrap_Inputfield_|wrap_/, '').trim(); } // If Ctrl + clicked then copy the label text else if(event.ctrlKey) { event.preventDefault(); event.stopImmediatePropagation(); text = $(this).text().trim(); // If AdminOnSteroids is installed use the below instead to exclude text within the AOS field edit link // text = $(this).clone().find('.aos_EditField').remove().end().text().trim(); } if(text) { copyToClipboard(text); $(this).effect('highlight', {}, 500); } }); }); Demo (using the Tracy console only as a convenient place to paste into for demonstration): Copying the field label is useful for getting the name of config fields too, for when you need them in your API code.
  5. If you have only one WireMail module installed it is used for all email sent by ProcessWire. If you have multiple WireMail modules installed there are ways you can choose which to use in any given case. https://processwire.com/modules/wire-mail-router/
  6. @Murray, did you take a look through the modules directory? https://processwire.com/modules/category/email/ https://processwire.com/modules/wire-mailgun/ https://processwire.com/modules/wire-mail-send-grid/
  7. Yes, it's because of the ProcessWire namespace. Add it when setting the function name to your variable: $func = 'ProcessWire\foo';
  8. Seeing as this only affects the specific case when you (the developer) are debugging 404s for URLs that PW doesn't allow, maybe the solution is just to temporarily modify the PW .htaccess for the debugging session. If you are on a local hosting or a dev site that doesn't have public access you can simply comment out rule 16A: # RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$" And if on a public site you could use a more permissive redirect just for your own IP address by adding this immediately after RewriteEngine On: # Use a less restrictive redirect just for my own trusted IP address RewriteCond %{REMOTE_ADDR} ^206\.83\.102\.77 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?it=$1 [L,QSA] When you're finished you'd revert the .htaccess to how it was before. This seems good enough to me, unless you can see a downside.
  9. Thanks for looking into this @adrian This didn't work for me. $_SERVER['HTTP_HOST'] and location.hostname just give me "mywebsite.com" and without the "https://" it doesn't form a valid base for the URL. Simply using "/" in each file worked. Or for an absolute path to the root maybe $_SERVER['HTTP_ORIGIN'] and location.origin would work. Maybe with a trailing slash added? I'm out of my depth here, but would it be a problem when the script that is executing is not in the site root? Some cases of this might be: 1. When Tracy is being used outside of ProcessWire and the executing script is /some-directory/some-file.php rather than everything being executed from an index.php 2. When PW is installed in a subdirectory and so index.php is not in the site root 3. When PW is bootstrapped from /some-directory/some-file.php
  10. @Jim Bailie, if you update the module to v0.2.3 there is a hookable method that fires when a file is about to be replaced. $wire->addHookAfter('FilesRenameReplace::replaceReady', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->arguments(0); /** @var Pagefile $pagefile */ $pagefile = $event->arguments(1); /** @var Pagefile $replacement */ $replacement = $event->arguments(2); // Do something here... }); I don't think you could do anything useful to the Pagefile objects at this point given that the original file is about to be deleted and the replacement file is about to have all its properties overwritten from the original file, but you could set some other field value on the page like this: $wire->addHookAfter('FilesRenameReplace::replaceReady', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->arguments(0); /** @var Pagefile $pagefile */ $pagefile = $event->arguments(1); /** @var Pagefile $replacement */ $replacement = $event->arguments(2); // Set a date field on the page $page = $inputfield->hasPage; if($page && $page->id) { $page->setAndSave('my_date_field', time()); } });
  11. Those template files need a comment that explains what is going on. I opened a GitHub issue: https://github.com/processwire/processwire-issues/issues/1806
  12. If item 2 is enabled in .htaccess then PW will still handle 404s for URLs that don't conform to its rules so you don't necessarily need to change items 16A or 16B. You could do something like this in /site/init.php: $wire->addHookBefore('ProcessPageView::pageNotFound', function(HookEvent $event) { $info = pathinfo($_SERVER['REQUEST_URI']); // Redirect or do whatever if(!empty($info['extension']) && strtolower($info['extension']) === 'pdf') { $event->wire()->session->location("/find-file/?filename={$info['basename']}"); } }); Unfortunately is seems that Tracy Debugger doesn't work on this kind of 404 which makes debugging harder, but I've asked about this in the Tracy subforum and @adrian might have a solution.
  13. Hi @adrian, If I dump something in the template file for my 404 page, or within a hook to ProcessPageView::pageNotFound, then I can see the debug bar and the dump when the requested URL is one that passes PW's rules in .htaccess, e.g. https://mywebsite.com/this-page/does-not-exist/ But if the URL doesn't conform to PW's rules... https://mywebsite.com/this-page/doesn't-exist/ ...then I still get a 404 page that is managed by PW and the associated template file (assuming item 2 is enabled in .htaccess) but there is no debug bar or dump. Is it possible to have the Tracy debug bar in this situation?
  14. @Jim Bailie, I updated the styling in a new release of the module. You don't want to encode entities when you set the value or you'll get a double-encoded string when you get uploadName when output formatting is on.
  15. @Jim Bailie, I've released v0.2.0 of Files Rename Replace which will now retain the uploadName property when a file is replaced.
  16. v0.2.0 is released, which adds support for multi-language, custom fields and upload name when a file is replaced.
  17. The upload name is shown in a tooltip when you hover on the file icon in the inputfield: If you want something that's always visible you could hook into the inputfield rendering: // Display upload name in InputfieldFile $wire->addHookAfter('InputfieldFile::renderItem', function(HookEvent $event) { /** @var Pagefile $pagefile */ $pagefile = $event->arguments(0); $event->return = "<p class='upload-name'>$pagefile->uploadName</p>" . $event->return; }); And then style it with some custom admin CSS: .InputfieldFileItem .upload-name { color:white; line-height:1.33; padding:6px 10px; margin:0; background-color:#606060; } There are several ways you can add custom CSS to the PW admin - here is one: // Add custom CSS to admin $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) { $config = $event->wire()->config; $parts = $event->return; $css_url = $config->urls->templates . 'admin-assets/admin-custom.css'; $modified = filemtime(rtrim($config->paths->root, '/') . $css_url); $parts['head'] .= "<link rel='stylesheet' href='$css_url?m=$modified'>"; $event->return = $parts; }); Result:
  18. Could you give more details about what you mean by this? Are you trying to import files via the API and this fails somehow? Or you mean that the $ character is not retained in the filename after you add the file to a Files field? If it's the latter I wrote a tutorial you might find useful:
  19. ProcessWire automatically sanitises the names of files that are uploaded to a Files field. For example, a file named "Café meals under $30.pdf" will become "cafe_meals_under_30.pdf" after it is uploaded. Since v3.0.212 ProcessWire stores the original unsanitised filename of each uploaded file, and this is accessible via $pagefile->uploadName https://processwire.com/blog/posts/pw-3.0.226/#file-and-image-improvements https://processwire.com/api/ref/pagefile/upload-name/ So if I have a field named "files" on my page and I want to provide downloads of the files with their original filename I can output links like this: $out = ''; foreach($page->files as $file) { // uploadName is entity-encoded when output formatting is on $original_name_unencoded = html_entity_decode($file->uploadName); $out .= "<p><a href='$file->url' download='$original_name_unencoded'>$file->uploadName</a></p>"; } echo $out; So far, so good. But I want my site visitors to be able to view PDFs in the browser rather than force a download, yet if they do download them after viewing them I want the files to get the original filename. For this I can use a URL hook to deliver the PDF via PHP rather than directly loading the file. In /site/ready.php: $wire->addHook('/view-pdf/{page_id}/{filename}', function($event) { $id = (int) $event->page_id; $filename = $event->wire()->sanitizer->text($event->filename); if(!$id || !$filename) return 'Invalid request'; // Get the Pagefile via PagefilesManager $pm = $event->wire()->pages->get($id)->filesManager; $file = $pm->getFile($filename); if(!$file) return 'File not found'; // uploadName is entity-encoded when output formatting is on $original_name_unencoded = html_entity_decode($file->uploadName); // Set headers and output the PDF content header("Content-Type: application/pdf"); header("Content-Disposition: inline; filename=$original_name_unencoded"); header("Content-Transfer-Encoding: binary"); header("Accept-Ranges: bytes"); @readfile($file->filename); return true; }); In the page template file: $out = ''; foreach($page->files as $file) { if($file->ext === 'pdf') { // Deliver PDF files via the URL hook $out .= "<p><a href='/view-pdf/$page->id/$file->basename'>$file->uploadName</a></p>"; } else { // Other files receive a download attribute // uploadName is entity-encoded when output formatting is on $original_name_unencoded = html_entity_decode($file->uploadName); $out .= "<p><a href='$file->url' download='$original_name_unencoded'>$file->uploadName</a></p>"; } } echo $out;
  20. In this code, $pt is already a Page object so you don't need to get it again from $pages. You can just call the render method on it directly. foreach($page->pagetable as $pt) { $content .= $pt->render(); } For this sort of thing you'll find that Repeater Matrix is money well spent. https://processwire.com/store/pro-fields/repeater-matrix/
  21. @Michael Mirula, this module is no longer being actively maintained by the author, but see @adrian's post above yours for a fix you can apply.
  22. I added support for automatic WebP to JPG conversion via the WebP To JPG module. To make use of this update to Add Image URLs v0.3.0 and install/update to WebP To JPG v0.2.0.
  23. The core InputfieldImage does not support webp format.
×
×
  • Create New...