PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / compatibility / WcTabManager / class-wcml-tab-manager.php
woocommerce-multilingual / compatibility / WcTabManager Last commit date
TranslationEditor 4 weeks ago Factory.php 4 weeks ago class-wcml-tab-manager.php 4 weeks ago
class-wcml-tab-manager.php
650 lines
1 <?php
2
3 class WCML_Tab_Manager implements \IWPML_Action {
4
5 const POST_TYPE = 'wc_product_tab';
6 const ELEMENT_TYPE = 'post_wc_product_tab';
7
8 const TAB_FIELD_PREFIX = 'product_tabs:';
9 const TAB_FIELD_CORE_INTERFIX = 'core_tab_';
10 const TAB_FIELD_PRODUCT_INTERFIX = 'product_tab:';
11
12 private $tp;
13
14 private $sitepress;
15
16 private $woocommerce_wpml;
17
18 private $wpdb;
19
20 public function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, wpdb $wpdb, WPML_Element_Translation_Package $tp ) {
21 $this->sitepress = $sitepress;
22 $this->woocommerce_wpml = $woocommerce_wpml;
23 $this->wpdb = $wpdb;
24 $this->tp = $tp;
25 }
26
27 public function add_hooks() {
28 add_action( 'wcml_update_extra_fields', [ $this, 'sync_tabs' ], 10, 4 );
29 add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
30 add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
31 add_filter( 'wpml_duplicate_custom_fields_exceptions', [ $this, 'duplicate_custom_fields_exceptions' ] );
32 add_action( 'wcml_after_duplicate_product', [ $this, 'duplicate_product_tabs' ], 10, 2 );
33
34 add_filter( 'wc_tab_manager_tab_id', [ $this, 'wc_tab_manager_tab_id' ], 10, 1 );
35 add_filter( 'option_wpml_config_files_arr', [ $this, 'make__product_tabs_not_translatable_by_default' ], 0 );
36
37 add_action( 'wpml_translation_job_saved', [ $this, 'save_custom_tabs_translation' ], 10, 3 );
38 add_filter( 'wpml_tm_post_md5_content', [ $this, 'adjust_tab_manager_product_signature' ], 10, 2 );
39
40 if ( is_admin() ) {
41
42 add_action( 'save_post', [ $this, 'force_set_language_information_on_product_tabs' ], 10, 2 );
43 add_action( 'save_post', [ $this, 'sync_product_tabs' ], 10, 2 );
44
45 add_filter( 'wpml_tm_translation_job_data', [ $this, 'append_custom_tabs_to_translation_package' ], 10, 2 );
46
47 add_filter( 'wcml_do_not_display_custom_fields_for_product', [ $this, 'replace_tm_editor_custom_fields_with_own_sections' ] );
48
49 add_filter( 'wpml_duplicate_custom_fields_exceptions', [ $this, 'duplicate_categories_exception' ] );
50 add_action( 'wpml_after_copy_custom_field', [ $this, 'translate_categories' ], 10, 3 );
51
52 add_action( 'woocommerce_product_data_panels', [ $this, 'show_pointer_info' ] );
53 } else {
54 add_filter( 'option_wc_tab_manager_default_layout', [ $this, 'filter_default_layout' ] );
55 }
56 }
57
58 public function make__product_tabs_not_translatable_by_default( $wpml_config_array ) {
59
60 if ( isset( $wpml_config_array->plugins['WooCommerce Tab Manager'] ) ) {
61 $wpml_config_array->plugins['WooCommerce Tab Manager'] =
62 str_replace(
63 '<custom-field action="translate">_product_tabs</custom-field>',
64 '<custom-field action="nothing">_product_tabs</custom-field>',
65 $wpml_config_array->plugins['WooCommerce Tab Manager']
66 );
67 }
68
69 return $wpml_config_array;
70 }
71
72 public function sync_tabs( $original_product_id, $trnsl_product_id, $data, $lang ) {
73 if ( ( isset( $_POST['icl_ajx_action'] ) && ( 'make_duplicates' === sanitize_text_field( $_POST['icl_ajx_action'] ) ) ) || ( get_post_meta( $trnsl_product_id, '_icl_lang_duplicate_of', true ) ) ) {
74 $this->duplicate_tabs( $original_product_id, $trnsl_product_id, $lang );
75 }
76
77 $orig_prod_tabs = $this->get_product_tabs( $original_product_id );
78
79 if ( $orig_prod_tabs ) {
80 $trnsl_product_tabs = [];
81 $i = 0;
82 foreach ( $orig_prod_tabs as $key => $orig_prod_tab ) {
83 switch ( $orig_prod_tab['type'] ) {
84 case 'core':
85 $default_language = $this->woocommerce_wpml->products->get_original_product_language( $original_product_id );
86 $current_language = $this->sitepress->get_current_language();
87 $trnsl_product_tabs[ $key ] = $orig_prod_tabs[ $key ];
88 $title = isset( $data[ md5( 'coretab_' . $orig_prod_tab['id'] . '_title' ) ] ) ? $data[ md5( 'coretab_' . $orig_prod_tab['id'] . '_title' ) ] : '';
89 $heading = isset( $data[ md5( 'coretab_' . $orig_prod_tab['id'] . '_heading' ) ] ) ? $data[ md5( 'coretab_' . $orig_prod_tab['id'] . '_heading' ) ] : '';
90
91 if ( $default_language !== $lang ) {
92
93 $this->refresh_text_domain( $lang );
94
95 if ( ! $title ) {
96 $title = isset( $_POST['product_tab_title'][ $orig_prod_tab['position'] ] ) ? $_POST['product_tab_title'][ $orig_prod_tab['position'] ] : $orig_prod_tabs[ $key ]['title'];
97 $title = __( $title, 'woocommerce' );
98 }
99
100 if ( ! $heading && ( isset( $orig_prod_tabs[ $key ]['heading'] ) || isset( $_POST['product_tab_heading'][ $orig_prod_tab['position'] ] ) ) ) {
101 $heading = isset( $_POST['product_tab_heading'][ $orig_prod_tab['position'] ] ) ? $_POST['product_tab_heading'][ $orig_prod_tab['position'] ] : $orig_prod_tabs[ $key ]['heading'];
102 $heading = __( $heading, 'woocommerce' );
103 }
104
105 $this->refresh_text_domain( $current_language );
106 }
107
108 $trnsl_product_tabs[ $key ]['title'] = $title;
109 $trnsl_product_tabs[ $key ]['heading'] = $heading;
110 break;
111 case 'global':
112 $trnsl_product_tabs = $this->set_global_tab( $orig_prod_tab, $trnsl_product_tabs, $lang );
113 break;
114 case 'product':
115 $tab_id = false;
116 $title_key = md5( 'tab_' . $orig_prod_tab['position'] . '_title' );
117 $heading_key = md5( 'tab_' . $orig_prod_tab['position'] . '_heading' );
118 $title = isset( $data[ $title_key ] ) ? sanitize_text_field( $data[ $title_key ] ) : '';
119 $content = isset( $data[ $heading_key ] ) ? wp_kses_post( $data[ $heading_key ] ) : '';
120
121 $trnsl_product_tabs = $this->set_product_tab( $orig_prod_tab, $trnsl_product_tabs, $lang, $trnsl_product_id, $tab_id, $title, $content );
122
123 $i++;
124 break;
125 }
126 }
127 update_post_meta( $trnsl_product_id, '_product_tabs', $trnsl_product_tabs );
128 }
129 }
130
131 public function duplicate_tabs( $original_product_id, $trnsl_product_id, $lang ) {
132 $orig_prod_tabs = maybe_unserialize( get_post_meta( $original_product_id, '_product_tabs', true ) );
133 $prod_tabs = [];
134 foreach ( $orig_prod_tabs as $key => $orig_prod_tab ) {
135 switch ( $orig_prod_tab['type'] ) {
136 case 'core':
137 $prod_tabs[ $key ] = $orig_prod_tab;
138 $this->refresh_text_domain( $lang );
139 $prod_tabs[ $key ]['title'] = __( $orig_prod_tab['title'], 'woocommerce' );
140 if ( isset( $orig_prod_tab['heading'] ) ) {
141 $prod_tabs[ $key ]['heading'] = __( $orig_prod_tab['heading'], 'woocommerce' );
142 }
143 $orig_lang = $this->sitepress->get_language_for_element( $original_product_id, 'post_product' );
144 $this->refresh_text_domain( $orig_lang );
145 break;
146 case 'global':
147 $prod_tabs = $this->set_global_tab( $orig_prod_tab, $prod_tabs, $lang );
148 break;
149 case 'product':
150 $original_tab = get_post( $orig_prod_tab['id'] );
151 $prod_tabs = $this->set_product_tab( $orig_prod_tab, $prod_tabs, $lang, $trnsl_product_id, false, $original_tab->post_title, $original_tab->post_content );
152 break;
153 }
154 }
155
156 update_post_meta( $trnsl_product_id, '_product_tabs', $prod_tabs );
157 }
158
159 public function refresh_text_domain( $lang ) {
160 $this->sitepress->switch_lang( $lang );
161 }
162
163 public function set_global_tab( $orig_prod_tab, $trnsl_product_tabs, $lang ) {
164 $tr_tab_id = apply_filters( 'wpml_object_id', $orig_prod_tab['id'], self::POST_TYPE, true, $lang );
165 $trnsl_product_tabs[ $orig_prod_tab['type'] . '_tab_' . $tr_tab_id ] = [
166 'position' => $orig_prod_tab['position'],
167 'type' => $orig_prod_tab['type'],
168 'id' => $tr_tab_id,
169 'name' => get_post( $tr_tab_id )->post_name,
170 ];
171 return $trnsl_product_tabs;
172 }
173
174 public function set_product_tab( $orig_prod_tab, $trnsl_product_tabs, $lang, $trnsl_product_id, $tab_id, $title, $content ) {
175 if ( ! $tab_id ) {
176 $tr_tab_id = apply_filters( 'wpml_object_id', $orig_prod_tab['id'], self::POST_TYPE, false, $lang );
177
178 if ( ! is_null( $tr_tab_id ) ) {
179 $tab_id = $tr_tab_id;
180 }
181 }
182
183 if ( $tab_id ) {
184 $args = [];
185 $args['post_title'] = $title;
186 $args['post_content'] = $content;
187 $this->wpdb->update( $this->wpdb->posts, $args, [ 'ID' => $tab_id ] );
188 } else {
189 $args = [];
190 $args['post_title'] = $title;
191 $args['post_content'] = $content;
192 $args['post_author'] = get_current_user_id();
193 $args['post_name'] = sanitize_title( $title );
194 $args['post_type'] = self::POST_TYPE;
195 $args['post_parent'] = $trnsl_product_id;
196 $args['post_status'] = 'publish';
197 $this->wpdb->insert( $this->wpdb->posts, $args );
198
199 $tab_id = $this->wpdb->insert_id;
200 $tab_trid = $this->sitepress->get_element_trid( $orig_prod_tab['id'], self::ELEMENT_TYPE );
201 if ( ! $tab_trid ) {
202 $this->sitepress->set_element_language_details( $orig_prod_tab['id'], self::ELEMENT_TYPE, false, $this->sitepress->get_default_language() );
203 $tab_trid = $this->sitepress->get_element_trid( $orig_prod_tab['id'], self::ELEMENT_TYPE );
204 }
205 $this->sitepress->set_element_language_details( $tab_id, self::ELEMENT_TYPE, $tab_trid, $lang );
206 }
207
208 if ( empty( $title ) || strlen( $title ) != strlen( utf8_encode( $title ) ) ) {
209 $tab_name = 'product-tab-' . $tab_id;
210 } else {
211 $tab_name = sanitize_title( $title );
212 }
213
214 $trnsl_product_tabs[ $orig_prod_tab['type'] . '_tab_' . $tab_id ] = [
215 'position' => $orig_prod_tab['position'],
216 'type' => $orig_prod_tab['type'],
217 'id' => $tab_id,
218 'name' => $tab_name,
219 ];
220
221 return $trnsl_product_tabs;
222 }
223
224 public function duplicate_custom_fields_exceptions( $exceptions ) {
225 $exceptions[] = '_product_tabs';
226 return $exceptions;
227 }
228
229 public function custom_box_html( $obj, $product_id, $data ) {
230
231 if ( 'yes' !== get_post_meta( $product_id, '_override_tab_layout', true ) ) {
232 return;
233 }
234
235 $orig_prod_tabs = $this->get_product_tabs( $product_id );
236 if ( ! $orig_prod_tabs ) {
237 return;
238 }
239
240 $tabs_section = new WPML_Editor_UI_Field_Section( __( 'Product tabs', 'woocommerce-multilingual' ) );
241
242 $keys = array_keys( $orig_prod_tabs );
243 $last_key = end( $keys );
244 $divider = true;
245
246 foreach ( $orig_prod_tabs as $key => $prod_tab ) {
247 if ( $key === $last_key ) {
248 $divider = false;
249 }
250
251 if ( in_array( $prod_tab['type'], [ 'product', 'core' ] ) ) {
252 if ( 'core' === $prod_tab['type'] ) {
253 $group = new WPML_Editor_UI_Field_Group( $prod_tab['title'], $divider );
254 $tab_field = new WPML_Editor_UI_Single_Line_Field( 'coretab_' . $prod_tab['id'] . '_title', __( 'Title', 'woocommerce-multilingual' ), $data, false );
255 $group->add_field( $tab_field );
256 $tab_field = new WPML_Editor_UI_Single_Line_Field( 'coretab_' . $prod_tab['id'] . '_heading', __( 'Heading', 'woocommerce-multilingual' ), $data, false );
257 $group->add_field( $tab_field );
258 $tabs_section->add_field( $group );
259 } else {
260 $group = new WPML_Editor_UI_Field_Group( ucfirst( str_replace( '-', ' ', $prod_tab['name'] ) ), $divider );
261 $tab_field = new WPML_Editor_UI_Single_Line_Field( 'tab_' . $prod_tab['position'] . '_title', __( 'Title', 'woocommerce-multilingual' ), $data, false );
262 $group->add_field( $tab_field );
263 $tab_field = new WCML_Editor_UI_WYSIWYG_Field( 'tab_' . $prod_tab['position'] . '_heading', null, $data, false );
264 $group->add_field( $tab_field );
265 $tabs_section->add_field( $group );
266 }
267 }
268 }
269 $obj->add_field( $tabs_section );
270 }
271
272 public function custom_box_html_data( $data, $product_id, $translation, $lang ) {
273
274 $orig_prod_tabs = $this->get_product_tabs( $product_id );
275
276 if ( empty( $orig_prod_tabs ) ) {
277 return $data;
278 }
279
280 foreach ( $orig_prod_tabs as $key => $prod_tab ) {
281 if ( in_array( $prod_tab['type'], [ 'product', 'core' ] ) ) {
282 if ( 'core' === $prod_tab['type'] ) {
283 $data[ 'coretab_' . $prod_tab['id'] . '_title' ] = [ 'original' => $prod_tab['title'] ];
284 $data[ 'coretab_' . $prod_tab['id'] . '_heading' ] = [ 'original' => isset( $prod_tab['heading'] ) ? $prod_tab['heading'] : '' ];
285 } else {
286 $data[ 'tab_' . $prod_tab['position'] . '_title' ] = [ 'original' => get_the_title( $prod_tab['id'] ) ];
287 $data[ 'tab_' . $prod_tab['position'] . '_heading' ] = [ 'original' => get_post( $prod_tab['id'] )->post_content ];
288 }
289 }
290 }
291
292 if ( is_object( $translation ) ) {
293 $tr_prod_tabs = $this->get_product_tabs( $translation->ID );
294
295 foreach ( $tr_prod_tabs as $key => $prod_tab ) {
296 if ( in_array( $prod_tab['type'], [ 'product', 'core' ] ) ) {
297 if ( 'core' === $prod_tab['type'] ) {
298 $data[ 'coretab_' . $prod_tab['id'] . '_title' ]['translation'] = $prod_tab['title'];
299 $data[ 'coretab_' . $prod_tab['id'] . '_heading' ]['translation'] = $prod_tab['heading'] ?? '';
300 } else {
301 $data[ 'tab_' . $prod_tab['position'] . '_title' ]['translation'] = get_the_title( $prod_tab['id'] );
302 $data[ 'tab_' . $prod_tab['position'] . '_heading' ]['translation'] = get_post( $prod_tab['id'] )->post_content;
303 }
304 }
305 }
306 } else {
307 $current_language = $this->sitepress->get_current_language();
308 foreach ( $orig_prod_tabs as $key => $prod_tab ) {
309 if ( 'core' === $prod_tab['type'] ) {
310 $this->sitepress->switch_lang( $lang );
311 $title = __( $prod_tab['title'], 'woocommerce' );
312 if ( $prod_tab['title'] !== $title ) {
313 $data[ 'coretab_' . $prod_tab['id'] . '_title' ]['translation'] = $title;
314 }
315
316 if ( ! isset( $prod_tab['heading'] ) ) {
317 $data[ 'coretab_' . $prod_tab['id'] . '_heading' ]['translation'] = '';
318 } else {
319 $heading = __( $prod_tab['heading'], 'woocommerce' );
320 if ( $prod_tab['heading'] !== $heading ) {
321 $data[ 'coretab_' . $prod_tab['id'] . '_heading' ]['translation'] = $heading;
322 }
323 }
324
325 $this->sitepress->switch_lang( $current_language );
326 }
327 }
328 }
329
330 return $data;
331 }
332
333 public function duplicate_product_tabs( $new_id, $original_post ) {
334 if ( function_exists( 'wc_tab_manager_duplicate_product' ) ) {
335 wc_tab_manager_duplicate_product( $new_id, $original_post );
336 }
337 }
338
339 public function force_set_language_information_on_product_tabs( $post_id, $post ) {
340 if ( self::POST_TYPE === $post->post_type ) {
341
342 $language = $this->sitepress->get_language_for_element( $post_id, self::ELEMENT_TYPE );
343 if ( empty( $language ) && $post->post_parent ) {
344 $parent_language = $this->sitepress->get_language_for_element( $post->post_parent, 'post_product' );
345 if ( $parent_language ) {
346 $this->sitepress->set_element_language_details( $post_id, self::ELEMENT_TYPE, null, $parent_language );
347 }
348 }
349 }
350 }
351
352 public function append_custom_tabs_to_translation_package( $package, $post ) {
353
354 if ( 'product' === $post->post_type ) {
355
356 $override_tab_layout = get_post_meta( $post->ID, '_override_tab_layout', true );
357
358 if ( 'yes' === $override_tab_layout ) {
359
360 $meta = (array) get_post_meta( $post->ID, '_product_tabs', true );
361
362 foreach ( $meta as $key => $value ) {
363
364 if ( preg_match( '/product_tab_([0-9]+)/', $key, $matches ) ) {
365
366 $wc_product_tab_id = $matches[1];
367 $wc_product_tab = get_post( $wc_product_tab_id );
368
369 $package['contents'][ self::TAB_FIELD_PREFIX . self::TAB_FIELD_PRODUCT_INTERFIX . $wc_product_tab_id . ':title' ] = [
370 'translate' => 1,
371 'data' => $this->tp->encode_field_data( $wc_product_tab->post_title ),
372 'format' => 'base64',
373 ];
374
375 $package['contents'][ self::TAB_FIELD_PREFIX . self::TAB_FIELD_PRODUCT_INTERFIX . $wc_product_tab_id . ':description' ] = [
376 'translate' => 1,
377 'data' => $this->tp->encode_field_data( $wc_product_tab->post_content ),
378 'format' => 'base64',
379 ];
380
381 } elseif ( preg_match( '/^' . self::TAB_FIELD_CORE_INTERFIX . '(.+)$/', $key, $matches ) ) {
382
383 $package['contents'][ self::TAB_FIELD_PREFIX . self::TAB_FIELD_CORE_INTERFIX . 'title:' . $matches[1] ] = [
384 'translate' => 1,
385 'data' => $this->tp->encode_field_data( $value['title'] ),
386 'format' => 'base64',
387 ];
388
389 if ( isset( $value['heading'] ) ) {
390 $package['contents'][ self::TAB_FIELD_PREFIX . self::TAB_FIELD_CORE_INTERFIX . 'heading:' . $matches[1] ] = [
391 'translate' => 1,
392 'data' => $this->tp->encode_field_data( $value['heading'] ),
393 'format' => 'base64',
394 ];
395 }
396 }
397 }
398 }
399 }
400
401 return $package;
402 }
403
404 public function save_custom_tabs_translation( $post_id, $data, $job ) {
405 $translated_product_tabs_updated = false;
406
407 $original_product_tabs = get_post_meta( $job->original_doc_id, '_product_tabs', true );
408
409 if ( $original_product_tabs ) {
410
411 $product_tab_translations = [];
412
413 foreach ( $data as $value ) {
414
415 if ( preg_match( '/' . self::TAB_FIELD_PREFIX . self::TAB_FIELD_PRODUCT_INTERFIX . '([0-9]+):(.+)/', $value['field_type'], $matches ) ) {
416
417 $wc_product_tab_id = $matches[1];
418 $field = $matches[2];
419
420 $product_tab_translations[ $wc_product_tab_id ][ $field ] = $value['data'];
421 }
422 }
423
424 if ( $product_tab_translations ) {
425
426 $translated_product_tabs = get_post_meta( $post_id, '_product_tabs', true );
427 $translated_product_tabs = $translated_product_tabs ?: [];
428
429 foreach ( $product_tab_translations as $wc_product_tab_id => $value ) {
430
431 $translated_wc_product_tab = [
432 'ID' => apply_filters( 'wpml_object_id', $wc_product_tab_id, self::POST_TYPE, false, $job->language_code ),
433 'post_type' => self::POST_TYPE,
434 'post_title' => $value['title'],
435 'post_content' => isset( $value['description'] ) ? $value['description'] : '',
436 'post_status' => 'publish',
437 'post_parent' => $post_id,
438 ];
439
440 $wc_product_tab_id_translated = wp_insert_post( $translated_wc_product_tab );
441
442 if ( $wc_product_tab_id_translated ) {
443
444 $wc_product_tab_trid = $this->sitepress->get_element_trid( $wc_product_tab_id, self::ELEMENT_TYPE );
445 $this->sitepress->set_element_language_details( $wc_product_tab_id_translated, self::ELEMENT_TYPE, $wc_product_tab_trid, $job->language_code );
446
447 $wc_product_tab_translated = get_post( $wc_product_tab_id_translated );
448
449 $translated_product_tabs[ 'product_tab_' . $wc_product_tab_id_translated ] = [
450 'position' => $original_product_tabs[ 'product_tab_' . $wc_product_tab_id ]['position'],
451 'type' => 'product',
452 'id' => $wc_product_tab_id_translated,
453 'name' => $wc_product_tab_translated->post_name,
454
455 ];
456 }
457 }
458
459 $translated_product_tabs_updated = true;
460 }
461
462 $product_tab_translations = [];
463
464 foreach ( $data as $value ) {
465
466 if ( preg_match( '/' . self::TAB_FIELD_PREFIX . self::TAB_FIELD_CORE_INTERFIX . '(.+):(.+)/', $value['field_type'], $matches ) ) {
467
468 $tab_field = $matches[1];
469 $tab_id = $matches[2];
470
471 $product_tab_translations[ $tab_id ][ $tab_field ] = $value['data'];
472 }
473 }
474
475 if ( $product_tab_translations ) {
476 foreach ( $product_tab_translations as $id => $tab ) {
477
478 $translated_product_tabs[ self::TAB_FIELD_CORE_INTERFIX . $id ] = [
479 'type' => 'core',
480 'position' => $original_product_tabs[ self::TAB_FIELD_CORE_INTERFIX . $id ]['position'],
481 'id' => $id,
482 'title' => $tab['title'],
483 ];
484
485 $translated_product_tabs[ self::TAB_FIELD_CORE_INTERFIX . $id ]['heading'] = isset( $tab['heading'] ) ? $tab['heading'] : '';
486 }
487
488 $translated_product_tabs_updated = true;
489 }
490
491 foreach ( $original_product_tabs as $original_product_tab ) {
492 if ( isset( $translated_product_tabs ) && 'global' === $original_product_tab['type'] ) {
493 $translated_product_tabs = $this->set_global_tab( $original_product_tab, $translated_product_tabs, $job->language_code );
494 $translated_product_tabs_updated = true;
495 }
496 }
497
498 if ( true === $translated_product_tabs_updated && isset( $translated_product_tabs ) ) {
499 update_post_meta( $post_id, '_product_tabs', $translated_product_tabs );
500 }
501 }
502 }
503
504 public function get_product_tabs( $product_id ): array {
505
506 $override_tab_layout = get_post_meta( $product_id, '_override_tab_layout', true );
507
508 if ( 'yes' == $override_tab_layout ) {
509 $product_tabs = get_post_meta( $product_id, '_product_tabs', true );
510 } else {
511 $product_tabs = get_option( 'wc_tab_manager_default_layout', false );
512 }
513
514 return is_array( $product_tabs ) ? $product_tabs : [];
515 }
516
517 public function sync_product_tabs( $post_id, $post ) {
518
519 $override_tab_layout = get_post_meta( $post_id, '_override_tab_layout', true );
520
521 if ( $override_tab_layout && $this->woocommerce_wpml->products->is_original_product( $post_id ) ) {
522
523 $original_product_tabs = $this->get_product_tabs( $post_id );
524
525 $trid = $this->sitepress->get_element_trid( $post_id, 'post_' . $post->post_type );
526 $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type, true );
527
528 foreach ( $translations as $language => $translation ) {
529
530 if ( empty( $translation->original ) ) {
531
532 $translated_product_tabs = $this->get_product_tabs( $translation->element_id );
533
534 foreach ( $original_product_tabs as $tab ) {
535 if ( $tab['type'] == 'product' ) {
536 $translated_tab_product_id = apply_filters( 'wpml_object_id', $tab['id'], self::POST_TYPE, false, $language );
537 if ( $translated_tab_product_id && is_array( $translated_product_tabs[ 'product_tab_' . $translated_tab_product_id ] ) ) {
538 $translated_product_tabs[ 'product_tab_' . $translated_tab_product_id ]['position'] = $tab['position'];
539 }
540 }
541 }
542
543 foreach ( $translated_product_tabs as $tab_key => $tab ) {
544 if ( $tab['type'] === 'core' && ! isset( $original_product_tabs[ $tab_key ] ) ) {
545 unset( $translated_product_tabs[ $tab_key ] );
546 }
547 }
548
549 update_post_meta( $translation->element_id, '_product_tabs', $translated_product_tabs );
550
551 }
552 }
553 }
554 }
555
556 public function wc_tab_manager_tab_id( $tab_id ) {
557 if ( is_int( $tab_id ) ) {
558 return apply_filters( 'wpml_object_id', $tab_id, self::POST_TYPE, true );
559 } else {
560 return $tab_id;
561 }
562 }
563
564 public function filter_default_layout( $default_tabs ) {
565
566 if ( is_array( $default_tabs ) ) {
567 foreach ( $default_tabs as $tab_key => $default_tab ) {
568 if ( substr( $tab_key, 0, 10 ) == 'global_tab' ) {
569 $trnsl_tab_id = apply_filters( 'wpml_object_id', $default_tab['id'], self::POST_TYPE, true, $this->sitepress->get_current_language() );
570
571 if ( $trnsl_tab_id != $default_tab['id'] ) {
572 $default_tabs[ 'global_tab_' . $trnsl_tab_id ] = $default_tab;
573 $default_tabs[ 'global_tab_' . $trnsl_tab_id ]['id'] = $trnsl_tab_id;
574 $default_tabs[ 'global_tab_' . $trnsl_tab_id ]['name'] = get_post( $trnsl_tab_id )->post_name;
575 unset( $default_tabs[ $tab_key ] );
576 }
577 }
578 }
579 }
580
581 return $default_tabs;
582 }
583
584 public function show_pointer_info() {
585 $pointerFactory = new WCML\PointerUi\Factory();
586 $pointerFactory
587 ->create( [
588 'content' => sprintf(
589 /* translators: %1$s and %2$s are opening and closing HTML link tags */
590 esc_html__( 'To translate custom per-product tabs, go to the %1$sTranslation Dashboard%2$s and send the associated product for translation.', 'woocommerce-multilingual' ),
591 '<a href="' . esc_url( \WCML\Utilities\AdminUrl::getWPMLTMDashboardProducts() ) . '">',
592 '</a>'
593 ),
594 'selectorId' => 'woocommerce_product_tabs>p',
595 'docLink' => WCML_Tracking_Link::getWcmlTabManagerDoc(),
596 ] )
597 ->show();
598 }
599
600 public function replace_tm_editor_custom_fields_with_own_sections( $fields ) {
601 $fields[] = '_product_tabs';
602
603 return $fields;
604 }
605
606 public function duplicate_categories_exception( $fields ) {
607 $fields[] = '_wc_tab_categories';
608
609 return $fields;
610 }
611
612 public function translate_categories( $post_id_from, $post_id_to, $meta_key ) {
613 if ( '_wc_tab_categories' === $meta_key ) {
614 unset( $_POST['wc_tab_manager_metabox_nonce'] );
615
616 $args = [
617 'element_id' => $post_id_to,
618 'element_type' => self::POST_TYPE,
619 ];
620 $language = apply_filters( 'wpml_element_language_code', false, $args );
621
622 $categories = [];
623 $meta_value = get_post_meta( $post_id_from, $meta_key, true );
624 foreach ( $meta_value as $category ) {
625 $categories[] = apply_filters( 'wpml_object_id', $category, 'product_cat', true, $language );
626 }
627
628 update_post_meta( $post_id_to, $meta_key, $categories, $meta_value );
629 }
630 }
631
632 public function adjust_tab_manager_product_signature( $content, $post = null ) {
633 if ( ! is_a( $post, 'WP_Post') ) {
634 return $content;
635 }
636 $tabs = get_posts( [
637 'post_parent' => $post->ID,
638 'post_type' => self::POST_TYPE,
639 'post_status' => 'publish',
640 'numberposts' => -1,
641 ] );
642
643 foreach ( $tabs as $tab ) {
644 $content .= $tab->post_title . ';' . $tab->post_content . ';';
645 }
646
647 return $content;
648 }
649 }
650