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 / Synchronization / Component / Attributes.php
woocommerce-multilingual / classes / Synchronization / Component Last commit date
Attachments.php 1 week ago Attributes.php 1 week ago DownloadableFiles.php 1 week ago Linked.php 1 week ago Meta.php 1 week ago Post.php 1 week ago Stock.php 1 week ago Synchronizer.php 1 week ago SynchronizerForMeta.php 1 week ago Taxonomies.php 1 week ago VariationAttachments.php 1 week ago VariationMeta.php 1 week ago VariationTaxonomies.php 1 week ago Variations.php 1 week ago
Attributes.php
227 lines
1 <?php
2
3 namespace WCML\Synchronization\Component;
4
5 use WCML\Utilities\DB;
6 use WCML\Utilities\WCTaxonomies;
7 use WPML\FP\Lst;
8 use WPML\FP\Obj;
9
10 class Attributes extends SynchronizerForMeta {
11
12 const DEFAULT_ATTRIBUTES_META_KEY = '_default_attributes';
13 const PRODUCT_ATTRIBUTES_META_KEY = '_product_attributes';
14
15 public function run( $product, $translationsIds, $translationsLanguages ) {
16 $productsIds = array_merge( [ $product->ID ], $translationsIds );
17 $storedAttributes = $this->getMeta( self::PRODUCT_ATTRIBUTES_META_KEY, $productsIds );
18
19 $this->runForAttributes( $product->ID, $translationsIds, $translationsLanguages, $storedAttributes );
20 $this->runForDefaultAttributes( $product->ID, $translationsIds, $translationsLanguages, $storedAttributes );
21 }
22
23 private function runForAttributes( $productId, $translationsIds, $translationsLanguages, $storedAttributes ) {
24 $productAttributes = $storedAttributes[ $productId ] ?? null;
25
26 if ( null === $productAttributes ) {
27 $translationsIdsToClear = array_intersect( $translationsIds, array_keys( $storedAttributes ) );
28 $this->clearTranslationsValue( $translationsIdsToClear, self::PRODUCT_ATTRIBUTES_META_KEY );
29 return;
30 }
31
32 if ( empty( $productAttributes ) ) {
33 $this->spreadEmptyValue( $translationsIds, $storedAttributes, self::PRODUCT_ATTRIBUTES_META_KEY );
34 return;
35 }
36
37 $hasLocalAttributes = (bool) Lst::find(
38 function( $attributeData ) {
39 return (bool) Obj::prop( 'is_taxonomy', $attributeData ) === false;
40 },
41 $productAttributes
42 );
43
44 $duplicationsIds = [];
45 if ( $hasLocalAttributes ) {
46 $duplicationsIds = $this->wpdb->get_col(
47 $this->wpdb->prepare(
48 "
49 SELECT post_id
50 FROM {$this->wpdb->postmeta}
51 WHERE meta_key = %s
52 AND post_id IN (" . DB::prepareIn( $translationsIds ) . ")
53 LIMIT %d
54 ",
55 '_icl_lang_duplicate_of',
56 count( $translationsIds )
57 )
58 );
59 }
60
61 $sanitizedAttributeNames = [];
62 foreach ( $productAttributes as $attribute => $attributeData ) {
63 $sanitizedAttributeNames[ $attribute ] = $attribute;
64 $sanitizedAttribute = $this->woocommerceWpml->attributes->getAttributeNameToSave( $attribute, $attributeData, $productId );
65 if ( $attribute !== $sanitizedAttribute ) {
66 $sanitizedAttributeNames[ $sanitizedAttribute ] = $attribute;
67 $productAttributes[ $sanitizedAttribute ] = $attributeData;
68 unset( $productAttributes[ $attribute ] );
69 }
70 }
71
72 $translationsIdsToInsert = [];
73 $translationsIdsToUpdate = [];
74 foreach ( $translationsIds as $translationId ) {
75 $translationAttributes = $productAttributes;
76 $storedTranslationAttributes = $storedAttributes[ $translationId ] ?? [];
77 foreach ( $translationAttributes as $attribute => $attributeData ) {
78 if ( $attributeData['is_taxonomy'] || in_array( $translationId, $duplicationsIds, true ) ) {
79 continue;
80 }
81
82 $attributeToSave = $sanitizedAttributeNames[ $attribute ];
83 if ( isset( $storedTranslationAttributes[ $attribute ] ) ) {
84 $translationAttributes[ $attributeToSave ]['value'] = $storedTranslationAttributes[ $attribute ]['value'];
85 } else if ( isset( $storedTranslationAttributes[ $attributeToSave ] ) ) {
86 $translationAttributes[ $attributeToSave ]['value'] = $storedTranslationAttributes[ $attributeToSave ]['value'];
87 } else if ( ! empty( $storedTranslationAttributes ) ) {
88 unset( $translationAttributes[ $attribute ] );
89 }
90 }
91 if ( maybe_serialize( $translationAttributes ) === maybe_serialize( $storedTranslationAttributes ) ) {
92 continue;
93 }
94 if ( array_key_exists( $translationId, $storedAttributes ) ) {
95 $translationsIdsToUpdate[ $translationId ] = $translationAttributes;
96 } else {
97 $translationsIdsToInsert[ $translationId ] = $translationAttributes;
98 }
99 }
100
101 $this->insertMeta( self::PRODUCT_ATTRIBUTES_META_KEY, $translationsIdsToInsert );
102 $this->updateMeta( self::PRODUCT_ATTRIBUTES_META_KEY, $translationsIdsToUpdate );
103 }
104
105 private function runForDefaultAttributes( $productId, $translationsIds, $translationsLanguages, $storedAttributes ) {
106 $productsIds = array_merge( [ $productId ], $translationsIds );
107 $storedDefaultAttributes = $this->getMeta( self::DEFAULT_ATTRIBUTES_META_KEY, $productsIds );
108 $defaultAttributes = $storedDefaultAttributes[ $productId ] ?? null;
109
110 if ( null === $defaultAttributes ) {
111 $translationsIdsToClear = array_intersect( $translationsIds, array_keys( $storedDefaultAttributes ) );
112 $this->clearTranslationsValue( $translationsIdsToClear, self::DEFAULT_ATTRIBUTES_META_KEY );
113 return;
114 }
115
116 if ( empty( $defaultAttributes ) ) {
117 $this->spreadEmptyValue( $translationsIds, $storedDefaultAttributes, self::DEFAULT_ATTRIBUTES_META_KEY );
118 return;
119 }
120
121 $defaultAttributesToUpdate = [];
122 foreach ( $defaultAttributes as $attribute => $defaultAttributeValue ) {
123 if ( WCTaxonomies::isProductAttribute( $attribute ) ) {
124 if ( $this->woocommerceWpml->attributes->is_translatable_attribute( $attribute ) ) {
125 $sanitizedAttributeName = wc_sanitize_taxonomy_name( $attribute );
126 $defaultTerm = $this->woocommerceWpml->terms->wcml_get_term_by_slug( $defaultAttributeValue, $sanitizedAttributeName );
127 $defaultTermTranslations = $defaultTerm
128 ? $this->elementTranslations->get_element_translations( $defaultTerm->term_taxonomy_id, false, false )
129 : [];
130
131 foreach ( $translationsLanguages as $translationId => $language ) {
132 $translatedDefaultAttributes = $storedDefaultAttributes[ $translationId ] ?? [];
133 $translatedDefaultTermTaxonomyId = $defaultTermTranslations[ $language ] ?? null;
134 $translatedDefaultTerm = $translatedDefaultTermTaxonomyId
135 ? $this->woocommerceWpml->terms->wcml_get_term_by_taxonomy_id( $translatedDefaultTermTaxonomyId, $sanitizedAttributeName )
136 : null;
137 $translatedDefaultAttributeValue = $translatedDefaultTerm
138 ? $translatedDefaultTerm->slug
139 : 0;
140 if (
141 ! array_key_exists( $attribute, $translatedDefaultAttributes )
142 || $translatedDefaultAttributes[ $attribute ] !== $translatedDefaultAttributeValue
143 ) {
144 $defaultAttributesToUpdate[ $translationId ][ $attribute ] = $translatedDefaultAttributeValue;
145 }
146 }
147 } else {
148 foreach ( $translationsIds as $translationId ) {
149 $translatedDefaultAttributes = $storedDefaultAttributes[ $translationId ] ?? [];
150 if (
151 ! array_key_exists( $attribute, $translatedDefaultAttributes )
152 || $translatedDefaultAttributes[ $attribute ] !== $defaultAttributeValue
153 ) {
154 $defaultAttributesToUpdate[ $translationId ][ $attribute ] = $defaultAttributeValue;
155 }
156 }
157 }
158 unset( $defaultAttributes[ $attribute ] );
159 }
160 }
161
162 if ( ! empty( $defaultAttributes ) ) {
163 $productAttributes = $storedAttributes[ $productId ] ?? [];
164
165 foreach ( $defaultAttributes as $attribute => $defaultAttributeValue ) {
166 if ( ! array_key_exists( $attribute, $productAttributes ) ) {
167 continue;
168 }
169
170 $productAttributeValues = explode( '|', $productAttributes[ $attribute ]['value'] );
171 $productAttributeValues = array_map( 'trim', $productAttributeValues );
172
173 foreach ( $productAttributeValues as $attributeIndex => $attributeValue ) {
174 $attributeValueSanitized = strtolower( sanitize_title( $attributeValue ) );
175 if (
176 $attributeValueSanitized !== $defaultAttributeValue
177 && trim( $attributeValue ) !== trim( $defaultAttributeValue )
178 ) {
179 continue;
180 }
181 foreach ( $translationsIds as $translationId ) {
182 $translatedStoredAttributes = $storedAttributes[ $translationId ] ?? [];
183 if ( ! array_key_exists( $attribute, $translatedStoredAttributes ) ) {
184 continue;
185 }
186 $translatedAttributeValues = explode( '|', $translatedStoredAttributes[ $attribute ]['value'] );
187 if ( ! isset( $translatedAttributeValues[ $attributeIndex ] ) ) {
188 $defaultAttributesToUpdate[ $translationId ][ $attribute ] = '';
189 continue;
190 }
191 if ( $attributeValueSanitized === $defaultAttributeValue ) {
192 $translatedAttributeValue = strtolower( sanitize_title( trim( $translatedAttributeValues[ $attributeIndex ] ) ) );
193 } else {
194 $translatedAttributeValue = trim( $translatedAttributeValues[ $attributeIndex ] );
195 }
196 if ( $translatedAttributeValue !== Obj::path( [ $translationId, $attribute ], $storedDefaultAttributes ) ) {
197 $defaultAttributesToUpdate[ $translationId ][ $attribute ] = $translatedAttributeValue;
198 }
199 }
200 }
201 }
202 }
203
204 if ( ! empty( $defaultAttributesToUpdate ) ) {
205 $metaToInsert = [];
206 $metaToUpdate = [];
207 foreach ( $defaultAttributesToUpdate as $translationId => $translationAttributes ) {
208 if ( ! array_key_exists( $translationId, $storedDefaultAttributes ) ) {
209 $metaToInsert[ $translationId ] = $translationAttributes;
210 continue;
211 }
212 $translationDefaultAttributes = $storedDefaultAttributes[ $translationId ];
213 if ( ! empty( $translationDefaultAttributes ) ) {
214 $metaToUpdate[ $translationId ] = $storedDefaultAttributes[ $translationId ];
215 foreach ( $translationAttributes as $attribute => $attributeValue ) {
216 $metaToUpdate[ $translationId ][ $attribute ] = $attributeValue;
217 }
218 }
219 }
220
221 $this->insertMeta( self::DEFAULT_ATTRIBUTES_META_KEY, $metaToInsert );
222 $this->updateMeta( self::DEFAULT_ATTRIBUTES_META_KEY, $metaToUpdate );
223 }
224 }
225
226 }
227