0

I'm trying to apply a filter, but I get a callback error and I'm not sure why. I think it might have to do with the fact that the filter I'm using includes a $this because I extracted the function from a plugin, and the extracted function was originally wrapped inside a class.

This is the error:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /wp-includes/class-wp-hook.php on line 298

Based on @toscho's answer here, I think the callback error might be related to the $this but can't quite figure it out how to apply the logic to this filter.

This is my hook and function in my functions.php file.

 add_filter( 'wp_get_attachment_image_src', array( $this, 'fix_wp_get_attachment_image_svg' ), 10, 4 );  /* the hook */

     function fix_wp_get_attachment_image_svg($image, $attachment_id, $size, $icon) {
        if (is_array($image) && preg_match('/\.svg$/i', $image[0]) && $image[1] == 1) {
            if(is_array($size)) {
                $image[1] = $size[0];
                $image[2] = $size[1];
            } elseif(($xml = simplexml_load_file($image[0])) !== false) {
                $attr = $xml->attributes();
                $viewbox = explode(' ', $attr->viewBox);
                $image[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
                $image[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
            } else {
                $image[1] = $image[2] = null;
            }
        }
        return $image;
    }

Is the $this to blame and is there an instance method approach i can apply to get this working? If there is, I would love to see an example of how to fix the code.

Thanks!

4
  • 3
    Replace array( $this, 'fix_wp_get_attachment_image_svg' ) with 'fix_wp_get_attachment_image_svg' Feb 7 '17 at 20:15
  • I like $this and I use it only when in a class. You should do as Nathan suggested, since you already copied that method into a global function.
    – Ismail
    Feb 7 '17 at 20:58
  • @NathanJohnson that's the answer, the error is gone! Do you want to submit it below to get the rep? Feb 7 '17 at 22:45
  • @coderscissorhands I'm writing up a response now Feb 7 '17 at 23:57
4

Problem

The issue is that WordPress uses call_user_func() or call_user_func_array() to allow plugin/theme developers to add callables to hooks. Callables, or callback functions, can be simple functions, object methods, or static class methods. We need to format the callable as either a string or array depending on the type of callback we want.

Simple Functions

Creating a callable to a simple function is nothing more than a string to a function, e.g. 'my_callable_function'. This will attempt a call to the globally namespaced function my_callable_function(). It's also possible to add a namespaced function - '\MyNamespace\my_callable_function' - which will call the my_callable_function() function located in the MyNamespace namespace. See the PHP documentation for more information on namespaces.

Object Methods

The pseudo-variable $this is available when a method is called from within an object context. See OOP basics. If you're not familiar with object-oriented programming, $this basically refers to the class when you're already "inside" the class. If you want to call a method of a class as a callback, we can use this in our callable callback. In this case, the callback needs to be an array with the first index being the object and the second index being the method. [ $this, 'MyMethod' ] is a valid callback (as long as the MyMethod method exists).

We can also use any object as a callable, not just the current one. In that case, we could use [ new MyObject(), 'MyMethod' ]. This would first create the MyObject object, and then use the MyMethod method as the callable.

Static Class Methods

Further, we can use static class methods in the callable. [ 'MyClass', 'MyMethod' ] would attempt to statically call the MyMethod method in MyClass.

Solution

What does this means in this particular case?

When I look at the code provided, we see that the original callable is array( $this, 'fix_wp_get_attachment_image_svg' ). For this to work, we need to be 'inside' a class already and referencing a method in the same class that we want to call. Instead, we see that fix_wp_get_attachment_image_svg() is a function in the global namespace, and thus the callable is the string of the named function.

Therefore, the solution is to fix the callable, so that it points to the correct function. In this case:

 add_filter( 'wp_get_attachment_image_src', 'fix_wp_get_attachment_image_svg', 10, 4 );
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.