Start with the Underscores apply_filters() call:
return apply_filters( 'theme_options_validate', $output, $input );
This says:
- The filter name is
theme_options_validate
- The filter is applied to the
$output content
- The
$input content passed into the validation function can also be passed on to a callback
So, here's how it works:
- WordPress passes
$input, which basically contains the $_POST data from the settings form, to the validation callback.
- The validation callback manipulates
$input, to sanitize/validate it
- The validation callback stores the manipulated results of
$input as $output
- The validation callback passes
$output through the theme_options_validate filter
- The validation callback returns the filtered result of
$output
So, when you write a callback to apply to the theme_options_validate filter, that callback receives and should return $output. That is: you're returning your manipulation of the already manipulated data:
function example_filter_theme_options_validate( $output ) {
// Do stuff to $output
// return $output
return $output;
}
add_filter( 'theme_options_validate', 'example_filter_theme_options_validate' );
That's great, if you want to make a change to the already manipulated data; but if you want to add data, you can't do that using only $output. For example, if you've added a Theme option via Child Theme, that option won't survive the default validation callback, because that option won't have been whitelisted in the callback. That option will be in $input, but it won't be in $output.
In steps the additional option in the apply_filters() call:
return apply_filters( 'theme_options_validate', $output, $input );
By adding $input as an additional parameter, Underscores is helpfully passing $input to any callback that wants to use it. So, instead of this:
function example_filter_theme_options_validate( $output ) {
// Do stuff;
// return $output
return $output;
}
Your function declaration will look like this:
function example_filter_theme_options_validate( $output, $input ) {
// Do stuff;
// return $output
return $output;
}
Now, your function has access to both $output and $input, and you can then manipulate your custom Theme option from $input, and then add it to $output, thereby whitelisting it.
Note that it is imperative to specify the number of parameters in your callback, by modifying your add_filter() call:
add_filter( $filter, $callback, $priority, $parameters );
Since you're now passing two variables, you have to set $parameters to 2 (the default is 1):
add_filter( 'theme_options_validate', 'example_filter_theme_options_validate', 10, 2 );
Putting it all together:
// this works
function add_validation( $output, $input ) {
if ( isset( $input['example'] ) && !empty( $input['example'] ) )
$output['example'] = wp_filter_nohtml_kses( $input['example'] );
return $output;
}
add_filter( 'theme_options_validate', 'add_validation', 10, 2 );