Since php is not threaded, how does this happen?

general code question:
i just coded a snippet for generating a coverimage für the lingonberry template., based on a special watermark.

code:

<?php
// define default-image filename
$defaultimagefilename = 'traildefault.jpg';
// define gpx file object from panel-field
$gpxfile = $item->mapgpx()->toFile();
// check if gpx.map.png (overlay) file exists, if so, go on, if not, generate it via bash script
($gpxfile->root() . '.map.png') ?: NULL; // replace "NULL" with bash script
// check if mapcoverimage-field is set, if so, set it in variable $image as object, if not, set defaultimage in variable $image as object
($image = $item->mapcoverimage()->toFile()) ?: $image = page('defaultimages')->image($defaultimagefilename);
// check if image is watermarked - if not, check if watermarked version of $image exists in $pagefolder, if so, use it, if not, generate watermarked version and set this in variable $image as object
(substr($image->root(), -16) == '.watermarked.jpg') ?: ( ($page->image($image->filename() . '.watermarked.jpg')) ?: watermark($image, url($gpxfile->url() . ".map.png"), $page->root()) AND $image = $page->image($image->filename() . '.watermarked.jpg') );

function watermark($baseIMG, $overlayPNG, $outputPATH) {
    $img = new abeautifulsite\SimpleImage($baseIMG->root());
    $img = $img->overlay($overlayPNG, 'bottom right', 1, -10, -10);
    $img->save($outputPATH . '/' . $baseIMG->filename()  . '.watermarked.jpg');
    }

// notes: eventuell dateinamen der watermarked dateien inkl. gpx datei. damit unterschiedliche maps pro coverimage gehen könnten

?>

<div class="featured-media">
  <a href="<?= $item->url() ?>">
    <img src="<?= $image->resize(766, null, 85)->url() ?>" rel="bookmark" title="<?= $item->title()->html() ?>"<?php e($image->alt()->isNotEmpty(), ' alt="' . $image->alt()->html() . '"') ?>>
    <?php if($image->caption()->isNotEmpty()) : ?>
    <div class="media-caption-container">
      <p class="media-caption">
        <?= $image->caption()->html() ?>
      </p>
    </div>
    <?php endif ?>
  </a>
</div>

Problem/question:
when i open page in browser the first time (and no corresponding watermarked image is insite page folder) the watermarked image will be generated (i checked at filesystem) but not shown, instead the un-watermarked image is shown.
When i reload page in browser, the watermarked version is shown.

i don’t understand why this happens. as far as i know, php is single-threaded/batched. so every command should start AFTER the other. so, generating the watermarked image has to be finished, before the php script goes on. but the script does not wait for this to finish.

how does this happen?
how to solve?

thx in advance

ok… it seems to be a logic-issue of the code.
i tried to insert a sleep(5) after $img->save() and the result is the same. at first time, the not-watermarked image is shown.
:thinking:

Honestly, I think you are trying to put too much logic into that one line. Might be that I’m missing something here, but I don’t see how the AND statement fits in here. I think your function should return something you can then assign to your $image variable.

as far as i understand, the AND statement is for multiple statements in a ternary statement. but i now try to solve this with “simple” if-then/else…

ok… i still can’t see where the fault in my code is…
i tried:

if(!$page->image($image->filename() . '.watermarked.jpg')) {
      watermark($image, url($gpxfile->url() . ".map.png"), $page->root()) ;
      sleep(5);
      echo $page->image($image->filename() . '.watermarked.jpg')->root();
}

function watermark($baseIMG, $overlayPNG, $outputPATH) {
     $img = new abeautifulsite\SimpleImage($baseIMG->root());
     $img = $img->overlay($overlayPNG, 'bottom right', 1, -10, -10);
     $img->save($outputPATH . '/' . $baseIMG->filename()  . '.watermarked.jpg');
    }

i always get an error Call to a member function root() on null on the first run. and no error on the second run.
the file is generated by the watermark function, then the script sleeps. (i checked, the file exists during the sleep).

the if-clause looks if file does exist, generates it, when it does not exist, and then tries to echo the path to the new generated file. but it fails on the echo.

i’m realy confused.

ok… i think i got it…

the $page object is loaded at start. and at start the file does not exist.
the script does not update the $page-object. so accessing data of the $page-object is not up-to-date, after generating a file.

any idea/solution on generating an image-object on a file that is generated after page-object is initialised?

updating page-object?
auto-reload page?
anything else?

Create a new File object after calling the watermark method:

$image = new File($page->files(), $image->name().'.watermarked.jpg') ;
1 Like

You are my hero!
this drove me crazy since two days… the final code seems to work now:

if(substr($image->root(), -16) != '.watermarked.jpg') {
    if(!$page->image($image->filename() . '.watermarked.jpg')) {
      watermark($image, url($gpxfile->url() . ".map.png"), $page->root()) ;
      }
    $image = new File($page->files(), $image->filename().'.watermarked.jpg');
}

this will also help on calling an external bash script in the next step… but not tonight =)