I created an ImageCache action that, when run, replaces the image file it acts upon with an entirely new image. (Needless to say this is part of a rather epic kludge.) It looks kind of like this:

function pirets_fetch_image(&$image, $data) {
  // Replace the image…
  $image = imageapi_image_open($image->source);
  return TRUE;
}

…But it wasn't working. It kept behaving as if the original image were being passed on to the next action. I investigated ImageCache's code, and noticed that the signature for the function that actually finds and calls the action functions looks like…

function _imagecache_apply_action($action, $image) {
// Do stuff, and return a boolean.
}

Given this, I was stumped as to why ImageCache ever worked at all, given as how there doesn't seem to be any way that the modifications to the $image object are persistent. Then, after much confusion, I finally remembered PHP's bizarre handling of objects passed to functions, and how if they're not explicitly received by reference, they're received by reference anyway, but only kind of…

Anyway, by just adding a & before $image, as this patch does, my action worked as expected.

I then un-hacked my hack to ImageCache's code and instead worked around it in my code by doing

$new_img = imageapi_image_open($image->source);
$image->info = $new_img->info;
$image->resource = $new_img->resource;

…but this one-character patch would make such silliness unnecessary, as well as make it more explicit to others reading the code just what is going on.

CommentFileSizeAuthor
_imagecache_apply_action.patch446 bytesGarrett Albright

Comments

drewish’s picture

Odd because in PHP 5 objects should always be passed by reference...

Garrett Albright’s picture

…But not really. It doesn't hold up if we try to replace the object instead of merely changing it.

$foo = new stdClass();
$foo->bar = "baz";
change_it($foo);
var_dump($foo);
replace_it($foo);
var_dump($foo);


function change_it($foo) {
  $foo->qux = "quux";
}

function replace_it($foo) {
  $foo = new stdClass();
  $foo->drupal = "rules";
}

The execution:

TNL ~> php -f test.php
object(stdClass)#1 (2) {
  ["bar"]=>
  string(3) "baz"
  ["qux"]=>
  string(4) "quux"
}
object(stdClass)#1 (2) {
  ["bar"]=>
  string(3) "baz"
  ["qux"]=>
  string(4) "quux"
}

PHP is screwed up, yo.

drewish’s picture

Yeah well you really shouldn't be replacing it. Just modify it.

drewish’s picture

especially since i'm getting ready to remove a bunch of other byref's over on #623770: _imagecache_apply_action(): Explicitly receive $image by ref?

Garrett Albright’s picture

Yeah well you really shouldn't be replacing it. Just modify it.

Are you speaking of the variable, or the image itself? If the latter, as I said, this is part of an epic kludge, but it's also the most elegant, least redundant-code-writing way to pull this off I've been able to deduce thus far.

As for #4, you seem to have linked to this same thread.

fizk’s picture

Status: Needs review » Closed (fixed)