Skip to content
This repository was archived by the owner on Mar 17, 2022. It is now read-only.

Commit 5b0fae2

Browse files
fix issue #320
wp_ to $table_prefix
1 parent dc5d2c4 commit 5b0fae2

File tree

1 file changed

+354
-0
lines changed

1 file changed

+354
-0
lines changed

src/Hyyan/WPI/Product/Variation.php

+354
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,360 @@ public static function getRelatedVariation($variatonID, $returnIDS = false)
110110
{
111111
$result = array();
112112

113+
//previous version of code using get_post_meta() was filtered at runtime by Polylang
114+
//even when adding 'suppress_filters' => true, so there was no way to adjust stock
115+
//on translations when processing new order
116+
//it also did not return all versions of post for deletion
117+
global $wpdb;
118+
$postids=$wpdb->get_col("select post_id from " . $table_prefix . "postmeta where meta_key='" .
119+
self::DUPLICATE_KEY . "' and meta_value=" . $variatonID);
120+
121+
if (true === $returnIDS) {
122+
return $postids;
123+
} else {
124+
$result = array();
125+
foreach ($postids as $postid) {
126+
$product = wc_get_product($postid);
127+
if ($product) {
128+
$result[]=$product;
129+
}
130+
}
131+
return $result;
132+
}
133+
}
134+
135+
/**
136+
* Delete all variation related to the given variation ID.
137+
*
138+
* @param int $variationID variation ID
139+
*/
140+
public static function deleteRelatedVariation($variationID)
141+
{
142+
$products = (array) static::getRelatedVariation($variationID);
143+
foreach ($products as $product) {
144+
wp_delete_post($product->get_id(), true);
145+
}
146+
}
147+
/**
148+
* Create new variation.
149+
*
150+
* @param \WC_Product_Variation $variation the variation product
151+
* @param array $metas variation array
152+
*/
153+
protected function insert(\WC_Product_Variation $variation, array $metas)
154+
{
155+
// Add the duplicate meta to the default language product variation,
156+
// just in case the product was created before plugin acivation.
157+
$this->addDuplicateMeta($variation->get_id());
158+
$data = (array) get_post($variation->get_id());
159+
unset($data['ID']);
160+
$data['post_parent'] = $this->to->get_id();
161+
$ID = wp_insert_post($data);
162+
if ($ID) {
163+
update_post_meta(
164+
$ID, self::DUPLICATE_KEY, $metas['variation_id']
165+
);
166+
$this->copyVariationMetas($variation->get_id(), $ID);
167+
}
168+
}
169+
/**
170+
* Update variation product from given post object.
171+
*
172+
* @param \WC_Product_Variation $variation
173+
* @param \WP_Post $post
174+
* @param array $metas
175+
*/
176+
protected function update(\WC_Product_Variation $variation, \WP_Post $post, array $metas)
177+
{
178+
$this->copyVariationMetas($variation->get_id(), $post->ID);
179+
}
180+
/**
181+
* Add duplicate meta key to products created before plugin activation.
182+
*
183+
* @param int $ID Id of the product in the default language
184+
*/
185+
public function addDuplicateMeta($ID)
186+
{
187+
if ($ID) {
188+
$meta = get_post_meta($ID, self::DUPLICATE_KEY);
189+
if (empty($meta)) {
190+
update_post_meta($ID, self::DUPLICATE_KEY, $ID);
191+
}
192+
}
193+
}
194+
/**
195+
* Sync Product Shipping Class.
196+
*
197+
* Shipping Class translation is not supported after WooCommerce 2.6
198+
* but it is still implemented by WooCommerce as a taxonomy (no longer a meta).
199+
* Therefore, Polylang will not copy the Shipping Class meta.
200+
*
201+
* @param int $from product variation ID
202+
* @param int $to product variation ID
203+
*/
204+
public function syncShippingClass($from, $to)
205+
{
206+
if (in_array('product_shipping_class', Meta::getProductMetaToCopy())) {
207+
$variation_from = wc_get_product($from);
208+
if ($variation_from) {
209+
$shipping_class = $variation_from->get_shipping_class();
210+
if ($shipping_class) {
211+
$shipping_terms = get_term_by('slug', $shipping_class, 'product_shipping_class');
212+
if ($shipping_terms) {
213+
wp_set_post_terms($to, array($shipping_terms->term_id), 'product_shipping_class');
214+
}
215+
} else {
216+
//if no shipping class found this would mean "Same as parent"
217+
//so we need to clear existing setting if there is one
218+
//however get_shipping_class() actually gets the parent value,
219+
//so this code shouldn't be executed,
220+
//instead the parent value will be copied to variation
221+
wp_set_post_terms($to, array(), 'product_shipping_class');
222+
}
223+
}
224+
}
225+
}
226+
/**
227+
* Copy variation meta.
228+
*
229+
* The method follow the same method polylang use to sync metas between
230+
* translations
231+
*
232+
* @param int $from product variation ID
233+
* @param int $to product variation ID
234+
*
235+
* @return boolean false if something went wrong
236+
*/
237+
protected function copyVariationMetas($from, $to)
238+
{
239+
/* copy or synchronize post metas and allow plugins to do the same */
240+
$metas_from = get_post_custom($from);
241+
$metas_to = get_post_custom($to);
242+
/* get public and protected meta keys */
243+
$keys = array_unique(array_merge(array_keys($metas_from), array_keys($metas_to)));
244+
/* metas disabled for sync */
245+
$metas_nosync = Meta::getDisabledProductMetaToCopy();
246+
/*
247+
* _variation_description meta is a text-based string and generally needs to be translated.
248+
* _variation_description meta is copied from product in default language to the translations
249+
* when the translation is first created. But the meta can be edited/changed and will not be
250+
* overwriten when product is saved or updated.
251+
*/
252+
if (isset($metas_to['_variation_description'])) {
253+
$metas_nosync[] = '_variation_description';
254+
}
255+
/* synchronize */
256+
foreach ($keys as $key) {
257+
if (!in_array($key, $metas_nosync)) {
258+
/*
259+
* the synchronization process of multiple values custom fields is
260+
* easier if we delete all metas first
261+
*/
262+
delete_post_meta($to, $key);
263+
if (isset($metas_from[$key])) {
264+
if (substr($key, 0, 10) == 'attribute_') {
265+
$translated = array();
266+
$tax = str_replace('attribute_', '', $key);
267+
foreach ($metas_from[$key] as $termSlug) {
268+
if (pll_is_translated_taxonomy($tax)) {
269+
$term = $this->getTermBySlug($tax, $termSlug);
270+
if ($term) {
271+
$term_id = $term->term_id;
272+
//ok we got a term to translate, now get translation if available
273+
$lang = isset($_GET['new_lang']) ? esc_attr($_GET['new_lang']) : pll_get_post_language($this->to->get_id());
274+
$translated_term = pll_get_term($term_id, $lang);
275+
if ($translated_term) {
276+
$translated[] = get_term_by('id', $translated_term, $tax)->slug;
277+
} else {
278+
// Attribute term has no translation, so get the previous term
279+
// and create the translation
280+
$result = false;
281+
$fromLang = pll_get_post_language($from);
282+
if (! $fromLang) {
283+
$fromLang = pll_get_post_language(wc_get_product($from)->get_parent_id());
284+
}
285+
if ($fromLang) {
286+
$term = pll_get_term($term_id, $fromLang);
287+
if ($term) {
288+
$term = get_term_by('id', $term, $tax);
289+
$result = Meta::createDefaultTermTranslation($tax, $term, $termSlug, $lang, false);
290+
}
291+
}
292+
if ($result) {
293+
$translated[] = $result;
294+
} else {
295+
$translated[] = $termSlug;
296+
}
297+
}
298+
} else {
299+
$translated[] = $termSlug;
300+
}
301+
} else {
302+
$translated[] = $termSlug;
303+
}
304+
}
305+
$metas_from[$key] = $translated;
306+
}
307+
foreach ($metas_from[$key] as $value) {
308+
/*
309+
* Important: always maybe_unserialize value coming from
310+
* get_post_custom. See codex.
311+
*/
312+
$value = maybe_unserialize($value);
313+
add_post_meta($to, $key, $value);
314+
}
315+
}
316+
}
317+
}
318+
319+
//add shipping class not included in metas as now a taxonomy
320+
$this->syncShippingClass($from, $to);
321+
322+
do_action(HooksInterface::PRODUCT_VARIATION_COPY_META_ACTION, $from, $to, $this->from, $this->to);
323+
}
324+
/**
325+
* Get Term By Slug.
326+
*
327+
* Why not get_term_by method ?! since 4.8 we were unable to force polylang to
328+
* fetch terms with the default language
329+
*
330+
* @param string $taxonomy taxonomy name
331+
* @param string $value term slug
332+
*
333+
* @return bool false if the term can not fetched , the term object otherwise
334+
*/
335+
private function getTermBySlug($taxonomy, $value)
336+
{
337+
$query = array(
338+
'get' => 'all',
339+
'number' => 1,
340+
'taxonomy' => $taxonomy,
341+
'update_term_meta_cache' => false,
342+
'orderby' => 'none',
343+
'suppress_filter' => true,
344+
'slug' => $value,
345+
'lang' => pll_default_language(),
346+
);
347+
$terms = get_terms($query);
348+
if (is_wp_error($terms) || empty($terms)) {
349+
return false;
350+
}
351+
$term = array_shift($terms);
352+
return get_term($term, $taxonomy);
353+
}
354+
}
355+
<?php
356+
/**
357+
* This file is part of the hyyan/woo-poly-integration plugin.
358+
* (c) Hyyan Abo Fakher <[email protected]>.
359+
*
360+
* For the full copyright and license information, please view the LICENSE
361+
* file that was distributed with this source code.
362+
*/
363+
namespace Hyyan\WPI\Product;
364+
365+
use Hyyan\WPI\HooksInterface;
366+
use Hyyan\WPI\Product\Meta;
367+
use Hyyan\WPI\Utilities;
368+
369+
/**
370+
* Variation.
371+
*
372+
* Handle Variation Duplicate
373+
*
374+
* @author Hyyan Abo Fakher <[email protected]>
375+
*/
376+
class Variation
377+
{
378+
const DUPLICATE_KEY = '_point_to_variation';
379+
/**
380+
* @var \WC_Product_Variable
381+
*/
382+
protected $from;
383+
/**
384+
* @var \WC_Product
385+
*/
386+
protected $to;
387+
/**
388+
* Construct object.
389+
*
390+
* @param \WC_Product_Variable $from the product which contains variations to
391+
* copy from
392+
* @param \WC_Product $to the product which we will copy the variation to
393+
*/
394+
public function __construct(\WC_Product_Variable $from, \WC_Product $to)
395+
{
396+
$this->from = $from;
397+
$this->to = $to;
398+
}
399+
/**
400+
* Handle variation duplicate.
401+
*
402+
* @return bool false if the from product conatins no variatoins
403+
*/
404+
public function duplicate()
405+
{
406+
//the variations of the product in the from product language
407+
$fromVariation = $this->from->get_available_variations();
408+
if (empty($fromVariation)) {
409+
return false;
410+
}
411+
if ($this->to->get_id() === $this->from->get_id()) {
412+
/*
413+
* In such a case just add the duplicate meta
414+
*/
415+
foreach ($fromVariation as $variation) {
416+
if (! metadata_exists('post', $variation['variation_id'], self::DUPLICATE_KEY)) {
417+
update_post_meta(
418+
$variation['variation_id'], self::DUPLICATE_KEY, $variation['variation_id']
419+
);
420+
}
421+
}
422+
} else {
423+
/* This could be a very long operation */
424+
set_time_limit(0);
425+
foreach ($fromVariation as $variation) {
426+
/*
427+
* First we check if the "to" product contains the duplicate meta
428+
* key to find out if we have to update or insert
429+
*/
430+
$posts = get_posts(array(
431+
'meta_key' => self::DUPLICATE_KEY,
432+
'meta_value' => $variation['variation_id'],
433+
'post_type' => 'product_variation',
434+
'post_parent' => $this->to->get_id(),
435+
));
436+
switch (count($posts)) {
437+
case 1:
438+
// update
439+
$this->update(
440+
wc_get_product($variation['variation_id']), $posts[0], $variation
441+
);
442+
break;
443+
case 0:
444+
// insert
445+
$this->insert(wc_get_product($variation['variation_id']), $variation);
446+
break;
447+
default:
448+
// we can not handle , something wrong here
449+
break;
450+
}
451+
}
452+
/* Restor original timeout */
453+
set_time_limit(ini_get('max_execution_time'));
454+
}
455+
}
456+
/**
457+
* Get array of variations IDS which point to the given variation ID.
458+
*
459+
* @param int $variatonID variation ID
460+
*
461+
* @return array array of posts
462+
*/
463+
public static function getRelatedVariation($variatonID, $returnIDS = false)
464+
{
465+
$result = array();
466+
113467
//previous version of code using get_post_meta() was filtered at runtime by Polylang
114468
//even when adding 'suppress_filters' => true, so there was no way to adjust stock
115469
//on translations when processing new order

0 commit comments

Comments
 (0)