WCML_Editor_UI_Product_Job

The WooCommerce Multilingual WCML Editor UI Product Job class.

Defined (1)

The class is defined in the following location(s).

/inc/translation-editor/class-wcml-editor-ui-product-job.php  
  1. class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job { 
  2.  
  3. private $data = array(); 
  4. private $woocommerce_wpml; 
  5. /** 
  6. * @var SitePress 
  7. */ 
  8. private $sitepress; 
  9. /** 
  10. * @var TranslationManagement 
  11. */ 
  12. private $tm_instance; 
  13. /** 
  14. * @var WPDB 
  15. */ 
  16. private $wpdb; 
  17. private $job_details; 
  18. private $product; 
  19. private $product_id; 
  20. private $product_type; 
  21. private $not_display_fields_for_variables_product; 
  22.  
  23. function __construct( $job_details, &$woocommerce_wpml, &$sitepress, &$wpdb ) { 
  24. global $iclTranslationManagement; 
  25.  
  26. $this->woocommerce_wpml =& $woocommerce_wpml; 
  27. $this->sitepress =& $sitepress; 
  28. $this->tm_instance =& $iclTranslationManagement; 
  29. $this->wpdb =& $wpdb; 
  30. $this->not_display_fields_for_variables_product = array( '_purchase_note', '_regular_price', '_sale_price',  
  31. '_price', '_min_variation_price', '_max_variation_price',  
  32. '_min_variation_regular_price', '_max_variation_regular_price',  
  33. '_min_variation_sale_price', '_max_variation_sale_price', '_downloadable_files' ); 
  34.  
  35. $this->job_details = $job_details; 
  36. $this->product = wc_get_product( $job_details[ 'job_id' ] ); 
  37. $this->original_post = get_post( $job_details[ 'job_id' ] ); 
  38. $this->product_id = WooCommerce_Functions_Wrapper::get_product_id( $this->product ); 
  39. $this->product_type = WooCommerce_Functions_Wrapper::get_product_type( $this->product_id ); 
  40.  
  41. $source_lang = $this->sitepress->get_language_for_element( $job_details[ 'job_id' ], 'post_product' ); 
  42. $target_lang = $job_details[ 'target']; 
  43. $translation_complete = $this->is_translation_complete(); 
  44. $duplicate = $this->is_duplicate(); 
  45.  
  46. parent::__construct( 
  47. $job_details[ 'job_id' ],  
  48. 'wc_product', __( 'Product', 'woocommerce-multilingual' ),  
  49. $this->original_post->post_title,  
  50. get_post_permalink( WooCommerce_Functions_Wrapper::get_product_id( $this->product ) ),  
  51. $source_lang,  
  52. $target_lang,  
  53. $translation_complete,  
  54. $duplicate 
  55. ); 
  56.  
  57. $this->data = $this->get_data(); 
  58.  
  59. $this->add_elements(); 
  60.  
  61. public function is_translation_complete() { 
  62.  
  63. $translation_complete = false; 
  64.  
  65. $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_product' ); 
  66. $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true ); 
  67. if ( isset( $this->job_details[ 'translation_complete' ] ) ) { 
  68. $translation_complete = $this->job_details[ 'translation_complete' ]; 
  69. } else if ( isset( $product_translations[ $this->get_target_language() ] ) ) { 
  70. $tr_status = $this->wpdb->get_var( 
  71. $this->wpdb->prepare(" 
  72. SELECT status FROM {$this->wpdb->prefix}icl_translation_status 
  73. WHERE translation_id = %d", $product_translations[ $this->get_target_language() ]->translation_id 
  74. ); 
  75.  
  76. $translation_complete = $tr_status === ICL_TM_COMPLETE; 
  77.  
  78. return $translation_complete; 
  79.  
  80. public function is_duplicate() { 
  81.  
  82. $is_duplicate_product = false; 
  83.  
  84. $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_product' ); 
  85. $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true ); 
  86. if ( isset( $product_translations[ $this->get_target_language() ] ) && get_post_meta( $product_translations[ $this->get_target_language() ]->element_id, '_icl_lang_duplicate_of', true ) === $this->product_id ) { 
  87. $is_duplicate_product = true; 
  88.  
  89. return $is_duplicate_product; 
  90.  
  91. public function add_elements( ) { 
  92.  
  93. $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'title', __( 'Title', 'woocommerce-multilingual' ), $this->data, true ) ); 
  94. $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'slug', __( 'Slug', 'woocommerce-multilingual' ), $this->data, true ) ); 
  95.  
  96. if( $this->woocommerce_wpml->page_builders->get_page_builders_string_packages( $this->product_id ) ) { 
  97. $page_builders_strings_section = $this->woocommerce_wpml->page_builders->get_page_builders_strings_section( $this->data, $this->product_id, $this->get_target_language() ); 
  98.  
  99. if( $page_builders_strings_section ) { 
  100. $this->add_field( $page_builders_strings_section ); 
  101. }else{ 
  102. $this->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_content', __( 'Content / Description', 'woocommerce-multilingual' ), $this->data, true ) ); 
  103.  
  104. $excerpt_section = new WPML_Editor_UI_Field_Section( __( 'Excerpt', 'woocommerce-multilingual' ) ); 
  105. $excerpt_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_excerpt', null, $this->data, true ) ); 
  106. $this->add_field( $excerpt_section ); 
  107.  
  108. $purchase_note_section = new WPML_Editor_UI_Field_Section( __( 'Purchase note', 'woocommerce-multilingual' ) ); 
  109. $purchase_note_section->add_field( new WPML_Editor_UI_TextArea_Field( '_purchase_note', null, $this->data, true ) ); 
  110. $this->add_field( $purchase_note_section ); 
  111.  
  112. /** 
  113. * Images 
  114. */ 
  115. $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id ); 
  116. // Exclude not-duplicated attachments and featured 
  117. $product_images = $this->woocommerce_wpml->media->exclude_not_duplicated_attachments( $product_images, $this->product_id ); 
  118.  
  119. if ( count( $product_images ) ) { 
  120.  
  121. $images_section = new WPML_Editor_UI_Field_Section( __( 'Images', 'woocommerce-multilingual' ) ); 
  122. foreach( $product_images as $image_id ) { 
  123. $image = new WPML_Editor_UI_Field_Image( 'image-id-' . $image_id, $image_id, $this->data, true ); 
  124. $images_section->add_field( $image ); 
  125. $this->add_field( $images_section ); 
  126.  
  127. $attributes = $this->get_custom_product_atributes( ); 
  128. if ( $attributes ) { 
  129. $attributes_section = new WPML_Editor_UI_Field_Section( __( 'Custom Product attributes', 'woocommerce-multilingual' ) ); 
  130. foreach( $attributes as $attr_key => $attribute ) { 
  131. $group = new WPML_Editor_UI_Field_Group( '', true ); 
  132. $attribute_field = new WPML_Editor_UI_Single_Line_Field( $attr_key . '_name', __( 'Name', 'woocommerce-multilingual' ), $this->data, false ); 
  133. $group->add_field( $attribute_field ); 
  134. $attribute_field = new WPML_Editor_UI_Single_Line_Field( $attr_key , __( 'Value(s)', 'woocommerce-multilingual' ), $this->data, false ); 
  135. $group->add_field( $attribute_field ); 
  136. $attributes_section->add_field( $group ); 
  137. $this->add_field( $attributes_section ); 
  138.  
  139. $custom_fields = $this->get_product_custom_fields_to_translate( $this->product_id ); 
  140.  
  141.  
  142. if( $this->product_type === 'external' ) { 
  143. $custom_fields = array_diff( $custom_fields, array( '_product_url', '_button_text' ) ); 
  144.  
  145. if( $custom_fields ) { 
  146.  
  147. $custom_fields_section = new WPML_Editor_UI_Field_Section( __( 'Custom Fields', 'woocommerce-multilingual' ) ); 
  148.  
  149. foreach( $custom_fields as $custom_field ) { 
  150.  
  151. $cf_settings = new WPML_Post_Custom_Field_Setting( $this->tm_instance, $custom_field ); 
  152. switch( $cf_settings->get_editor_style() ) { 
  153. case 'visual': 
  154. $cf_field = new WPML_Editor_UI_WYSIWYG_Field( $custom_field, $cf_settings->get_editor_label(), $this->data, true ); 
  155. break; 
  156. case 'textarea': 
  157. $cf_field = new WPML_Editor_UI_TextArea_Field( $custom_field, $cf_settings->get_editor_label(), $this->data, true ); 
  158. break; 
  159. default: //line 
  160. $cf_field = new WPML_Editor_UI_Single_Line_Field( $custom_field, $cf_settings->get_editor_label(), $this->data, true ); 
  161.  
  162. $custom_fields_section->add_field( $cf_field ); 
  163.  
  164.  
  165. $this->add_field( $custom_fields_section ); 
  166.  
  167. if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ) { 
  168. $variations = $this->product->get_available_variations(); 
  169.  
  170. if( !empty( $variations ) ) { 
  171. $variations_data_section = new WPML_Editor_UI_Field_Section( __( 'Variations data', 'woocommerce-multilingual' ) ); 
  172. foreach( $variations as $variation ) { 
  173. $var_custom_fields = $this->get_product_custom_fields_to_translate( $variation[ 'variation_id' ] ); 
  174. if( $var_custom_fields ) { 
  175. $this->add_custom_fields_ui_section( $variations_data_section, $var_custom_fields, $variation[ 'variation_id' ] ); 
  176. $this->add_field( $variations_data_section ); 
  177.  
  178. if( $this->product->is_downloadable() ) { 
  179. $is_variable = false; 
  180. if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ) { 
  181. $files_data = $this->get_files_for_variations(); 
  182. $is_variable = true; 
  183. }else{ 
  184. $files_data = array( $this->product_id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product_id ) ); 
  185.  
  186. foreach( $files_data as $post_id => $file_data ) { 
  187. $custom_product_sync = get_post_meta( $post_id, 'wcml_sync_files', true ); 
  188. if ( ( $custom_product_sync && $custom_product_sync === 'self' ) || ( ! $custom_product_sync && ! $this->woocommerce_wpml->settings['file_path_sync'] ) ) { 
  189.  
  190. if( $is_variable ) { 
  191. $files_section = new WPML_Editor_UI_Field_Section( sprintf( __( 'Download Files for Variation #%s', 'woocommerce-multilingual' ), $post_id ) ); 
  192. }else{ 
  193. $files_section = new WPML_Editor_UI_Field_Section( __( 'Download Files', 'woocommerce-multilingual' ) ); 
  194.  
  195. foreach( $file_data as $key => $file ) { 
  196. $sub_group = new WPML_Editor_UI_Field_Group(); 
  197. $field_input = new WPML_Editor_UI_Single_Line_Field( 'file-name'.$key.$post_id, __( 'Name', 'woocommerce-multilingual' ), $this->data, false ); 
  198. $sub_group->add_field( $field_input ); 
  199. $field_input = new WPML_Editor_UI_Single_Line_Field( 'file-url'.$key.$post_id, __( 'File URL', 'woocommerce-multilingual' ), $this->data, false ); 
  200. $sub_group->add_field( $field_input ); 
  201.  
  202. $files_section->add_field( $sub_group ); 
  203.  
  204. if( $is_variable ) { 
  205. $this->add_field( $files_section ); 
  206.  
  207.  
  208. if( isset( $files_section ) && !$is_variable ) { 
  209. $this->add_field( $files_section ); 
  210.  
  211. $taxonomies = get_object_taxonomies( 'product', 'objects' ); 
  212. foreach( $taxonomies as $taxonomy => $taxonomy_obj ) { 
  213. if( $taxonomy != 'product_type' && is_taxonomy_translated( $taxonomy ) ) { 
  214. $product_terms = wp_get_post_terms( $this->product_id, $taxonomy ); 
  215. if( $product_terms ) { 
  216. $tax_section = new WPML_Editor_UI_Field_Section( $taxonomy_obj->label, __( 'Changes in these translations will affect terms in general! ( Not only for this product )', 'woocommerce-multilingual' )); 
  217. foreach( $product_terms as $term ) { 
  218. if( 
  219. $this->sitepress->get_setting( 'tm_block_retranslating_terms' ) && 
  220. !is_null( apply_filters( 'translate_object_id', $term->term_id, $taxonomy, false, $this->get_target_language() ) ) 
  221. ) { 
  222. continue; 
  223. $term_field = new WPML_Editor_UI_Single_Line_Field( 't_'. $term->term_id, '', $this->data, false ); 
  224. $tax_section->add_field( $term_field ); 
  225. if( isset( $term_field ) ) { 
  226. $this->add_field( $tax_section ); 
  227.  
  228. if( $this->product_type === 'external' ) { 
  229. $external_product_section = new WPML_Editor_UI_Field_Section( __( 'External Product', 'woocommerce-multilingual' ) ); 
  230. $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_product_url', __( 'Product url', 'woocommerce-multilingual' ), $this->data, true ) ); 
  231. $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_button_text', __( 'Button text', 'woocommerce-multilingual' ), $this->data, true ) ); 
  232. $this->add_field( $external_product_section ); 
  233.  
  234. do_action( 'wcml_gui_additional_box_html', $this, $this->product_id, $this->data ); 
  235.  
  236.  
  237. public function add_custom_fields_ui_section( $custom_fields_section, $custom_fields, $variation_id = false ) { 
  238.  
  239. foreach( $custom_fields as $custom_field ) { 
  240.  
  241. $custom_field_id = $variation_id ? $custom_field.$variation_id : $custom_field; 
  242.  
  243. if( key( $this->data[ $custom_field_id ] ) != 'original' ) { 
  244. $group = new WPML_Editor_UI_Field_Group( $this->get_product_custom_field_label( $custom_field, $variation_id ), true ); 
  245. foreach( $this->data[ $custom_field_id ] as $custom_field_key => $custom_field_array ) { 
  246. if( $custom_field == '_variation_description' ) { 
  247. $custom_field_input = new WPML_Editor_UI_TextArea_Field( $custom_field_key, '', $this->data[ $custom_field_id ], false ); 
  248. }else{ 
  249. $custom_field_input = new WPML_Editor_UI_Single_Line_Field( $custom_field_key, '', $this->data[ $custom_field_id ], false ); 
  250.  
  251. $group->add_field( $custom_field_input ); 
  252. $custom_fields_section->add_field( $group ); 
  253. }else{ 
  254. if( $custom_field == '_variation_description' ) { 
  255. $custom_field_input = new WPML_Editor_UI_TextArea_Field( $custom_field_id, $this->get_product_custom_field_label( $custom_field, $variation_id ), $this->data, true ); 
  256. }else{ 
  257. $custom_field_input = new WPML_Editor_UI_Single_Line_Field( $custom_field_id, $this->get_product_custom_field_label( $custom_field, $variation_id ), $this->data, true ); 
  258. $custom_fields_section->add_field( $custom_field_input ); 
  259.  
  260.  
  261. /** 
  262. * @return array 
  263. */ 
  264. function get_data() { 
  265.  
  266. $trn_product_id = apply_filters( 'translate_object_id', $this->product_id, 'product', false, $this->get_target_language() ); 
  267. $translation = false; 
  268. $is_variable_product = $this->woocommerce_wpml->products->is_variable_product( $this->product_id ); 
  269. if ( null !== $trn_product_id ) { 
  270. $translation = get_post( $trn_product_id ); 
  271.  
  272. $element_data = array( 'title' => array( 'original' => $this->original_post->post_title ),  
  273. 'slug' => array( 'original' => urldecode( $this->original_post->post_name ) ),  
  274. 'product_excerpt' => array( 'original' => $this->original_post->post_excerpt ),  
  275. '_purchase_note' => array( 'original' => get_post_meta( $this->product_id, '_purchase_note', true ) ) 
  276. ); 
  277.  
  278. if ( $translation ) { 
  279. $element_data[ 'title' ][ 'translation' ] = $translation->post_title; 
  280. $element_data[ 'slug' ][ 'translation' ] = urldecode( $translation->post_name ); 
  281. $element_data[ 'product_excerpt' ][ 'translation' ] = $translation->post_excerpt; 
  282. $element_data[ '_purchase_note' ][ 'translation' ] = get_post_meta( $translation->ID, '_purchase_note', true ); 
  283.  
  284. if( $this->woocommerce_wpml->page_builders->get_page_builders_string_packages( $this->product_id ) ) { 
  285. $element_data = $this->woocommerce_wpml->page_builders->page_builders_data( $element_data, $this->product_id, $this->get_target_language() ); 
  286. }else{ 
  287. $element_data[ 'product_content' ] = array( 
  288. 'original' => $this->original_post->post_content 
  289. ); 
  290. if ( $translation ) { 
  291. $element_data[ 'product_content' ][ 'translation' ] = $translation->post_content; 
  292.  
  293. $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id ); 
  294. foreach( $product_images as $image_id ) { 
  295. $attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title, post_excerpt, post_content FROM {$this->wpdb->posts} WHERE ID = %d", $image_id ) ); 
  296. if( !$attachment_data ) continue; 
  297. $alt_text = get_post_meta( $image_id, '_wp_attachment_image_alt', true ); 
  298. $alt_text = $alt_text ? $alt_text : ''; 
  299. $element_data[ 'image-id-' . $image_id . '-title' ] = array( 'original' => $attachment_data->post_title ); 
  300. $element_data[ 'image-id-' . $image_id . '-caption' ] = array( 'original' => $attachment_data->post_excerpt ); 
  301. $element_data[ 'image-id-' . $image_id . '-description' ] = array( 'original' => $attachment_data->post_content ); 
  302. $element_data[ 'image-id-' . $image_id . '-alt-text' ] = array( 'original' => $alt_text ); 
  303.  
  304. $trnsl_prod_image = apply_filters( 'translate_object_id', $image_id, 'attachment', false, $this->get_target_language() ); 
  305. if ( null !== $trnsl_prod_image ) { 
  306. $trnsl_attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title, post_excerpt, post_content FROM {$this->wpdb->posts} WHERE ID = %d", $trnsl_prod_image ) ); 
  307. $alt_text = get_post_meta( $trnsl_prod_image, '_wp_attachment_image_alt', true ); 
  308. $alt_text = $alt_text ? $alt_text : ''; 
  309. $element_data[ 'image-id-' . $image_id . '-title' ][ 'translation' ] = $trnsl_attachment_data->post_title; 
  310. $element_data[ 'image-id-' . $image_id . '-caption' ][ 'translation' ] = $trnsl_attachment_data->post_excerpt; 
  311. $element_data[ 'image-id-' . $image_id . '-description' ][ 'translation' ] = $trnsl_attachment_data->post_content; 
  312. $element_data[ 'image-id-' . $image_id . '-alt-text' ][ 'translation' ] = $alt_text; 
  313.  
  314. $attributes = $this->get_custom_product_atributes( ); 
  315. if( $attributes ) { 
  316. foreach( $attributes as $attr_key => $attribute ) { 
  317. $element_data[ $attr_key.'_name' ] = array( 'original' => $attribute['name'] ); 
  318. $element_data[ $attr_key ] = array( 'original' => $attribute['value'] ); 
  319.  
  320. $trn_attribute = $this->woocommerce_wpml->attributes->get_custom_attribute_translation( $this->product_id, $attr_key, $attribute, $this->get_target_language() ); 
  321.  
  322. $element_data[ $attr_key.'_name' ][ 'translation' ] = $trn_attribute['name'] ? $trn_attribute['name'] : ''; 
  323. $element_data[ $attr_key ][ 'translation' ] = $trn_attribute['value'] ? $trn_attribute['value'] : ''; 
  324.  
  325. $taxonomies = get_object_taxonomies( 'product', 'objects' ); 
  326. foreach( $taxonomies as $taxonomy => $taxonomy_obj ) { 
  327. if( $taxonomy != 'product_type' && is_taxonomy_translated( $taxonomy ) ) { 
  328. $product_terms = wp_get_post_terms( $this->product_id, $taxonomy ); 
  329. if( $product_terms ) { 
  330. foreach( $product_terms as $term ) { 
  331. $translated_term = $this->woocommerce_wpml->terms->wcml_get_translated_term( $term->term_id, $taxonomy, $this->get_target_language() ); 
  332. if( 
  333. $this->sitepress->get_setting( 'tm_block_retranslating_terms' ) && 
  334. $translated_term->term_id != $term->term_id 
  335. ) { 
  336. continue; 
  337.  
  338. $element_data[ 't_'.$term->term_id ] = array( 'original' => $term->name ); 
  339. $element_data[ 't_'.$term->term_id ][ 'translation' ] = $translated_term->term_id != $term->term_id ? $translated_term->name : ''; 
  340.  
  341. $element_data = $this->add_custom_field_to_element_data( $element_data, $this->product_id, isset( $translation->ID ) ? $translation->ID : false, false ); 
  342.  
  343. if( $is_variable_product ) { 
  344. $variations = $this->product->get_available_variations(); 
  345.  
  346. if( !empty( $variations ) ) { 
  347. foreach( $variations as $variation ) { 
  348. $element_data[ '_variation_description'.$variation[ 'variation_id' ] ] = array( 'original' => strip_tags( $variation[ 'variation_description' ] ) ); 
  349. $translated_variation_id = apply_filters( 'translate_object_id', $variation[ 'variation_id' ], 'product_variation', false, $this->get_target_language() ); 
  350. $element_data[ '_variation_description'.$variation[ 'variation_id' ] ][ 'translation' ] = $translated_variation_id ? get_post_meta( $translated_variation_id, '_variation_description', true ) : ''; 
  351.  
  352. $element_data = $this->add_custom_field_to_element_data( $element_data, $variation[ 'variation_id' ], $translated_variation_id, true ); 
  353.  
  354.  
  355. $files_data = array( $this->product_id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product_id ) ); 
  356. if( $is_variable_product ) { 
  357. $files_data = $this->get_files_for_variations(); 
  358.  
  359. foreach( $files_data as $post_id => $file_data ) { 
  360.  
  361. $custom_product_sync = get_post_meta( $post_id, 'wcml_sync_files', true); 
  362. if ( ( $custom_product_sync && $custom_product_sync === 'self' ) || ( ! $custom_product_sync && ! $this->woocommerce_wpml->settings['file_path_sync'] ) ) { 
  363. $orig_product_files = $file_data; 
  364. $trnsl_product_files = array(); 
  365. if( $is_variable_product ) { 
  366. $trnsl_variation_id = apply_filters( 'translate_object_id', $post_id, 'product_variation', false, $this->get_target_language() ); 
  367. if( $trnsl_variation_id ) { 
  368. $trnsl_product_files = $this->woocommerce_wpml->downloadable->get_files_data( $trnsl_variation_id ); 
  369. }elseif ( isset( $translation->ID ) && $translation->ID ) { 
  370. $trnsl_product_files = $this->woocommerce_wpml->downloadable->get_files_data( $translation->ID ); 
  371.  
  372. foreach ($orig_product_files as $key => $product_file) { 
  373.  
  374. $element_data['file-name' . $key.$post_id] = array('original' => $product_file['label']); 
  375. $element_data['file-url' . $key.$post_id] = array('original' => $product_file['value']); 
  376.  
  377.  
  378. $element_data['file-name' . $key.$post_id]['translation'] = isset( $trnsl_product_files[$key] ) ? $trnsl_product_files[$key]['label'] : ''; 
  379. $element_data['file-url' . $key.$post_id]['translation'] = isset( $trnsl_product_files[$key] ) ? $trnsl_product_files[$key]['value'] : ''; 
  380.  
  381. $element_data = apply_filters( 'wcml_gui_additional_box_data', $element_data, $this->product_id, $translation, $this->get_target_language() ); 
  382.  
  383. return $element_data; 
  384.  
  385. public function add_custom_field_to_element_data( $element_data, $element_id, $translation_id, $is_variation = false ) { 
  386. $custom_fields = $this->get_product_custom_fields_to_translate( $element_id ); 
  387. if( $custom_fields ) { 
  388. foreach( $custom_fields as $custom_field ) { 
  389. $orig_custom_field_values = get_post_meta( $element_id, $custom_field ); 
  390. $trnsl_custom_field_values = array(); 
  391. $trnsl_mid_ids = array(); 
  392.  
  393. if ( $translation_id ) { 
  394. $trnsl_custom_field_values = get_post_meta( $translation_id, $custom_field ); 
  395. $trnsl_mid_ids = $this->woocommerce_wpml->products->get_mid_ids_by_key( $translation_id, $custom_field ); 
  396.  
  397. if( $is_variation ) { 
  398. $custom_field .= $element_id; 
  399.  
  400. foreach( $orig_custom_field_values as $val_key => $orig_custom_field_value ) { 
  401. if( count( $orig_custom_field_values ) == 1 ) { 
  402. $element_data[ $custom_field ] = array( 'original' => $orig_custom_field_value ); 
  403. $element_data[ $custom_field ][ 'translation' ] = ( $translation_id && isset( $trnsl_custom_field_values[ $val_key ] ) ) ? $trnsl_custom_field_values[ $val_key ] : ''; 
  404. }else{ 
  405.  
  406. $custom_field_key = $custom_field.':'. ( isset( $trnsl_mid_ids[ $val_key ] ) ? $trnsl_mid_ids[ $val_key ] : 'new_'. $val_key ); 
  407.  
  408. $element_data[ $custom_field ][ $custom_field_key ] = array( 'original' => $orig_custom_field_value ); 
  409. $element_data[ $custom_field ][ $custom_field_key ][ 'translation' ] = ($translation_id && isset( $trnsl_custom_field_values[ $val_key ] ) ) ? $trnsl_custom_field_values[ $val_key ] : ''; 
  410.  
  411. return $element_data; 
  412.  
  413. public function save_translations( $translations ) { 
  414. /** @var TranslationManagement $iclTranslationManagement */ 
  415. global $iclTranslationManagement; 
  416.  
  417. $return = array(); 
  418.  
  419. if ( $this->original_post->post_type !== 'product' ) { 
  420. return $return; 
  421.  
  422. $languages = $this->sitepress->get_active_languages(); 
  423.  
  424. $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_' . $this->original_post->post_type ); 
  425. $tr_product_id = apply_filters( 'translate_object_id', $this->product_id, 'product', false, $this->get_target_language() ); 
  426.  
  427. new WCML_Editor_Save_Filters( $product_trid, $this->get_target_language() ); 
  428. if ( get_magic_quotes_gpc() ) { 
  429. foreach ( $translations as $key => $data_item ) { 
  430. if ( !is_array( $data_item ) ) { 
  431. $translations[$key] = stripslashes( $data_item ); 
  432.  
  433. if ( null === $tr_product_id ) { 
  434.  
  435. //insert new post 
  436. $args = array(); 
  437. $args[ 'post_title' ] = $translations[ md5( 'title' ) ]; 
  438. $args[ 'post_name' ] = $translations[ md5( 'slug' ) ]; 
  439. $args[ 'post_type' ] = $this->original_post->post_type; 
  440. $args[ 'post_content' ] = isset( $translations[ md5( 'product_content' ) ] ) ? $translations[ md5( 'product_content' ) ] : ''; 
  441. $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ]; 
  442.  
  443. if ( !$args[ 'post_title' ] && !$args[ 'post_content' ] && !$args[ 'post_excerpt' ] ) { 
  444. return new WP_Error( 'empty_content', __( 'Content, title, and excerpt are empty.' ) ); 
  445.  
  446. $args[ 'post_status' ] = $this->original_post->post_status; 
  447. $args[ 'menu_order '] = $this->original_post->menu_order; 
  448. $args[ 'ping_status' ] = $this->original_post->ping_status; 
  449. $args[ 'comment_status' ] = $this->original_post->comment_status; 
  450. $product_parent = apply_filters( 'translate_object_id', $this->original_post->post_parent, 'product', false, $this->get_target_language() ); 
  451. $args['post_parent'] = null === $product_parent ? 0 : $product_parent; 
  452.  
  453. //TODO: remove after change required WPML version > 3.3 
  454. $_POST[ 'to_lang' ] = $this->get_target_language(); 
  455. // for WPML > 3.3 
  456. $_POST[ 'icl_post_language' ] = $this->get_target_language(); 
  457.  
  458. if ( $this->woocommerce_wpml->settings[ 'products_sync_date' ] ) { 
  459. $args[ 'post_date' ] = $this->original_post->post_date; 
  460.  
  461. $this->sitepress->switch_lang( $this->get_target_language() ); 
  462.  
  463. $tr_product_id = wp_insert_post( $args ); 
  464.  
  465. $this->sitepress->switch_lang(); // switch back 
  466.  
  467. $translation_id = $this->wpdb->get_var( $this->wpdb->prepare( 
  468. "SELECT translation_id 
  469. FROM {$this->wpdb->prefix}icl_translations 
  470. WHERE element_type=%s AND trid=%d AND language_code=%s AND element_id IS NULL ",  
  471. 'post_product', $product_trid, $this->get_target_language() ) ); 
  472.  
  473. if ( $translation_id ) { 
  474. $this->wpdb->query( 
  475. $this->wpdb->prepare( 
  476. "DELETE FROM {$this->wpdb->prefix}icl_translations WHERE element_id=%d AND trid=%d",  
  477. $tr_product_id, $product_trid 
  478. ); 
  479.  
  480. $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'element_id' => $tr_product_id ), array( 'translation_id' => $translation_id ) ); 
  481. } else { 
  482. $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->original_post->post_type, $product_trid, $this->get_target_language() ); 
  483.  
  484. } else { 
  485. //update post 
  486. $args = array(); 
  487. $args[ 'ID' ] = $tr_product_id; 
  488. $args[ 'post_title' ] = $translations[ md5( 'title' ) ]; 
  489. $args[ 'post_content' ] = isset( $translations[ md5( 'product_content' ) ] ) ? $translations[ md5( 'product_content' ) ] : ''; 
  490. $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ]; 
  491. $args[ 'post_status' ] = $this->original_post->post_status; 
  492. $args[ 'ping_status' ] = $this->original_post->ping_status; 
  493. $args[ 'comment_status' ] = $this->original_post->comment_status; 
  494. $product_parent = apply_filters( 'translate_object_id', $this->original_post->post_parent, 'product', false, $this->get_target_language() ); 
  495. $args['post_parent'] = null === $product_parent ? 0 : $product_parent; 
  496. $_POST[ 'to_lang' ] = $this->get_target_language(); 
  497.  
  498. $this->sitepress->switch_lang( $this->get_target_language() ); 
  499. wp_update_post( $args ); 
  500. $this->sitepress->switch_lang(); 
  501.  
  502. $post_name = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT post_name FROM {$this->wpdb->posts} WHERE ID=%d", $tr_product_id ) ); 
  503. if ( isset( $translations[ md5( 'slug' ) ] ) && $translations[ md5( 'slug' ) ] !== $post_name ) { 
  504. // update post_name 
  505. // need set POST variable ( WPML used them when filtered this function) 
  506.  
  507. $new_post_name = sanitize_title( $translations[ md5( 'slug' ) ] ? $translations[ md5( 'slug' ) ] : $translations[ md5( 'title' ) ]); 
  508. $_POST[ 'new_title' ] = $translations[ md5( 'title' ) ]; 
  509. $_POST[ 'new_slug' ] = $new_post_name; 
  510. $new_slug = wp_unique_post_slug( $new_post_name, $tr_product_id, $this->original_post->post_status, $this->original_post->post_type, $args[ 'post_parent' ] ); 
  511. $this->wpdb->update( $this->wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $tr_product_id ) ); 
  512.  
  513. $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->original_post->post_type, $product_trid, $this->get_target_language() ); 
  514.  
  515.  
  516. $product_translations = $this->sitepress->get_element_translations( $product_trid , 'post_product', false, false, true ); 
  517.  
  518. do_action( 'wcml_before_sync_product_data', $this->product_id, $tr_product_id, $this->get_target_language() ); 
  519.  
  520. $this->woocommerce_wpml->sync_product_data->duplicate_product_post_meta( $this->product_id, $tr_product_id, $translations ); 
  521.  
  522. $this->woocommerce_wpml->page_builders->save_page_builders_strings( $translations, $this->product_id, $this->get_target_language() ); 
  523.  
  524. $this->save_translated_terms( ); 
  525. //sync taxonomies 
  526. $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies( $this->product_id, $tr_product_id, $this->get_target_language() ); 
  527.  
  528. do_action( 'wcml_update_extra_fields', $this->product_id, $tr_product_id, $translations, $this->get_target_language() ); 
  529.  
  530. $this->woocommerce_wpml->attributes->sync_product_attr( $this->product_id, $tr_product_id, $this->get_target_language(), $translations ); 
  531.  
  532. $this->woocommerce_wpml->attributes->sync_default_product_attr( $this->product_id, $tr_product_id, $this->get_target_language() ); 
  533.  
  534. //sync media 
  535. if ( $this->woocommerce_wpml->media->settings[ 'duplicate_featured' ] ) { 
  536. //sync feature image 
  537. $this->woocommerce_wpml->media->sync_thumbnail_id( $this->product_id, $tr_product_id, $this->get_target_language() ); 
  538.  
  539. if ( $this->woocommerce_wpml->media->settings[ 'duplicate_media' ] ) { 
  540. //sync product gallery 
  541. $this->woocommerce_wpml->media->sync_product_gallery( $this->product_id ); 
  542.  
  543. // synchronize post variations 
  544. $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $this->product_id, $tr_product_id, $this->get_target_language(), $translations, true ); 
  545.  
  546. $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() ); 
  547. //save images texts 
  548. $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id ); 
  549.  
  550. if ( $product_images ) { 
  551. foreach ( $product_images as $image_id ) { 
  552. $trnsl_prod_image = apply_filters( 'translate_object_id', $image_id, 'attachment', false, $this->get_target_language() ); 
  553. //update image texts 
  554. $this->wpdb->update( 
  555. $this->wpdb->posts,  
  556. array( 
  557. 'post_title' => $translations[ md5( 'image-id-' . $image_id . '-title' ) ],  
  558. 'post_content' => $translations[ md5( 'image-id-' . $image_id . '-description' ) ],  
  559. 'post_excerpt' => $translations[ md5( 'image-id-' . $image_id . '-caption' ) ] 
  560. ),  
  561. array( 'id' => $trnsl_prod_image ) 
  562. ); 
  563. if ( isset( $translations[ md5( 'image-id-' . $image_id . '-alt-text' ) ] ) ) { 
  564. update_post_meta( $trnsl_prod_image, '_wp_attachment_image_alt', $translations[ md5( 'image-id-' . $image_id . '-alt-text' ) ] ); 
  565.  
  566. if( $product_translations ) { 
  567. $iclTranslationManagement->update_translation_status( 
  568. array( 
  569. 'status' => $this->is_translation_complete() ? ICL_TM_COMPLETE : ICL_TM_IN_PROGRESS,  
  570. 'needs_update' => 0,  
  571. 'translation_id' => $product_translations[ $this->get_target_language() ]->translation_id,  
  572. 'translator_id' => get_current_user_id() 
  573. )); 
  574.  
  575. if ( ob_get_length() > 0 ) { 
  576. ob_clean(); 
  577. ob_start(); 
  578.  
  579. $this->woocommerce_wpml->products->get_translation_statuses( $this->product_id, $product_translations, $languages, isset( $translations['slang'] ) 
  580. && $translations['slang'] 
  581. !== 'all' ? $translations['slang'] : false, $product_trid, $this->get_target_language() ); 
  582. $return[ 'status_link' ] = ob_get_clean(); 
  583.  
  584. // no longer a duplicate 
  585. delete_post_meta( $tr_product_id, '_icl_lang_duplicate_of', $this->product_id ); 
  586.  
  587. return $return; 
  588.  
  589.  
  590. private function save_translated_terms() { 
  591. $job_data = array(); 
  592. parse_str( $_POST['data'], $job_data ); 
  593.  
  594. foreach( $job_data['fields'] as $field_key => $field ) { 
  595. if( substr( $field_key, 0, 2 ) === 't_' ) { 
  596. $update = array(); 
  597. if ( isset( $field[ 'data' ] ) ) { 
  598. $update[ 'field_data_translated' ] = base64_encode( $field[ 'data' ] ); 
  599.  
  600. $update[ 'field_finished' ] = 1; 
  601.  
  602. $this->wpdb->update( 
  603. $this->wpdb->prefix . 'icl_translate',  
  604. $update,  
  605. array( 'field_type' => $field_key ) 
  606. ); 
  607.  
  608. $job = new WPML_Post_Translation_Job( $job_data[ 'job_id' ] ); 
  609. $job->save_terms_to_post(); 
  610.  
  611. public function get_custom_product_atributes( ) 
  612. $attributes = get_post_meta( $this->product_id, '_product_attributes', true); 
  613. if (!is_array($attributes)) { 
  614. $attributes = array(); 
  615.  
  616. foreach ($attributes as $key => $attribute) { 
  617. if ($attribute['is_taxonomy']) { 
  618. unset($attributes[$key]); 
  619.  
  620. return $attributes; 
  621.  
  622. //get product content labels 
  623. public function get_product_custom_field_label( $field, $variation_id = false ) 
  624. global $sitepress; 
  625. $settings = $sitepress->get_settings(); 
  626. $label = ''; 
  627. if ( isset( $settings['translation-management']['custom_fields_translation'][ $field ] ) && $settings['translation-management']['custom_fields_translation'][ $field ] == WPML_TRANSLATE_CUSTOM_FIELD ) { 
  628. if ( in_array( $field, $this->not_display_fields_for_variables_product, true ) ) { 
  629. return false; 
  630.  
  631. $exception = apply_filters('wcml_product_content_exception', true, $this->product_id, $field); 
  632. if ( !$exception ) { 
  633. return false; 
  634.  
  635. $custom_key_label = apply_filters('wcml_product_content_label', $field, $this->product_id); 
  636. if ( $custom_key_label !== $field ) { 
  637. $label = $custom_key_label; 
  638. return $label; 
  639.  
  640. $custom_key_label = str_replace('_', ' ', $field); 
  641. $label = trim($custom_key_label[0]) ? ucfirst($custom_key_label) : ucfirst(substr($custom_key_label, 1)); 
  642.  
  643. if( $variation_id ) { 
  644. $label .= ' #'.$variation_id; 
  645.  
  646.  
  647. return $label; 
  648.  
  649. public function get_files_for_variations( ) { 
  650.  
  651. global $wpdb; 
  652.  
  653. $variations = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'product_variation'", $this->product_id)); 
  654. $variations_files = array(); 
  655.  
  656. foreach ($variations as $variation) { 
  657.  
  658. if ( get_post_meta( $variation->ID, '_downloadable', true ) === 'yes' ) { 
  659.  
  660. $variation_files = $this->woocommerce_wpml->downloadable->get_files_data( $variation->ID ); 
  661.  
  662. if ( count( $variation_files ) ) { 
  663. $variations_files[ $variation->ID ] = $variation_files; 
  664.  
  665.  
  666.  
  667. return $variations_files; 
  668.  
  669.  
  670. //get product content 
  671. public function get_product_custom_fields_to_translate( $product_id ) { 
  672. $settings = $this->sitepress->get_settings(); 
  673. $contents = array(); 
  674.  
  675. foreach( get_post_custom_keys( $product_id ) as $meta_key ) { 
  676. if ( isset( $settings['translation-management']['custom_fields_translation'][ $meta_key ] ) && $settings['translation-management']['custom_fields_translation'][ $meta_key ] == WPML_TRANSLATE_CUSTOM_FIELD ) { 
  677. if( $this->check_custom_field_is_single_value( $product_id, $meta_key ) ) { 
  678. if ( in_array( $meta_key, apply_filters( 'wcml_not_display_single_fields_to_translate', $this->not_display_fields_for_variables_product ), true ) ) { 
  679. continue; 
  680. }else{ 
  681. $exception = apply_filters( 'wcml_product_content_exception', true, $product_id, $meta_key ); 
  682. if( $exception ) { 
  683. continue; 
  684. $contents[] = $meta_key; 
  685. return apply_filters('wcml_product_content_fields', $contents, $product_id); 
  686.  
  687. public function check_custom_field_is_single_value( $product_id, $meta_key ) { 
  688. $meta_value = maybe_unserialize( get_post_meta( $product_id, $meta_key, true ) ); 
  689.  
  690. if( is_array( $meta_value ) ) { 
  691. return false; 
  692. } else { 
  693. return apply_filters( 'wcml_check_is_single', true, $product_id, $meta_key ); 
  694.  
  695.  
  696.  
  697. public function requires_translation_complete_for_each_field() { 
  698. return false; 
  699.  
  700. public function is_hide_empty_fields() { 
  701. return false; 
  702.  
  703. public function show_media_button() { 
  704. return true; 
  705.