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

Commit

Permalink
fixes #391, #299
Browse files Browse the repository at this point in the history
fixes #391, fixes #299 and most other stock related concerns by
rewriting the Stock.php by handling and using the standard WooCommerce
stock adjustment function
  • Loading branch information
Jon007 committed May 23, 2019
1 parent 3bbc1bf commit 17e29b9
Showing 1 changed file with 67 additions and 159 deletions.
226 changes: 67 additions & 159 deletions src/Hyyan/WPI/Product/Stock.php
Expand Up @@ -6,171 +6,79 @@
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* This file was written by J.Moore to replace the existing Stock.php file which had
* multiple issues: this version takes a different approach
*/

namespace Hyyan\WPI\Product;

use Hyyan\WPI\Utilities;
use Hyyan\WPI\Product\Variation;
use Hyyan\WPI\Admin\Settings;
use Hyyan\WPI\Admin\MetasList;

/**
* Product Stock.
*
* Handle stock sync
*
* @author Hyyan Abo Fakher <hyyanaf@gmail.com>
*/
class Stock
{
const STOCK_REDUCE_ACTION = 'reduce';
const STOCK_INCREASE_ACTION = 'increase';

/**
* Construct object.
*/
public function __construct()
{
// sync stock
add_action(
'woocommerce_reduce_order_stock', array($this, 'reduceStock')
);
add_filter(
'woocommerce_restore_order_stock_quantity', array($this, 'increaseStock')
);
}

/**
* Reduce stock for product and its translation.
*
* @param \WC_Order $order
*/
public function reduceStock($order)
{

/* Get array of ordered products */
$items = $order->get_items();

/* Reduce stock */
foreach ($items as $item) {
$this->change($item, self::STOCK_REDUCE_ACTION);
}
}

/**
* Increase stock for product and its translation.
*
* @param int $change the stock change
*
* @return int stock change
*/
public function increaseStock($change)
{
$orderId = absint($_POST['order_id']);
$order = new \WC_Order($orderId);

/* Get array of ordered products */
$items = $order->get_items();

/* Increase stock */
foreach ($items as $item) {
$item->change = $change;
$this->change($item, self::STOCK_INCREASE_ACTION);
}
}

/**
* Change the product stock in the given order item.
*
* @param array $item the order data
* @param string $action STOCK_REDUCE_ACTION | STOCK_INCREASE_ACTION
*/
protected function change(\WC_Order_Item_Product $item, $action = self::STOCK_REDUCE_ACTION)
{
$productID = Utilities::get_order_item_productid($item);
$productObject = wc_get_product($productID);
//$productLang = pll_get_post_language($productID); //#184
$orderLang = pll_get_post_language($item->get_order_id());
$variationID = Utilities::get_order_item_variationid($item);

/* Handle Products */
if ($productObject && $orderLang) {

/* Get the translations IDS */
$translations = Utilities::getProductTranslationsArrayByObject(
$productObject
);

$method = ($action === self::STOCK_REDUCE_ACTION) ?
'decrease' :
'increase';
$change = ($action === self::STOCK_REDUCE_ACTION) ?
Utilities::get_order_item_quantity($item) :
Utilities::get_order_item_change($item);


$isManageStock = $productObject->managing_stock();
$isVariation = $variationID && $variationID > 0;

//in 3.0.8 at least, current lang item must not be removed from array if is variable
if ($isManageStock && (!$isVariation)) {
/* Remove the current product from translation array */
unset($translations[$orderLang]);
}

/* Sync stock for all translation */
foreach ($translations as $ID) {

/* Only if product is managing stock
* including variation with stock managed at product level*/
if ($isManageStock) {
if (($translation = wc_get_product($ID))) {
\wc_update_product_stock($translation, $change, $method);
}
}

$general = Settings::getOption(
'general', MetasList::getID(), array('total_sales')
);
if (in_array('total_sales', $general)) {
update_post_meta(
$ID, 'total_sales', get_post_meta($productID, 'total_sales', true)
);
}
}

/* Handle variation stock UNLESS stock is managed on the parent
* there is a function for this $variation->get_stock_managed_by_id() however in woo-poly-context
* this returns the master language id of either the variation of the parent.
*/
if (($isVariation) && !($isManageStock)) {
//unfortunately pll functions can't be used as the
//variations are not currently linked using pll_save_post_translations
//still it might be more sensible to get master in base language, and synchronise from that
//$variationMaster = (pll_get_post_language($variationID) == pll_default_language()) ?
// wc_get_product($variationID) : Utilities::getProductTranslationByID($variationID, pll_default_language());
class Stock {
public function __construct() {
// sync stock
add_action(
'woocommerce_product_set_stock', array( __CLASS__, 'SyncStockSimple' )
);
add_action(
'woocommerce_variation_set_stock', array( __CLASS__, 'SyncStockVariation' )
);
}

/*
* Unhook the action, synchronise the stock and rehook the action
*
* @param \WC_Product $product the product which has had stock updated
*/
public static function SyncStockSimple( \WC_Product $product ) {
//first remove this action to avoid recusive call when setting translation stock
remove_action( 'woocommerce_product_set_stock', array( __CLASS__, __FUNCTION__ ), 10 );
static::SyncStock( $product );
add_action( 'woocommerce_product_set_stock', array( __CLASS__, __FUNCTION__ ), 10 );
}

/*
* Unhook the action, synchronise the stock and rehook the action
*
* @param \WC_Product $product the product which has had stock updated
*/
public static function SyncStockVariation( \WC_Product $product ) {
//first remove this action to avoid recusive call when setting translation stock
remove_action( 'woocommerce_variation_set_stock', array( __CLASS__, __FUNCTION__ ), 10 );
static::SyncStock( $product );
add_action( 'woocommerce_variation_set_stock', array( __CLASS__, __FUNCTION__ ), 10 );
}

/*
* Synchronise stock levels across translations any time stock is updated
* through the product api [always now via wc_update_product_stock()]
*
* @param \WC_Product $product the product which has had stock updated
*/
public static function SyncStock( \WC_Product $product ) {
//use same logic as wc_update_product_stock to get the product which is actually managing the stock
$product_id_with_stock = $product->get_stock_managed_by_id();
$product_with_stock = $product_id_with_stock !== $product->get_id() ? wc_get_product( $product_id_with_stock ) : $product;

if ( $product_with_stock ) {
$targetValue = $product_with_stock->get_stock_quantity();

//update all the translations to the same stock level..
$product_translations = ($product_with_stock->is_type( 'variation' )) ?
Variation::getRelatedVariation( get_post_meta( $product_with_stock->get_id(), Variation::DUPLICATE_KEY, true ), true ) :
Utilities::getProductTranslationsArrayByObject( $product_with_stock );

foreach ( $product_translations as $product_translation ) {
if ( $product_translation != $product_with_stock->get_id() ) {
$translation = wc_get_product( $product_translation );
if ( $translation ) {
wc_update_product_stock( $translation, $targetValue );
}
}
}
}
}

$variationMasterID = get_post_meta($variationID, Variation::DUPLICATE_KEY, true);
$variationMaster = wc_get_product($variationMasterID);
if ($variationMaster) {
$variationMasterManagerStock = $variationMaster->managing_stock();
if ($variationMasterManagerStock) {
//$posts = Utilities::getProductTranslationsArrayByObject($variationMaster);
$posts = Variation::getRelatedVariation($variationMasterID);
foreach ($posts as $post) {
$variation = wc_get_product($post);
if ($variation) {
//tested with orderlang, actually here it is the product language as currently variation item
//is added and handled in original language even if order switched language
if (pll_get_post_language($variation->get_parent_id()) != pll_get_post_language($productID)) {
\wc_update_product_stock($variation, $change, $method);
}
}
}
}
}
}
}
}
}

0 comments on commit 17e29b9

Please sign in to comment.