public function _CommitImportProduct($ProductId, &$Data, &$Images, &$Variations, &$CustomFields, $DiscountRules = array(), &$Err = null, &$ProductFields = array(), $isImport = false)
 {
     // Commit the details for the product to the database
     $query = "";
     $err = null;
     $searchData = array("prodname" => $Data['prodname'], "prodcode" => $Data['prodcode'], "proddesc" => $Data['proddesc'], "prodsearchkeywords" => $Data['prodsearchkeywords']);
     // Start the transaction
     $GLOBALS["ISC_CLASS_DB"]->Query("start transaction");
     $updateImageQuery = "";
     if ($ProductId == 0) {
         // Add the date this product was modified
         $entity = new ISC_ENTITY_PRODUCT();
         $prodId = $entity->add($Data);
         $GLOBALS['NewProductId'] = $prodId;
         // ---- Build the query for the product_search table ----
         $searchData['productid'] = $prodId;
         $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_search", $searchData);
         // Build the queries for the images table -----
         if (isset($Images) && !empty($Images)) {
             $imageSort = array();
             // First clear out any product images that already exist (in case of a previous import etc)
             $query = "DELETE FROM [|PREFIX|]product_images\n\t\t\t\t\tWHERE imageprodid='" . $GLOBALS['ISC_CLASS_DB']->Quote($prodId) . "'";
             $GLOBALS['ISC_CLASS_DB']->Query($query);
             // Next, try and add the full sized images
             for ($i = 1; $i <= 5; $i++) {
                 if (isset($Images["image" . $i]) && $Images["image" . $i] != "") {
                     // Store the image reference in the images table
                     $newImage = array("imageprodid" => $prodId, "imagefile" => $Images['image' . $i], "imageisthumb" => 0, "imagesort" => $i);
                     $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $newImage);
                     $imageSort[] = $i;
                 }
             }
             if (!empty($imageSort)) {
                 $updateImageQuery .= " AND imagesort not in (" . implode(",", $imageSort) . ")";
             }
             // Now the query for the thumbnail image
             if (isset($Images['thumb']) && !empty($Images['thumb'])) {
                 $thumbImage = array("imageprodid" => $prodId, "imagefile" => $Images['thumb'], "imageisthumb" => 1);
                 $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $thumbImage);
                 if ($Images['thumb'] != '') {
                     $updateImageQuery .= " AND imageisthumb!=1";
                 }
             }
             // And finally query for the tiny thumbnail image
             if (isset($Images['tiny']) && !empty($Images['tiny'])) {
                 $tinyImage = array("imageprodid" => $prodId, "imagefile" => $Images['tiny'], "imageisthumb" => 2);
                 $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $tinyImage);
                 if ($Images['tiny'] != '') {
                     $updateImageQuery .= " AND imageisthumb!=2";
                 }
             }
         }
         // Set some $_GET variables so the newest product appears at the top of the list
         $_GET['sortField'] = "productid";
         $_GET['sortOrder'] = "desc";
         // Save the product tags
         $this->SaveProductTags($Data['prodtags'], $prodId, true);
     } else {
         // Update the existing products details
         $prodId = $Data['productid'] = (int) $ProductId;
         $entity = new ISC_ENTITY_PRODUCT();
         $entity->edit($Data);
         // Update the search data
         $GLOBALS['ISC_CLASS_DB']->UpdateQuery("product_search", $searchData, "productid='" . $GLOBALS['ISC_CLASS_DB']->Quote($prodId) . "'");
         if (isset($Data['prodcats']) && $Data['prodcats'] != null) {
             // Remove the existing category associations
             $query = sprintf("DELETE FROM [|PREFIX|]categoryassociations WHERE productid='%d'", $prodId);
             $GLOBALS['ISC_CLASS_DB']->Query($query);
         }
         // Build the queries for the images table -----
         if (isset($Images) && !empty($Images)) {
             $currImages = $this->_GetImageData($prodId);
             $newImages = $this->_GetImageData();
             for ($i = 1; $i <= 5; $i++) {
                 if ($_FILES["prodImage" . $i]['name'] == "") {
                     // Do nothing -- leave the existing image
                 } else {
                     if (isc_strtolower($_FILES["prodImage" . $i]['name']) == "none" && $i > 1) {
                         // Remove the existing image
                         unset($currImages["image" . $i]);
                     } else {
                         // It's a new image
                         $currImages["image" . $i] = $Images["image" . $i];
                     }
                 }
             }
             // Now the query for the thumbnail image
             if ($Images['thumb'] != "") {
                 $currImages['thumb'] = $Images['thumb'];
             }
             if (isset($Images['tiny']) && $Images['tiny'] != "") {
                 $currImages['tiny'] = $Images['tiny'];
             }
             // Build the query to delete current images -----
             $query = sprintf("delete from [|PREFIX|]product_images where imageprodid='%d'", $prodId);
             $GLOBALS['ISC_CLASS_DB']->Query($query);
             for ($i = 1; $i <= 5; $i++) {
                 if (isset($currImages["image" . $i])) {
                     if (!isset($currImages["id" . $i]) || isset($currImages["id" . $i]) && !isset($_POST["delete_image_" . $currImages["id" . $i]])) {
                         $newImage = array("imageprodid" => $prodId, "imagefile" => $currImages['image' . $i], "imageisthumb" => 0, "imagesort" => $i);
                         $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $newImage);
                     }
                 }
             }
             // Add the thumbnail image
             // Now the query for the thumbnail image
             if (!isset($_POST['delete_image_thumb'])) {
                 $thumbImage = array("imageprodid" => $prodId, "imagefile" => $currImages['thumb'], "imageisthumb" => 1);
                 $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $thumbImage);
                 // And finally query for the tiny thumbnail image
                 if (isset($currImages['tiny'])) {
                     $tinyImage = array("imageprodid" => $prodId, "imagefile" => $currImages['tiny'], "imageisthumb" => 2);
                     $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_images", $tinyImage);
                 }
             }
         }
         // Save the product tags
         $this->SaveProductTags($Data['prodtags'], $ProductId, false);
     }
     // Build the queries for the category associations table -----
     $accessibleCategories = array();
     if ($GLOBALS['ISC_CLASS_ADMIN_AUTH']->GetVendorId()) {
         $vendorInfo = $GLOBALS['ISC_CLASS_ADMIN_AUTH']->GetVendor();
         if ($vendorInfo['vendoraccesscats']) {
             $accessibleCategories = explode(',', $vendorInfo['vendoraccesscats']);
         }
     }
     if (isset($Data['prodcats']) and $Data['prodcats'] != "") {
         foreach ($Data['prodcats'] as $cat) {
             // If this user doesn't have permission to place products in this category, skip over it
             if (!empty($accessibleCategories) && !in_array($cat, $accessibleCategories)) {
                 continue;
             }
             $newAssociation = array("productid" => $prodId, "categoryid" => $cat);
             $GLOBALS['ISC_CLASS_DB']->InsertQuery("categoryassociations", $newAssociation);
         }
     }
     /**
      * Was this product commited from the batch importer? If so then exit now or we'll ruin all the other product linked tables
      */
     if ($isImport) {
         if ($GLOBALS["ISC_CLASS_DB"]->GetErrorMsg() == "") {
             // The product was commited successfully, commit the transaction
             $GLOBALS["ISC_CLASS_DB"]->Query("commit");
             return true;
         } else {
             // The product commit failed
             $GLOBALS["ISC_CLASS_DB"]->Query("rollback");
             return false;
         }
     }
     // Build the queries for the product variation combinations table -----
     $sumCurrent = 0;
     $sumLow = 0;
     /**
      * Associated any hashed variations with the new product ID
      */
     if (isset($Data['prodhash']) && $Data['prodhash'] !== '') {
         $savedata = array('vcproductid' => $prodId, 'vcproducthash' => '');
         $GLOBALS['ISC_CLASS_DB']->UpdateQuery('product_variation_combinations', $savedata, "vcproducthash='" . $GLOBALS['ISC_CLASS_DB']->Quote($Data['prodhash']) . "'");
     }
     if (isset($Data['prodvariationid']) && $Data['prodvariationid'] != 0 && isset($Variations) && is_array($Variations)) {
         // Are we updating an existing variation, or creating a totally new one?
         if ($Data['productVariationExisting'] == $Data['prodvariationid']) {
             // We're updating an existing variation
             foreach ($Variations as $Variation) {
                 // First up, do we need to delete the image?
                 if ($Variation['vcimage'] == "REMOVE") {
                     // Yes, get the image details
                     $query = sprintf("SELECT vcimage, vcthumb FROM [|PREFIX|]product_variation_combinations WHERE combinationid='%d'", $Variation['combinationid']);
                     $result = $GLOBALS["ISC_CLASS_DB"]->Query($query);
                     if ($row = $GLOBALS["ISC_CLASS_DB"]->Fetch($result)) {
                         @unlink(APP_ROOT . "/../" . GetConfig('ImageDirectory') . "/" . $row['vcimage']);
                         @unlink(APP_ROOT . "/../" . GetConfig('ImageDirectory') . "/" . $row['vcthumb']);
                     }
                 }
                 // Now update the record
                 $updatedCombo = array("vcproductid" => $prodId, "vcvariationid" => $Variation['vcvariationid'], "vcenabled" => $Variation['vcenabled'], "vcoptionids" => $Variation['vcoptionids'], "vcsku" => $Variation['vcsku'], "vcpricediff" => $Variation['vcpricediff'], "vcprice" => $Variation['vcprice'], "vcweightdiff" => $Variation['vcweightdiff'], "vcweight" => $Variation['vcweight'], "vcstock" => $Variation['vcstock'], "vclowstock" => $Variation['vclowstock']);
                 // Only update the images if they've changed
                 if ($Variation['vcimage'] == "REMOVE") {
                     $updatedCombo['vcimage'] = "";
                     $updatedCombo['vcthumb'] = "";
                 } else {
                     if ($Variation['vcimage'] != "") {
                         $updatedCombo['vcimage'] = $Variation['vcimage'];
                         $updatedCombo['vcthumb'] = $Variation['vcthumb'];
                     }
                 }
                 $GLOBALS['ISC_CLASS_DB']->UpdateQuery("product_variation_combinations", $updatedCombo, "combinationid='" . $GLOBALS['ISC_CLASS_DB']->Quote($Variation['combinationid']) . "'");
                 $sumCurrent += $Variation['vcstock'];
                 $sumLow += $Variation['vclowstock'];
             }
         } else {
             // If it's an existing product then we need to delete all of the variation combinations, images, etc
             if ($Data['productVariationExisting'] > 0) {
                 $this->_DeleteVariationCombinationsForProduct($prodId);
             }
             // We're adding a new variation
             foreach ($Variations as $Variation) {
                 $newCombo = array("vcproductid" => $prodId, "vcvariationid" => $Variation['vcvariationid'], "vcenabled" => $Variation['vcenabled'], "vcoptionids" => $Variation['vcoptionids'], "vcsku" => $Variation['vcsku'], "vcpricediff" => $Variation['vcpricediff'], "vcprice" => $Variation['vcprice'], "vcweightdiff" => $Variation['vcweightdiff'], "vcweight" => $Variation['vcweight'], "vcimage" => $Variation['vcimage'], "vcthumb" => $Variation['vcthumb'], "vcstock" => $Variation['vcstock'], "vclowstock" => $Variation['vclowstock']);
                 $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_variation_combinations", $newCombo);
                 $sumCurrent += $Variation['vcstock'];
                 $sumLow += $Variation['vclowstock'];
             }
         }
         // If the inventory tracking is happening per product variation then we need to add
         // the current and low stock level sums to the products table
         if ($Data['prodinvtrack'] == 2) {
             $updatedProduct = array("prodcurrentinv" => $sumCurrent, "prodlowinv" => $sumLow);
             $GLOBALS['ISC_CLASS_DB']->UpdateQuery("products", $updatedProduct, "productid='" . $GLOBALS['ISC_CLASS_DB']->Quote($prodId) . "'");
         }
     } else {
         // If it's an existing product then we need to delete all of the variation combinations, images, etc
         if ($prodId > 0) {
             $this->_DeleteVariationCombinationsForProduct($prodId);
         }
     }
     // Build the queries for the custom fields table -----
     $GLOBALS['ISC_CLASS_DB']->Query("DELETE FROM [|PREFIX|]product_customfields WHERE fieldprodid='" . $GLOBALS['ISC_CLASS_DB']->Quote((int) $prodId) . "'");
     if (!empty($CustomFields)) {
         foreach ($CustomFields as $c) {
             $newField = array("fieldprodid" => $prodId, "fieldname" => $c['name'], "fieldvalue" => $c['value']);
             $GLOBALS['ISC_CLASS_DB']->InsertQuery("product_customfields", $newField);
         }
     }
     $this->_SaveProductFields($ProductFields, $prodId);
     // Upload any product downloads if we have them
     if (isset($_FILES) && isset($_FILES['newdownload']) && isset($_FILES['newdownload']['name']) && $_FILES['newdownload']['name'] != '') {
         $this->SaveProductDownload($err);
     }
     // Associate any product images and downloads which were uploaded earlier with this product
     if (isset($Data['prodhash']) && $Data['prodhash'] !== '') {
         $updateImages = array("imageprodid" => $prodId, "imageprodhash" => '');
         $GLOBALS['ISC_CLASS_DB']->UpdateQuery("product_images", $updateImages, "imageprodhash='" . $GLOBALS['ISC_CLASS_DB']->Quote($Data['prodhash']) . "'" . $updateImageQuery);
         $updatedDownloads = array("productid" => $prodId, "prodhash" => '');
         $GLOBALS['ISC_CLASS_DB']->UpdateQuery("product_downloads", $updatedDownloads, "prodhash='" . $GLOBALS['ISC_CLASS_DB']->Quote($Data['prodhash']) . "'");
     }
     // Now we add our discount rules
     $GLOBALS['ISC_CLASS_DB']->DeleteQuery('product_discounts', 'WHERE discountprodid=' . (int) $prodId);
     // If we have variations then do not process them
     if ((!isset($Data['prodvariationid']) || !isId($Data['prodvariationid'])) && empty($Variations)) {
         foreach ($DiscountRules as $rule) {
             // If the min and max quantities are astrixes then convert them to 0
             if ($rule['quantitymin'] == '*') {
                 $rule['quantitymin'] = 0;
             }
             if ($rule['quantitymax'] == '*') {
                 $rule['quantitymax'] = 0;
             }
             // Change the type of the amount, just in case
             if (isc_strtolower($rule['type']) == 'percent') {
                 $rule['amount'] = (int) $rule['amount'];
             } else {
                 $rule['amount'] = (double) $rule['amount'];
             }
             $newRule = array('discountprodid' => (int) $prodId, 'discountquantitymin' => (int) $rule['quantitymin'], 'discountquantitymax' => (int) $rule['quantitymax'], 'discounttype' => isc_strtolower($rule['type']), 'discountamount' => DefaultPriceFormat($rule['amount']));
             $GLOBALS['ISC_CLASS_DB']->InsertQuery('product_discounts', $newRule);
         }
     }
     if ($GLOBALS["ISC_CLASS_DB"]->GetErrorMsg() == "") {
         // The product was commited successfully, commit the transaction
         $GLOBALS["ISC_CLASS_DB"]->Query("commit");
         return true;
     } else {
         // The product commit failed
         $GLOBALS["ISC_CLASS_DB"]->Query("rollback");
         return false;
     }
 }