I’m on a plugin, where I want to provide a way to my clients to filter data before saving. I know the best way is to provide a filter hook. So I introduced a new filter hook to filter all the post data, including post data and post meta data.
But then I found that, there’s already a hook available for post data. So I realized that, it’s unnecessary to introduce another hook to filter post data.
Now I’m wondering is there any such hook available for post meta data? If so, then I won’t need to provide any new filter hook, I can direct my users to those filter hooks from the core.
I found an article by Igor Benic about metadata filter hook. I tried with the following code and some of its variances:
function wpse22728_meta($check, $object_id, $meta_key, $meta_value, $unique) {
if( get_post_type($object_id) == 'mycpt' ) {
if( $meta_key == 'mycustomkey' ) {
// var_dump($meta_value); //value going to store is: 'old_value'
return $meta_value="new_value";
}
}
}
add_filter('add_post_metadata', 'wpse22728_meta', 20, 5);
add_filter('update_post_metadata', 'wpse22728_meta', 20, 5);
But actually failed.
How can I filter meta data before storing them? Is there any other hook available?
The add_post_metadata
and update_post_metadata
filters are meant to allow filtering whether a specific meta data should be saved (added/updated) or not, only. The default value (of $check
) is a null
, and if you return anything other than exactly null
(i.e. !== null
), the meta data will not be saved (into the database).
However, the add_metadata()
function (used by add_post_meta()
) and the update_metadata()
function (used by update_post_meta()
), both use sanitize_meta()
for sanitizing the meta value (although sanitization are done via filters and not the function itself), and the Codex says:
Applies filters that can be hooked to perform specific sanitization
procedures for the particular metadata type and key. Does not sanitize
anything on its own. Custom filters must be hooked in to do the
work. The filter hook tag has the form
“sanitize_{$meta_type}_meta_{$meta_key}
“.
So in your case, the $meta_type
would be post
, and $meta_key
would be mycustomkey
, and you could filter the value like so:
add_filter( 'sanitize_post_meta_mycustomkey', function( $value ){
return 'new_value';
} );
Check also this example.
Drawback
Unfortunately, the sanitize_meta()
doesn’t pass the “object” (e.g. post or user) ID to the sanitization filters (i.e. functions hooked to sanitize_{$meta_type}_meta_{$meta_key}
).
There’s a way to overcome that, but it will depend on your code/context, so I can’t explain the “how”.
UPDATE
Actually, there’s a tricky (or hacky?) solution, which works fine with the add_post_metadata
and update_post_metadata
filters. But I’m not including the code here (yet), and you can find it on Pastebin.