Access post ID in “content_save_pre”

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.