tmg =& $iclTranslationManagement;
$this->xliff_reader_factory = new WPML_TM_Xliff_Reader_Factory( $this->job_factory );
$wpml_tm_records = new WPML_TM_Records( $wpdb, $wpml_post_translations, $wpml_term_translations );
$this->cms_id_helper = new WPML_TM_CMS_ID( $wpml_tm_records, $job_factory );
$this->sitepress = $sitepress;
add_filter( 'xmlrpc_methods', array( $this, 'custom_xmlrpc_methods' ) );
add_action(
'post_submitbox_start',
array(
$this,
'post_submitbox_start',
)
);
add_action(
'icl_ajx_custom_call',
array(
$this,
'ajax_calls',
),
10,
2
);
add_action( 'wpml_minor_edit_for_gutenberg', array( $this, 'gutenberg_minor_edit' ), 10, 0 );
$this->update_pm = new WPML_Update_PickUp_Method( $this->sitepress );
}
/**
* @return WPML_TM_CMS_ID
*/
public function &get_cms_id_helper() {
return $this->cms_id_helper;
}
/**
* @param string $call
* @param array $data
*/
function ajax_calls( $call, $data ) {
switch ( $call ) {
case 'set_pickup_mode':
$response = $this->update_pm->update_pickup_method( $data, $this->get_current_project() );
if ( 'no-ts' === $response ) {
wp_send_json_error( array( 'message' => __( 'Please activate translation service first.', 'wpml-translation-management' ) ) );
}
if ( 'cant-update' === $response ) {
wp_send_json_error( array( 'message' => __( 'Could not update the translation pickup mode.', 'wpml-translation-management' ) ) );
}
wp_send_json_success( array( 'message' => __( 'Ok', 'wpml-translation-management' ) ) );
break;
}
}
public function get_current_project() {
return TranslationProxy::get_current_project();
}
/**
* @param WP_Post|WPML_Package $post
* @param array $target_languages
* @param int $translator_id
* @param int $job_id
*
* @return bool|int
*/
function send_post( $post, $target_languages, $translator_id, $job_id ) {
/** @var TranslationManagement $iclTranslationManagement */
global $sitepress, $iclTranslationManagement;
$this->maybe_init_translation_management( $iclTranslationManagement );
if ( is_numeric( $post ) ) {
$post = get_post( $post );
}
if ( ! $post ) {
return false;
}
$post_id = $post->ID;
$post_type = $post->post_type;
$element_type_prefix = $iclTranslationManagement->get_element_type_prefix_from_job_id( $job_id );
$element_type = $element_type_prefix . '_' . $post_type;
$note = WPML_TM_Translator_Note::get( $post_id );
if ( ! $note ) {
$note = null;
}
$err = false;
$tp_job_id = false;
$source_language = $sitepress->get_language_for_element( $post_id, $element_type );
$target_language = is_array( $target_languages ) ? end( $target_languages ) : $target_languages;
if ( empty( $target_language ) || $target_language === $source_language ) {
return false;
}
$translation = $this->tmg->get_element_translation( $post_id, $target_language, $element_type );
if ( ! $translation ) { // translated the first time
$err = true;
}
if ( ! $err && ( $translation->needs_update || $translation->status == ICL_TM_NOT_TRANSLATED || $translation->status == ICL_TM_WAITING_FOR_TRANSLATOR ) ) {
$project = TranslationProxy::get_current_project();
if ( $iclTranslationManagement->is_external_type( $element_type_prefix ) ) {
$job_object = new WPML_External_Translation_Job( $job_id );
} else {
$job_object = new WPML_Post_Translation_Job( $job_id );
$job_object->load_terms_from_post_into_job();
}
list( $err, $project, $tp_job_id ) = $job_object->send_to_tp( $project, $translator_id, $this->cms_id_helper, $this->tmg, $note );
if ( $err ) {
$this->enqueue_project_errors( $project );
}
}
return $err ? false : $tp_job_id; // last $ret
}
function server_languages_map( $language_name, $server2plugin = false ) {
if ( is_array( $language_name ) ) {
return array_map( array( $this, 'server_languages_map' ), $language_name );
}
$map = array(
'Norwegian Bokmål' => 'Norwegian',
'Portuguese, Brazil' => 'Portuguese',
'Portuguese, Portugal' => 'Portugal Portuguese',
);
$map = $server2plugin ? array_flip( $map ) : $map;
return isset( $map[ $language_name ] ) ? $map[ $language_name ] : $language_name;
}
/**
* @param $methods
*
* @return array
*/
public function custom_xmlrpc_methods( $methods ) {
$icl_methods['translationproxy.test_xmlrpc'] = '__return_true';
$icl_methods['translationproxy.updated_job_status'] = array(
$this,
'xmlrpc_updated_job_status',
);
$methods = array_merge( $methods, $icl_methods );
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && preg_match( '#([^<]+)#i', $this->sitepress->get_wp_api()->get_raw_post_data(), $matches ) ) {
$method = $matches[1];
if ( array_key_exists( $method, $icl_methods ) ) {
set_error_handler( array( $this, 'translation_error_handler' ), E_ERROR | E_USER_ERROR );
}
}
return $methods;
}
/**
* @param array $args
*
* @return int|IXR_Error
*/
public function xmlrpc_updated_job_status( $args ) {
global $wpdb;
$tp_id = isset( $args[0] ) ? $args[0] : 0;
$cms_id = isset( $args[1] ) ? $args[1] : 0;
$status = isset( $args[2] ) ? $args[2] : '';
$signature = isset( $args[3] ) ? $args[3] : '';
if ( ! $this->authenticate_request( $tp_id, $cms_id, $status, $signature ) ) {
return new IXR_Error( 401, 'Wrong signature' );
}
try {
/** @var WPML_TM_Jobs_Repository $jobs_repository */
$jobs_repository = wpml_tm_get_jobs_repository();
$job_match = $jobs_repository->get(
new WPML_TM_Jobs_Search_Params(
array(
'scope' => 'remote',
'tp_id' => $tp_id,
)
)
);
if ( $job_match ) {
$jobs_array = $job_match->toArray();
$job = $jobs_array[0];
$job->set_status( WPML_TP_Job_States::map_tp_state_to_local( $status ) );
$tp_sync_updated_job = new WPML_TP_Sync_Update_Job( $wpdb, $this->sitepress );
$job_updated = $tp_sync_updated_job->update_state( $job );
if ( $job_updated && WPML_TP_Job_States::CANCELLED !== $status ) {
$apply_tp_translation = new WPML_TP_Apply_Single_Job(
wpml_tm_get_tp_translations_repository(),
new WPML_TP_Apply_Translation_Strategies( $wpdb )
);
$apply_tp_translation->apply( $job );
}
return 1;
}
} catch ( Exception $e ) {
return new IXR_Error( $e->getCode(), $e->getMessage() );
}
return 0;
}
/**
* @return bool
*/
private function authenticate_request( $tp_id, $cms_id, $status, $signature ) {
$project = TranslationProxy::get_current_project();
return sha1( $project->id . $project->access_key . $tp_id . $cms_id . $status ) === $signature;
}
/**
* @return WPML_WP_API
*/
function get_wpml_wp_api() {
return $this->sitepress->get_wp_api();
}
/**
*
* Cancel translation for given cms_id
*
* @param $rid
* @param $cms_id
*
* @return bool
*/
function cancel_translation( $rid, $cms_id ) {
/**
* @var WPML_String_Translation|null $WPML_String_Translation
* @var TranslationManagement $iclTranslationManagement
*/
global $WPML_String_Translation, $iclTranslationManagement;
$res = false;
if ( empty( $cms_id ) ) { // it's a string
if ( isset( $WPML_String_Translation ) ) {
$res = $WPML_String_Translation->cancel_remote_translation( $rid );
}
} else {
$translation_id = $this->cms_id_helper->get_translation_id( $cms_id );
if ( $translation_id ) {
$iclTranslationManagement->cancel_translation_request( $translation_id );
$res = true;
}
}
return $res;
}
/**
*
* Downloads translation from TP and updates its document
*
* @param $translation_proxy_job_id
* @param $cms_id
*
* @return bool|string
*/
function download_and_process_translation( $translation_proxy_job_id, $cms_id ) {
global $wpdb;
if ( empty( $cms_id ) ) { // it's a string
// TODO: [WPML 3.3] this should be handled as any other element type in 3.3
$target = $wpdb->get_var( $wpdb->prepare( "SELECT target FROM {$wpdb->prefix}icl_core_status WHERE rid=%d", $translation_proxy_job_id ) );
return $this->process_translated_string( $translation_proxy_job_id, $target );
} else {
$translation_id = $this->cms_id_helper->get_translation_id( $cms_id, TranslationProxy::get_current_service() );
return ! empty( $translation_id ) && $this->add_translated_document( $translation_id, $translation_proxy_job_id );
}
}
/**
* @param int $translation_id
* @param int $translation_proxy_job_id
*
* @return bool
*/
function add_translated_document( $translation_id, $translation_proxy_job_id ) {
global $wpdb, $sitepress;
$project = TranslationProxy::get_current_project();
$translation_info = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}icl_translations WHERE translation_id=%d", $translation_id ) );
$translation = $project->fetch_translation( $translation_proxy_job_id );
if ( ! $translation ) {
$this->errors = array_merge( $this->errors, $project->errors );
} else {
$translation = apply_filters( 'icl_data_from_pro_translation', $translation );
}
$ret = true;
if ( ! empty( $translation ) && strpos( $translation, 'xliff' ) !== false ) {
try {
/** @var $job_xliff_translation WP_Error|array */
$job_xliff_translation = $this->xliff_reader_factory
->general_xliff_import()->import( $translation, $translation_id );
if ( is_wp_error( $job_xliff_translation ) ) {
$this->add_error( $job_xliff_translation->get_error_message() );
return false;
}
kses_remove_filters();
wpml_tm_save_data( $job_xliff_translation );
kses_init();
$translations = $sitepress->get_element_translations( $translation_info->trid, $translation_info->element_type, false, true, true );
if ( isset( $translations[ $translation_info->language_code ] ) ) {
$translation = $translations[ $translation_info->language_code ];
if ( isset( $translation->element_id ) && $translation->element_id ) {
$translation_post_type_prepared = $wpdb->prepare( "SELECT post_type FROM $wpdb->posts WHERE ID=%d", array( $translation->element_id ) );
$translation_post_type = $wpdb->get_var( $translation_post_type_prepared );
} else {
$translation_post_type = implode( '_', array_slice( explode( '_', $translation_info->element_type ), 1 ) );
}
if ( $translation_post_type == 'page' ) {
$url = get_option( 'home' ) . '?page_id=' . $translation->element_id;
} else {
$url = get_option( 'home' ) . '?p=' . $translation->element_id;
}
$project->update_job( $translation_proxy_job_id, $url );
} else {
$project->update_job( $translation_proxy_job_id );
}
} catch ( Exception $e ) {
$ret = false;
}
}
return $ret;
}
private static function content_get_link_paths( $body ) {
$regexp_links = array(
"/]*href\s*=\s*([\"\']??)([^\"^>]+)[\"\']??([^>]*)>/i",
);
$links = array();
foreach ( $regexp_links as $regexp ) {
if ( preg_match_all( $regexp, $body, $matches, PREG_SET_ORDER ) ) {
foreach ( $matches as $match ) {
$links[] = $match;
}
}
}
return $links;
}
public function fix_links_to_translated_content( $element_id, $target_lang_code, $element_type = 'post' ) {
global $wpdb, $sitepress;
$sitepress->switch_lang( $target_lang_code );
$wpml_element_type = $element_type;
$body = false;
$string_type = null;
if ( strpos( $element_type, 'post' ) === 0 ) {
$post_prepared = $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE ID=%d", array( $element_id ) );
$post = $wpdb->get_row( $post_prepared );
$body = $post->post_content;
$wpml_element_type = 'post_' . $post->post_type;
} elseif ( $element_type == 'string' ) {
$string_prepared = $wpdb->prepare( "SELECT string_id, value FROM {$wpdb->prefix}icl_string_translations WHERE id=%d", array( $element_id ) );
$data = $wpdb->get_row( $string_prepared );
$body = $data->value;
$original_string_id = $data->string_id;
$string_type = $wpdb->get_var( $wpdb->prepare( "SELECT type FROM {$wpdb->prefix}icl_strings WHERE id=%d", $original_string_id ) );
if ( 'LINK' === $string_type ) {
$body = 'removeit';
}
}
$translate_link_targets = make( 'WPML_Translate_Link_Targets' );
$absolute_links = make( 'AbsoluteLinks' );
$getTranslatedLink = function ( $link ) use ( $translate_link_targets, $absolute_links, $element_type, $target_lang_code ) {
if ( $absolute_links->is_home( $link[2] ) ) {
$translatedLink = $absolute_links->convert_url( $link[2], $target_lang_code );
$translatedLink = Str::replace( $link[2], $translatedLink, $link[0] );
} else {
add_filter( 'wpml_force_translated_permalink', '__return_true' );
$translatedLink = $translate_link_targets->convert_text( $link[0] );
remove_filter( 'wpml_force_translated_permalink', '__return_true' );
if ( self::should_links_be_converted_back_to_sticky( $element_type ) ) {
$translatedLink = $absolute_links->convert_text( $translatedLink );
}
}
return $translatedLink !== $link[0]
? [
'from' => $link[0],
'to' => $translatedLink,
]
: null;
};
$getTranslatedLinks = pipe(
Fns::map( $getTranslatedLink ),
Fns::filter( Fns::identity() )
);
$links = self::content_get_link_paths( $body );
$translatedLinks = $getTranslatedLinks( $links );
$replaceLink = function ( $body, $link ) {
return str_replace( $link['from'], $link['to'], $body );
};
$new_body = Fns::reduce( $replaceLink, $body, $translatedLinks );
if ( $new_body != $body ) {
if ( strpos( $element_type, 'post' ) === 0 ) {
$wpdb->update( $wpdb->posts, array( 'post_content' => $new_body ), array( 'ID' => $element_id ) );
} elseif ( $element_type == 'string' ) {
if ( 'LINK' === $string_type ) {
$new_body = str_replace( array( 'removeit' ), array( '', '' ), $new_body );
$wpdb->update(
$wpdb->prefix . 'icl_string_translations',
array(
'value' => $new_body,
'status' => ICL_TM_COMPLETE,
),
array( 'id' => $element_id )
);
do_action( 'icl_st_add_string_translation', $element_id );
} else {
$wpdb->update( $wpdb->prefix . 'icl_string_translations', array( 'value' => $new_body ), array( 'id' => $element_id ) );
}
}
}
$links_fixed_status_factory = new WPML_Links_Fixed_Status_Factory( $wpdb, new WPML_WP_API() );
$links_fixed_status = $links_fixed_status_factory->create( $element_id, $wpml_element_type );
$links_fixed_status->set( Lst::length( $links ) === Lst::length( $translatedLinks ) );
$sitepress->switch_lang();
return sizeof( $translatedLinks );
}
function translation_error_handler( $error_number, $error_string, $error_file, $error_line ) {
switch ( $error_number ) {
case E_ERROR:
case E_USER_ERROR:
throw new Exception( $error_string . ' [code:e' . $error_number . '] in ' . $error_file . ':' . $error_line );
case E_WARNING:
case E_USER_WARNING:
return true;
default:
return true;
}
}
private static function should_links_be_converted_back_to_sticky( $element_type ) {
return 'string' !== $element_type && ! empty( $GLOBALS['WPML_Sticky_Links'] );
}
function post_submitbox_start() {
$show_box_style = $this->get_show_minor_edit_style();
if ( false !== $show_box_style ) {
?>
get_show_minor_edit_style();
if ( false !== $show_box_style ) {
?>
ID ) {
return false;
}
$translations = $iclTranslationManagement->get_element_translations( $post->ID, 'post_' . $post->post_type );
$show_box_style = 'display:none';
foreach ( $translations as $t ) {
if ( $t->element_id == $post->ID ) {
return false;
}
if ( $t->status == ICL_TM_COMPLETE && ! $t->needs_update ) {
$show_box_style = '';
break;
}
}
return $show_box_style;
}
private function process_translated_string( $translation_proxy_job_id, $language ) {
$project = TranslationProxy::get_current_project();
$translation = $project->fetch_translation( $translation_proxy_job_id );
$translation = apply_filters( 'icl_data_from_pro_translation', $translation );
$ret = false;
$translation = $this->xliff_reader_factory->string_xliff_reader()->get_data( $translation );
if ( $translation ) {
$ret = icl_translation_add_string_translation( $translation_proxy_job_id, $translation, $language );
if ( $ret ) {
$project->update_job( $translation_proxy_job_id );
}
}
return $ret;
}
private function add_error( $project_error ) {
$this->errors[] = $project_error;
}
/**
* @param $project TranslationProxy_Project
*/
function enqueue_project_errors( $project ) {
if ( isset( $project ) && isset( $project->errors ) && $project->errors ) {
foreach ( $project->errors as $project_error ) {
$this->add_error( $project_error );
}
}
}
/**
* @param TranslationManagement $iclTranslationManagement
*/
private function maybe_init_translation_management( $iclTranslationManagement ) {
if ( empty( $this->tmg->settings ) ) {
$iclTranslationManagement->init();
}
}
}