PageRenderTime 66ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/wp-content/plugins/sitepress-multilingual-cms/inc/translation-management/pro-translation.class.php

https://bitbucket.org/dkrzos/phc
PHP | 2138 lines | 1829 code | 222 blank | 87 comment | 202 complexity | 41e364292868e7ffbbffc54924dfffc1 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. // deprecated - used for string translations
  3. define ( 'CMS_TARGET_LANGUAGE_CREATED', 0);
  4. define ( 'CMS_TARGET_LANGUAGE_ASSIGNED', 1);
  5. define ( 'CMS_TARGET_LANGUAGE_TRANSLATED', 2);
  6. define ( 'CMS_TARGET_LANGUAGE_DONE', 3);
  7. define ( 'CMS_REQUEST_DONE', 6);
  8. define ( 'CMS_REQUEST_FAILED', 7);
  9. class ICL_Pro_Translation{
  10. private $tmg;
  11. protected static $__asian_languages = array('ja', 'ko', 'zh-hans', 'zh-hant', 'mn', 'ne', 'hi', 'pa', 'ta', 'th');
  12. function __construct(){
  13. global $iclTranslationManagement;
  14. $this->tmg =& $iclTranslationManagement;
  15. add_filter('xmlrpc_methods',array($this, 'custom_xmlrpc_methods'));
  16. add_action('post_submitbox_start', array($this, 'post_submitbox_start'));
  17. add_action('icl_ajx_custom_call', array($this, 'ajax_calls'), 10, 2);
  18. add_action('icl_hourly_translation_pickup', array($this, 'poll_for_translations'));
  19. }
  20. function ajax_calls($call, $data){
  21. global $sitepress_settings, $sitepress;
  22. switch($call){
  23. case 'set_pickup_mode':
  24. $method = intval($data['icl_translation_pickup_method']);
  25. $iclsettings['translation_pickup_method'] = $method;
  26. $iclsettings['icl_disable_reminders'] = isset($_POST['icl_disable_reminders']) ? 1 : 0;
  27. $sitepress->save_settings($iclsettings);
  28. if(!empty($sitepress_settings) && !empty($sitepress_settings['site_id']) && !empty($sitepress_settings['access_key'])){
  29. $data['site_id'] = $sitepress_settings['site_id'];
  30. $data['accesskey'] = $sitepress_settings['access_key'];
  31. $data['create_account'] = 0;
  32. $data['pickup_type'] = $method;
  33. $icl_query = new ICanLocalizeQuery();
  34. $res = $icl_query->updateAccount($data);
  35. }
  36. if($method == ICL_PRO_TRANSLATION_PICKUP_XMLRPC){
  37. wp_clear_scheduled_hook('icl_hourly_translation_pickup');
  38. }else{
  39. wp_schedule_event(time(), 'hourly', 'icl_hourly_translation_pickup');
  40. }
  41. echo json_encode(array('message'=>'OK'));
  42. break;
  43. case 'pickup_translations':
  44. if($sitepress_settings['translation_pickup_method']==ICL_PRO_TRANSLATION_PICKUP_POLLING){
  45. $fetched = $this->poll_for_translations(true);
  46. echo json_encode(array('message'=>'OK', 'fetched'=> urlencode('&nbsp;' . sprintf(__('Fetched %d translations.', 'sitepress'), $fetched))));
  47. }else{
  48. echo json_encode(array('error'=>__('Manual pick up is disabled.', 'sitepress')));
  49. }
  50. break;
  51. }
  52. }
  53. function send_post($post, $target_languages, $translator_id = 0){
  54. global $sitepress, $sitepress_settings, $wpdb, $iclTranslationManagement;
  55. // don't wait for init
  56. if(empty($this->tmg->settings)){
  57. $iclTranslationManagement->init();
  58. }
  59. if(is_numeric($post)){
  60. $post = get_post($post);
  61. }
  62. $post_id = $post->ID;
  63. $err = false;
  64. if(!$post){
  65. return false;
  66. }
  67. $orig_lang = $sitepress->get_language_for_element($post_id, 'post_' . $post->post_type);
  68. $__ld = $sitepress->get_language_details($orig_lang);
  69. $orig_lang_for_server = $this->server_languages_map($__ld['english_name']);
  70. if(empty($target_languages)) return false;
  71. // Make sure the previous request is complete.
  72. // Only send if it needs update
  73. foreach($target_languages as $target_lang){
  74. if($target_lang == $orig_lang) continue;
  75. $translation = $this->tmg->get_element_translation($post_id, $target_lang, 'post_' . $post->post_type);
  76. if(empty($translation)){ // translated the first time
  77. $tdata = array(
  78. 'translate_from' => array($orig_lang),
  79. 'translate_to' => array($target_lang=>1),
  80. 'post' => array($post_id),
  81. 'translator' => $translator_id,
  82. 'service' => 'icanlocalize'
  83. );
  84. $this->tmg->send_jobs($tdata);
  85. $translation = $this->tmg->get_element_translation($post_id, $target_lang, 'post_' . $post->post_type);
  86. }
  87. if($translation->needs_update || $translation->status == ICL_TM_NOT_TRANSLATED || $translation->status == ICL_TM_WAITING_FOR_TRANSLATOR){
  88. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  89. if($post->post_type=='page'){
  90. $post_url = get_option('home') . '?page_id=' . ($post_id);
  91. }else{
  92. $post_url = get_option('home') . '?p=' . ($post_id);
  93. }
  94. $__ld = $sitepress->get_language_details($target_lang);
  95. $target_for_server = $this->server_languages_map($__ld['english_name']);
  96. if (isset($post->external_type) && $post->external_type) {
  97. $data['url'] = htmlentities($post_url);
  98. $data['target_languages'] = array($target_for_server);
  99. foreach ($post->string_data as $key => $value) {
  100. $data['contents'][$key] = array(
  101. 'translate' => 1,
  102. 'data' => base64_encode($value),
  103. 'format' => 'base64'
  104. );
  105. }
  106. $data['contents']['original_id'] = array(
  107. 'translate' => 0,
  108. 'data' => $post->post_id,
  109. );
  110. } else {
  111. // TAGS
  112. // ***************************************************************************
  113. foreach(wp_get_object_terms($post_id, 'post_tag') as $tag){
  114. $post_tags[$tag->term_taxonomy_id] = $tag->name;
  115. }
  116. if(@is_array($post_tags)){
  117. //only send tags that don't have a translation
  118. foreach($post_tags as $term_taxonomy_id=>$pc){
  119. $trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_id='{$term_taxonomy_id}' AND element_type='tax_post_tag'");
  120. foreach($target_languages as $lang){
  121. $not_translated = false;
  122. if($trid != $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE language_code='{$lang}' AND trid='{$trid}' AND element_id IS NOT NULL")){
  123. $not_translated = true;
  124. break;
  125. }
  126. }
  127. if($not_translated){
  128. $tags_to_translate[$term_taxonomy_id] = $pc;
  129. }
  130. }
  131. sort($post_tags, SORT_STRING);
  132. }
  133. // CATEGORIES
  134. // ***************************************************************************
  135. foreach(wp_get_object_terms($post_id, 'category') as $cat){
  136. $post_categories[$cat->term_taxonomy_id] = $cat->name;
  137. }
  138. if(@is_array($post_categories)){
  139. //only send categories that don't have a translation
  140. foreach($post_categories as $term_taxonomy_id=>$pc){
  141. $trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_id='{$term_taxonomy_id}' AND element_type='tax_category'");
  142. foreach($target_languages as $lang){
  143. $not_translated = false;
  144. if($trid != $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE language_code='{$lang}' AND trid='{$trid}' AND element_id IS NOT NULL")){
  145. $not_translated = true;
  146. break;
  147. }
  148. }
  149. if($not_translated){
  150. $categories_to_translate[$term_taxonomy_id] = $pc;
  151. }
  152. }
  153. sort($post_categories, SORT_STRING);
  154. }
  155. // CUSTOM TAXONOMIES
  156. // ***************************************************************************
  157. $taxonomies = $wpdb->get_col("
  158. SELECT DISTINCT tx.taxonomy
  159. FROM {$wpdb->term_taxonomy} tx JOIN {$wpdb->term_relationships} tr ON tx.term_taxonomy_id = tr.term_taxonomy_id
  160. WHERE tr.object_id = {$post_id}
  161. ");
  162. foreach($taxonomies as $t){
  163. if(@intval($sitepress_settings['taxonomies_sync_option'][$t]) == 1){
  164. $object_terms = $wpdb->get_results("
  165. SELECT x.term_taxonomy_id, t.name
  166. FROM {$wpdb->terms} t
  167. JOIN {$wpdb->term_taxonomy} x ON t.term_id=x.term_id
  168. JOIN {$wpdb->term_relationships} r ON x.term_taxonomy_id = r.term_taxonomy_id
  169. WHERE x.taxonomy = '{$t}' AND r.object_id = $post_id
  170. ");
  171. foreach($object_terms as $trm){
  172. $trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations
  173. WHERE element_id='{$trm->term_taxonomy_id}' AND element_type='tax_{$t}'");
  174. foreach($target_languages as $lang){
  175. $not_translated = false;
  176. if($trid != $wpdb->get_var("
  177. SELECT trid FROM {$wpdb->prefix}icl_translations WHERE l.english_name='{$lang}' AND trid='{$trid}' AND element_id IS NOT NULL
  178. ")){
  179. $not_translated = true;
  180. break;
  181. }
  182. }
  183. if($not_translated){
  184. $taxonomies_to_translate[$t][$trm->term_taxonomy_id] = $trm->name;
  185. }
  186. }
  187. }
  188. }
  189. $data['url'] = htmlentities($post_url);
  190. $data['contents']['title'] = array(
  191. 'translate'=>1,
  192. 'data'=>base64_encode($post->post_title),
  193. 'format'=>'base64'
  194. );
  195. if($sitepress_settings['translated_document_page_url'] == 'translate'){
  196. $data['contents']['URL'] = array(
  197. 'translate'=>1,
  198. 'data'=>base64_encode($post->post_name),
  199. 'format'=>'base64'
  200. );
  201. }
  202. if(!empty($post->post_excerpt))
  203. $data['contents']['excerpt'] = array(
  204. 'translate'=>1,
  205. 'data'=>base64_encode($post->post_excerpt),
  206. 'format'=>'base64'
  207. );
  208. $data['contents']['body'] = array(
  209. 'translate'=>1,
  210. 'data'=>base64_encode($post->post_content),
  211. 'format'=>'base64'
  212. );
  213. $data['contents']['original_id'] = array(
  214. 'translate'=>0,
  215. 'data'=>$post_id
  216. );
  217. $data['target_languages'] = array($target_for_server);
  218. $custom_fields = array();
  219. foreach((array)$iclTranslationManagement->settings['custom_fields_translation'] as $cf => $op){
  220. if ($op == 2) {
  221. $custom_fields[] = $cf;
  222. }
  223. }
  224. foreach($custom_fields as $cf){
  225. $custom_fields_value = get_post_meta($post_id, $cf, true);
  226. if ($custom_fields_value != '') {
  227. $data['contents']['field-'.$cf] = array(
  228. 'translate' => 1,
  229. 'data' => base64_encode($custom_fields_value),
  230. 'format' => 'base64',
  231. );
  232. $data['contents']['field-'.$cf.'-name'] = array(
  233. 'translate' => 0,
  234. 'data' => $cf,
  235. );
  236. $data['contents']['field-'.$cf.'-type'] = array(
  237. 'translate' => 0,
  238. 'data' => 'custom_field',
  239. );
  240. }
  241. }
  242. if(@is_array($categories_to_translate)){
  243. $data['contents']['categories'] = array(
  244. 'translate'=>1,
  245. 'data'=> implode(',', array_map(create_function('$e', 'return \'&quot;\'.base64_encode($e).\'&quot;\';'), $categories_to_translate)),
  246. 'format'=>'csv_base64'
  247. );
  248. $data['contents']['category_ids'] = array(
  249. 'translate'=>0,
  250. 'data'=> implode(',', array_keys($categories_to_translate)),
  251. 'format'=>''
  252. );
  253. }
  254. if(@is_array($tags_to_translate)){
  255. $data['contents']['tags'] = array(
  256. 'translate'=>1,
  257. 'data'=> implode(',', array_map(create_function('$e', 'return \'&quot;\'.base64_encode($e).\'&quot;\';'), $tags_to_translate)),
  258. 'format'=>'csv_base64'
  259. );
  260. $data['contents']['tag_ids'] = array(
  261. 'translate'=>0,
  262. 'data'=> implode(',', array_keys($tags_to_translate)),
  263. 'format'=>''
  264. );
  265. }
  266. if(@is_array($taxonomies_to_translate)){
  267. foreach($taxonomies_to_translate as $k=>$v){
  268. $data['contents'][$k] = array(
  269. 'translate'=>1,
  270. 'data'=> implode(',', array_map(create_function('$e', 'return \'&quot;\'.base64_encode($e).\'&quot;\';'), $v)),
  271. 'format'=>'csv_base64'
  272. );
  273. $data['contents'][$k.'_ids'] = array(
  274. 'translate'=>0,
  275. 'data'=> implode(',', array_keys($v)),
  276. 'format'=>''
  277. );
  278. }
  279. }
  280. if($post->post_status=='publish'){
  281. $permlink = $post_url;
  282. }else{
  283. $permlink = false;
  284. }
  285. $note = get_post_meta($post_id, '_icl_translator_note', true);
  286. // if this is an old request having a old request_id, include that
  287. if($wpdb->prefix.'icl_content_status' == $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}icl_content_status'")){
  288. $prev_rid = $wpdb->get_var($wpdb->prepare("SELECT MAX(rid) FROM {$wpdb->prefix}icl_content_status WHERE nid=%d", $post_id));
  289. if(!empty($prev_rid)){
  290. $data['previous_cms_request_id'] = $prev_rid;
  291. }
  292. }
  293. }
  294. $data = apply_filters('icl_data_for_pro_translation', $data);
  295. $xml = $iclq->build_cms_request_xml($data, $orig_lang_for_server);
  296. $cms_id = sprintf('%s_%d_%s_%s', $post->post_type, $post->ID, $orig_lang, $target_lang);
  297. $args = array(
  298. 'cms_id' => $cms_id,
  299. 'xml' => $xml,
  300. 'title' => $post->post_title,
  301. 'to_languages' => array($target_for_server),
  302. 'orig_language' => $orig_lang_for_server,
  303. 'permlink' => isset($permlink) ? $permlink : false,
  304. 'translator_id' => $translator_id,
  305. 'note' => isset($note) ? $note : '',
  306. );
  307. $res = $iclq->send_request($args);
  308. if($res > 0){
  309. $this->tmg->update_translation_status(array(
  310. 'translation_id'=>$translation->translation_id,
  311. 'status' => ICL_TM_IN_PROGRESS,
  312. 'needs_update' => 0
  313. ));
  314. }else{
  315. $_prevstate = $wpdb->get_var($wpdb->prepare("SELECT _prevstate FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d", $translation->translation_id));
  316. if(!empty($_prevstate)){
  317. $_prevstate = unserialize($_prevstate);
  318. $wpdb->update($wpdb->prefix . 'icl_translation_status',
  319. array(
  320. 'status' => $_prevstate['status'],
  321. 'translator_id' => $_prevstate['translator_id'],
  322. 'status' => $_prevstate['status'],
  323. 'needs_update' => $_prevstate['needs_update'],
  324. 'md5' => $_prevstate['md5'],
  325. 'translation_service' => $_prevstate['translation_service'],
  326. 'translation_package' => $_prevstate['translation_package'],
  327. 'timestamp' => $_prevstate['timestamp'],
  328. 'links_fixed' => $_prevstate['links_fixed']
  329. ),
  330. array('translation_id'=>$translation->translation_id)
  331. );
  332. }else{
  333. $wpdb->update($wpdb->prefix . 'icl_translation_status',
  334. array('status'=>ICL_TM_NOT_TRANSLATED, 'needs_update'=>0), array('translation_id'=>$translation->translation_id));
  335. }
  336. $err = true;
  337. }
  338. } // if needs translation
  339. } // foreach target lang
  340. return $err ? false : $res; //last $ret
  341. }
  342. public function server_languages_map($language_name, $server2plugin = false){
  343. if(is_array($language_name)){
  344. return array_map(array($this, 'icl_server_languages_map'), $language_name);
  345. }
  346. $map = array(
  347. 'Norwegian Bokmål' => 'Norwegian',
  348. 'Portuguese, Brazil' => 'Portuguese',
  349. 'Portuguese, Portugal' => 'Portugal Portuguese'
  350. );
  351. if($server2plugin){
  352. $map = array_flip($map);
  353. }
  354. if(isset($map[$language_name])){
  355. return $map[$language_name];
  356. }else{
  357. return $language_name;
  358. }
  359. }
  360. function custom_xmlrpc_methods($methods){
  361. $icl_methods['icanlocalize.update_status_by_cms_id'] = array($this, 'get_translated_document');
  362. // for migration to 2.0.0
  363. $icl_methods['icanlocalize.set_translation_status'] = array($this,'_legacy_set_translation_status');
  364. //$icl_methods['icanlocalize.set_translation_status'] = array($this,'get_translated_string'); // use for strings - old method
  365. //$icl_methods['icanlocalize.list_posts'] = array($this, '_list_posts');
  366. //$icl_methods['icanlocalize.translate_post'] = array($this, '_remote_control_translate_post');
  367. $icl_methods['icanlocalize.test_xmlrpc'] = array($this, '_test_xmlrpc');
  368. $icl_methods['icanlocalize.cancel_translation_by_cms_id'] = array($this, '_xmlrpc_cancel_translation');
  369. // for migration to 2.0.0
  370. $icl_methods['icanlocalize.cancel_translation'] = array($this, '_legacy_xmlrpc_cancel_translation');
  371. $icl_methods['icanlocalize.notify_comment_translation'] = array($this, '_xmlrpc_add_message_translation');
  372. $methods = $methods + $icl_methods;
  373. if(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST){
  374. preg_match('#<methodName>([^<]+)</methodName>#i', $GLOBALS['HTTP_RAW_POST_DATA'], $matches);
  375. $method = $matches[1];
  376. if(in_array($method, array_keys($icl_methods))){
  377. //error_reporting(E_NONE);
  378. //ini_set('display_errors', '0');
  379. $old_error_handler = set_error_handler(array($this, "_translation_error_handler"),E_ERROR|E_USER_ERROR);
  380. }
  381. }
  382. return $methods;
  383. }
  384. function _legacy_set_translation_status($args){
  385. global $sitepress_settings, $sitepress, $wpdb;
  386. try{
  387. $signature = $args[0];
  388. $site_id = $args[1];
  389. $request_id = $args[2];
  390. $original_language = $args[3];
  391. $language = $args[4];
  392. $status = $args[5];
  393. $message = $args[6];
  394. if ($site_id != $sitepress_settings['site_id']) {
  395. return 3;
  396. }
  397. //check signature
  398. $signature_chk = sha1($sitepress_settings['access_key'].$sitepress_settings['site_id'].$request_id.$language.$status.$message);
  399. if($signature_chk != $signature){
  400. return 2;
  401. }
  402. $lang_code = $sitepress->get_language_code($this->server_languages_map($language, true));//the 'reverse' language filter
  403. $cms_request_info = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}icl_core_status WHERE rid={$request_id} AND target='{$lang_code}'");
  404. if (empty($cms_request_info)){
  405. $this->_throw_exception_for_mysql_errors();
  406. return 4;
  407. }
  408. if ($this->_legacy_process_translated_document($request_id, $language, $args)){
  409. $this->_throw_exception_for_mysql_errors();
  410. return 1;
  411. } else {
  412. $this->_throw_exception_for_mysql_errors();
  413. return 6;
  414. }
  415. }catch(Exception $e) {
  416. return $e->getMessage();
  417. }
  418. }
  419. function _legacy_process_translated_document($request_id, $language, $args){
  420. global $sitepress_settings, $wpdb, $sitepress, $iclTranslationManagement;
  421. $ret = false;
  422. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  423. $post_type = $wpdb->get_var($wpdb->prepare("SELECT p.post_type FROM {$wpdb->posts} p JOIN {$wpdb->prefix}icl_content_status c ON p.ID = c.nid WHERE c.rid=%d", $request_id));
  424. $trid = $wpdb->get_var($wpdb->prepare("
  425. SELECT trid
  426. FROM {$wpdb->prefix}icl_translations t
  427. JOIN {$wpdb->prefix}icl_content_status c ON t.element_id = c.nid AND t.element_type='post_{$post_type}' AND c.rid=%d",$request_id));
  428. $translation = $iclq->cms_do_download($request_id, $language);
  429. if($translation){
  430. if (icl_is_string_translation($translation)){
  431. $ret = $this->get_translated_string($args);
  432. } else {
  433. // we need to create a cms_id for this
  434. list($lang_from, $lang_to) = $wpdb->get_row($wpdb->prepare("
  435. SELECT origin, target FROM {$wpdb->prefix}icl_core_status WHERE rid=%d ORDER BY id DESC LIMIT 1
  436. ", $request_id), ARRAY_N);
  437. $translation_id = $wpdb->get_var($wpdb->prepare("
  438. SELECT translation_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d and language_code='%s'
  439. ", $trid, $lang_to));
  440. if(!$translation_id){
  441. $wpdb->insert($wpdb->prefix.'icl_translations', array(
  442. 'element_type' => 'post_' . $post_type,
  443. 'trid' => $trid,
  444. 'language_code' => $lang_to,
  445. 'source_language_code' => $lang_from
  446. ));
  447. $translation_id = $wpdb->insert_id;
  448. }
  449. $original_post_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND source_language_code IS NULL", $trid));
  450. $translation_package = $iclTranslationManagement->create_translation_package($original_post_id);
  451. $md5 = $iclTranslationManagement->post_md5($original_post_id);
  452. $translator_id = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM {$wpdb->posts} WHERE ID=%d", $original_post_id));
  453. // add translation_status record
  454. list($rid, $update) = $iclTranslationManagement->update_translation_status(array(
  455. 'translation_id' => $translation_id,
  456. 'status' => 2,
  457. 'translator_id' => $translator_id,
  458. 'needs_update' => 0,
  459. 'md5' => $md5,
  460. 'translation_service' => 'icanlocalize',
  461. 'translation_package' => serialize($translation_package)
  462. ));
  463. $job_ids[] = $iclTranslationManagement->add_translation_job($rid, $translator_id, $translation_package);
  464. $ret = $this->add_translated_document($translation_id, $request_id);
  465. }
  466. if($ret){
  467. $iclq->cms_update_request_status($request_id, CMS_TARGET_LANGUAGE_DONE, $language);
  468. }
  469. }
  470. return $ret;
  471. }
  472. /*
  473. * 0 - unknown error
  474. * 1 - success
  475. * 2 - signature mismatch
  476. * 3 - website_id incorrect
  477. * 4 - cms_id not found
  478. * 5 - icl translation not enabled
  479. * 6 - unknown error processing translation
  480. */
  481. function get_translated_document($args){
  482. global $sitepress_settings, $sitepress, $wpdb;
  483. try{
  484. $signature = $args[0];
  485. $site_id = $args[1];
  486. $request_id = $args[2];
  487. $cms_id = $args[3];
  488. $status = $args[4];
  489. $message = $args[5];
  490. if ($site_id != $sitepress_settings['site_id']) {
  491. return 3;
  492. }
  493. //check signature
  494. $signature_chk = sha1($sitepress_settings['access_key'].$sitepress_settings['site_id'].$cms_id.$status.$message);
  495. if($signature_chk != $signature){
  496. return 2;
  497. }
  498. // decode cms_id
  499. $int = preg_match('#(.+)_([0-9]+)_([^_]+)_([^_]+)#', $cms_id, $matches);
  500. $_element_type = $matches[1];
  501. $_element_id = $matches[2];
  502. $_original_lang = $matches[3];
  503. $_lang = $matches[4];
  504. $trid = $sitepress->get_element_trid($_element_id, 'post_'. $_element_type);
  505. if(!$trid){
  506. return 4;
  507. }
  508. $translation = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND language_code=%s", $trid, $_lang));
  509. if (empty($translation)){ // if the translation was deleted re-create it
  510. $wpdb->insert($wpdb->prefix.'icl_translations', array(
  511. 'element_type' => 'post_' . $_element_type,
  512. 'trid' => $trid,
  513. 'language_code' => $_lang,
  514. 'source_language_code' => $_original_lang
  515. ));
  516. $translation_id = $wpdb->insert_id;
  517. $md5 = $this->tmg->post_md5($_element_id);
  518. $translation_package = $this->tmg->create_translation_package($_element_id);
  519. $translator_id = 0; //TO FIX!
  520. list($rid, $update) = $this->tmg->update_translation_status(array(
  521. 'translation_id' => $translation_id,
  522. 'status' => ICL_TM_IN_PROGRESS,
  523. 'translator_id' => $translator_id,
  524. 'needs_update' => 0,
  525. 'md5' => $md5,
  526. 'translation_service' => 'icanlocalize',
  527. 'translation_package' => serialize($translation_package)
  528. ));
  529. $this->tmg->add_translation_job($rid, $translator_id, $translation_package);
  530. }else{
  531. $translation_id = $translation->translation_id;
  532. // if the post is trashed set the element_id to null
  533. if('trash' == $wpdb->get_var($wpdb->prepare("SELECT post_status FROM {$wpdb->posts} WHERE ID=%d", $translation->element_id))){
  534. $wpdb->query("UPDATE {$wpdb->prefix}icl_translations SET element_id = NULL WHERE translation_id={$translation->translation_id}");
  535. }
  536. }
  537. if ($this->add_translated_document($translation_id, $request_id) === true){
  538. $this->_throw_exception_for_mysql_errors();
  539. return 1;
  540. } else {
  541. $this->_throw_exception_for_mysql_errors();
  542. return 6;
  543. }
  544. }catch(Exception $e) {
  545. return $e->getMessage();
  546. }
  547. }
  548. function add_translated_document($translation_id, $request_id){
  549. global $sitepress_settings, $wpdb, $sitepress;
  550. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  551. $tinfo = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}icl_translations WHERE translation_id=%d", $translation_id));
  552. $_lang = $sitepress->get_language_details($tinfo->language_code);
  553. $translation = $iclq->cms_do_download($request_id, $this->server_languages_map($_lang['english_name']));
  554. $translation = apply_filters('icl_data_from_pro_translation', $translation);
  555. $ret = false;
  556. if(!empty($translation)){
  557. $language_code = $wpdb->get_var($wpdb->prepare("
  558. SELECT language_code FROM {$wpdb->prefix}icl_translations WHERE translation_id=%d", $translation_id
  559. ));
  560. $parts = explode('_', $translation['original_id']);
  561. if ($parts[0] == 'external') {
  562. // Translations are saved in the string table for 'external' types
  563. $id = array_pop($parts);
  564. unset($parts[0]);
  565. $type = implode('_', $parts);
  566. unset($translation['original_id']);
  567. foreach($translation as $field => $value){
  568. if (function_exists('icl_st_is_registered_string')) {
  569. $value = str_replace('&#0A;', "\n", $value);
  570. $string_id = icl_st_is_registered_string($type, $id . '_' . $field);
  571. if (!$string_id) {
  572. icl_register_string($type, $id . '_' . $field, $value);
  573. $string_id = icl_st_is_registered_string($type, $id . '_' . $field);
  574. }
  575. if ($string_id) {
  576. icl_add_string_translation($string_id, $language_code, $value, ICL_STRING_TRANSLATION_COMPLETE);
  577. }
  578. }
  579. }
  580. $ret = true;
  581. } else {
  582. $ret = $this->save_post_translation($translation_id, $translation);
  583. }
  584. if($ret){
  585. $lang_details = $sitepress->get_language_details($language_code);
  586. $language_server = $this->server_languages_map($lang_details['english_name']);
  587. $iclq->cms_update_request_status($request_id, CMS_TARGET_LANGUAGE_DONE, $language_server);
  588. $translations = $sitepress->get_element_translations($tinfo->trid, $tinfo->element_type);
  589. if(isset($translations[$tinfo->language_code])){
  590. $iclq->report_back_permalink($request_id, $language_server, $translations[$tinfo->language_code]);
  591. }
  592. }
  593. }
  594. return $ret;
  595. }
  596. function save_post_translation($translation_id, $translation){
  597. global $wpdb, $sitepress_settings, $sitepress, $wp_taxonomies, $icl_adjust_id_url_filter_off;
  598. $icl_adjust_id_url_filter_off = true;
  599. $taxonomies = array_diff(array_keys((array)$wp_taxonomies), array('post_tag','category'));
  600. $tinfo = $wpdb->get_row($wpdb->prepare("
  601. SELECT * FROM {$wpdb->prefix}icl_translations tr
  602. JOIN {$wpdb->prefix}icl_translation_status ts ON ts.translation_id = tr.translation_id
  603. WHERE tr.translation_id=%d", $translation_id));
  604. $lang_code = $tinfo->language_code;
  605. $trid = $tinfo->trid;
  606. $original_post_details = $wpdb->get_row("
  607. SELECT p.post_author, p.post_type, p.post_status, p.comment_status, p.ping_status, p.post_parent, p.menu_order, p.post_date, t.language_code
  608. FROM {$wpdb->prefix}icl_translations t
  609. JOIN {$wpdb->posts} p ON t.element_id = p.ID AND CONCAT('post_',p.post_type) = t.element_type
  610. WHERE trid='{$trid}' AND p.ID = '{$translation['original_id']}'
  611. ");
  612. //is the original post a sticky post?
  613. remove_filter('option_sticky_posts', array($sitepress,'option_sticky_posts')); // remove filter used to get language relevant stickies. get them all
  614. $sticky_posts = get_option('sticky_posts');
  615. $is_original_sticky = $original_post_details->post_type=='post' && in_array($translation['original_id'], $sticky_posts);
  616. $this->_content_fix_image_paths_in_body($translation);
  617. $this->_content_fix_relative_link_paths_in_body($translation);
  618. $this->_content_decode_shortcodes($translation);
  619. // deal with tags
  620. if(isset($translation['tags'])){
  621. $translated_tags = $translation['tags'];
  622. $translated_tag_ids = explode(',', $translation['tag_ids']);
  623. foreach($translated_tags as $k=>$v){
  624. $tag_trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_id='{$translated_tag_ids[$k]}' AND element_type='tax_post_tag'");
  625. // before adding the new term make sure that another tag with the same name doesn't exist. If it does append @lang
  626. // same term name exists in a different language?
  627. $term_different_language = $wpdb->get_var("
  628. SELECT tm.term_id
  629. FROM {$wpdb->term_taxonomy} tx
  630. JOIN {$wpdb->terms} tm ON tx.term_id = tm.term_id
  631. JOIN {$wpdb->prefix}icl_translations tr ON tx.term_taxonomy_id = tr.element_id
  632. WHERE tm.name='".$wpdb->escape($v)."' AND tr.element_type LIKE 'tax\\_%' AND tr.language_code <> '{$lang_code}'
  633. ");
  634. if($term_different_language){
  635. $v .= ' @'.$lang_code;
  636. }
  637. //tag exists? (in the current language)
  638. $etag = get_term_by('name', htmlspecialchars($v), 'post_tag');
  639. if(!$etag){
  640. $etag = get_term_by('name', htmlspecialchars($v) . ' @'.$lang_code, 'post_tag');
  641. }
  642. if(!$etag){
  643. $tmp = wp_insert_term($v, 'post_tag');
  644. if(!is_wp_error($tmp) && isset($tmp['term_taxonomy_id'])){
  645. $wpdb->update($wpdb->prefix.'icl_translations',
  646. array('language_code'=>$lang_code, 'trid'=>$tag_trid, 'source_language_code'=>$original_post_details->language_code),
  647. array('element_type'=>'tax_post_tag','element_id'=>$tmp['term_taxonomy_id']));
  648. }
  649. }else{
  650. $term_taxonomy_id = $etag->term_taxonomy_id;
  651. // check whether we have an orphan translation - the same trid and language but a different element id
  652. $__translation_id = $wpdb->get_var("
  653. SELECT translation_id FROM {$wpdb->prefix}icl_translations
  654. WHERE trid = '{$tag_trid}'
  655. AND language_code = '{$lang_code}'
  656. AND element_id <> '{$term_taxonomy_id}'
  657. ");
  658. if($__translation_id){
  659. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_translations WHERE translation_id={$__translation_id}");
  660. }
  661. $tag_translation_id = $wpdb->get_var("SELECT translation_id FROM {$wpdb->prefix}icl_translations WHERE element_id={$term_taxonomy_id} AND element_type='tax_post_tag'");
  662. if($tag_translation_id){
  663. $wpdb->update($wpdb->prefix.'icl_translations',
  664. array('language_code'=>$lang_code, 'trid'=>$tag_trid, 'source_language_code'=>$original_post_details->language_code),
  665. array('element_type'=>'tax_post_tag','translation_id'=>$tag_translation_id));
  666. }else{
  667. $wpdb->insert($wpdb->prefix.'icl_translations',
  668. array('language_code'=>$lang_code, 'trid'=>$tag_trid, 'element_type'=>'tax_post_tag', 'element_id'=>$term_taxonomy_id, 'source_language_code'=>$original_post_details->language_code));
  669. }
  670. }
  671. }
  672. }
  673. $original_post_tags = array();
  674. foreach(wp_get_object_terms($translation['original_id'] , 'post_tag') as $t){
  675. $original_post_tags[] = $t->term_taxonomy_id;
  676. }
  677. if($original_post_tags){
  678. $tag_trids = $wpdb->get_col("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_post_tag' AND element_id IN (".join(',',$original_post_tags).")");
  679. if(!empty($tag_trids))
  680. $tag_tr_tts = $wpdb->get_col("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_post_tag' AND language_code='{$lang_code}' AND trid IN (".join(',',$tag_trids).")");
  681. if(!empty($tag_tr_tts))
  682. $translated_tags = $wpdb->get_col("SELECT t.name FROM {$wpdb->terms} t JOIN {$wpdb->term_taxonomy} tx ON tx.term_id = t.term_id WHERE tx.taxonomy='post_tag' AND tx.term_taxonomy_id IN (".join(',',$tag_tr_tts).")");
  683. }
  684. // deal with categories
  685. if(isset($translation['categories'])){
  686. $translated_cats = $translation['categories'];
  687. $translated_cats_ids = explode(',', $translation['category_ids']);
  688. foreach($translated_cats as $k=>$v){
  689. //$v = trim(str_replace('<p>', '', $v));
  690. $cat_trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_id='{$translated_cats_ids[$k]}' AND element_type='tax_category'");
  691. // before adding the new term make sure that another tag with the same name doesn't exist. If it does append @lang
  692. // same term name exists in a different language?
  693. $term_different_language = $wpdb->get_var("
  694. SELECT tm.term_id
  695. FROM {$wpdb->term_taxonomy} tx
  696. JOIN {$wpdb->terms} tm ON tx.term_id = tm.term_id
  697. JOIN {$wpdb->prefix}icl_translations tr ON tx.term_taxonomy_id = tr.element_id
  698. WHERE tm.name='".$wpdb->escape($v)."' AND tr.element_type LIKE 'tax\\_%' AND tr.language_code <> '{$lang_code}'
  699. ");
  700. if($term_different_language){
  701. $v .= ' @'.$lang_code;
  702. }
  703. //cat exists?
  704. $ecat = get_term_by('name', htmlspecialchars($v), 'category');
  705. if(!$ecat){
  706. $ecat = get_term_by('name', htmlspecialchars($v) . ' @'.$lang_code, 'category');
  707. }
  708. if(!$ecat){
  709. // get original category parent id
  710. $original_category_parent_id = $wpdb->get_var($wpdb->prepare("SELECT parent FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d",$translated_cats_ids[$k]));
  711. if($original_category_parent_id){
  712. $_op_tax_id = $wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE taxonomy='category' AND term_id=%d",$original_category_parent_id));
  713. $_op_trid = $wpdb->get_var($wpdb->prepare("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_category' AND element_id=%d",$_op_tax_id));
  714. // get id of the translated category parent
  715. $_tp_tax_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE language_code='{$lang_code}' AND trid=%d",$_op_trid));
  716. if($_tp_tax_id){
  717. $category_parent_id = $wpdb->get_var($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE taxonomy='category' AND term_taxonomy_id=%d",$_tp_tax_id));
  718. }else{
  719. $category_parent_id = 0;
  720. }
  721. }else{
  722. $category_parent_id = 0;
  723. }
  724. $tmp = wp_insert_term($v, 'category', array('parent'=>$category_parent_id));
  725. if(!is_wp_error($tmp) && isset($tmp['term_taxonomy_id'])){
  726. $wpdb->update($wpdb->prefix.'icl_translations',
  727. array('language_code'=>$lang_code, 'trid'=>$cat_trid, 'source_language_code'=>$original_post_details->language_code),
  728. array('element_type'=>'tax_category','element_id'=>$tmp['term_taxonomy_id']));
  729. // if this is a parent category, make sure that nesting is correct for all translations
  730. $orig_cat_tax_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND source_language_code IS NULL", $cat_trid));
  731. $orig_cat_term_id = $wpdb->get_var($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d AND taxonomy='category'",$orig_cat_tax_id));
  732. $orig_cat_children = $wpdb->get_col($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent=%d",$orig_cat_term_id));
  733. if(!empty($orig_cat_children)) foreach($orig_cat_children as $ch){
  734. $_tr_child = icl_object_id($ch, 'category', false, $lang_code);
  735. if($_tr_child){
  736. $wpdb->update($wpdb->term_taxonomy, array('parent'=>$tmp['term_id']), array(
  737. 'taxonomy'=>'category', 'term_id' => $_tr_child
  738. ));
  739. }
  740. }
  741. delete_option('category_children');
  742. }
  743. }else{
  744. $term_taxonomy_id = $ecat->term_taxonomy_id;
  745. // check whether we have an orphan translation - the same trid and language but a different element id
  746. $__translation_id = $wpdb->get_var("
  747. SELECT translation_id FROM {$wpdb->prefix}icl_translations
  748. WHERE trid = '{$cat_trid}'
  749. AND language_code = '{$lang_code}'
  750. AND element_id <> '{$term_taxonomy_id}'
  751. ");
  752. if($__translation_id){
  753. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_translations WHERE translation_id={$__translation_id}");
  754. }
  755. $cat_translation_id = $wpdb->get_var("SELECT translation_id FROM {$wpdb->prefix}icl_translations WHERE element_id={$term_taxonomy_id} AND element_type='tax_category'");
  756. if($cat_translation_id){
  757. $wpdb->update($wpdb->prefix.'icl_translations',
  758. array('language_code'=>$lang_code, 'trid'=>$cat_trid, 'source_language_code'=>$original_post_details->language_code),
  759. array('element_type'=>'tax_category','translation_id'=>$cat_translation_id));
  760. }else{
  761. $wpdb->insert($wpdb->prefix.'icl_translations',
  762. array('language_code'=>$lang_code, 'trid'=>$cat_trid, 'element_type'=>'tax_category', 'element_id'=>$term_taxonomy_id, 'source_language_code'=>$original_post_details->language_code));
  763. }
  764. }
  765. }
  766. }
  767. $original_post_cats = array();
  768. foreach(wp_get_object_terms($translation['original_id'] , 'category') as $t){
  769. $original_post_cats[] = $t->term_taxonomy_id;
  770. }
  771. if($original_post_cats){
  772. $cat_trids = $wpdb->get_col("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_category' AND element_id IN (".join(',',$original_post_cats).")");
  773. if(!empty($cat_trids))
  774. $cat_tr_tts = $wpdb->get_col("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_category' AND language_code='{$lang_code}' AND trid IN (".join(',',$cat_trids).")");
  775. if(!empty($cat_tr_tts))
  776. $translated_cats_ids = $wpdb->get_col("SELECT t.term_id FROM {$wpdb->terms} t JOIN {$wpdb->term_taxonomy} tx ON tx.term_id = t.term_id WHERE tx.taxonomy='category' AND tx.term_taxonomy_id IN (".join(',',$cat_tr_tts).")");
  777. }
  778. // deal with custom taxonomies
  779. if(!empty($sitepress_settings['taxonomies_sync_option'])){
  780. foreach($sitepress_settings['taxonomies_sync_option'] as $taxonomy=>$value){
  781. if($value == 1 && isset($translation[$taxonomy])){
  782. $translated_taxs[$taxonomy] = $translation[$taxonomy];
  783. $translated_tax_ids[$taxonomy] = explode(',', $translation[$taxonomy.'_ids']);
  784. foreach($translated_taxs[$taxonomy] as $k=>$v){
  785. $tax_trid = $wpdb->get_var("
  786. SELECT trid FROM {$wpdb->prefix}icl_translations
  787. WHERE element_id='{$translated_tax_ids[$taxonomy][$k]}' AND element_type='tax_{$taxonomy}'");
  788. // before adding the new term make sure that another tag with the same name doesn't exist. If it does append @lang
  789. // same term name exists in a different language?
  790. $term_different_language = $wpdb->get_var("
  791. SELECT tm.term_id
  792. FROM {$wpdb->term_taxonomy} tx
  793. JOIN {$wpdb->terms} tm ON tx.term_id = tm.term_id
  794. JOIN {$wpdb->prefix}icl_translations tr ON tx.term_taxonomy_id = tr.element_id
  795. WHERE tm.name='".$wpdb->escape($v)."' AND tr.element_type LIKE 'tax\\_%' AND tr.language_code <> '{$lang_code}'
  796. ");
  797. if($term_different_language){
  798. $v .= ' @'.$lang_code;
  799. }
  800. //tax exists? (in the current language)
  801. $etag = get_term_by('name', htmlspecialchars($v), $taxonomy);
  802. if(!$etag){
  803. $etag = get_term_by('name', htmlspecialchars($v) . ' @'.$lang_code, $taxonomy);
  804. }
  805. if(!$etag){
  806. // get original category parent id
  807. $original_t_parent_id = $wpdb->get_var($wpdb->prepare("SELECT parent FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d",$translated_tax_ids[$taxonomy][$k]));
  808. if($original_t_parent_id){
  809. $_op_tax_id = $wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE taxonomy='category' AND term_id=%d",$original_t_parent_id));
  810. $_op_trid = $wpdb->get_var($wpdb->prepare("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_type='tax_category' AND element_id=%d",$_op_tax_id));
  811. // get id of the translated category parent
  812. $_tp_tax_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE language_code='{$lang_code}' AND trid=%d",$_op_trid));
  813. if($_tp_tax_id){
  814. $t_parent_id = $wpdb->get_var($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE taxonomy='category' AND term_taxonomy_id=%d",$_tp_tax_id));
  815. }else{
  816. $t_parent_id = 0;
  817. }
  818. }else{
  819. $t_parent_id = 0;
  820. }
  821. $tmp = wp_insert_term($v, $taxonomy);
  822. if(!is_wp_error($tmp) && isset($tmp['term_taxonomy_id'])){
  823. $wpdb->update($wpdb->prefix.'icl_translations',
  824. array('language_code'=>$lang_code, 'trid'=>$tax_trid, 'source_language_code'=>$original_post_details->language_code),
  825. array('element_type'=>'tax_'.$taxonomy,'element_id'=>$tmp['term_taxonomy_id']));
  826. // if this is a parent category, make sure that nesting is correct for all translations
  827. $orig_tax_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND source_language_code IS NULL", $tax_trid));
  828. $orig_term_id = $wpdb->get_var($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d AND taxonomy='{$taxonomy}'", $orig_tax_id));
  829. $orig_tax_children = $wpdb->get_col($wpdb->prepare("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent=%d", $orig_term_id));
  830. if(!empty($orig_tax_children)) foreach($orig_tax_children as $ch){
  831. $_tr_child = icl_object_id($ch, $taxonomy, false, $lang_code);
  832. if($_tr_child){
  833. $wpdb->update($wpdb->term_taxonomy, array('parent'=>$tmp['term_id']), array(
  834. 'taxonomy'=>$taxonomy, 'term_id' => $_tr_child
  835. ));
  836. }
  837. }
  838. delete_option($taxonomy . '_children');
  839. }
  840. }else{
  841. $term_taxonomy_id = $etag->term_taxonomy_id;
  842. // check whether we have an orphan translation - the same trid and language but a different element id
  843. $__translation_id = $wpdb->get_var("
  844. SELECT translation_id FROM {$wpdb->prefix}icl_translations
  845. WHERE trid = '{$tax_trid}'
  846. AND language_code = '{$lang_code}'
  847. AND element_id <> '{$term_taxonomy_id}'
  848. ");
  849. if($__translation_id){
  850. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_translations WHERE translation_id={$__translation_id}");
  851. }
  852. $tax_translation_id = $wpdb->get_var("
  853. SELECT translation_id FROM {$wpdb->prefix}icl_translations
  854. WHERE element_id={$term_taxonomy_id} AND element_type='tax_{$taxonomy}'");
  855. if($tax_translation_id){
  856. $wpdb->update($wpdb->prefix.'icl_translations',
  857. array('language_code'=>$lang_code, 'trid'=>$tax_trid, 'source_language_code'=>$original_post_details->language_code),
  858. array('element_type'=>'tax_'.$taxonomy,'translation_id'=>$tax_translation_id));
  859. }else{
  860. $wpdb->insert($wpdb->prefix.'icl_translations',
  861. array('language_code'=>$lang_code, 'trid'=>$tax_trid, 'element_type'=>'tax_'.$taxonomy,
  862. 'element_id'=>$term_taxonomy_id, 'source_language_code'=>$original_post_details->language_code));
  863. }
  864. }
  865. }
  866. }
  867. $oterms = wp_get_object_terms($translation['original_id'] , $taxonomy);
  868. if(!is_wp_error($oterms)){
  869. foreach($oterms as $t){
  870. $original_post_taxs[$taxonomy][] = $t->term_taxonomy_id;
  871. }
  872. }
  873. if(!empty($original_post_taxs[$taxonomy])){
  874. $tax_trids = $wpdb->get_col("SELECT trid FROM {$wpdb->prefix}icl_translations
  875. WHERE element_type='tax_{$taxonomy}' AND element_id IN (".join(',',$original_post_taxs[$taxonomy]).")");
  876. if(!empty($tax_trids)){
  877. $tax_tr_tts = $wpdb->get_col("SELECT element_id FROM {$wpdb->prefix}icl_translations
  878. WHERE element_type='tax_{$taxonomy}' AND language_code='{$lang_code}' AND trid IN (".join(',',$tax_trids).")");
  879. }
  880. if(!empty($tax_tr_tts)){
  881. if($wp_taxonomies[$taxonomy]->hierarchical){
  882. $translated_tax_ids[$taxonomy] = $wpdb->get_col("SELECT term_id FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id IN (".join(',',$tax_tr_tts).")");
  883. }else{
  884. $translated_taxs[$taxonomy] = $wpdb->get_col("SELECT t.name FROM {$wpdb->terms} t
  885. JOIN {$wpdb->term_taxonomy} tx ON tx.term_id = t.term_id
  886. WHERE tx.taxonomy='{$taxonomy}' AND tx.term_taxonomy_id IN (".join(',',$tax_tr_tts).")");
  887. }
  888. }
  889. }
  890. }
  891. }
  892. // handle the page parent and set it to the translated parent if we have one.
  893. if($original_post_details->post_parent){
  894. $post_parent_trid = $wpdb->get_var("SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_type='post_{$original_post_details->post_type}' AND element_id='{$original_post_details->post_parent}'");
  895. if($post_parent_trid){
  896. $parent_id = $wpdb->get_var("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type='post_{$original_post_details->post_type}' AND trid='{$post_parent_trid}' AND language_code='{$lang_code}'");
  897. }
  898. }
  899. // determine post id based on trid
  900. $post_id = $tinfo->element_id;
  901. if($post_id){
  902. // see if the post really exists - make sure it wasn't deleted while the plugin was
  903. if(!$wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE ID={$post_id}")){
  904. $is_update = false;
  905. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_translations WHERE element_type='post_{$original_post_details->post_type}' AND element_id={$post_id}");
  906. }else{
  907. $is_update = true;
  908. $postarr['ID'] = $_POST['post_ID'] = $post_id;
  909. }
  910. }else{
  911. $is_update = false;
  912. }
  913. $postarr['post_title'] = $translation['title'];
  914. if($sitepress_settings['translated_document_page_url'] == 'translate' && isset($translation['URL'])){
  915. $postarr['post_name'] = $translation['URL'];
  916. }
  917. $postarr['post_content'] = $translation['body'];
  918. if (isset($translation['excerpt']) && $translation['excerpt'] != "") {
  919. $postarr['post_excerpt'] = $translation['excerpt'];
  920. }
  921. if(@is_array($translated_tags)){
  922. $postarr['tags_input'] = join(',',(array)$translated_tags);
  923. }
  924. if(@is_array($translated_taxs)){
  925. foreach($translated_taxs as $taxonomy=>$values){
  926. $postarr['tax_input'][$taxonomy] = join(',',(array)$values);
  927. }
  928. }
  929. if(@is_array($translated_tax_ids)){
  930. $postarr['tax_input'] = $translated_tax_ids;
  931. }
  932. if(isset($translated_cats_ids)){
  933. $postarr['post_category'] = $translated_cats_ids;
  934. }
  935. $postarr['post_author'] = $original_post_details->post_author;
  936. $postarr['post_type'] = $original_post_details->post_type;
  937. if($sitepress_settings['sync_comment_status']){
  938. $postarr['comment_status'] = $original_post_details->comment_status;
  939. }
  940. if($sitepress_settings['sync_ping_status']){
  941. $postarr['ping_status'] = $original_post_details->ping_status;
  942. }
  943. if($sitepress_settings['sync_page_ordering']){
  944. $postarr['menu_order'] = $original_post_details->menu_order;
  945. }
  946. if($sitepress_settings['sync_private_flag'] && $original_post_details->post_status=='private'){
  947. $postarr['post_status'] = 'private';
  948. }
  949. if(!$is_update){
  950. $postarr['post_status'] = !$sitepress_settings['translated_document_status'] ? 'draft' : $original_post_details->post_status;
  951. } else {
  952. // set post_status to the current post status.
  953. $postarr['post_status'] = $wpdb->get_var("SELECT post_status FROM {$wpdb->prefix}posts WHERE ID = ".$post_id);
  954. }
  955. if($sitepress_settings['sync_post_date']){
  956. $postarr['post_date'] = $original_post_details->post_date;
  957. }
  958. if(isset($parent_id) && $sitepress_settings['sync_page_parent']){
  959. $_POST['post_parent'] = $postarr['post_parent'] = $parent_id;
  960. $_POST['parent_id'] = $postarr['parent_id'] = $parent_id;
  961. }
  962. if($is_update){
  963. $postarr['post_name'] = $wpdb->get_var($wpdb->prepare("SELECT post_name FROM {$wpdb->posts} WHERE ID=%d", $post_id));
  964. }
  965. $_POST['trid'] = $trid;
  966. $_POST['lang'] = $lang_code;
  967. $_POST['skip_sitepress_actions'] = true;
  968. global $wp_rewrite;
  969. if(!isset($wp_rewrite)) $wp_rewrite = new WP_Rewrite();
  970. kses_remove_filters();
  971. $postarr = apply_filters('icl_pre_save_pro_translation', $postarr);
  972. $new_post_id = wp_insert_post($postarr);
  973. do_action('icl_pro_translation_saved', $new_post_id);
  974. // associate custom taxonomies by hand
  975. if ( !empty($postarr['tax_input']) ) {
  976. foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
  977. if($wp_taxonomies[$taxonomy]->hierarchical){
  978. wp_set_post_terms( $new_post_id, $tags, $taxonomy );
  979. }else{
  980. wp_set_post_terms( $new_post_id, $translated_taxs[$taxonomy], $taxonomy );
  981. }
  982. }
  983. }
  984. // set stickiness
  985. if($is_original_sticky && $sitepress_settings['sync_sticky_flag']){
  986. stick_post($new_post_id);
  987. }else{
  988. if($original_post_details->post_type=='post' && $is_update){
  989. unstick_post($new_post_id); //just in case - if this is an update and the original post stckiness has changed since the post was sent to translation
  990. }
  991. }
  992. foreach((array)$sitepress_settings['translation-management']['custom_fields_translation'] as $cf => $op){
  993. if ($op == 1) {
  994. update_post_meta($new_post_id, $cf, get_post_meta($translation['original_id'],$cf,true));
  995. }elseif ($op == 2 && isset($translation['field-'.$cf])) {
  996. $field_translation = $translation['field-'.$cf];
  997. $field_type = $translation['field-'.$cf.'-type'];
  998. if ($field_type == 'custom_field') {
  999. $field_translation = str_replace ( '&#0A;', "\n", $field_translation );
  1000. // always decode html entities eg decode &amp; to &
  1001. $field_translation = html_entity_decode($field_translation);
  1002. update_post_meta($new_post_id, $cf, $field_translation);
  1003. }
  1004. }
  1005. }
  1006. // set specific custom fields
  1007. $copied_custom_fields = array('_top_nav_excluded', '_cms_nav_minihome');
  1008. foreach($copied_custom_fields as $ccf){
  1009. $val = get_post_meta($translation['original_id'], $ccf, true);
  1010. update_post_meta($new_post_id, $ccf, $val);
  1011. }
  1012. // sync _wp_page_template
  1013. if($sitepress_settings['sync_page_template']){
  1014. $_wp_page_template = get_post_meta($translation['original_id'], '_wp_page_template', true);
  1015. update_post_meta($new_post_id, '_wp_page_template', $_wp_page_template);
  1016. }
  1017. if(!$new_post_id){
  1018. return false;
  1019. }
  1020. if(!$is_update){
  1021. $wpdb->update($wpdb->prefix.'icl_translations', array('element_id'=>$new_post_id), array('translation_id' => $translation_id));
  1022. }
  1023. update_post_meta($new_post_id, '_icl_translation', 1);
  1024. TranslationManagement::set_page_url($new_post_id);
  1025. global $iclTranslationManagement;
  1026. $ts = array(
  1027. 'status'=>ICL_TM_COMPLETE, 'needs_update'=>0,
  1028. 'translation_id'=>$translation_id
  1029. );
  1030. $translator_id = $wpdb->get_var($wpdb->prepare("SELECT translator_id FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d", $translation_id));
  1031. if(!$translator_id){
  1032. foreach($sitepress_settings['icl_lang_status'] as $lpair){
  1033. if($lpair['from'] == $original_post_details->language_code && $lpair['to'] == $lang_code && isset($lpair['translators'][0]['id'])){
  1034. $ts['translator_id'] = $lpair['translators'][0]['id'];
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. // update translation status
  1040. $iclTranslationManagement->update_translation_status($ts);
  1041. // add new translation job
  1042. //$translation_package = $iclTranslationManagement->create_translation_package(get_post($translation['original_id']));
  1043. //$job_id = $iclTranslationManagement->add_translation_job($tinfo->rid, $tinfo->translator_id, $translation_package);
  1044. $job_id = $iclTranslationManagement->get_translation_job_id($trid, $lang_code);
  1045. // save the translation
  1046. $iclTranslationManagement->mark_job_done($job_id);
  1047. $parts = explode('_', $translation['original_id']);
  1048. if ($parts[0] != 'external') {
  1049. $iclTranslationManagement->save_job_fields_from_post($job_id, get_post($new_post_id));
  1050. $this->_content_fix_links_to_translated_content($new_post_id, $lang_code, "post_{$original_post_details->post_type}");
  1051. if(function_exists('icl_st_fix_links_in_strings')){
  1052. icl_st_fix_links_in_strings($new_post_id);
  1053. }
  1054. // Now try to fix links in other translated content that may link to this post.
  1055. $sql = "SELECT
  1056. tr.element_id
  1057. FROM
  1058. {$wpdb->prefix}icl_translations tr
  1059. JOIN
  1060. {$wpdb->prefix}icl_translation_status ts
  1061. ON
  1062. tr.translation_id = ts.translation_id
  1063. WHERE
  1064. ts.links_fixed = 0 AND tr.element_type = 'post_{$original_post_details->post_type}' AND tr.language_code = '{$lang_code}' AND tr.element_id IS NOT NULL";
  1065. $needs_fixing = $wpdb->get_results($sql);
  1066. foreach($needs_fixing as $id){
  1067. if($id->element_id != $new_post_id){ // fix all except the new_post_id. We have already done this.
  1068. $this->_content_fix_links_to_translated_content($id->element_id, $lang_code, "post_{$original_post_details->post_type}");
  1069. }
  1070. }
  1071. // if this is a parent page then make sure it's children point to this.
  1072. $this->fix_translated_children($translation['original_id'], $new_post_id, $lang_code);
  1073. }
  1074. return true;
  1075. }
  1076. // old style - for strings
  1077. function get_translated_string($args){
  1078. global $sitepress_settings, $sitepress, $wpdb;
  1079. try{
  1080. $signature = $args[0];
  1081. $site_id = $args[1];
  1082. $request_id = $args[2];
  1083. $original_language = $args[3];
  1084. $language = $args[4];
  1085. $status = $args[5];
  1086. $message = $args[6];
  1087. if ($site_id != $sitepress_settings['site_id']) {
  1088. return 3;
  1089. }
  1090. //check signature
  1091. $signature_chk = sha1($sitepress_settings['access_key'].$sitepress_settings['site_id'].$request_id.$language.$status.$message);
  1092. if($signature_chk != $signature){
  1093. return 2;
  1094. }
  1095. $lang_code = $sitepress->get_language_code($this->server_languages_map($language, true));//the 'reverse' language filter
  1096. $cms_request_info = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}icl_core_status WHERE rid={$request_id} AND target='{$lang_code}'");
  1097. if (empty($cms_request_info)){
  1098. $this->_throw_exception_for_mysql_errors();
  1099. return 4;
  1100. }
  1101. //return $this->process_translated_string($request_id, $language);
  1102. if ($this->process_translated_string($request_id, $language) === true){
  1103. $this->_throw_exception_for_mysql_errors();
  1104. return 1;
  1105. } else {
  1106. $this->_throw_exception_for_mysql_errors();
  1107. return 6;
  1108. }
  1109. }catch(Exception $e) {
  1110. return $e->getMessage();
  1111. }
  1112. }
  1113. // old style - for strings
  1114. function process_translated_string($request_id, $language){
  1115. global $sitepress_settings, $wpdb, $sitepress;
  1116. $ret = false;
  1117. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  1118. $translation = $iclq->cms_do_download($request_id, $language);
  1119. if($translation){
  1120. $ret = icl_translation_add_string_translation($request_id, $translation, $sitepress->get_language_code($this->server_languages_map($language, true)));
  1121. if($ret){
  1122. $iclq->cms_update_request_status($request_id, CMS_TARGET_LANGUAGE_DONE, $language);
  1123. }
  1124. }
  1125. // if there aren't any other unfullfilled requests send a global 'done'
  1126. if(0 == $wpdb->get_var("SELECT COUNT(rid) FROM {$wpdb->prefix}icl_core_status WHERE rid='{$request_id}' AND status < ".CMS_TARGET_LANGUAGE_DONE)){
  1127. $iclq->cms_update_request_status($request_id, CMS_REQUEST_DONE, false);
  1128. }
  1129. return $ret;
  1130. }
  1131. function _content_fix_image_paths_in_body(&$translation) {
  1132. $body = $translation['body'];
  1133. $image_paths = $this->_content_get_image_paths($body);
  1134. $source_path = get_permalink($translation['original_id']);
  1135. foreach($image_paths as $path) {
  1136. $src_path = $this->resolve_url($source_path, $path[2]);
  1137. if ($src_path != $path[2]) {
  1138. $search = $path[1] . $path[2] . $path[1];
  1139. $replace = $path[1] . $src_path . $path[1];
  1140. $new_link = str_replace($search, $replace, $path[0]);
  1141. $body = str_replace($path[0], $new_link, $body);
  1142. }
  1143. }
  1144. $translation['body'] = $body;
  1145. }
  1146. /*
  1147. Decode any html encoding in shortcodes
  1148. http://codex.wordpress.org/Shortcode_API
  1149. */
  1150. function _content_decode_shortcodes(&$translation) {
  1151. $body = $translation['body'];
  1152. global $shortcode_tags;
  1153. if (isset($shortcode_tags)) {
  1154. $tagnames = array_keys($shortcode_tags);
  1155. $tagregexp = join( '|', array_map('preg_quote', $tagnames) );
  1156. $regexp = '/\[('.$tagregexp.')\b(.*?)\]/s';
  1157. if (preg_match_all($regexp, $body, $matches, PREG_SET_ORDER)) {
  1158. foreach ($matches as $match) {
  1159. $body = str_replace($match[0], '[' . $match[1] . html_entity_decode($match[2]) . ']', $body);
  1160. }
  1161. }
  1162. }
  1163. $translation['body'] = $body;
  1164. }
  1165. /**
  1166. * get the paths to images in the body of the content
  1167. */
  1168. function _content_get_image_paths($body) {
  1169. $regexp_links = array(
  1170. "/<img\ssrc\s*=\s*([\"\']??)([^\"]*)\".*>/siU",
  1171. "/&lt;script\ssrc\s*=\s*([\"\']??)([^\"]*)\".*>/siU",
  1172. "/<embed\ssrc\s*=\s*([\"\']??)([^\"]*)\".*>/siU",
  1173. );
  1174. $links = array();
  1175. foreach($regexp_links as $regexp) {
  1176. if (preg_match_all($regexp, $body, $matches, PREG_SET_ORDER)) {
  1177. foreach ($matches as $match) {
  1178. $links[] = $match;
  1179. }
  1180. }
  1181. }
  1182. return $links;
  1183. }
  1184. /**
  1185. * Resolve a URL relative to a base path. This happens to work with POSIX
  1186. * filenames as well. This is based on RFC 2396 section 5.2.
  1187. */
  1188. function resolve_url($base, $url) {
  1189. if (!strlen($base)) return $url;
  1190. // Step 2
  1191. if (!strlen($url)) return $base;
  1192. // Step 3
  1193. if (preg_match('!^[a-z]+:!i', $url)) return $url;
  1194. $base = parse_url($base);
  1195. if ($url{0} == "#") {
  1196. // Step 2 (fragment)
  1197. $base['fragment'] = substr($url, 1);
  1198. return $this->unparse_url($base);
  1199. }
  1200. unset($base['fragment']);
  1201. unset($base['query']);
  1202. if (substr($url, 0, 2) == "//") {
  1203. // Step 4
  1204. return $this->unparse_url(array(
  1205. 'scheme'=>$base['scheme'],
  1206. 'path'=>$url,
  1207. ));
  1208. } else if ($url{0} == "/") {
  1209. // Step 5
  1210. $base['path'] = $url;
  1211. } else {
  1212. // Step 6
  1213. $path = explode('/', $base['path']);
  1214. $url_path = explode('/', $url);
  1215. // Step 6a: drop file from base
  1216. array_pop($path);
  1217. // Step 6b, 6c, 6e: append url while removing "." and ".." from
  1218. // the directory portion
  1219. $end = array_pop($url_path);
  1220. foreach ($url_path as $segment) {
  1221. if ($segment == '.') {
  1222. // skip
  1223. } else if ($segment == '..' && $path && $path[sizeof($path)-1] != '..') {
  1224. array_pop($path);
  1225. } else {
  1226. $path[] = $segment;
  1227. }
  1228. }
  1229. // Step 6d, 6f: remove "." and ".." from file portion
  1230. if ($end == '.') {
  1231. $path[] = '';
  1232. } else if ($end == '..' && $path && $path[sizeof($path)-1] != '..') {
  1233. $path[sizeof($path)-1] = '';
  1234. } else {
  1235. $path[] = $end;
  1236. }
  1237. // Step 6h
  1238. $base['path'] = join('/', $path);
  1239. }
  1240. // Step 7
  1241. return $this->unparse_url($base);
  1242. }
  1243. function unparse_url($parsed){
  1244. if (! is_array($parsed)) return false;
  1245. $uri = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
  1246. $uri .= isset($parsed['user']) ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
  1247. $uri .= isset($parsed['host']) ? $parsed['host'] : '';
  1248. $uri .= isset($parsed['port']) ? ':'.$parsed['port'] : '';
  1249. if(isset($parsed['path']))
  1250. {
  1251. $uri .= (substr($parsed['path'],0,1) == '/')?$parsed['path']:'/'.$parsed['path'];
  1252. }
  1253. $uri .= isset($parsed['query']) ? '?'.$parsed['query'] : '';
  1254. $uri .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
  1255. return $uri;
  1256. }
  1257. function _content_fix_relative_link_paths_in_body(&$translation) {
  1258. $body = $translation['body'];
  1259. $link_paths = $this->_content_get_link_paths($body);
  1260. $source_path = get_permalink($translation['original_id']);
  1261. foreach($link_paths as $path) {
  1262. if ($path[2][0] != "#"){
  1263. $src_path = $this->resolve_url($source_path, $path[2]);
  1264. if ($src_path != $path[2]) {
  1265. $search = $path[1] . $path[2] . $path[1];
  1266. $replace = $path[1] . $src_path . $path[1];
  1267. $new_link = str_replace($search, $replace, $path[0]);
  1268. $body = str_replace($path[0], $new_link, $body);
  1269. }
  1270. }
  1271. }
  1272. $translation['body'] = $body;
  1273. }
  1274. function _content_get_link_paths($body) {
  1275. $regexp_links = array(
  1276. /*"/<a.*?href\s*=\s*([\"\']??)([^\"]*)[\"\']>(.*?)<\/a>/i",*/
  1277. "/<a[^>]*href\s*=\s*([\"\']??)([^\"^>]+)[\"\']??([^>]*)>/i",
  1278. );
  1279. $links = array();
  1280. foreach($regexp_links as $regexp) {
  1281. if (preg_match_all($regexp, $body, $matches, PREG_SET_ORDER)) {
  1282. foreach ($matches as $match) {
  1283. $links[] = $match;
  1284. }
  1285. }
  1286. }
  1287. return $links;
  1288. }
  1289. public static function _content_make_links_sticky($element_id, $element_type='post', $string_translation = true) {
  1290. if(strpos($element_type, 'post') === 0){
  1291. // only need to do it if sticky links is not enabled.
  1292. // create the object
  1293. require_once ICL_PLUGIN_PATH . '/inc/absolute-links/absolute-links.class.php';
  1294. $icl_abs_links = new AbsoluteLinks;
  1295. $icl_abs_links->process_post($element_id);
  1296. }elseif($element_type=='string'){
  1297. require_once ICL_PLUGIN_PATH . '/inc/absolute-links/absolute-links.class.php';
  1298. $icl_abs_links = new AbsoluteLinks; // call just for strings
  1299. $icl_abs_links->process_string($element_id, $string_translation);
  1300. }
  1301. }
  1302. function _content_fix_links_to_translated_content($element_id, $target_lang_code, $element_type='post'){
  1303. global $wpdb, $sitepress, $sitepress_settings, $wp_taxonomies;
  1304. self::_content_make_links_sticky($element_id, $element_type);
  1305. if(strpos($element_type, 'post') === 0){
  1306. $post = $wpdb->get_row("SELECT * FROM {$wpdb->posts} WHERE ID={$element_id}");
  1307. $body = $post->post_content;
  1308. }elseif($element_type=='string'){
  1309. $body = $wpdb->get_var("SELECT value FROM {$wpdb->prefix}icl_string_translations WHERE id=" . $element_id);
  1310. }
  1311. $new_body = $body;
  1312. $base_url_parts = parse_url(get_option('home'));
  1313. $links = $this->_content_get_link_paths($body);
  1314. $all_links_fixed = 1;
  1315. $pass_on_qvars = array();
  1316. $pass_on_fragments = array();
  1317. foreach($links as $link_idx => $link) {
  1318. $path = $link[2];
  1319. $url_parts = parse_url($path);
  1320. if(isset($url_parts['fragment'])){
  1321. $pass_on_fragments[$link_idx] = $url_parts['fragment'];
  1322. }
  1323. if((!isset($url_parts['host']) or $base_url_parts['host'] == $url_parts['host']) and
  1324. (!isset($url_parts['scheme']) or $base_url_parts['scheme'] == $url_parts['scheme']) and
  1325. isset($url_parts['query'])) {
  1326. $query_parts = split('&', $url_parts['query']);
  1327. foreach($query_parts as $query){
  1328. // find p=id or cat=id or tag=id queries
  1329. list($key, $value) = split('=', $query);
  1330. $translations = NULL;
  1331. $is_tax = false;
  1332. if($key == 'p'){
  1333. $kind = 'post_' . $wpdb->get_var("SELECT post_type FROM {$wpdb->posts} WHERE ID='{$value}'");
  1334. } else if($key == "page_id"){
  1335. $kind = 'post_page';
  1336. } else if($key == 'cat' || $key == 'cat_ID'){
  1337. $kind = 'tax_category';
  1338. $taxonomy = 'category';
  1339. } else if($key == 'tag'){
  1340. $is_tax = true;
  1341. $taxonomy = 'post_tag';
  1342. $kind = 'tax_' . $taxonomy;
  1343. $value = $wpdb->get_var("SELECT term_taxonomy_id FROM {$wpdb->terms} t
  1344. JOIN {$wpdb->term_taxonomy} x ON t.term_id = x.term_id WHERE x.taxonomy='{$taxonomy}' AND t.slug='{$value}'");
  1345. } else {
  1346. $found = false;
  1347. foreach($wp_taxonomies as $ktax => $tax){
  1348. if($tax->query_var && $key == $tax->query_var){
  1349. $found = true;
  1350. $is_tax = true;
  1351. $kind = 'tax_' . $ktax;
  1352. $value = $wpdb->get_var("
  1353. SELECT term_taxonomy_id FROM {$wpdb->terms} t
  1354. JOIN {$wpdb->term_taxonomy} x ON t.term_id = x.term_id WHERE x.taxonomy='{$ktax}' AND t.slug='{$value}'");
  1355. $taxonomy = $ktax;
  1356. }
  1357. }
  1358. if(!$found){
  1359. $pass_on_qvars[$link_idx][] = $query;
  1360. continue;
  1361. }
  1362. }
  1363. $link_id = (int)$value;
  1364. if (!$link_id) {
  1365. continue;
  1366. }
  1367. $trid = $sitepress->get_element_trid($link_id, $kind);
  1368. if(!$trid){
  1369. continue;
  1370. }
  1371. if($trid !== NULL){
  1372. $translations = $sitepress->get_element_translations($trid, $kind);
  1373. }
  1374. if(isset($translations[$target_lang_code]) && $translations[$target_lang_code]->element_id != null){
  1375. // use the new translated id in the link path.
  1376. $translated_id = $translations[$target_lang_code]->element_id;
  1377. if($is_tax){
  1378. $translated_id = $wpdb->get_var("SELECT slug FROM {$wpdb->terms} t JOIN {$wpdb->term_taxonomy} x ON t.term_id=x.term_id WHERE x.term_taxonomy_id=$translated_id");
  1379. }
  1380. // if absolute links is not on turn into WP permalinks
  1381. if(empty($GLOBALS['WPML_Sticky_Links'])){
  1382. ////////
  1383. if(preg_match('#^post_#', $kind)){
  1384. $replace = get_permalink($translated_id);
  1385. }elseif(preg_match('#^tax_#', $kind)){
  1386. if(is_numeric($translated_id)) $translated_id = intval($translated_id);
  1387. $replace = get_term_link($translated_id, $taxonomy);
  1388. }
  1389. $new_link = str_replace($link[2], $replace, $link[0]);
  1390. $replace_link_arr[$link_idx] = array('from'=> $link[2], 'to'=>$replace);
  1391. }else{
  1392. $replace = $key . '=' . $translated_id;
  1393. $new_link = str_replace($query, $replace, $link[0]);
  1394. $replace_link_arr[$link_idx] = array('from'=> $query, 'to'=>$replace);
  1395. }
  1396. // replace the link in the body.
  1397. // $new_body = str_replace($link[0], $new_link, $new_body);
  1398. $all_links_arr[$link_idx] = array('from'=> $link[0], 'to'=>$new_link);
  1399. // done in the next loop
  1400. } else {
  1401. // translation not found for this.
  1402. $all_links_fixed = 0;
  1403. }
  1404. }
  1405. }
  1406. }
  1407. if(!empty($replace_link_arr))
  1408. foreach($replace_link_arr as $link_idx => $rep){
  1409. $rep_to = $rep['to'];
  1410. $fragment = '';
  1411. // if sticky links is not ON, fix query parameters and fragments
  1412. if(empty($GLOBALS['WPML_Sticky_Links'])){
  1413. if(!empty($pass_on_fragments[$link_idx])){
  1414. $fragment = '#' . $pass_on_fragments[$link_idx];
  1415. }
  1416. if(!empty($pass_on_qvars[$link_idx])){
  1417. $url_glue = (strpos($rep['to'], '?') === false) ? '?' : '&';
  1418. $rep_to = $rep['to'] . $url_glue . join('&', $pass_on_qvars[$link_idx]);
  1419. }
  1420. }
  1421. $all_links_arr[$link_idx]['to'] = str_replace($rep['to'], $rep_to . $fragment, $all_links_arr[$link_idx]['to']);
  1422. }
  1423. if(!empty($all_links_arr))
  1424. foreach($all_links_arr as $link){
  1425. $new_body = str_replace($link['from'], $link['to'], $new_body);
  1426. }
  1427. if ($new_body != $body){
  1428. // save changes to the database.
  1429. if(strpos($element_type, 'post') === 0){
  1430. $wpdb->update($wpdb->posts, array('post_content'=>$new_body), array('ID'=>$element_id));
  1431. // save the all links fixed status to the database.
  1432. $icl_element_type = 'post_' . $post->post_type;
  1433. $translation_id = $wpdb->get_var("SELECT translation_id FROM {$wpdb->prefix}icl_translations WHERE element_id={$element_id} AND element_type='{$icl_element_type}'");
  1434. $wpdb->query("UPDATE {$wpdb->prefix}icl_translation_status SET links_fixed='{$all_links_fixed}' WHERE translation_id={$translation_id}");
  1435. }elseif($element_type == 'string'){
  1436. $wpdb->update($wpdb->prefix.'icl_string_translations', array('value'=>$new_body), array('id'=>$element_id));
  1437. }
  1438. }
  1439. }
  1440. function fix_translated_children($original_id, $translated_id, $lang_code){
  1441. global $wpdb, $sitepress;
  1442. // get the children of of original page.
  1443. $original_children = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = {$original_id} AND post_type = 'page'");
  1444. foreach($original_children as $original_child){
  1445. // See if the child has a translation.
  1446. $trid = $sitepress->get_element_trid($original_child, 'post_page');
  1447. if($trid){
  1448. $translations = $sitepress->get_element_translations($trid, 'post_page');
  1449. if (isset($translations[$lang_code]) && isset($translations[$lang_code]->element_id)){
  1450. $current_parent = $wpdb->get_var("SELECT post_parent FROM {$wpdb->posts} WHERE ID = ".$translations[$lang_code]->element_id);
  1451. if ($current_parent != $translated_id){
  1452. $wpdb->query("UPDATE {$wpdb->posts} SET post_parent={$translated_id} WHERE ID = ".$translations[$lang_code]->element_id);
  1453. }
  1454. }
  1455. }
  1456. }
  1457. }
  1458. function fix_translated_parent($original_id, $translated_id, $lang_code){
  1459. global $wpdb, $sitepress;
  1460. $original_parent = $wpdb->get_var("SELECT post_parent FROM {$wpdb->posts} WHERE ID = {$original_id} AND post_type = 'page'");
  1461. if ($original_parent){
  1462. $trid = $sitepress->get_element_trid($original_parent, 'post_page');
  1463. if($trid){
  1464. $translations = $sitepress->get_element_translations($trid, 'post_page');
  1465. if (isset($translations[$lang_code])){
  1466. $current_parent = $wpdb->get_var("SELECT post_parent FROM {$wpdb->posts} WHERE ID = ".$translated_id);
  1467. if ($current_parent != $translations[$lang_code]->element_id){
  1468. $wpdb->query("UPDATE {$wpdb->posts} SET post_parent={$translations[$lang_code]->element_id} WHERE ID = ".$translated_id);
  1469. }
  1470. }
  1471. }
  1472. }
  1473. }
  1474. function _throw_exception_for_mysql_errors(){
  1475. global $EZSQL_ERROR, $sitepress_settings;
  1476. if(isset($sitepress_settings['troubleshooting_options']['raise_mysql_errors']) && $sitepress_settings['troubleshooting_options']['raise_mysql_errors']){
  1477. if(!empty($EZSQL_ERROR)){
  1478. foreach($EZSQL_ERROR as $k=>$v){
  1479. $mysql_errors[] = $v['error_str'] . ' [' . $v['query'] . ']';
  1480. }
  1481. throw new Exception(join("\n", $mysql_errors));
  1482. }
  1483. }
  1484. }
  1485. function _translation_error_handler($errno, $errstr, $errfile, $errline){
  1486. switch($errno){
  1487. case E_ERROR:
  1488. case E_USER_ERROR:
  1489. throw new Exception ($errstr . ' [code:e' . $errno . '] in '. $errfile . ':' . $errline);
  1490. case E_WARNING:
  1491. case E_USER_WARNING:
  1492. return true;
  1493. //throw new Exception ($errstr . ' [code:w' . $errno . '] in '. $errfile . ':' . $errline);
  1494. default:
  1495. return true;
  1496. }
  1497. }
  1498. function post_submitbox_start(){
  1499. global $post, $iclTranslationManagement;
  1500. if(empty($post)|| !$post->ID){
  1501. return;
  1502. }
  1503. $translations = $iclTranslationManagement->get_element_translations($post->ID, 'post_' . $post->post_type);
  1504. $show_box = 'display:none';
  1505. foreach($translations as $t){
  1506. if($t->element_id == $post->ID){
  1507. if(!empty($t->source_language_code)) return;
  1508. else continue;
  1509. }
  1510. if($t->status == ICL_TM_COMPLETE && !$t->needs_update){
  1511. $show_box = '';
  1512. break;
  1513. }
  1514. }
  1515. echo '<p id="icl_minor_change_box" style="float:left;padding:0;margin:3px;'.$show_box.'">';
  1516. echo '<label><input type="checkbox" name="icl_minor_edit" value="1" style="min-width:15px;" />&nbsp;';
  1517. echo __('Minor edit - don\'t update translation','sitepress');
  1518. echo '</label>';
  1519. echo '<br clear="all" />';
  1520. echo '</p>';
  1521. }
  1522. public function estimate_word_count($data, $lang_code) {
  1523. $words = 0;
  1524. if(isset($data->post_title)){
  1525. if(in_array($lang_code, self::$__asian_languages)){
  1526. $words += strlen(strip_tags($data->post_title)) / 6;
  1527. } else {
  1528. $words += count(explode(' ',$data->post_title));
  1529. }
  1530. }
  1531. if(isset($data->post_content)){
  1532. if(in_array($lang_code, self::$__asian_languages)){
  1533. $words += strlen(strip_tags($data->post_content)) / 6;
  1534. } else {
  1535. $words += count(explode(' ',strip_tags($data->post_content)));
  1536. }
  1537. }
  1538. return (int)$words;
  1539. }
  1540. function estimate_custom_field_word_count($post_id, $lang_code) {
  1541. global $sitepress_settings;
  1542. $words = 0;
  1543. $custom_fields = array();
  1544. foreach((array)$sitepress_settings['translation-management']['custom_fields_translation'] as $cf => $op){
  1545. if ($op == 2) {
  1546. $custom_fields[] = $cf;
  1547. }
  1548. }
  1549. foreach($custom_fields as $cf){
  1550. $custom_fields_value = get_post_meta($post_id, $cf, true);
  1551. if ($custom_fields_value != "" && is_scalar($custom_fields_value)) {
  1552. if(in_array($lang_code, self::$__asian_languages)){
  1553. $words += strlen(strip_tags($custom_fields_value)) / 6;
  1554. } else {
  1555. $words += count(explode(' ',strip_tags($custom_fields_value)));
  1556. }
  1557. }
  1558. }
  1559. return (int)$words;
  1560. }
  1561. public function get_translator_name($translator_id){
  1562. global $sitepress_settings;
  1563. static $translators;
  1564. if(is_null($translators)){
  1565. foreach($sitepress_settings['icl_lang_status'] as $lp){
  1566. if(!empty($lp['translators'])){
  1567. foreach($lp['translators'] as $tr){
  1568. $translators[$tr['id']] = $tr['nickname'];
  1569. }
  1570. }
  1571. }
  1572. }
  1573. if(isset($translators[$translator_id])){
  1574. return $translators[$translator_id];
  1575. }else{
  1576. return false;
  1577. }
  1578. }
  1579. function _xmlrpc_cancel_translation($args){
  1580. global $sitepress_settings, $sitepress, $wpdb;
  1581. $signature = $args[0];
  1582. $website_id = $args[1];
  1583. $request_id = $args[2];
  1584. $cms_id = $args[3];
  1585. $checksum = $sitepress_settings['access_key'] . $sitepress_settings['site_id'] . $request_id . $cms_id;
  1586. // decode cms_id
  1587. $int = preg_match('#(.+)_([0-9]+)_([^_]+)_([^_]+)#', $cms_id, $matches);
  1588. $_element_type = $matches[1];
  1589. $_element_id = $matches[2];
  1590. $_original_lang = $matches[3];
  1591. $_lang = $matches[4];
  1592. $trid = $sitepress->get_element_trid($_element_id, 'post_' . $_element_type);
  1593. if (sha1 ( $checksum ) == $signature) {
  1594. $wid = $sitepress_settings['site_id'];
  1595. if ($website_id == $wid) {
  1596. $translation_entry = $wpdb->get_row("SELECT *
  1597. FROM {$wpdb->prefix}icl_translation_status s JOIN {$wpdb->prefix}icl_translations t ON t.translation_id = s.translation_id
  1598. WHERE t.trid={$trid} AND t.language_code='{$_lang}'");
  1599. if (empty($translation_entry)){
  1600. return 4; // cms_request not found
  1601. }
  1602. $job_id = $wpdb->get_var($wpdb->prepare("SELECT job_id FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d AND revision IS NULL", $translation_entry->rid));
  1603. if($job_id){
  1604. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_translate_job WHERE job_id=%d", $job_id));
  1605. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_translate WHERE job_id=%d", $job_id));
  1606. $wpdb->query($wpdb->prepare("UPDATE {$wpdb->prefix}icl_translate_job SET revision = NULL WHERE rid=%d ORDER BY job_id DESC LIMIT 1", $translation_entry->rid));
  1607. }
  1608. if(!empty($translation_entry->_prevstate)){
  1609. $_prevstate = unserialize($translation_entry->_prevstate);
  1610. $wpdb->update($wpdb->prefix . 'icl_translation_status',
  1611. array(
  1612. 'status' => $_prevstate['status'],
  1613. 'translator_id' => $_prevstate['translator_id'],
  1614. 'status' => $_prevstate['status'],
  1615. 'needs_update' => $_prevstate['needs_update'],
  1616. 'md5' => $_prevstate['md5'],
  1617. 'translation_service' => $_prevstate['translation_service'],
  1618. 'translation_package' => $_prevstate['translation_package'],
  1619. 'timestamp' => $_prevstate['timestamp'],
  1620. 'links_fixed' => $_prevstate['links_fixed']
  1621. ),
  1622. array('translation_id'=>$translation_entry->translation_id)
  1623. );
  1624. $wpdb->query($wpdb->prepare("UPDATE {$wpdb->prefix}icl_translation_status SET _prevstate = NULL WHERE translation_id=%d",$translation_entry->translation_id));
  1625. }else{
  1626. $wpdb->update($wpdb->prefix . 'icl_translation_status', array('status'=>ICL_TM_NOT_TRANSLATED, 'needs_update'=>0), array('translation_id'=>$translation_entry->translation_id));
  1627. }
  1628. return 1;
  1629. } else {
  1630. return 3; // Website id incorrect
  1631. }
  1632. } else {
  1633. return 2; // Signature failed
  1634. }
  1635. return 0; // Should not have got here - unknown error.
  1636. }
  1637. function _legacy_xmlrpc_cancel_translation($args){
  1638. global $sitepress_settings, $sitepress, $wpdb;
  1639. $signature = $args[0];
  1640. $website_id = $args[1];
  1641. $request_id = $args[2];
  1642. $accesskey = $sitepress_settings['access_key'];
  1643. $checksum = $accesskey . $website_id . $request_id;
  1644. $args['sid'] = sha1 ( $checksum );
  1645. if (sha1 ( $checksum ) == $signature) {
  1646. $wid = $sitepress_settings['site_id'];
  1647. if ($website_id == $wid) {
  1648. $cms_request_info = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}icl_core_status WHERE rid={$request_id}");
  1649. if (empty($cms_request_info)){
  1650. return 4; // cms_request not found
  1651. }
  1652. // cms_request have been found.
  1653. // delete it
  1654. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_core_status WHERE rid={$request_id}");
  1655. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_content_status WHERE rid={$request_id}");
  1656. // find cms_id
  1657. $nid = $wpdb->get_var($wpdb->prepare("SELECT nid FROM {$wpdb->prefix}icl_content_status WHERE rid=%d", $request_id));
  1658. if($nid){
  1659. $trid = $wpdb->get_var($wpdb->prepare("
  1660. SELECT trid FROM {$wpdb->prefix}icl_translations
  1661. WHERE element_id=%d AND post_type LIKE 'post\_%'", $nid)
  1662. );
  1663. $translation = $wpdb->get_row($wpdb->prepare("SELECT translation_id FROM {$wpdb->prefix}icl_translations
  1664. WHERE trid=%d AND language_code=%s", $trid, $cms_request_info->target)
  1665. );
  1666. $original_element_id = $wpdb->get_var($wpdb->prepare("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND language_code=%s",
  1667. $translation->trid, $translation->source_language_code));
  1668. $cms_id = sprintf('%s_%d_%s_%s', preg_replace('#^post_#','', $translation->element_type, $original_element_id, $translation->source_language_code, $translation->language_code)); }
  1669. if($cms_id){
  1670. $args[3] = $cms_id;
  1671. return $this->_xmlrpc_cancel_translation($args);
  1672. }
  1673. return 1;
  1674. } else {
  1675. return 3; // Website id incorrect
  1676. }
  1677. } else {
  1678. return 2; // Signature failed
  1679. }
  1680. return 0; // Should not have got here - unknown error.
  1681. }
  1682. function _test_xmlrpc(){ return true; }
  1683. function _xmlrpc_add_message_translation($args){
  1684. global $wpdb, $sitepress, $sitepress_settings, $wpml_add_message_translation_callbacks;
  1685. $signature = $args[0];
  1686. $site_id = $args[1];
  1687. $rid = $args[2];
  1688. $translation = $args[3];
  1689. $signature_check = md5($sitepress_settings['access_key'] . $sitepress_settings['site_id'] . $rid);
  1690. if($signature != $signature_check){
  1691. return 0; // array('err_code'=>1, 'err_str'=> __('Signature mismatch','sitepress'));
  1692. }
  1693. $res = $wpdb->get_row("SELECT to_language, object_id, object_type FROM {$wpdb->prefix}icl_message_status WHERE rid={$rid}");
  1694. if(!$res){
  1695. return 0;
  1696. }
  1697. $to_language = $res->to_language;
  1698. $object_id = $res->object_id;
  1699. $object_type = $res->object_type;
  1700. try{
  1701. if(is_array($wpml_add_message_translation_callbacks[$object_type])){
  1702. foreach($wpml_add_message_translation_callbacks[$object_type] as $callback){
  1703. if ( !is_null($callback) ) {
  1704. call_user_func($callback, $object_id, $to_language, $translation);
  1705. }
  1706. }
  1707. }
  1708. $wpdb->update($wpdb->prefix.'icl_message_status', array('status'=>MESSAGE_TRANSLATION_COMPLETE), array('rid'=>$rid));
  1709. }catch(Exception $e){
  1710. return $e->getMessage().'[' . $e->getFile() . ':' . $e->getLine() . ']';
  1711. }
  1712. return 1;
  1713. }
  1714. function get_jobs_in_progress(){
  1715. global $wpdb;
  1716. $jip = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->prefix}icl_translation_status WHERE status=%d AND translation_service='icanlocalize'", ICL_TM_IN_PROGRESS));
  1717. return $jip;
  1718. }
  1719. function get_strings_in_progress(){
  1720. global $wpdb;
  1721. $sip = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->prefix}icl_core_status WHERE status < %d", 3));
  1722. return $sip;
  1723. }
  1724. function poll_for_translations($force = false){
  1725. global $sitepress_settings, $sitepress, $wpdb;
  1726. if (!$force) {
  1727. // Limit to once per hour
  1728. $toffset = strtotime(current_time('mysql')) - @intval($sitepress_settings['last_picked_up']) - 3600;
  1729. if($toffset < 0 || $force){
  1730. return 0;
  1731. }
  1732. }
  1733. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  1734. $pending = $iclq->cms_requests();
  1735. $fetched = 0;
  1736. if(!empty($pending)){
  1737. foreach($pending as $doc){
  1738. if(empty($doc['cms_id'])){ // it's a string
  1739. $target = $wpdb->get_var($wpdb->prepare("SELECT target FROM {$wpdb->prefix}icl_core_status WHERE rid=%d", $doc['id']));
  1740. $__ld = $sitepress->get_language_details($target);
  1741. $language = $this->server_languages_map($__ld['english_name']);
  1742. $ret = $this->process_translated_string($doc['id'], $language);
  1743. if($ret){
  1744. $fetched++;
  1745. }
  1746. }else{
  1747. // decode cms_id
  1748. $int = preg_match('#(.+)_([0-9]+)_([^_]+)_([^_]+)#', $doc['cms_id'], $matches);
  1749. $_element_type = $matches[1];
  1750. $_element_id = $matches[2];
  1751. $_original_lang = $matches[3];
  1752. $_lang = $matches[4];
  1753. $trid = $sitepress->get_element_trid($_element_id, 'post_'. $_element_type);
  1754. $translation = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND language_code=%s", $trid, $_lang));
  1755. $ret = $this->add_translated_document($translation->translation_id, $doc['id']);
  1756. if($ret){
  1757. $fetched++;
  1758. }
  1759. }
  1760. }
  1761. }
  1762. $iclsettings['last_picked_up'] = strtotime(current_time('mysql'));
  1763. $sitepress->save_settings($iclsettings);
  1764. return $fetched;
  1765. }
  1766. function get_icl_manually_tranlations_box($wrap_class=""){
  1767. global $sitepress_settings;
  1768. if(isset($_GET['icl_pick_message'])){
  1769. ?>
  1770. <span id="icl_tm_pickup_wrap"><p><?php echo esc_html($_GET['icl_pick_message']) ?></p></div>
  1771. <?php
  1772. }
  1773. if($sitepress_settings['translation_pickup_method'] == ICL_PRO_TRANSLATION_PICKUP_POLLING
  1774. && ($job_in_progress = $this->get_jobs_in_progress() || $this->get_strings_in_progress()))
  1775. {
  1776. $last_time_picked_up = !empty($sitepress_settings['last_picked_up']) ? date_i18n('Y, F jS @g:i a', $sitepress_settings['last_picked_up']) : __('never', 'sitepress');
  1777. $toffset = strtotime(current_time('mysql')) - @intval($sitepress_settings['last_picked_up']) - 5 * 60;
  1778. if($toffset < 0){
  1779. $gettdisabled = ' disabled="disabled" ';
  1780. $waittext = '<p><i>' . sprintf(__('You can check again in %s minutes.', 'sitepress'), '<span id="icl_sec_tic">' . floor(abs($toffset)/60) . '</span>') . '</i></p>';
  1781. }else{
  1782. $waittext = '';
  1783. $gettdisabled = '';
  1784. }
  1785. ?>
  1786. <span id="icl_tm_pickup_wrap">
  1787. <div class="<?php echo $wrap_class ?>">
  1788. <p><?php printf(__('%d job(s) sent to ICanLocalize.', 'sitepress'), $job_in_progress); ?></p>
  1789. <p><input type="button" class="button-secondary" value="<?php _e('Get completed translations', 'sitepress')?>" id="icl_tm_get_translations"<?php echo $gettdisabled ?>/><?php echo $waittext ?></p>
  1790. <?php wp_nonce_field('pickup_translations_nonce', '_icl_nonce_pickt'); ?>
  1791. <p><?php printf(__('Last time translations were picked up: %s', 'sitepress'), $last_time_picked_up) ?></p>
  1792. </div></span>
  1793. <br clear="all" />
  1794. <?php
  1795. }
  1796. }
  1797. }
  1798. ?>