I was creating my application to automate all of my blogs from my desktop.
Target, I’ll post blog. That’s all.
I used XMLRPC service, as you know “xmlrpc.php”.
I built many of parts, near to done… But stucked at custom fields which are starting with (_) an underscore.
I would like to save as “_thumbnail_id” => (int)number. Nothing happened.
But when I tried “thumbnail_id” or something like that without starting with underscore. It’s ok. Working well but start with underscore…
I need it for determine featured image of post. Without that tag; I couldn’t. And I don’t know alternatives.
I find this: https://wordpress.org/support/topic/how-can-i-change-protected-params-xmlrpc
But not solving my problem. I don’t want to change wordpress files. If I have to, I can write a small script without RPC.
Any help will be FANTASTIC!
2 Answers
Playing with XML-RPC and underscored custom fields:
Let’s say we want to set the featured image to a given post with $remote_post_id
.
We want it to be the attachment with ID equal to 300
, so we want _thumbnail_id
to be 300
.
Here are three methods how one could achieve that:
Method #1 – Using post_thumbnail
It’s possible to update/add the featured image with the post_thumbnail
parameter:
$result = $client->query(
'wp.editPost',
array(
$blog_id,
$username,
$password,
$remote_post_id,
$post_data = array(
'post_thumbnail' => '300',
),
)
);
as can be seen [here in the wp_xmlrpc_server
][1] class.
Method #2 – Using custom_fields
with meta_id
If we want to update a custom field of a post, we must know it’s database meta_id
value.
But how do we know the meta_id
?
The custom fields are actually included by default, when we fetch a post with:
$result = $client->query(
'wp.getPost',
array(
$blog_id,
$username,
$password,
$remote_post_id,
)
);
If the post has a featured post thumbnail, then the above result will contain this part:
<member>
<name>custom_fields</name>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>id</name>
<value>
<string>560</string>
</value>
</member>
<member>
<name>key</name>
<value>
<string>_thumbnail_id</string>
</value>
</member>
<member>
<name>value</name>
<value>
<string>200</string>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</member>
where the meta_id
is for example 560
and the old meta_value
is 200
.
Now we can update the meta value of _thumbnail_id
with our new value:
$result = $client->query(
'wp.editPost',
array(
$blog_id,
$username,
$password,
$remote_post_id,
$post_data = array(
'custom_fields' => array(
array(
'id' => '560',
'key' => '_thumbnail_id',
'value' => 300
)
),
),
)
);
Notice that if we skip the meta_id
part, we would only run add_post_meta()
, instead of the [update_metadata_by_mid()
][2] that was
introduced in this trac. We must also have the edit_post_meta capability.
But this is not the whole story, because meta keys that begin with underscore (_) are protected.
We can fix that by using the [register_meta()
][3] function on the remote site.
For example:
/**
* Unprotect the _thumbnail_id meta key to allow updates via XML-RPC
* We need to set this up on the remote site.
*/
add_action( 'init', function() {
register_meta( 'post', '_thumbnail_id', 'absint', '__return_true' );
});
to unprotect the _thumbnail_id
meta key. I first tried the intval
as a sanitization callback but that didn’t work.
We could use a similar setup for other protected meta keys.
Method #3 Using a custom XML-RPC method.
As @MarkKaplun mentioned in his answer, we could extend the XML-RPC setup to our needs. We could for example use the xmlrpc_methods
filter to add our own method.
The Codex provides more information on that matter.
References:
Here are some links that helped me while testing this:
-
https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-xmlrpc-server.php
-
XML RPC @Codex
-
Trac ticket #17850 @wp.org
-
update_metadata_by_mid()
-
Automattics “syndication” repo @GitHub:
class-syndication-wp-xmlrpc-client.php
-
Content Type Standards @GitHub (props @kaiser) – and more specifically this issue, which explains the use case for
register_meta()
a bit more in detail, in the same repo.