_imagecache_apply_action(): Explicitly receive $image by ref?

Garrett Albright - November 4, 2009 - 23:45
Project:ImageCache
Version:6.x-2.0-beta10
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:needs review
Description

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:

<?php
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…

<?php
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

<?php
$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.

AttachmentSize
_imagecache_apply_action.patch446 bytes

#1

drewish - November 6, 2009 - 14:14

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

#2

Garrett Albright - November 6, 2009 - 16:30

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

<?php
$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.

#3

drewish - November 6, 2009 - 21:49

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

#4

drewish - November 6, 2009 - 21:50

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?

#5

Garrett Albright - November 6, 2009 - 23:52

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.

 
 

Drupal is a registered trademark of Dries Buytaert.