Jump to content

snck

Members
  • Posts

    78
  • Joined

  • Last visited

Posts posted by snck

  1. +1 for uptime-kuma. Setup as a docker container is really straightforward. I have it running on a Synology NAS and use Pushover for push notifications to my iPhone. The only downside is getting data out of uptime-kuma. It stores everything in a sqlite db and you have to get that out of your docker container and use some other tool to generate CSVs for example. Possible, of course, but not as easy as the UI of the frontend might suggest. 😉

    • Like 1
  2. Hey @teppo, I occasionally noticed some PHP Warnings when editing pages that use repeaters:

    PHP Warning: Attempt to read property "type" on null in .../modules/VersionControl/ProcessVersionControl.module:668

    Could be changed to the following to suppress the warning:

    // before
    if ($diff && wire('fields')->get($field)->type instanceof FieldtypeFile) $diff = "";
    
    // after
    if ($diff && wire('fields')->get($field) !== null && wire('fields')->get($field)->type instanceof FieldtypeFile) $diff = "";

    Maybe something that could be addressed in a future release?

  3. This seems to be a bug in the core that is still present in the current release (3.0.229, main branch) and has to do with the query generation for the next page. For superusers there is no problem because of PageFinder.php:2230 (getQueryAllowedTemplates()), superuser just skips the checks for allowed templates in the query completely:

    16093559_Bildschirmfoto2024-03-25um15_03_44.thumb.png.7ee6741d92f3f824110f85a62f10bd5d.png

    Comparing the database queries for the superusers with the one for other (logged in) users showed the error in the query.

    Query for superuser: 

    1819387920_Bildschirmfoto2024-03-25um13_18_08.thumb.png.c32b805dceaaf2023207ffde0a472db9.png

    Query for other (logged in) user:

    611641267_Bildschirmfoto2024-03-25um12_28_36.thumb.png.e06e51073d70fc74515227e6df730224.png

    It is quite obvious that there is an error in the SQL syntax. 

    The problem has to do with the number of templates that a user is allowed to edit. In this case, the user (editor, no superuser) is allowed to edit all templates (inheriting page-edit permissions from the homepage). As soon as I add a template that no user is allowed to even view, the „Save + Next“ action is working as expected and—obviously—the query changes and everything is working:

     304263044_Bildschirmfoto2024-03-25um15_18_49.thumb.png.0680a04f843dd4334d42e0df305f663a.png

    Query for editor after adding a template that nobody (except superusers) can access:

    507653477_Bildschirmfoto2024-03-25um15_22_55.thumb.png.5acdb9191169aef8f2bb956ee64b7a47.png

    Maybe @ryan can have a look and dig a little deeper? This might be an edge case that almost never happens (because in most cases template access might be restricted for every role to some extend) and adding a template without access is a workaround, but it would be cool to have it fixed nonetheless.

    Cheers
    Flo

  4. Hey @bernhard, I have used AdminStyleRock multiple times and also really liked being able to adapt it to a client's corporate design in no time. I am (as usual) really busy at the moment, but willing to at least give some input (if you want me to).

    The main problems I see with AdminStyleRock are the ones that I also have with the standard AdminThemeUikit. Many of my clients have complex forms in the backend and while the general theme is simple and quite minimalistic, UI elements take a lot of space, editors have to scroll a lot and that is something that makes up for a bad user experience. A good backend should feel like a tool that supports you in doing your job as efficient as possible. For me and a lot of clients AdminThemeUikit never felt this way, the Default theme, however, feels outdated. AdminThemeUikit might be fine for a simple blog page or forms that consist of only a few fields, but for more complex things I still prefer the default theme.

    I would love to have more configuration options in AdminStyleRock that make it easy to not only adjust colors and maybe how shades are calculated (could be nice to have, if you want to adjust contrast or the general feel of the style to an existing corporate design without overcomplicating things), but also be able to adjust margins and paddings (or choose between 2 or 3 optimized and battle-tested variations) to be able to create a more compact/dense/tool-like experience.

    I hope, that makes sense?

    If there is no pressure involved in the development and sporadic feedback is appreciated, I'd be happy to help. I should be able to join in on Friday, but me and my family are struggling with Covid at the moment, so don't be mad if I have to cancel it last minute.

    Flo

    • Like 1
  5. @da² Thanks for your input!

    Regarding save vs. saved:

    Quote

    This is the same as hooking after Pages::save, except that it occurs before other save-related hooks. Whereas Pages::save hooks occur after. In most cases, the distinction does not matter. (https://processwire.com/api/ref/pages/saved/)

    This is why I chose save, but both should work.

    I was aware of the 'noHooks' option, but thinking it would prevent the page updating after the rename action. 

    I finally found a solution that serves all my needs and works well so far. I outsourced the renaming part to a function:

    function renameApplicationEntryFiles($page){
      if($page->parent->template->name == "application_entries"){
        // only do this for application entries
        $fileFields = $page->fields->find('type=FieldtypeFile');
        $page->of(false);
        $renamedFiles = false;
        foreach($fileFields as $fileField){
          $fieldname = $fileField->name;
          $pagefiles = $page->get($fieldname);
          $index = 1;
          foreach($pagefiles as $pagefile){
            $newFilename = $fieldname;
            // if there are multiple files, add index to filename
            if(count($pagefiles) > 1){
              $newFilename .= "-".$index;
              $index++;
            } 
            $newFilename .= '.'.$pagefile->ext;
            // only rename if filename is not already set
            if($pagefile->basename() != $newFilename){
              $page->get($fieldname)->trackChange('basename');
              bd("renamed: ".$pagefile->basename()." -> ".$newFilename);
              $pagefile->rename($newFilename);
              $pagefile->save();
              $renamedFiles = true;
            } 
          }
        }
        if($renamedFiles === true){
          $page->save(['noHooks' => true]);
          return true;
        }
      } else {
        return false;
      }
    }

    This function gets called on save and through the conditional Pagefile::install hook which covers all of the cases I need to cover:

    $this->wire->addHookAfter("Pages::save(template^=application_entry)", function(HookEvent $event) {
      $page = $event->arguments(0);
      $fileFields = $page->fields->find('type=FieldtypeFile');
      $empty_pagefiles = false;
      foreach($fileFields as $fileField){
        $fieldname = $fileField->name;
        $pagefiles = $page->get($fieldname);
        if($pagefiles->count == 0){
          $empty_pagefiles = true;
        } 
      }
      if($empty_pagefiles === true){
        $event->addHookAfter('Pagefile::install', function(HookEvent $event) use($page) {
          renameApplicationEntryFiles($page);
          $event->removeHook(null);
        });
      } else {
        renameApplicationEntryFiles($page);
      }
    });

    Maybe this journey can be useful for someone, I had a hard time finding forum threads dealing with hooks related to Pagefiles. And of course I am still open for suggestions on how to optimise my solution. 🙂

  6. @poljpocket Thanks! Wanted to delete that (stupid) post, but since you referenced it, I'll leave it where it is. 😉

    My problem with saveReady is that this only works for pages (and files) that have been saved before (so files are already present). I think I got a lot closer to what I want to achieve with this:

    $this->wire->addHookAfter("Pages::save(template^=application_entry)", function(HookEvent $event) {
    
      $page = $event->arguments(0);
    
      if($page->savedByThisHook) return;
    
      bd("save hook triggered");
    
      // get all fields of fieldtype file
      $fileFields = $page->fields->find('type=FieldtypeFile');
      // bd($fileFields);
        
      $page->of(false);
      $empty_pagefiles = false;
      $renamedFiles = false;
    
      // loop through all file fields
      foreach($fileFields as $fileField){
    
        $fieldname = $fileField->name;
        $pagefiles = $page->get($fieldname);
        $index = 1;
    
        // bd($pagefiles);
    
        if($pagefiles->count == 0){
          $empty_pagefiles = true;
        } else {
          foreach($pagefiles as $pagefile){
            $newFilename = $fieldname;
            // if there are multiple files, add index to filename
            if(count($pagefiles) > 1){
              $newFilename .= "-".$index;
              $index++;
            } 
            $newFilename .= '.'.$pagefile->ext;
      
            // only rename if filename is not already set
            if($pagefile->basename() != $newFilename){
              $page->get($fieldname)->trackChange('basename');
              bd("renamed: ".$pagefile->basename()." -> ".$newFilename);
              $pagefile->rename($newFilename);
              $pagefile->save();
              $renamedFiles = true;
            } else {
              bd("not renamed: ".$pagefile->basename()." -> ".$newFilename);
            }
          }
        }
      }
    
      if($empty_pagefiles === true){
        // $pagefiles still empty, not yet installed?
        // add hook!
        $event->addHookAfter('Pagefile::install', function(HookEvent $event) use($page) {
          // trigger page save again to rename files
          bd("conditional hook triggered, installed file". $event->arguments(0));
          bd("is_file: ".is_file($event->arguments(0)));
          $page->savedByThisHook = false;
          $page->save();
          $event->removeHook(null);
        });
      }
    
      if($renamedFiles === true){
        $page->savedByThisHook = true; // prevent infinite loop
        $page->save();
      }
    });

    The key to finally having the database reflect the filename changes was 

    $page->get($fieldname)->trackChange('basename');

    This works fine for pages that have been saved before, but I can only rename files that are already present in the filesystem, which seems to happen while/after save() has been called. Is there any method I did not find (maybe it's too late) that I can use elegantly that fires when alle pagefiles are already present?

    My strategy was to add another conditional hook when I recognize a $pagefiles->count of 0 after Pagefile::install, save the page again (and in consequence trigger the renaming process). This works almost the way it should, because it triggers the renaming for 2 of 3 files, but the 3rd will never be triggered automatically (without saving the page manually again). This is what happens:

    878684391_Bildschirmfoto2023-12-20um02_50_19.thumb.png.90d7fd5a8c5b1d86934f42d266ca0ee0.png

    Although this does not look as elegant (and short) as I thought it could, it does almost what I want. As I feel very close, I'd be really thankful for help. Maybe there is a completely different approach to this problem? Or maybe just small changes that make it work the way I want?

  7. @ryan  Today I made another observation. I used the rename() method on the Pagefiles object and got a fatal error:

    $this->wire->addHookAfter("Pages::saved(template^=application_entry)", function(HookEvent $event) {
    
      $page = $event->arguments(0);
    
      // get all fields of fieldtype file
      $fileFields = $page->fields->find('type=FieldtypeFile');
    
      $page->of(false);
    
      // loop through all file fields
      foreach($fileFields as $field){
    
        $fieldname = $field->name;
        $field = $page->get($field->name);
        $index = 1;
    
        foreach($field as $item){
    
          $newFilename = $fieldname;
          // if there are multiple files, add index to filename
          if(count($field) > 1){
            $newFilename .= "-".$index;
            $index++;
          } 
          $newFilename .= '.'.$item->ext;
    
          bd($item->basename()." -> ".$newFilename);
          // only rename if filename is not already set
          if($item->basename() != $newFilename){
            // $item->rename($newFilename); 
            $field->rename($item, $newFilename);
          }
        }
      }
      $page->save();
    });

    1395427881_Bildschirmfoto2023-12-19um23_35_56.thumb.png.eed3df7b5ba1da08d7cd7931e7fff8af.png

    1024 MiB exhausted?

  8. I am using FormBuilder to collect data and save it to pages. The forms (and the page templates used) use file fields to collect PDF files. The uploaded files should automatically be renamed to match the name of the fields. This should happen every time a page is saved. The first time after the form is saved to the page, but also on every other page save, because editors could have added or exchanged some of the files and then they should be renamed again.

    I tried to solve this in different ways, but nothing really worked as expected. What I tried:

    $this->wire->addHookBefore("Pages::saveReady(template^=application_entry)", function(HookEvent $event) {
    
      $page = $event->arguments(0);
    
      // get all fields of fieldtype file
      $fileFields = $page->fields->find('type=FieldtypeFile');
    
      // loop through all file fields
      foreach($fileFields as $field){
    
        $fieldname = $field->name;
        $field = $page->get($field->name);
        $index = 1;
    
        foreach($field as $item){
    
          $newFilename = $fieldname;
          // if there are multiple files, add index to filename
          if(count($field) > 1){
            $newFilename .= "-".$index;
            $index++;
          } 
          $newFilename .= '.'.$item->ext;
          // bd($item->basename()." -> ".$newFilename);
          // only rename if filename is not already set
          if($item->basename() != $newFilename){
            $item->rename($newFilename);
          }
        }
      }
      $event->arguments(0, $page);
    });

    When I save an existing page, the files are renamed, but I get the following error message and the filename change is not reflected in the database:

    Quote

    WireFileTools: rename: Given pathname ($oldName) that does not exist: /var/www/html/site/assets/files/-8176/original_filename.pdf

    If the page has not existed before save (got created by FormBuilder) I get a message that it was created, but it does not get created and FormBuilder shows a Not yet created in the entries list.

    Another approach was this: 

    $this->wire->addHookAfter("Pages::saved(template^=application_entry)", function(HookEvent $event) {
    
      $page = $event->arguments(0);
    
      // get all fields of fieldtype file
      $fileFields = $page->fields->find('type=FieldtypeFile');
    
      $page->of(false);
    
      // loop through all file fields
      foreach($fileFields as $field){
    
        $fieldname = $field->name;
        $field = $page->get($field->name);
        $index = 1;
    
        foreach($field as $item){
    
          $newFilename = $fieldname;
          // if there are multiple files, add index to filename
          if(count($field) > 1){
            $newFilename .= "-".$index;
            $index++;
          } 
          $newFilename .= '.'.$item->ext;
    
          bd($item->basename()." -> ".$newFilename);
          // only rename if filename is not already set
          if($item->basename() != $newFilename){
            $item->rename($newFilename);
            $page->save();
          }
        }
      }
    });

    This also renames the file on save, but the filename in the field is still the old name. I am using pagefileSecure on this template (if that matters).

    Any help his highly appreciated!

    Thanks in advance,
    Flo

  9. Hey @Juergen,

    today I ran into a really strange issue and it took me a while to track it down. I use FormBuilder and automatically save entries to PW pages. I had the issue that although I selected to save to published pages (in FormBuilder config for the form) my pages always had the unpublished status. I wanted to blame FormBuilder first, but then I noticed that there was a hook in JKPublishPages on page save:

    /**
    * Set page status to unpublished or remove unpublished status depending on if date range is out of date or not
    * This runs on manual save
    * @param HookEvent $event
    * @return void
    */
    protected function setPageStatusManually(HookEvent $event): void
    {
        $page = $event->arguments(0);
    
        $from = true;
        if ($page->jk_publish_from) {
            $from = $page->jk_publish_from < time();
        } else {
            $page->jk_publish_from = time();
        }
    
        $to = true;
        if ($page->jk_publish_until) {
            $to = ($page->jk_publish_until > time());
        }
    
        if (!$from || !$to) {
            $page->addStatus(Page::statusUnpublished);
        }
    }

    Shouldn't this contain a check so it only applies to the templates selected in JKPublicPages' module settings? 

    In my case it sets pages that have no jk_publish_from and jk_publish_to fields to unpublished. When I comment out $page->addStatus(Page::statusUnpublished); or deactivate your module everything works as expected.

    Could you please check that and provide a fix? I guess this causes issues for others as well when creating pages from the API.

    Cheers,
    Flo

    • Like 1
  10. I had a problem with PHP 8.1.8 an saving pages containing the field. I got this error:

    Quote

    Fatal Error: Uncaught TypeError: round(): Argument #1 ($num) must be of type int|float, string given in site/modules/FieldtypeMapMarker/InputfieldLeafletMapMarker.module:193

    I changed lines 193 and 194 to make sure all values that get rounded are floats:

     if( ((string) round(floatval($lat), $precision)) != ((string) round(floatval($this->defaultLat), $precision)) ||
         ((string) round(floatval($lng), $precision)) != ((string) round(floatval($this->defaultLng), $precision))) {

    Maybe this could be included in a future version?

    Cheers,
    Flo

    • Like 2
  11. I stumbled upon a thing that might be a bug. I want to embed this podcast player:

    <script class="podigee-podcast-player" data-src="https://player.podigee-cdn.net/podcast-player/javascripts/podigee-podcast-player.js" data-configuration="..."></script>

    I am using the following code:

    <script type="text/plain" data-type="text/javascript" class="podigee-podcast-player" data-ask-consent="1" data-category="external_media" data-src="https://player.podigee-cdn.net/podcast-player/javascripts/podigee-podcast-player.js" data-configuration="..."></script>

    The placeholder is appearing just fine, but when the user accepted the cookie, I only get this:

    <script data-configuration="..." type="text/javascript" src="https://player.podigee-cdn.net/podcast-player/javascripts/podigee-podcast-player.js" async=""></script>

    The class attribute (class="podigee-podcast-player") is getting removed and therefore the player will not load. I guess that this is not the intended behavior?

    Cheers,
    Flo

    • Like 1
  12. On 6/29/2023 at 11:04 PM, nbcommunication said:

    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.

    Hi @nbcommunication, thanks for the quick reponse! Unfortunately the update did not solve my problem. You are right regarding the markup string, but that has nothing to do with my problem (source tags output fallback to original image instead of (upscaled) version with correct aspect ratio). I will scale the image before calling render, but if you find a solution or come up with an update, I am happy to try it again.

    Cheers,
    Flo

  13. 9 hours ago, nbcommunication said:

    What would you expect the markup to be in this case?

    I would expect it to contain only images with the exact dimensions I specified, like this:

    <picture>
      <source srcset="FILENAME.800x400-srcset.webp 800w, FILENAME.1600x800-srcset.webp 1600w" sizes="(max-width: 900px) 100vw,
        ((min-width: 901px) and (max-width: 1200px)) 67vw,
        ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/webp">
      <source srcset="FILENAME.800x400-srcset.jpg 800w, FILENAME.1600x800-srcset.jpg 1600w" sizes="(max-width: 900px) 100vw,
        ((min-width: 901px) and (max-width: 1200px)) 67vw,
        ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/jpeg">
      <img src="FILENAME.800x400.jpg" alt="..." class="hero-img" width="800" height="400" loading="lazy">
    </picture>

    Instead of the 1600x800 variants I get the original image URL again. Disabling upscaling does not change it. Of course I could resize the image before rendering as in your example, but shouldn't it be possible to pass an array for the srcset and get exactly the values you specified? This is a fix of course, but feels more like a hack than a solution.

    Cheers,
    Flo

  14. On 6/22/2023 at 12:48 AM, snck said:

    Hi @nbcommunication,

    thanks for the quick reaction! The update fixed it for me. 👍

    Cheers,
    Flo

    @nbcommunication  I have to correct: The update fixed it in one specific case. I still have the problem in another place:

    $img->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='".$img->size(800, 400)->url."' alt='{alt}' class='{class}' width='".$img->size(800, 400)->width."' height='".$img->size(800, 400)->height."'>",
    	]
    )

    leads to this markup:

    <picture>
      <source srcset="FILENAME.800x400-srcset.webp 800w, FILENAME.webp 1600w" sizes="(max-width: 900px) 100vw,
        ((min-width: 901px) and (max-width: 1200px)) 67vw,
        ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/webp">
      <source srcset="FILENAME.800x400-srcset.jpg 800w, FILENAME.jpg 1600w" sizes="(max-width: 900px) 100vw,
        ((min-width: 901px) and (max-width: 1200px)) 67vw,
        ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/jpeg">
      <img src="FILENAME.800x400.jpg" alt="..." class="hero-img" width="800" height="400" loading="lazy">
    </picture>

    The intrinsic dimensions of the image are 1080x721.

    I am really curious why the update worked in one place and not in the other. Do you need more information to investigate?

  15. Hey @nbcommunication, I have a strange problem here. I am using the following code:

    $img->render([
    		'picture' => true,
    		'srcset' => [
    		'rules' => ['800x267', '1600x534'],
    		'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' => $img_class,
    	'alt' => $alt,
    	'markup' => "<img src='".$img->size($img_tag_width, $img_tag_height)->url."' alt='{alt}' class='{class}' width='".$img->size($img_tag_width, $img_tag_height)->width."' height='".$img->size($img_tag_width, $img_tag_height)->height."'>",
    ]);

    My image has a width of 1600px, but a different aspect ratio (original dimensions: 1600 x 1093). I am expecting to get two variations rendered ('800x267', '1600x534'), but instead of a scaled/cropped 1600px wide version, I get the original image, which is bad, because it has the wrong aspect ratio. How can I force PageimageSource to generate the variation with the correct dimensions?

    Thank you in advance!

  16. Thanks, @teppo🙂

    I am facing a different problem now. I have a site in debug mode and was not able to upload images realiably since installing SearchEngine. I found out that the JSON response of the server for the image upload returned a PHP error related to the Indexer:

    Quote

    Warning:  foreach() argument must be of type array|object, null given in /site/modules/SearchEngine/lib/Indexer.php on line 315

    I am using a RepeaterMatrix field on the page (and Repeaters nested in RepeaterMatrix fields on other pages).

    Do you have a solution for this problem? Obviously disabling debug mode is a temporary fix, but not ideal.

  17. I am using RockMigrations for a while now (and am honestly in love with it!) and just recently ran into a problem that I had not encountered before. I am using the deployment features and a setup that automatically deploys the two (dev and main) branches in my Github repo to different locations. This works perfectly fine most of the time, however last time PHP ran out of memory and I did not notice it, because the job was marked as successful in Github actions. Running out of memory led to the current symlink not getting generated and the website being not accessible (without me noticing it).

    @bernhard and I already had a chat about it, but we were wondering whether you guys had ideas or suggestions on how to deal with errors and warnings during the deployment process and appreciate your input.

    ac97a62a-2376-49c9-8bde-35a45eb44c98.jpg

    • Like 2
  18. From my understanding is_nan(null) === false (in prior PHP versions). To fix lines 247 and 248 something like the following should do the trick:

    if($c2 !== null && is_nan($c2)) $e3 = $e4 = 64;
    else if($c3 !== null && is_nan($c3)) $e4 = 64;

    At least for me this stops the deprecation warning from appearing and keeps the functionality.

    • Like 1
  19. 2 hours ago, BrendonKoz said:

    Relevancy is not (necessasrily/typically) the same as number of matches (per matched database record). For anything outside of MySQL's default capabilities, something external would likely need to be integrated, such as Apache Lucene or ElasticSearch.

    Thanks for your reply! You're right that the number of matches is not necessarily an indicator for relevancy. As I stumbled over the quoted question I was just curious whether there was a selector or option that would allow me to quickly try it out because I have a project that could benefit from it. SearchEngine is a great module nonetheless. 🙂

    • Like 1
×
×
  • Create New...