Try this:
add_action('init', 'replace_title_logic');
function replace_title_logic() {
add_filter('wp_insert_post_data', 'replace_title_before_update', 20, 2);
add_action('wp_insert_post', 'replace_title_after_save', 20, 2);
add_filter('wp_insert_post_empty_content', 'allow_empty_content_for_listing', 20 , 2);
}
function replace_title_before_update( $data, $postarr ) {
if ( is_int($postarr['ID']) && ($data['post_type'] == 'listing') ) {
$custom = get_post_meta($postarr['ID'], 'ref._nr.', true );
if ( $custom && ( $custom != $data['post_title'] ) ) $data['post_title'] = $custom;
}
return $data;
}
function replace_title_after_save( $post_ID, $post ) {
if ( $post->post_type != 'listing' ) return;
$custom = get_post_meta($post_ID, 'ref._nr.', true );
if ( $custom && ( $custom != $post->post_title ) && $post->post_status != 'trash') {
remove_action('wp_insert_post', 'replace_title_after_save', 20, 2);
remove_filter('wp_insert_post_data', 'replace_title_before_update', 20, 2);
$postarr = ( array('ID' => $post_ID, 'post_title' => $custom) );
wp_insert_post($postarr);
}
}
function allow_empty_content_for_listing( $maybe_empty, $postarr ) {
if ( $postarr['post_type'] == 'listing' ) return false;
}