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 / inc / translation-editor / class-wcml-synchronize-product-data.php
woocommerce-multilingual / inc / translation-editor Last commit date
class-wcml-downloadable-products.php 1 month ago class-wcml-editor-save-filters.php 1 month ago class-wcml-editor-ui-product-job.php 1 month ago class-wcml-editor-ui-wysiwyg-field.php 5 years ago class-wcml-page-builders.php 1 month ago class-wcml-synchronize-product-data.php 1 month ago class-wcml-synchronize-variations-data.php 1 month ago class-wcml-translation-editor.php 1 month ago class-wcml-wc-admin-duplicate-product.php 1 month ago
class-wcml-synchronize-product-data.php
512 lines
1 <?php
2
3 use WCML\Terms\SuspendWpmlFiltersFactory;
4 use WCML\Utilities\DB;
5 use WCML\Utilities\SyncHash;
6 use function WCML\functions\isCli;
7
8 class WCML_Synchronize_Product_Data {
9
10 const CUSTOM_FIELD_KEY_SEPARATOR = ':::';
11
12 const PRIORITY_BEFORE_STOCK_EMAIL_TRIGGER = 9;
13
14 private $woocommerce_wpml;
15 private $sitepress;
16 private $post_translations;
17 private $wpdb;
18
19 public function __construct( woocommerce_wpml $woocommerce_wpml, SitePress $sitepress, WPML_Post_Translation $post_translations, wpdb $wpdb ) {
20 $this->woocommerce_wpml = $woocommerce_wpml;
21 $this->sitepress = $sitepress;
22 $this->post_translations = $post_translations;
23 $this->wpdb = $wpdb;
24 }
25
26 public function add_hooks() {
27 if ( is_admin() || isCli() ) {
28 add_action( 'deleted_term_relationships', [ $this, 'delete_term_relationships_update_term_count' ], 10, 2 );
29 }
30
31 add_action( 'woocommerce_product_set_visibility', [ $this, 'sync_product_translations_visibility' ] );
32
33 add_action( 'woocommerce_recorded_sales', [ $this, 'sync_product_total_sales' ] );
34
35 add_action( 'woocommerce_product_set_stock_status', [ $this, 'sync_stock_status_for_translations' ], 100, 2 );
36 add_action( 'woocommerce_variation_set_stock_status', [ $this, 'sync_stock_status_for_translations' ], 10, 2 );
37
38 add_filter( 'future_product', [ $this, 'set_schedule_for_translations' ], 10, 2 );
39 }
40
41 public function synchronize_products( $post_id, $post, $force_valid_context = false, $wpRestRequest = null ) {
42 do_action( \WCML\Synchronization\Hooks::HOOK_SYNCHRONIZE_PRODUCT_TRANSLATIONS, $post, [], [] );
43 }
44
45 public function sync_product_data( $original_product_id, $tr_product_id, $lang, $duplicate = false ) {
46 do_action( \WCML\Synchronization\Hooks::HOOK_SYNCHRONIZE_PRODUCT_TRANSLATIONS, get_post( $original_product_id ), [ $tr_product_id ], [ $tr_product_id => $lang ] );
47 }
48
49 public function sync_product_taxonomies( $original_product_id, $tr_product_id, $lang ) {
50 do_action( \WCML\Synchronization\Hooks::HOOK_SYNCHRONIZE_PRODUCT_COMPONENT, get_post( $original_product_id ), [ $tr_product_id ], [ $tr_product_id => $lang ], \WCML\Synchronization\Store::COMPONENT_TAXONOMIES );
51 }
52
53 public function delete_term_relationships_update_term_count( $object_id, $tt_ids ) {
54
55 if ( get_post_type( $object_id ) === 'product' ) {
56
57 $original_product_id = $this->post_translations->get_original_element( $object_id );
58 $translations = $this->post_translations->get_element_translations( $original_product_id, false, true );
59
60 $filtersSuspend = SuspendWpmlFiltersFactory::create();
61 foreach ( $translations as $translation ) {
62 $this->wcml_update_term_count_by_ids( $tt_ids, $this->post_translations->get_element_lang_code( $translation ) );
63 }
64 $filtersSuspend->resume();
65 }
66 }
67
68
69 public function wcml_update_term_count_by_ids( $tt_ids, $language, $taxonomy = '', $tr_product_id = false ) {
70 global $wpml_term_translations;
71 $tt_ids_trans = [];
72
73 foreach ( $tt_ids as $tt_id ) {
74 $tt_id_trans = $wpml_term_translations->element_id_in( $tt_id, $language );
75 if ( $tt_id_trans ) {
76 $tt_ids_trans[] = $tt_id_trans;
77 }
78 }
79
80 $tt_ids_trans = array_values( array_unique( array_map( 'intval', $tt_ids_trans ) ) );
81
82 if ( empty( $tt_ids_trans ) ) {
83 return;
84 }
85
86 if ( in_array( $taxonomy, [ 'product_cat', 'product_tag' ] ) ) {
87 $this->sitepress->switch_lang( $language );
88 wp_update_term_count( $tt_ids_trans, $taxonomy );
89 $this->sitepress->switch_lang();
90 }
91
92 if ( $tr_product_id ) {
93 $t_ids = $this->wpdb->get_col(
94 $this->wpdb->prepare(
95 "SELECT term_id FROM {$this->wpdb->term_taxonomy} WHERE term_taxonomy_id IN (" . DB::prepareIn( $tt_ids_trans, '%d' ) . ") LIMIT %d",
96 count( $tt_ids_trans )
97 )
98 );
99 $t_ids = array_unique( array_map( 'intval', $t_ids ) );
100 wp_set_post_terms( $tr_product_id, $t_ids, $taxonomy );
101 }
102 }
103
104 public function sync_linked_products( $product_id, $translated_product_id, $lang ) {
105
106 $this->sync_up_sells_products( $product_id, $translated_product_id, $lang );
107 $this->sync_cross_sells_products( $product_id, $translated_product_id, $lang );
108 $this->sync_grouped_products( $product_id, $translated_product_id, $lang );
109
110 $translated_product_parent_id = wp_get_post_parent_id( $translated_product_id );
111 if ( $translated_product_parent_id ) {
112 delete_transient( 'wc_product_children_' . $translated_product_parent_id );
113 delete_transient( '_transient_wc_product_children_ids_' . $translated_product_parent_id );
114 }
115
116 }
117
118 public function sync_up_sells_products( $product_id, $translated_product_id, $lang ) {
119
120 $original_up_sells = maybe_unserialize( get_post_meta( $product_id, '_upsell_ids', true ) );
121 $trnsl_up_sells = [];
122 if ( $original_up_sells ) {
123 foreach ( $original_up_sells as $original_up_sell_product ) {
124 $trnsl_up_sells[] = apply_filters( 'wpml_object_id', $original_up_sell_product, get_post_type( $original_up_sell_product ), false, $lang );
125 }
126 }
127 update_post_meta( $translated_product_id, '_upsell_ids', $trnsl_up_sells );
128
129 }
130
131 public function sync_cross_sells_products( $product_id, $translated_product_id, $lang ) {
132
133 $original_cross_sells = maybe_unserialize( get_post_meta( $product_id, '_crosssell_ids', true ) );
134 $trnsl_cross_sells = [];
135 if ( $original_cross_sells ) {
136 foreach ( $original_cross_sells as $original_cross_sell_product ) {
137 $trnsl_cross_sells[] = apply_filters( 'wpml_object_id', $original_cross_sell_product, get_post_type( $original_cross_sell_product ), false, $lang );
138 }
139 }
140 update_post_meta( $translated_product_id, '_crosssell_ids', $trnsl_cross_sells );
141
142 }
143
144 public function sync_grouped_products( $product_id, $translated_product_id, $lang ) {
145
146 $original_children = maybe_unserialize( get_post_meta( $product_id, '_children', true ) );
147 $translated_children = [];
148 if ( $original_children ) {
149 foreach ( $original_children as $original_children_product ) {
150 $translated_children[] = apply_filters( 'wpml_object_id', $original_children_product, get_post_type( $original_children_product ), false, $lang );
151 }
152 }
153 update_post_meta( $translated_product_id, '_children', $translated_children );
154
155 }
156
157 public function sync_product_stock( $product, $translatedProduct = false ) {
158 $productId = $product->get_id();
159
160 if ( $translatedProduct ) {
161 $translatedProductId = $translatedProduct->get_id();
162 $translations = [ $translatedProductId ];
163 $translationsLanguages = [ $translatedProductId => $this->post_translations->get_element_lang_code( $translatedProductId ) ];
164 } else {
165 $translations = $this->post_translations->get_element_translations( $productId );
166 if ( empty( $translations ) ) {
167 return;
168 }
169
170 $translationsLanguages = [];
171 foreach ( $translations as $index => $translation ) {
172 if ( $productId === (int) $translation ) {
173 unset( $translations[ $index ] );
174 } else {
175 $translationsLanguages[ $translation ] = $this->post_translations->get_element_lang_code( $translation );
176 }
177 }
178 }
179
180 do_action( \WCML\Synchronization\Hooks::HOOK_SYNCHRONIZE_PRODUCT_COMPONENT, get_post( $productId ), $translations, $translationsLanguages, \WCML\Synchronization\Store::COMPONENT_STOCK );
181 }
182
183 public function sync_product_stock_hook( $product ) {
184 $productId = $product->get_id();
185 $translations = $this->post_translations->get_element_translations( $productId );
186 if ( empty( $translations ) ) {
187 return;
188 }
189
190 $translationsLanguages = [];
191 foreach ( $translations as $index => $translation ) {
192 if ( $productId === (int) $translation ) {
193 unset( $translations[ $index ] );
194 } else {
195 $translationsLanguages[ $translation ] = $this->post_translations->get_element_lang_code( $translation );
196 }
197 }
198
199 do_action( \WCML\Synchronization\Hooks::HOOK_SYNCHRONIZE_PRODUCT_COMPONENT, get_post( $productId ), $translations, $translationsLanguages, \WCML\Synchronization\Store::COMPONENT_STOCK );
200 }
201
202 public function sync_product_total_sales( $order_id ) {
203
204 $order = wc_get_order( $order_id );
205
206 foreach ( $order->get_items() as $item ) {
207
208 if ( $item instanceof WC_Order_Item_Product ) {
209 $product_id = $item->get_product_id();
210 $qty = $item->get_quantity();
211 } else {
212 $product_id = $item['product_id'];
213 $qty = $item['qty'];
214 }
215
216 $qty = apply_filters( 'wcml_order_item_quantity', $qty, $order, $item );
217
218 $data_store = WC_Data_Store::load( 'product' );
219 $translations = $this->post_translations->get_element_translations( $product_id );
220 foreach ( $translations as $translation ) {
221 if ( $product_id !== (int) $translation ) {
222 $data_store->update_product_sales( (int) $translation, absint( $qty ), 'increase' );
223 }
224 }
225 }
226 }
227
228 public function sync_stock_status_for_translations( $product_id, $status ) {
229
230 if ( $this->woocommerce_wpml->products->is_original_product( $product_id ) ) {
231
232 $translations = $this->post_translations->get_element_translations( $product_id, false, true );
233
234 foreach ( $translations as $translation ) {
235 $this->woocommerce_wpml->products->update_stock_status( $translation, $status );
236 $this->wc_taxonomies_recount_after_stock_change( $translation );
237 }
238 }
239 }
240
241 private function wc_taxonomies_recount_after_stock_change( $product_id ) {
242
243 remove_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1 );
244
245 wp_cache_delete( $product_id, 'product_cat_relationships' );
246 wp_cache_delete( $product_id, 'product_tag_relationships' );
247
248 wc_recount_after_stock_change( $product_id );
249
250 add_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1, 1 );
251
252 }
253
254 public function sync_date_and_parent( $original_product_id, $tr_product_id, $lang ) {
255 $tr_parent_id = apply_filters( 'wpml_object_id', wp_get_post_parent_id( $original_product_id ), 'product', false, $lang );
256 $tr_parent_id = is_null( $tr_parent_id ) ? 0 : (int) $tr_parent_id;
257 $args = [];
258 if ( wp_get_post_parent_id( $tr_product_id ) !== $tr_parent_id ) {
259 $args['post_parent'] = $tr_parent_id;
260 }
261 if ( ! empty( $this->woocommerce_wpml->settings['products_sync_date'] ) ) {
262 $orig_product = get_post( $original_product_id );
263 $args['post_date'] = $orig_product->post_date;
264 }
265 if ( ! empty( $args ) ) {
266 $this->wpdb->update(
267 $this->wpdb->posts,
268 $args,
269 [ 'id' => $tr_product_id ]
270 );
271 }
272 }
273
274 public function set_schedule_for_translations( $deprecated, $post ) {
275
276 if ( $this->woocommerce_wpml->products->is_original_product( $post->ID ) ) {
277 $translations = $this->post_translations->get_element_translations( $post->ID, false, true );
278 foreach ( $translations as $translation ) {
279 wp_clear_scheduled_hook( 'publish_future_post', [ $translation ] );
280 wp_schedule_single_event( strtotime( get_gmt_from_date( $post->post_date ) . ' GMT' ), 'publish_future_post', [ $translation ] );
281 }
282 }
283 }
284
285 public function icl_pro_translation_completed( $tr_product_id ) {}
286
287 public function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ) {}
288
289 public function woocommerce_product_quick_edit_save( $product ) {}
290
291 public function sync_downloadable_files( $originalProductId, $translationId ) {
292 global $iclTranslationManagement;
293 $settingFactory = new WPML_Custom_Field_Setting_Factory( $iclTranslationManagement );
294 $postmetaFieldSetting = $settingFactory->post_meta_setting( '_downloadable_files' );
295 $postmetaFieldStatus = $postmetaFieldSetting->status();
296 if ( WPML_IGNORE_CUSTOM_FIELD === $postmetaFieldStatus ) {
297 return;
298 }
299 $this->woocommerce_wpml->downloadable->sync_files_to_translations( $originalProductId, $translationId );
300
301 self::syncDeletedCustomFields( $originalProductId, $translationId );
302
303 do_action( 'wcml_after_duplicate_product_post_meta', $originalProductId, $translationId, false );
304 }
305
306 public function duplicate_product_post_meta( $original_product_id, $translated_product_id, $data = false ) {
307 if ( ! $data ) {
308 $this->sync_downloadable_files( $original_product_id, $translated_product_id );
309 $wcml_data_store = wcml_product_data_store_cpt();
310 $wcml_data_store->update_lookup_table_data( $translated_product_id );
311 return;
312 }
313
314 global $iclTranslationManagement;
315 $custom_fields = get_post_custom( $original_product_id );
316 $post_fields = null;
317 $settings_factory = new WPML_Custom_Field_Setting_Factory( $iclTranslationManagement );
318
319 unset( $custom_fields['_thumbnail_id'] );
320 unset( $custom_fields[ SyncHash::META_KEY ] );
321
322 foreach ( $custom_fields as $key => $meta ) {
323 $setting = $settings_factory->post_meta_setting( $key );
324
325 if ( WPML_IGNORE_CUSTOM_FIELD === $setting->status() ) {
326 continue;
327 }
328
329 if ( '_downloadable_files' === $key ) {
330 $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_product_id, $translated_product_id, $data );
331 } elseif ( WPML_TRANSLATE_CUSTOM_FIELD === $setting->status() ) {
332 $post_fields = $this->sync_custom_field_value( $key, $data, $translated_product_id, $post_fields, $original_product_id );
333 }
334 }
335
336 self::syncDeletedCustomFields( $original_product_id, $translated_product_id );
337
338 $wcml_data_store = wcml_product_data_store_cpt();
339 $wcml_data_store->update_lookup_table_data( $translated_product_id );
340
341 do_action( 'wcml_after_duplicate_product_post_meta', $original_product_id, $translated_product_id, $data );
342 }
343
344 public function sync_custom_field_value( $custom_field, $translation_data, $trnsl_product_id, $post_fields, $original_product_id = false, $is_variation = false ) {
345
346 if ( is_null( $post_fields ) ) {
347 $post_fields = [];
348 if ( isset( $_POST['data'] ) && ! is_array( $_POST['data'] ) ) {
349 $job_data = [];
350 parse_str( $_POST['data'], $job_data );
351 $post_fields = $job_data['fields'];
352 }
353 }
354
355 $custom_filed_key = $is_variation && $original_product_id ? $custom_field . $original_product_id : $custom_field;
356
357 if ( isset( $translation_data[ md5( $custom_filed_key ) ] ) ) {
358 $meta_value = $translation_data[ md5( $custom_filed_key ) ];
359 $meta_value = apply_filters( 'wcml_meta_value_before_add', $meta_value, $custom_filed_key );
360 update_post_meta( $trnsl_product_id, $custom_field, $meta_value );
361 unset( $post_fields[ $custom_filed_key ] );
362 } else {
363 foreach ( $post_fields as $post_field_key => $post_field ) {
364
365 if ( 1 === preg_match( '/field-' . $custom_field . '-.*?/', $post_field_key ) ) {
366 delete_post_meta( $trnsl_product_id, $custom_field );
367
368 $custom_fields = get_post_meta( $original_product_id, $custom_field );
369 $single = count( $custom_fields ) === 1;
370 $custom_fields = $single ? $custom_fields[0] : $custom_fields;
371
372 $filtered_custom_fields = array_filter( $custom_fields );
373 $custom_fields_values = array_values( $filtered_custom_fields );
374 $custom_fields_keys = array_keys( $filtered_custom_fields );
375
376 foreach ( $custom_fields_values as $custom_field_index => $custom_field_value ) {
377 $custom_fields_values =
378 $this->get_translated_custom_field_values(
379 $custom_fields_values,
380 $translation_data,
381 $custom_field,
382 $custom_field_value,
383 $custom_field_index
384 );
385 }
386
387 $custom_fields_translated = $custom_fields;
388
389 foreach ( $custom_fields_values as $index => $value ) {
390 if ( ! $single ) {
391 add_post_meta( $trnsl_product_id, $custom_field, $value, $single );
392 } else {
393 $custom_fields_translated[ $custom_fields_keys[ $index ] ] = $value;
394 }
395 }
396 if ( $single ) {
397 update_post_meta( $trnsl_product_id, $custom_field, $custom_fields_translated );
398 }
399 } else {
400 $meta_value = $translation_data[ md5( $post_field_key ) ];
401 $field_key = explode( ':', $post_field_key );
402 if ( $field_key[0] == $custom_filed_key ) {
403 if ( 'new' === substr( $field_key[1], 0, 3 ) ) {
404 add_post_meta( $trnsl_product_id, $custom_field, $meta_value );
405 } else {
406 update_meta( $field_key[1], $custom_field, $meta_value );
407 }
408 unset( $post_fields[ $post_field_key ] );
409 }
410 }
411 }
412 }
413
414 return $post_fields;
415 }
416
417 public function get_translated_custom_field_values( $custom_fields_values, $translation_data, $custom_field, $custom_field_value, $custom_field_index ) {
418
419 if ( is_scalar( $custom_field_value ) ) {
420 $key_index = $custom_field . '-' . $custom_field_index;
421 $cf = 'field-' . $key_index;
422 $meta_keys = explode( '-', $custom_field_index );
423 $meta_keys = array_map( [ $this, 'replace_separator' ], $meta_keys );
424 $custom_fields_values = $this->insert_under_keys(
425 $meta_keys,
426 $custom_fields_values,
427 $translation_data[ md5( $cf ) ]
428 );
429 } else {
430 foreach ( $custom_field_value as $ind => $value ) {
431 $field_index = $custom_field_index . '-' . str_replace( '-', self::CUSTOM_FIELD_KEY_SEPARATOR, $ind );
432 $custom_fields_values = $this->get_translated_custom_field_values( $custom_fields_values, $translation_data, $custom_field, $value, $field_index );
433 }
434 }
435
436 return $custom_fields_values;
437
438 }
439
440 private function replace_separator( $el ) {
441 return str_replace( self::CUSTOM_FIELD_KEY_SEPARATOR, '-', $el );
442 }
443
444 private function insert_under_keys( $keys, $array, $value ) {
445 $array[ $keys[0] ] = count( $keys ) === 1
446 ? $value
447 : $this->insert_under_keys(
448 array_slice( $keys, 1 ),
449 ( $array[ $keys[0] ] ?? [] ),
450 $value
451 );
452
453 return $array;
454 }
455
456 public function icl_connect_translations_action() {}
457
458 public function check_if_product_fields_sync_needed( $original_id, $trnsl_post_id, $fields_group ) {}
459
460 public function sync_product_translations_visibility( $product_id ) {
461 $translations = $this->post_translations->get_element_translations( $product_id, false, true );
462 if ( $translations ) {
463
464 $product = wc_get_product( $product_id );
465 $terms = [];
466
467 if ( $this->woocommerce_wpml->products->is_original_product( $product_id ) ) {
468 if ( $product->is_featured() ) {
469 $terms[] = 'featured';
470 }
471 }
472
473 if ( 'outofstock' === $product->get_stock_status() ) {
474 $terms[] = 'outofstock';
475 }
476
477 $rating = min( 5, round( $product->get_average_rating() ) );
478
479 if ( $rating > 0 ) {
480 $terms[] = 'rated-' . $rating;
481 }
482
483 foreach ( $translations as $translation ) {
484 if ( $product_id !== (int) $translation ) {
485 wp_set_post_terms( $translation, $terms, 'product_visibility', false );
486 }
487 }
488 }
489 }
490
491 public static function syncDeletedCustomFields( $originalId, $translationId ) {
492 $settingsFactory = wpml_load_core_tm()->settings_factory();
493
494 $isCopiedField = function( $field ) use ( $settingsFactory ) {
495 return WPML_COPY_CUSTOM_FIELD === $settingsFactory->post_meta_setting( $field )->status();
496 };
497
498 $deleteFieldInTranslation = function( $field ) use ( $translationId ) {
499 delete_post_meta( $translationId, $field );
500 };
501
502 $deletedInOriginal = wpml_collect( array_diff(
503 array_keys( get_post_custom( $translationId ) ),
504 array_keys( get_post_custom( $originalId ) )
505 ) );
506
507 $deletedInOriginal
508 ->filter( $isCopiedField )
509 ->map( $deleteFieldInTranslation );
510 }
511 }
512