After asking around and looking for alternatives, I came up with a working solution that works in the web frontend and in the Android/iOS XML-RPC based apps.
This is the filter.
add_filter('wp_insert_post_data', array($this, 'save_content2'), 9, 2);
I am pretty sure it is called before the content_save_pre
filter. It allows direct access to the post fields like the post content and the post metadata like the ID.
public function save_content2($data, $post) {
$content = $data['post_content'];
// short circuit if special ignore tag is included anywhere in content
if ( stripos($content, "<!--ignore-->") != false ) {
return $data;
}
if ( trim($content) == '' ) {
return $data;
}
$lines = explode("\n", $content);
if ( count($lines) == 0 ) {
return $data;
}
// added href handling so that HTML anchor-links can be handled
$regex = '/(?:href="https://wordpress.stackexchange.com/questions/158300/([^\s"]+))|((?:http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(?:\/\S*)?)/';
$match = preg_match($regex, $lines[0], $matches);
if ( $match ) {
$url = $matches[0];
$url = preg_replace('/&?utm_(.*?)\=[^&]+/im', '', $url);
if ( !isset($post) || !isset($post['ID']) || $post['ID'] == 0 ) {
return $data;
}
$result = $this->common_save($post['ID'], \LinkedList\Meta::SOURCE_URL, $url);
// prevent save fields from overwriting a blank on top of just added value
add_filter('linked_list_save_fields', function($bool){
return false;
});
set_post_format($post['ID'], 'link');
unset($lines[0]);
$data['post_content'] = join("\n", $lines);
return $data;
}
return $data;
}
What has changed: the arguments, now the data and some post metadata like the ID, both are available here cleanly. The return values have been swapped from $content
to $data
and when the first line is indeed altered, the result is saved back into the $data['post_content']
field and the entire array is returned.
While this works, any other suggestions are absolutely welcome.