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 / classes / media / Wrapper / Translatable.php
woocommerce-multilingual / classes / media / Wrapper Last commit date
Factory.php 1 week ago IMedia.php 1 week ago NonTranslatable.php 1 week ago Translatable.php 1 week ago
Translatable.php
246 lines
1 <?php
2
3 namespace WCML\Media\Wrapper;
4
5 use WCML\Options\WPML;
6 use wpdb;
7 use WPML\Media\Option;
8 use WPML_Media_Attachments_Duplication_Factory;
9
10 class Translatable implements IMedia {
11
12 const META_KEY_THUMBNAIL_ID = '_thumbnail_id';
13 const META_KEY_PRODUCT_IMAGE_GALLERY = '_product_image_gallery';
14
15 private $sitepress;
16 private $wpdb;
17
18 public $settings = [];
19
20 private $products_being_synced = [];
21
22 public function __construct( \SitePress $sitepress, $wpdb ) {
23 $this->sitepress = $sitepress;
24 $this->wpdb = $wpdb;
25 }
26
27 public function add_hooks() {
28 add_action( 'wpml_media_create_duplicate_attachment', [ $this, 'sync_product_gallery_duplicate_attachment' ], 11, 2 );
29 }
30
31 private function is_wpml_media_translation_adds_media_automatically(): bool {
32 if ( ! WPML::useAte() ) {
33 return false;
34 }
35
36 if ( ! class_exists( \WPML\Media\Option::class ) ) {
37 return false;
38 }
39 if ( Option::getTranslateMediaLibraryTexts() || Option::shouldHandleMediaAuto() ) {
40 return true;
41 }
42
43 return false;
44 }
45
46 public function product_images_ids( $product_id ) {
47 $product_images_ids = [];
48
49 if ( ! $this->is_wpml_media_translation_adds_media_automatically() ) {
50 $tmb = get_post_meta( $product_id, self::META_KEY_THUMBNAIL_ID, true );
51 if ( $tmb ) {
52 $product_images_ids[] = $tmb;
53 }
54
55 $product_gallery = get_post_meta( $product_id, self::META_KEY_PRODUCT_IMAGE_GALLERY, true );
56 if ( $product_gallery ) {
57 $product_gallery = explode( ',', $product_gallery );
58 foreach ( $product_gallery as $img ) {
59 $product_images_ids[] = $img;
60 }
61 }
62 }
63
64 foreach ( wp_get_post_terms( $product_id, 'product_type', [ 'fields' => 'names' ] ) as $type ) {
65 $product_type = $type;
66 }
67
68 if ( isset( $product_type ) && 'variable' === $product_type ) {
69 $get_post_variations_image = $this->wpdb->get_col(
70 $this->wpdb->prepare(
71 "SELECT pm.meta_value FROM {$this->wpdb->posts} AS p
72 LEFT JOIN {$this->wpdb->postmeta} AS pm ON p.ID = pm.post_id
73 WHERE pm.meta_key='" . self::META_KEY_THUMBNAIL_ID . "'
74 AND p.post_status IN ('publish','private')
75 AND p.post_type = 'product_variation'
76 AND p.post_parent = %d
77 ORDER BY ID",
78 $product_id
79 )
80 );
81 foreach ( $get_post_variations_image as $variation_image ) {
82 if ( $variation_image ) {
83 $product_images_ids[] = $variation_image;
84 }
85 }
86 }
87
88 $product_images_ids = array_unique( array_map( 'intval', $product_images_ids ) );
89
90 foreach ( $product_images_ids as $key => $image ) {
91 if ( ! get_post_status( $image ) ) {
92 unset( $product_images_ids[ $key ] );
93 }
94 }
95
96 return $product_images_ids;
97 }
98
99 public function sync_thumbnail_id( $original_product_id, $translated_product_id, $language ) {
100 if ( $this->is_thumbnail_image_duplication_enabled( $original_product_id ) ) {
101 $translated_thumbnail_id = $this->get_translated_thumbnail_id( $original_product_id, $language );
102 if ( $translated_thumbnail_id ) {
103 update_post_meta( $translated_product_id, self::META_KEY_THUMBNAIL_ID, $translated_thumbnail_id );
104 }
105 }
106 }
107
108 public function sync_variation_thumbnail_id( $variation_id, $translated_variation_id, $language ) {
109 if ( $this->is_thumbnail_image_duplication_enabled( wp_get_post_parent_id( $variation_id ) ) ) {
110 $translated_thumbnail_id = $this->get_translated_thumbnail_id( $variation_id, $language );
111 if ( ! $translated_thumbnail_id ) {
112 return null;
113 }
114
115 $stored_translated_variation_thumbnail_id = (int) get_post_meta( $translated_variation_id, self::META_KEY_THUMBNAIL_ID, true );
116 if ( (int) $translated_thumbnail_id !== $stored_translated_variation_thumbnail_id ) {
117 update_post_meta( $translated_variation_id, self::META_KEY_THUMBNAIL_ID, $translated_thumbnail_id );
118 update_post_meta( $variation_id, '_wpml_media_duplicate', 1 );
119 update_post_meta( $variation_id, '_wpml_media_featured', 1 );
120 }
121 }
122 }
123
124 private function get_translated_thumbnail_id( $post_id, $language ) {
125 $thumbnail_id = get_post_meta( $post_id, self::META_KEY_THUMBNAIL_ID, true );
126 if ( ! $thumbnail_id ) {
127 return null;
128 }
129
130 $translated_thumbnail_id = $this->sitepress->get_object_id( $thumbnail_id, 'attachment', false, $language );
131 if ( is_null( $translated_thumbnail_id ) ) {
132 $factory = new WPML_Media_Attachments_Duplication_Factory();
133
134 $media_duplicate = $factory->create();
135 $translated_thumbnail_id = $media_duplicate->create_duplicate_attachment(
136 $thumbnail_id,
137 wp_get_post_parent_id( $thumbnail_id ),
138 $language
139 );
140 }
141
142 return $translated_thumbnail_id;
143 }
144
145 public function sync_product_gallery( $orig_post_id, $trnsl_post_id, $lang ) {
146 if ( $this->is_media_duplication_enabled( $orig_post_id ) ) {
147 $product_gallery = get_post_meta( $orig_post_id, self::META_KEY_PRODUCT_IMAGE_GALLERY, true );
148 $gallery_ids = explode( ',', $product_gallery );
149 $translated_gallery_ids = $this->translated_gallery_ids( $gallery_ids, $trnsl_post_id, $lang );
150 $translated_gallery_ids_value = implode( ',', $translated_gallery_ids );
151 update_post_meta( $trnsl_post_id, self::META_KEY_PRODUCT_IMAGE_GALLERY, $translated_gallery_ids_value );
152 }
153 }
154
155 public function sync_product_gallery_to_all_languages( $product_id ) {
156 if ( $this->is_media_duplication_enabled( $product_id ) ) {
157 $product_gallery = get_post_meta( $product_id, self::META_KEY_PRODUCT_IMAGE_GALLERY, true );
158 $gallery_ids = explode( ',', $product_gallery );
159 $trid = $this->sitepress->get_element_trid( $product_id, 'post_product' );
160 $translations = $this->sitepress->get_element_translations( $trid, 'post_product', true );
161
162 foreach ( $translations as $translation ) {
163 if ( $translation->original ) {
164 continue;
165 }
166 $translated_gallery_ids = $this->translated_gallery_ids( $gallery_ids, $translation->element_id, $translation->language_code );
167 $translated_gallery_ids_value = implode( ',', $translated_gallery_ids );
168 update_post_meta( $translation->element_id, self::META_KEY_PRODUCT_IMAGE_GALLERY, $translated_gallery_ids_value );
169 }
170 }
171 }
172
173 private function translated_gallery_ids( $gallery_ids, $translation_id, $lang ) {
174 $translated_gallery_ids = [];
175 foreach ( $gallery_ids as $image_id ) {
176 if ( null === get_post( $image_id ) ) {
177 continue;
178 }
179 $duplicated_id = apply_filters(
180 'wpml_object_id',
181 $image_id,
182 'attachment',
183 false,
184 $lang
185 );
186 if ( is_null( $duplicated_id ) && $image_id ) {
187 $duplicated_id = $this->create_base_media_translation(
188 $image_id,
189 $translation_id,
190 $lang
191 );
192 }
193 $translated_gallery_ids[] = $duplicated_id;
194 }
195 return $translated_gallery_ids;
196 }
197
198 public function create_base_media_translation( $attachment_id, $parent_id, $target_lang ) {
199 $factory = new WPML_Media_Attachments_Duplication_Factory();
200
201 $media_duplicate = $factory->create();
202 $duplicated_id = $media_duplicate->create_duplicate_attachment( $attachment_id, $parent_id, $target_lang );
203
204 return $duplicated_id;
205 }
206
207 public function sync_product_gallery_duplicate_attachment( $att_id, $dup_att_id ) {
208 $product_id = wp_get_post_parent_id( $att_id );
209 $post_type = get_post_type( $product_id );
210 if ( 'product' !== $post_type || array_key_exists( $product_id, $this->products_being_synced ) ) {
211 return;
212 }
213 $this->products_being_synced[ $product_id ] = 1;
214 $this->sync_product_gallery_to_all_languages( $product_id );
215 unset( $this->products_being_synced[ $product_id ] );
216 }
217
218 private function is_thumbnail_image_duplication_enabled( $product_id ) {
219 return $this->is_duplication_enabled( $product_id, 'WPML\Media\Option::DUPLICATE_FEATURED_KEY', 'WPML_Admin_Post_Actions::DUPLICATE_FEATURED_GLOBAL_KEY' );
220 }
221
222 private function is_media_duplication_enabled( $product_id ) {
223 return $this->is_duplication_enabled( $product_id, 'WPML\Media\Option::DUPLICATE_MEDIA_KEY', 'WPML_Admin_Post_Actions::DUPLICATE_MEDIA_GLOBAL_KEY' );
224 }
225
226 private function is_duplication_enabled( $product_id, $meta_key, $global_key ) {
227
228 $setting_value = get_post_meta(
229 $product_id,
230 $this->sitepress->get_wp_api()->constant( $meta_key ),
231 true
232 );
233
234 if ( '' === $setting_value ) {
235 $media_options = get_option( '_wpml_media', [] );
236 $global_setting_key = $this->sitepress->get_wp_api()->constant( $global_key );
237 if ( isset( $media_options['new_content_settings'][ $global_setting_key ] ) ) {
238 $setting_value = $media_options['new_content_settings'][ $global_setting_key ];
239 }
240 }
241
242 return (bool) $setting_value;
243 }
244
245 }
246