I’m trying to add a button (its function is beyond the scope of this question, suffice it to say that it needs the refund id as an argument) to each refund line in a WooCommerce order. I found that those lines are created in woocommerce\includes\admin\meta-boxes\views\html-order-refund.php which can’t be overridden. However there is an action:
do_action( 'woocommerce_admin_order_item_values', null, $refund, $refund->get_id() );
This seemed perfect for my purpose, so I tried adding the following code to functions.php to test if it could work:
add_filter('woocommerce_admin_order_item_values', 'test_refund_id');
function test_refund_id($nullvar, $refund, $refund_id) {
if ( !empty($refund->refunded_by) ){
echo '<td>Refund ID: '.$refund_id.'</td>';
}
}
I used if ( !empty($refund->refunded_by) )
because woocommerce_admin_order_item_values
also gets called in html-order-shipping.php, html-order-item.php and html-order-fee.php, with an “order item” object (instead of a “refund” object) as the second argument, so there’s no refunded_by
property and my instruction should be ignored.
Much to my disappointment, though, I get the following error:
Fatal error: Uncaught ArgumentCountError: Too few arguments to
function test_refund_id(), 1 passed in \wp-includes\class-wp-hook.php
on line 290 and exactly 3 expected in
\wp-content\themes\mytheme\functions.php:1087
I know that, as a matter of fact, three arguments are passed in the line I quoted above (namely a null, the refund object and the refund id), but I went and checked the script the error was referring to (\wp-includes\class-wp-hook.php) around line 290, and I found this in the apply_filters()
function:
// Avoid the array_slice if possible.
if ( $the_['accepted_args'] == 0 ) {
$value = call_user_func( $the_['function'] );
} elseif ( $the_['accepted_args'] >= $num_args ) {
$value = call_user_func_array( $the_['function'], $args );
} else {
$value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int) $the_['accepted_args'] ) );
}
Just for testing purposes I tried to temporarily change the last “else” clause, replacing the “sliced” arguments array with the original one, thereby forcing the script to keep all the arguments anyway, so array_slice( $args, 0, (int) $the_['accepted_args'] )
became simply $args
. Surprise, surprise, now everything works smoothly!
Now, I’m well aware that’s of course not a solution since I can’t edit a core WP script. I would just want to understand WHY apply_filters()
thinks that the accepted arguments are less than the passed ones and therefore it trims the argument array down to just the first one.
Thanks a lot in advance to anyone who’d like to shed some light on the matter.