public static function unstock(UnstockOrderEvent $Event) { if (empty($Event->order)) { return shopp_debug('Can not unstock. No event order.'); } $Purchase = $Event->order(); if (!$Purchase->stocked) { return true; } // no inventory in purchase $prices = array(); $allocated = array(); foreach ($Purchase->purchased as $Purchased) { if (is_a($Purchased->addons, 'ObjectMeta') && !empty($Purchased->addons->meta)) { foreach ($Purchased->addons->meta as $index => $Addon) { if (!Shopp::str_true($Addon->value->inventory)) { continue; } $allocated[$Addon->value->id] = new PurchaseStockAllocation(array('purchased' => $Purchased->id, 'addon' => $index, 'sku' => $Addon->value->sku, 'price' => $Addon->value->id, 'quantity' => $Purchased->quantity)); $prices[$Addon->value->id] = array($Purchased->name, isset($prices[$Addon->value->id]) ? $prices[$Addon->value->id][1] + $Purchased->quantity : $Purchased->quantity); } } if (!Shopp::str_true($Purchased->inventory)) { continue; } $allocated[$Purchased->id] = new PurchaseStockAllocation(array('purchased' => $Purchased->id, 'sku' => $Purchased->sku, 'price' => $Purchased->price, 'quantity' => $Purchased->quantity)); $prices[$Purchased->price] = array($Purchased->name, isset($prices[$Purchased->price]) ? $prices[$Purchased->price][1] + $Purchased->quantity : $Purchased->quantity); } if (empty($allocated)) { return; } $pricetable = ShoppDatabaseObject::tablename(ShoppPrice::$table); $lowlevel = shopp_setting('lowstock_level'); foreach ($prices as $price => $data) { list($productname, $qty) = $data; sDB::query("UPDATE {$pricetable} SET stock=(stock-" . (int) $qty . ") WHERE id='{$price}' LIMIT 1"); $inventory = sDB::query("SELECT label, stock, stocked FROM {$pricetable} WHERE id='{$price}' LIMIT 1", 'auto'); $product = "{$productname}, {$inventory->label}"; if (0 == $inventory->stock) { shopp_add_error(Shopp::__('%s is now out-of-stock!', $product), SHOPP_STOCK_ERR); } elseif ($inventory->stock / $inventory->stocked * 100 <= $lowlevel) { shopp_add_error(Shopp::__('%s has low stock levels and should be re-ordered soon.', $product), SHOPP_STOCK_ERR); } } $Event->unstocked($allocated); // If out of stock products should be hidden from catalog, // go ahead and invalidate the cache after unstock if (!Shopp::str_true(shopp_setting('outofstock_catalog'))) { Shopp::invalidate_cache(); } }
/** * Handles loading, saving and deleting products in the context of workflows * * @author Jonathan Davis * @since 1.0 * @version 1.2 * * @return void **/ public function workflow() { global $Shopp, $post; $defaults = array('page' => false, 'action' => false, 'selected' => array(), 'id' => false, 'save' => false, 'duplicate' => false, 'next' => false); $args = array_merge($defaults, $_REQUEST); extract($args, EXTR_SKIP); if (!is_array($selected)) { $selected = array($selected); } if (!defined('WP_ADMIN') || !isset($page) || $this->Admin->pagename('products') != $page) { return false; } $adminurl = admin_url('admin.php'); if ($this->Admin->pagename('products') == $page && (false !== $action || isset($_GET['delete_all']))) { if (isset($_GET['delete_all'])) { $action = 'emptytrash'; } switch ($action) { case 'publish': ShoppProduct::publishset($selected, 'publish'); break; case 'unpublish': ShoppProduct::publishset($selected, 'draft'); break; case 'feature': ShoppProduct::featureset($selected, 'on'); break; case 'defeature': ShoppProduct::featureset($selected, 'off'); break; case 'restore': ShoppProduct::publishset($selected, 'draft'); break; case 'trash': ShoppProduct::publishset($selected, 'trash'); break; case 'delete': foreach ($selected as $id) { $P = new ShoppProduct($id); $P->delete(); } break; case 'emptytrash': $Template = new ShoppProduct(); $trash = sDB::query("SELECT ID FROM {$Template->_table} WHERE post_status='trash' AND post_type='" . ShoppProduct::posttype() . "'", 'array', 'col', 'ID'); foreach ($trash as $id) { $P = new ShoppProduct($id); $P->delete(); } break; } // Gracefully invalidate Shopp object caching Shopp::invalidate_cache(); $redirect = add_query_arg($_GET, $adminurl); $redirect = remove_query_arg(array('action', 'selected', 'delete_all'), $redirect); Shopp::redirect($redirect); } if ($duplicate) { // Gracefully invalidate Shopp object caching Shopp::invalidate_cache(); $Product = new ShoppProduct($duplicate); $Product->duplicate(); $this->index($Product); Shopp::redirect(add_query_arg(array('page' => $this->Admin->pagename('products'), 'paged' => $_REQUEST['paged']), $adminurl)); } if (isset($id) && $id != "new") { $Shopp->Product = new ShoppProduct($id); $Shopp->Product->load_data(); // Adds CPT compatibility support for third-party plugins/themes global $post; if (is_null($post)) { $post = get_post($Shopp->Product->id); } } else { $Shopp->Product = new ShoppProduct(); } if ($save) { // Gracefully invalidate Shopp object caching Shopp::invalidate_cache(); $this->save($Shopp->Product); $this->notice(sprintf(__('%s has been saved.', 'Shopp'), '<strong>' . stripslashes($Shopp->Product->name) . '</strong>')); // Workflow handler if (isset($_REQUEST['settings']) && isset($_REQUEST['settings']['workflow'])) { $workflow = $_REQUEST['settings']['workflow']; $worklist = $this->worklist; $working = array_search($id, $this->worklist); switch ($workflow) { case 'close': $next = 'close'; break; case 'new': $next = 'new'; break; case 'next': $key = $working + 1; break; case 'previous': $key = $working - 1; break; case 'continue': $next = $id; break; } if (isset($key)) { $next = isset($worklist[$key]) ? $worklist[$key] : 'close'; } } if ($next) { $query = $_GET; if (isset($this->worklist['query'])) { $query = array_merge($_GET, $this->worklist['query']); } $redirect = add_query_arg($query, $adminurl); $cleanup = array('action', 'selected', 'delete_all'); if ('close' == $next) { $cleanup[] = 'id'; $next = false; } $redirect = remove_query_arg($cleanup, $redirect); if ($next) { $redirect = add_query_arg('id', $next, $redirect); } Shopp::redirect($redirect); } if (empty($id)) { $id = $Shopp->Product->id; } $Shopp->Product = new ShoppProduct($id); $Shopp->Product->load_data(); } // WP post type editing support for other plugins if (!empty($Shopp->Product->id)) { $post = get_post($Shopp->Product->id); } }