Example #1
0
 /**
  * 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);
     }
 }
Example #2
0
/**
 * Comprehensive product creation through Product Developer API.
 *
 * This function will do everything needed for creating a product except
 * attach product images and products. That is done in the Asset API. :)
 * You should be able to build an importer from another system using this function.
 *
 * It is also possible to update an existing product (by passing the
 * existing id as part of the $data array) or else you can alternatively
 * use shopp_update_product() for that.
 *
 * @todo possibly remove the capability of passing in an id to update a product
 *
 * @api
 * @since 1.2
 *
 * @param array $data (required) associative array structure containing a single product definition, see _validate_product_data for how this array is structured/validated.
 * @return Product the created product object, or boolean false on a failure.
 **/
function shopp_add_product($data = array())
{
    if (empty($data)) {
        shopp_debug(__FUNCTION__ . " failed: Empty data parameter.");
        return false;
    }
    $problems = _validate_product_data($data);
    if (!empty($problems)) {
        shopp_debug("Problems detected: " . Shopp::object_r($problems));
        return false;
    }
    $Product = new ShoppProduct();
    // Set Product publish status
    if (isset($data['publish'])) {
        $Product->publish = _shopp_product_publish_date($data['publish']);
        if ($Product->publish > 0) {
            $Product->status = 'future';
        }
    }
    // Set Product name
    if (empty($data['name'])) {
        shopp_debug(__FUNCTION__ . " failed: Missing product name.");
    }
    $Product->name = $data['name'];
    // Set Product slug
    if (!empty($data['slug'])) {
        $Product->slug = $data['slug'];
    }
    if (empty($Product->slug)) {
        $Product->slug = sanitize_title($Product->name);
    }
    $Product->slug = wp_unique_post_slug($Product->slug, $Product->id, $Product->status, ShoppProduct::posttype(), 0);
    $Product->updates($data, array('meta', 'categories', 'prices', 'tags', 'publish'));
    $Product->save();
    ShoppProduct::publishset(array($Product->id), $data['publish']['flag'] ? 'publish' : 'draft');
    if (empty($Product->id)) {
        shopp_debug(__FUNCTION__ . " failed: Failure to create new Product object.");
        return false;
    }
    // Product-wide settings
    $Product->featured = isset($data['featured']) && true === $data['featured'] ? "on" : "off";
    $Product->variants = isset($data['variants']) ? "on" : "off";
    $Product->addons = isset($data['addons']) ? "on" : "off";
    if (isset($data['packaging'])) {
        $packaging_set = shopp_product_set_packaging($Product->id, $data['packaging']);
        if (!$packaging_set) {
            shopp_debug(__FUNCTION__ . " failed: Failure to set packaging setting.");
            return false;
        }
    }
    // Save Taxonomies
    // Categories
    if (isset($data['categories']) && isset($data['categories']['terms'])) {
        $cats_set = shopp_product_add_categories($Product->id, $data['categories']['terms']);
        if (!$cats_set) {
            shopp_debug(__FUNCTION__ . " failed: Failure to add product categories to product.");
            return false;
        }
    }
    // Tags
    if (isset($data['tags']) && isset($data['tags']['terms'])) {
        $tags_set = shopp_product_add_tags($Product->id, $data['tags']['terms']);
        if (!$tags_set) {
            shopp_debug(__FUNCTION__ . " failed: Failure to add product tags to product.");
            return false;
        }
    }
    // Terms
    if (isset($data['terms']) && isset($data['terms']['terms']) && isset($data['terms']['taxonomy'])) {
        $terms_set = shopp_product_add_terms($Product->id, $data['terms']['terms'], $data['terms']['taxonomy']);
        if (!$terms_set) {
            shopp_debug(__FUNCTION__ . " failed: Failure to add product taxonomy terms to product.");
            return false;
        }
    }
    // Create Specs
    if (isset($data['specs'])) {
        $specs_set = shopp_product_set_specs($Product->id, $data['specs']);
        if (!$specs_set) {
            shopp_debug(__FUNCTION__ . " failed: Failure to add product specs to product.");
            return false;
        }
    }
    $subjects = array();
    $prices = array();
    // Create Prices
    if (isset($data['single'])) {
        if (!empty($data['single'])) {
            $subjects['product'] = array($data['single']);
        }
    } else {
        if (isset($data['variants'])) {
            // Construct and Populate variants
            if (!isset($data['variants']['menu']) || empty($data['variants']['menu'])) {
                shopp_debug(__FUNCTION__ . " failed: variants menu is empty.");
                return false;
            }
            $new_variants = shopp_product_set_variant_options($Product->id, $data['variants']['menu'], false);
            $pricekeys = $prices = array();
            foreach ($new_variants as $Price) {
                $prices[$Price->id] = $pricekeys[$Price->optionkey] = $Price;
            }
            if (!$prices) {
                shopp_debug(__FUNCTION__ . " failed: Unable to set variant options.");
                return false;
            }
            $subjects['variants'] = $data['variants'];
        }
    }
    // Create the "product" Price
    $Price = new ShoppPrice();
    $Price->label = __('Price & Delivery', 'Shopp');
    $Price->context = 'product';
    $Price->product = $Product->id;
    if (isset($subjects['variants'])) {
        $Price->type = 'N/A';
    }
    // disabled
    $Price->save();
    $prices[$Price->id] = $productprice = $Price;
    // Create Addons
    if (isset($data['addons'])) {
        if (!isset($data['addons']['menu']) || empty($data['addons']['menu'])) {
            shopp_debug(__FUNCTION__ . " failed: addons menu is empty");
            return false;
        }
        $new_addons = shopp_product_set_addon_options($Product->id, $data['addons']['menu'], false);
        $addon_prices = array();
        foreach ($new_addons as $Addon) {
            $addon_prices[$Addon->id] = $Addon;
        }
        if (!$addon_prices) {
            shopp_debug(__FUNCTION__ . " failed: Unable to set addon options.");
            return false;
        }
        $prices = $prices + $addon_prices;
        $subjects['addons'] = $data['addons'];
    }
    $contexts = array('addons' => 'addon', 'product' => 'product', 'variants' => 'variant');
    foreach ($subjects as $pricetype => $variants) {
        // apply settings for each priceline
        foreach ($variants as $key => $variant) {
            if (!is_numeric($key)) {
                continue;
            }
            $price = null;
            if ('product' == $pricetype) {
                $price = $productprice->id;
            } else {
                // 'option' => 'array',	// array option example: Color=>Blue, Size=>Small
                if (!isset($variant['option']) || empty($variant['option'])) {
                    shopp_debug(__FUNCTION__ . " failed: variant {$key} missing variant options.");
                    return false;
                }
                list($optionkey, $options, $label, $mapping) = $Product->optionmap($variant['option'], $variants['menu'], 'variants' == $pricetype ? 'variant' : 'addon');
                if ('variants' == $pricetype && isset($pricekeys[$optionkey])) {
                    $price = $pricekeys[$optionkey]->id;
                } else {
                    // Find the correct Price
                    foreach ($addon_prices as $index => $Price) {
                        if ($Price->options == $options && $Price->label == $label) {
                            $price = $index;
                            break;
                        }
                    }
                }
            }
            if (null === $price || !isset($prices[$price])) {
                shopp_debug(__FUNCTION__ . " failed: Variant {$key} not valid for this option set.");
                return false;
            }
            // modify each priceline
            $prices[$price] = shopp_product_set_variant($prices[$price], $variant, $contexts[$pricetype]);
            if (!$prices[$price]) {
                shopp_debug(__FUNCTION__ . " failed: Product variant setup failed.");
                return false;
            }
            // save priceline settings
            if (isset($prices[$price]->settings)) {
                shopp_set_meta($prices[$price]->id, 'price', 'settings', $prices[$price]->settings);
            }
            // We have everything we need to complete this price line
            $prices[$price]->save();
        }
        //end variants foreach
    }
    // end subjects foreach
    // Reset rollup figures for prices.
    $Product->resum();
    // Calculates aggregate product stats
    // foreach ( $prices as $Price ) {
    // 	$Product->sumprice($Price);
    // }
    // Skeleton summary
    $Summary = new ProductSummary();
    $sum_props = array_keys($Summary->_datatypes);
    // init default summary items
    foreach ($sum_props as $prop) {
        if (!isset($Product->{$prop})) {
            $Product->{$prop} = NULL;
        }
    }
    // Process pricing stats
    $records = null;
    foreach ($prices as $Price) {
        $Product->pricing($records, $Price);
    }
    // Saves generated stats to the product summary
    $Product->sumup();
    return shopp_product($Product->id);
}