private function HandleVariations($row) { //========Product Variations==========// if ($row['prodvariationid'] == 0) { $row['productVariations'] = array(); return $row; } // get the position of the options in the variation fields $option_position = $this->GetFieldPosition('productVarDetails', $this->fields['productVariations']['fields']); // get the variation options $query = "SELECT * FROM [|PREFIX|]product_variation_options WHERE vovariationid = " . $row['prodvariationid'] . " ORDER BY voptionid"; $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $options_cache = array(); while ($optionRow = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) { $options_cache[$optionRow['voname']][] = array("id" => $optionRow['voptionid'], "value" => $optionRow['vovalue']); } // get a list of all possible combinations using the options for this variation $options = Interspire_Array::generateCartesianProduct($options_cache, true); $new_options = array(); // the options for each variation foreach ($options as $option) { $optionids = ""; $description = ""; // build strings of the id's and values of each option foreach ($option as $key => $value) { if ($optionids) { $optionids .= ","; } $optionids .= $value["id"]; if ($description) { $description .= ", "; } $description .= $key . ": " . $value["value"]; } $new_options[$optionids] = array( "options" => $option, "description" => $description ); } // get the data for the combinations $query = "SELECT * FROM [|PREFIX|]product_variation_combinations WHERE vcproductid = " . $row['prodid']; $result = $GLOBALS['ISC_CLASS_DB']->Query($query); while ($comborow = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) { // get the specific combination of options $options = $new_options[$comborow['vcoptionids']]['options']; $prodoptions = array(); $prodoptions['productVarDetails'] = $new_options[$comborow['vcoptionids']]['description']; $prodoptions['productVarSKU'] = $comborow['vcsku']; switch ($comborow['vcpricediff']) { case "add": $pricediff = "+"; break; case "substract": $pricediff = "-"; break; default: $pricediff = ""; } $prodoptions['productVarPrice'] = $pricediff . $comborow['vcprice']; switch ($comborow['vcweightdiff']) { case "add": $weightdiff = "+"; break; case "substract": $weightdiff = "-"; break; default: $weightdiff = ""; } $prodoptions['productVarWeight'] = $weightdiff . $comborow['vcweight']; $prodoptions['productVarStockLevel'] = $comborow['vcstock']; $prodoptions['productVarLowStockLevel'] = $comborow['vclowstock']; $prodoptions = $this->CreateSubItemArray($prodoptions, $this->fields['productVariations']['fields']); if ($this->fields['productVariations']['fields']['productVarDetails']['used']) { $optionkeys = array(); $optionvalues = array(); foreach ($options as $key => $value) { $optionvalues[$key] = $value['value']; $optionkeys[] = $key; } $keys = array_keys($prodoptions); // insert the fields into correct position array_splice($prodoptions, $option_position, 0, $optionvalues); array_splice($keys, $option_position, 0, $optionkeys); $prodoptions = array_combine($keys, $prodoptions); } $prodvariations[] = $prodoptions; } $row["productVariations"] = $prodvariations; return $row; }
private function continueRebuildVariationsAction() { $sessionId = $_POST['session']; if (!isset($_SESSION['variations'][$sessionId])) { ISC_JSON::output('session ' . $sessionId . ' not found', false); } $session = &$_SESSION['variations'][$sessionId]; // get the next product id $query = " SELECT productid FROM [|PREFIX|]products WHERE productid > " . $session['lastProductId'] . " AND prodvariationid = " . $session['variationId'] . " ORDER BY productid LIMIT 1 "; $res = $this->db->Query($query); $productId = $this->db->FetchOne($res); // no more products to process? done. if (empty($productId)) { unset($_SESSION['variations'][$sessionId]); if (empty($_SESSION['variations'])) { unset($_SESSION['variations']); } ISC_JSON::output('', true, array('done' => true)); } if ($this->db->StartTransaction() === false) { ISC_JSON::output('failed to start transaction', false); } $existingData = $session['existingData']; // were new option values (eg a new colour) added? we'll need to create some blank combinations to fill in the missing gaps. if (!empty($session['newValues'])) { $newValues = $session['newValues']; // iterate over the new option values foreach ($newValues as $optionName => $newValueIds) { foreach ($newValueIds as $newValueId) { // build combination id set $optionIdSets = array(); foreach ($existingData['options'] as $optionIndex => $option) { if ($optionName == $option['name']) { $optionIdSets[$optionIndex][] = $newValueId; continue; } foreach ($option['values'] as $valueIndex => $value) { $optionIdSets[$optionIndex][] = $value['valueid']; } } // build a cartesian product of all the combinations that we need to generate $cartesian = Interspire_Array::generateCartesianProduct($optionIdSets); // iterate over each combination and insert to DB for all products using this variation foreach ($cartesian as $combination) { $combinationString = implode(',', $combination); $newCombination = array( 'vcproductid' => $productId, 'vcvariationid' => $session['variationId'], 'vcoptionids' => $combinationString, 'vclastmodified' => time(), ); $this->db->InsertQuery('product_variation_combinations', $newCombination); } } } } // process new option set (eg. Material) if (!empty($session['newOptionValues'])) { $valuesForNewOption = $session['newOptionValues']; $likeMatch = str_repeat(",%", count($existingData['options']) - 2); $likeMatch = "%" . $likeMatch; foreach ($valuesForNewOption as $newOptionIndex => $newValueIds) { $newOptionCount = 0; foreach ($newValueIds as $newValueId) { // for the first new option value, we don't want to insert new combinations, but update the existing ones // store the option id for later and continue on if ($newOptionCount == 0) { $delayForUpdate = $newValueId; $newOptionCount++; continue; } $query = " INSERT INTO [|PREFIX|]product_variation_combinations (vcproductid, vcproducthash, vcvariationid, vcenabled, vcoptionids, vcsku, vcpricediff, vcprice, vcweightdiff, vcweight, vcimage, vcimagezoom, vcimagestd, vcimagethumb, vcstock, vclowstock, vclastmodified) SELECT vcproductid, vcproductid, vcvariationid, vcenabled, CONCAT(vcoptionids, ',', " . $newValueId . "), vcsku, vcpricediff, vcprice, vcweightdiff, vcweight, vcimage, vcimagezoom, vcimagestd, vcimagethumb, vcstock, vclowstock, " . time() . " FROM [|PREFIX|]product_variation_combinations WHERE vcproductid = " . $productId . " AND vcproducthash = '' "; $this->db->Query($query); $newOptionCount++; } } // for the first new option id, add it onto the remaining existing row if (!empty($delayForUpdate)) { $query = " UPDATE [|PREFIX|]product_variation_combinations SET vcoptionids = CONCAT(vcoptionids, ',', " . $delayForUpdate . ") WHERE vcproductid = " . $productId . " AND vcproducthash = '' "; $this->db->Query($query); } // blank the hash $query = " UPDATE [|PREFIX|]product_variation_combinations SET vcproducthash = '' WHERE vcproductid = " . $productId . " "; $this->db->Query($query); } if ($this->db->CommitTransaction() === false) { $this->db->RollbackTransaction(); ISC_JSON::output('failed to commit transaction', false); } $session['lastProductId'] = $productId; ISC_JSON::output('', true); }
/** * Returns an array containing all possible variation combinations * * @param int The product ID to get combinations for * @param string Optional option name to exclude in the combinations * @return array Array of all combinations */ function GetVariationCombinations($productID, $excludeOption = '') { $where = ""; if ($excludeOption) { $where = " AND voname != '" . $GLOBALS['ISC_CLASS_DB']->Quote($excludeOption) . "' "; } $query = " SELECT voname, GROUP_CONCAT(voptionid ORDER BY voptionid) AS optionids FROM [|PREFIX|]product_variation_options INNER JOIN [|PREFIX|]products p ON vovariationid = prodvariationid WHERE p.productid = " . $productID . " " . $where . " GROUP BY voname "; $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $optionArray = array(); while ($optionRow = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) { $optionArray[$optionRow['voname']] = explode(',', $optionRow['optionids']); } // calculate all the combinations return Interspire_Array::generateCartesianProduct($optionArray, true); }