Das Modul wäre eigentlich ganz super wenn nicht eine "Unschönheit" da wäre, die ich mit meinen - eher maginalen PHP-Kenntnissen - leider nicht beheben kann!
Das Modul "merkt" sich Optionwerte eines Attributs in Abhängigkeit der Optionswerte des anderen Attributs was zu unschönen Anzeigefehlern führt.
Ich habe zwei Attribute angelegt:
1. GRÖSSE mit den Optionswerten S, M, L, XL (horizontal)
2. FARBE mit den Optionswerten Rot, Blau, Gelb, Grün (vertikal)
Klicke ich auf die
GRÖSSE S und die FARBE Blau
erscheint das passende Bild in Blau
soweit ok
Klicke ich danach auf
GÖSSE M und die FARBE GELB
erscheint das passende Bild in Gelb
soweit noch ok
Klicke ich jetzt zurück auf
GRÖSSE S
erscheint im unteren FARB-Attributskasten der Optionswert Blau !!!!!!!!
================================================
das Bild bleibt aber Gelb
Richtig wäre wenn der Farb-Attribut-Wert einfach bleiben würde (Gelb) und sich nicht verändern würde, er würde dann auch zum Bild passen.
www.megashirts.de/product_info.php?products_id=8Irgendwo scheint die Abhängigkeit der Optionswerte der beiden Attribute zwischengespeichert zu werden.
Ich vermute den Fehler in der product_matrix_functions.php.(?)
Vielleicht könnte mir da mal jemand auf die Sprünge helfen!
<?php// Products Matrix Module (c) Timo Doerr <timo.doerr@work-less.de>// Licensed under GNU GPLdefine("MATRIX_DEBUG",true);// MULTI-MATRIX STUFF GOES HERE// get MatrixList from $_POST datafunction createMatrixListFromPOST
(){ $matrixlist = new ProductMatrixList
(); if($_POST['matrixlist']){ foreach($_POST['matrixlist'] as $matrix_id){ $matrix = createMatrixFromPOST
($matrix_id); $matrixlist->AddMatrix($matrix); } } return $matrixlist;}class ProductMatrixList
{ var $matrix_count=0; // number of matrices to this product var $matrices; // holds the matrix classes var $products_id; function ProductMatrixList
($prod_ID = 0){ require("matrix_library/matrix.php"); } function AddMatrix
($matrix){ $this->matrices[$this->matrix_count] = $matrix; $this->matrix_count++; } function RenderMatrices
($change_stock = false){ echo $this->GetRenderedMatrices($change_stock); } function SaveMatrices
(){ foreach($this->matrices as $matrix){ $matrix->SaveEntries(); } } function GetRenderedMatrices
($change_stock = false){ // returns HTML code of renderes matrices $output = ""; for($i=0; $i<$this->matrix_count;$i++) $output .= $this->matrices[$i]->GetRenderedMatrix($change_stock); return $output; }}// SINGLE MATRIX DEFINITIONS START HERE// helper functions which are needed BEFORE// an instance of ProductMatrix existsfunction hasProductMatrix
($prod_ID){ if(getProductMatrixID
($prod_ID)){ return true; }else{ return false; }}function getProductMatrixID
($prod_ID){ // checks if product has a matrix and returns its matrix_id $tmpquery = "SELECT matrix_id FROM products_options_matrix WHERE products_id = ".$prod_ID." LIMIT 1"; $tmpresult = xtc_db_query
($tmpquery); $tmpdata = xtc_db_fetch_array
($tmpresult); if(xtc_db_num_rows
($tmpresult) != 0){ return $tmpdata['matrix_id']; }else{ return false; }}// would make sense to have these as member functions// of ProductMatrix class, but leave it for performance// reasons atm (to much sql queries)function deleteMatrix
($matrix_id){ //first delete all previous matrices for this product $tmpquery = "DELETE FROM products_options_matrix WHERE matrix_id = " . $matrix_id; xtc_db_query
($tmpquery); deleteMatrixEntries
($matrix_id);}function deleteMatrixEntries
($matrix_id){ // delete previous matrix entries for this product $tmpquery = "DELETE FROM products_options_matrix_values WHERE matrix_id = " . $matrix_id; xtc_db_query
($tmpquery);}// reads in matrix from $_POST data// name must be matrix-INDEX-I-J// i.e matrix-66-1-1 for matrix coord 1,1function createMatrixFromPOST
($index){ // returns a matrix // uses POSTDATA and needs the matrix_id as $index $POSTDATA = $_POST; $product_matrix = new ProductMatrix
($index); for($i=0; $i <= $product_matrix->horiz_size-1;$i++){ for($j=0; $j <= $product_matrix->vert_size-1;$j++){ $poststring = 'matrix-' . $index . '-' . $i . '-'. $j; if($POSTDATA[$poststring]){ $product_matrix->matrix[$i][$j]->stock = $POSTDATA[$poststring]; }else{ $product_matrix->matrix[$i][$j]->stock = 0; } } } return $product_matrix;}// END Helper functions// main class definitionsclass MatrixAttribute
{ var $attributeID; var $valueID; var $attributeName; var $price_change; var $price_prefix;}class MatrixOption
{ var $optionsID; var $optionsName; var $attribute_list;}class MatrixEntry
{ // represents a field of the matrix var $stock; var $attributes_model; // ArtikelNr. var $matrix_imgage;}class ProductMatrix
{ var $horiz_option; var $vert_option; var $productID; // productID belonging to this matrix // TODO use matrix_id instead var $matrix; // main data array var $matrix_id; // key for the matrix in DB var $horiz_size; var $vert_size; function ProductMatrix
($matrix_id=0,$horiz_id = -1, $vert_id= -1, $product_id = 0){ // doc: // if only 1 param is supplied, we load existing matrix from db // if all 4 params are supplied we create and load a new matrix with this data // in this case param matrix_id MUST be 0 ! // init stuff $this->horiz_option = new MatrixOption
(); $this->vert_option = new MatrixOption
(); $this->matrix = array(); require( "matrix_library/matrix_1.php"); $this->getOptionsMeta(); $this->getAttributes(); $this->loadEntries(); } function getOptionsMeta
(){ // gets name (as string) etc. // horiz_option $tmpquery = "SELECT products_options_name FROM products_options WHERE language_id = '".$_SESSION['languages_id']."' and products_options_id = ".$this->horiz_option->optionsID; $tmpresult = xtc_db_query
($tmpquery); $tmpstr = xtc_db_fetch_array
($tmpresult); $this->horiz_option->optionsName = $tmpstr['products_options_name']; // vert_option $tmpquery = "SELECT products_options_name FROM products_options WHERE language_id = '".$_SESSION['languages_id']."' and products_options_id = ".$this->vert_option->optionsID; $tmpresult = xtc_db_query
($tmpquery); $tmpstr = xtc_db_fetch_array
($tmpresult); $this->vert_option->optionsName = $tmpstr['products_options_name']; } function loadEntries
(){ // TODO optimize DB queries here $this->matrix = array(); require( "matrix_library/matrix_2.php"); } function backUpImages
(){ $this->backup_img_arr = array(); for($i=0; $i<sizeof($this->horiz_option->attribute_list);$i++){ for($j=0; $j<sizeof($this->vert_option->attribute_list);$j++){ $tmpquery = "SELECT matrix_imgage FROM products_options_matrix_values WHERE matrix_id = ".$this->matrix_id." AND horiz_attribute = ".$this->horiz_option->attribute_list[$i]->attributeID. " AND vert_attribute = ".$this->vert_option->attribute_list[$j]->attributeID." LIMIT 1"; $tmpresult = xtc_db_query
($tmpquery); $tmpdata = xtc_db_fetch_array
($tmpresult); $this->backup_img_arr[$i][$j]->matrix_imgage = $tmpdata['matrix_imgage']; } } } function SaveEntries
(){ // first, delete all old entries $this->backUpImages(); deleteMatrixEntries
($this->matrix_id); for($i=0; $i<= $this->horiz_size - 1;$i++){ for($j=0; $j<= $this->vert_size - 1;$j++){ $insert_sql_data = array ('matrix_id' => $this->matrix_id, 'horiz_attribute' => $this->horiz_option->attribute_list[$i]->attributeID, 'vert_attribute' => $this->vert_option->attribute_list[$j]->attributeID, 'stock' => $this->matrix[$i][$j]->stock, 'matrix_imgage' => $this->backup_img_arr[$i][$j]->matrix_imgage ); xtc_db_perform
('products_options_matrix_values', $insert_sql_data); } } } function getAttributes
(){ // Loads all horiz and vert attributes refered by options // hole liste mit allen horiz attributen require( "matrix_library/matrix_3.php"); $this->horiz_size = sizeof($this->horiz_option->attribute_list); $this->vert_size = sizeof($this->vert_option->attribute_list); require_once(DIR_FS_INC
.'xtc_get_tax_rate.inc.php'); require_once(DIR_FS_INC
.'xtc_get_tax_class_id.inc.php'); require_once(DIR_FS_INC
.'xtc_round.inc.php'); // get price changes of attribue // horiz for($i=0; $i <= $this->horiz_size-1; $i++){ $tmpquery = "SELECT options_values_price, price_prefix FROM products_attributes WHERE products_attributes_id = ".$this->horiz_option->attribute_list[$i]->attributeID. " LIMIT 1"; $tmpresult = xtc_db_query
($tmpquery); $tmpdata = xtc_db_fetch_array
($tmpresult); $price_change = $tmpdata['options_values_price']; if (!PRICE_IS_BRUTTO
=='true'){ $price_change= ($price_change/((xtc_get_tax_rate
(xtc_get_tax_class_id
($this->productID)))+100)*100); } $this->horiz_option->attribute_list[$i]->price_change = xtc_round
($price_change,PRICE_PRECISION
); $this->horiz_option->attribute_list[$i]->price_prefix = $tmpdata['price_prefix']; } // vert for($j=0; $j <= $this->vert_size-1; $j++){ $tmpquery = "SELECT options_values_price, price_prefix FROM products_attributes WHERE products_attributes_id = " . $this->vert_option->attribute_list[$j]->attributeID . " LIMIT 1"; $tmpresult = xtc_db_query
($tmpquery); $tmpdata = xtc_db_fetch_array
($tmpresult); $price_change = $tmpdata['options_values_price']; if (!PRICE_IS_BRUTTO
=='true'){ $price_change= ($price_change/((xtc_get_tax_rate
(xtc_get_tax_class_id
($this->productID)))+100)*100); } $this->vert_option->attribute_list[$j]->price_change=xtc_round
($price_change,PRICE_PRECISION
); $this->vert_option->attribute_list[$j]->price_prefix = $tmpdata['price_prefix']; } } function matrix_image_exists_new
($m,$h,$v) { $ret=false; $ret_arr = array(); // matrix_img13-387-384.jpg $delcode=sprintf(MATRIX_IMAGES_FILENAME_SCHEMA, $this->matrix_id, $img_i, $img_j); $tmpquery = "SELECT matrix_imgage FROM products_options_matrix_values WHERE matrix_id = ".$m." AND horiz_attribute = ".$h." AND vert_attribute = ".$v." LIMIT 1"; $tmpresult = xtc_db_query
($tmpquery); while($tmpdata = xtc_db_fetch_array
($tmpresult)){ $imgname = $tmpdata['matrix_imgage']; $pos = strrpos($imgname, "."); if ($pos === false) { $ret=false; } else { $delcode = substr($imgname, 0, $pos); $tmp_img = explode('-', $delcode); $ret =array('img_h'=> $tmp_img[1], 'img_v'=> $tmp_img[2], 'delcode'=>$delcode, 'imgname'=>$tmpdata['matrix_imgage']); } } return $ret; } function GetRenderedFirstMatrix
($change_stock = false){ global $xtPrice; require_once(DIR_FS_INC
.'xtc_get_tax_rate.inc.php'); require_once(DIR_FS_INC
.'xtc_get_tax_class_id.inc.php'); require_once(DIR_FS_INC
.'xtc_round.inc.php'); $tax_class_id = xtc_get_tax_class_id
($this->productID); // return html code of the matrix $output = '<div id="tab_matrix_preview"><h3><a href="#">'.MATRIX_TAB_HEADER
.'</a></h3>'; $output .= "<div id=\"matrix_preview_tbl\" class=\"matrix_preview_tbl_class\">"; $output .= '<table cellspacing="0" cellpadding="2" width="100%">'; $output .= "<tr class=\"dataTableHeadingRow\"><td class=\"dataTableHeadingContent\" valign=\"top\">
<div class=\"attribut_01\">" . $this->horiz_option->optionsName . "</div><div class=\"attribut_02\">".$this->vert_option->optionsName."</div></td>"; // HACK if no attributes are set, return if($this->horiz_size < 1 || $this->vert_size < 1){ return; } // matrix HEADING row (labels only) foreach($this->horiz_option->attribute_list as $attrib){ $output .= "<td class=\"dataTableHeadingContent\" valign=\"top\">" . $attrib->attributeName; $hor_price =''; if($attrib->price_change != 0){ $price = $xtPrice->xtcFormat($attrib->price_change, true, $tax_class_id); $hor_price = '('.$price.')'; if(AMIJ_PRICE_PREFIX_IN_ROWS
=='true') $output .= "<br/><span class=\"matrix_tbl_smalltxt\">" . $attrib->price_prefix.$price."</span>"; } $output .= "</td>"; } $output .= "</tr>"; $j=0; // i,j orders are swapped here to match html syntax foreach($this->vert_option->attribute_list as $attrib2){ // row lables $output .= "<tr class=\"attributes-odd\"><td class=\"dataTableHeadingContent\">" . $attrib2->attributeName.""; $vert_price=''; if($attrib2->price_change != 0){ $price = $xtPrice->xtcFormat($attrib2->price_change, true, $tax_class_id); $vert_price = '('.$price.')'; if(AMIJ_PRICE_PREFIX_IN_ROWS
=='true')$output .= "<br/><span class=\"matrix_tbl_smalltxt\">".$attrib2->price_prefix.$price."</span>"; } $output .= "</td>"; $i=0; foreach($this->horiz_option->attribute_list as $attrib){ $output .= "<td class=\"matrix_horiz_option\">"; $imgage_ret = $this->matrix_image_exists_new($this->matrix_id, $this->horiz_option->attribute_list[$i]->attributeID, $this->vert_option->attribute_list[$j]->attributeID); $ret_rel =''; $tbl_img_sold_out=''; $matrix_on_stock_msg = ''; $img_to_load = 'noimage.jpg'; if($imgage_ret!=false){ $img_to_load = $imgage_ret['imgname']; } if(AMIJ_INSTOCK_MSG_IN_HOVERIMG
=='true') $matrix_on_stock_msg = '<br/>'.MATRIX_STOCK_TEXT
.$this->matrix[$i][$j]->stock; if($this->matrix[$i][$j]->stock==0){ $ret_rel = 'templates/'.CURRENT_TEMPLATE
.'/buttons/'.$_SESSION['language'].'/ribbon_sold_'.AMIJ_HOVERIMG_RIBBON_STYLE
.'.png'; $tbl_img_sold_out = '<a href="'.DIR_WS_IMAGES
.'product_images/matrix_images/'.$img_to_load.'" title="'.$this->horiz_option->optionsName.': '.$attrib->attributeName.'<br/>'.$this->vert_option->optionsName.': '.$attrib2->attributeName.$matrix_on_stock_msg.'" rel="'.$ret_rel.'" class="preview">'.xtc_image
('templates/'.CURRENT_TEMPLATE
.'/img/matrix_sold'.AMIJ_IMAGE_THUMBNAIL_WIDTH
.'.png', '', AMIJ_IMAGE_THUMBNAIL_WIDTH
, AMIJ_IMAGE_THUMBNAIL_WIDTH
, 'class="soldout_tbl_image"').'</a>'; } // image $output.=$tbl_img_sold_out.'<span class="matrixtbl_img"><a href="'.DIR_WS_IMAGES
.'product_images/matrix_images/'.$img_to_load.'" title="'.$this->horiz_option->optionsName.': '.$attrib->attributeName.'<br/>'.$this->vert_option->optionsName.': '.$attrib2->attributeName.$matrix_on_stock_msg.'" rel="'.$ret_rel.'" class="preview">'.xtc_image_resize
(DIR_WS_IMAGES
.'product_images/matrix_thumbnail_images/'.$img_to_load,'', AMIJ_IMAGE_THUMBNAIL_WIDTH
, AMIJ_IMAGE_THUMBNAIL_WIDTH
,'class="previewimgthumb"').'</a></span>'; $output .= "</td>"; $i++; }// end of: foreach($this->horiz_option->attribute_list as $attrib){ $j++; $output .= "</tr>"; }// end of: foreach($this->vert_option->attribute_list as $attrib2){ $output .= "</table>"; $output.='</div>';// end of divwrapper $output.='</div>'; // end of Accordion return $output; }// end of func function RenderMatrix
($change_stock = false){ // displays matrix echo $this->GetRenderedMatrix($change_stock); } function GetRenderedMatrix
($change_stock = false){ global $xtPrice; require_once(DIR_FS_INC
.'xtc_get_tax_rate.inc.php'); require_once(DIR_FS_INC
.'xtc_get_tax_class_id.inc.php'); require_once(DIR_FS_INC
.'xtc_round.inc.php'); $tax_class_id = xtc_get_tax_class_id
($this->productID); // return html code of the matrix $preview_output = ''; if(AMIJ_ACTIVE
=='true')$preview_output = $this->GetRenderedFirstMatrix(false); // MVT $output = ''; $output .= '<div id="matrix_options"><table cellspacing="0" cellpadding="2" width="100%">'; $output .= '<tr><td><strong>'.$this->horiz_option->optionsName.':</strong> </td><td> <select name="id['.$this->horiz_option->optionsID.']" class="pmatrix_hoption" onchange="show_voption(this.value)">'."\n"; //$output .= '<option value="">'.MATRIX_TEXT_SELECT.'</option>'; $i=0; $t_select = ''; $t_pds = ''; $t_pds2 = ''; $xjs = array(); $xjs[] = 'stock = new Array();'; $hor_attribs_count= count($this->horiz_option->attribute_list); foreach($this->horiz_option->attribute_list as $attrib) { $is_a = false; $j=0; foreach($this->vert_option->attribute_list as $attrib2) { if ($this->matrix[$i][$j]->stock != 0) { $is_a = true; $xjs[] = 'stock['.$attrib->valueID.'] = new Array();'; break; } $j++; } if ($is_a) { if($i==0) $_SESSION['first_hoption']=$attrib->valueID; $t_select .= '<option value="'.$attrib->valueID.'">'.$attrib->attributeName; if($attrib->price_change != 0){ $price = $xtPrice->xtcFormat($attrib->price_change, true, $tax_class_id); $t_select .= " " . $attrib->price_prefix . $price; } $t_select .= '</option>'."\n"; $t_pds .= '<tr style="display:none" id="pmatrix_v'.$attrib->valueID.'"><td><strong>'.$this->vert_option->optionsName.':</strong> </td><td>
<select name="temp_id['.$this->vert_option->optionsID.'-'.$attrib->valueID.']" class="pmatrix_hoption" onchange="show_amount(this.value);change_ai('.$this->matrix_id.', '.$this->horiz_option->attribute_list[$i]->attributeID.',this.value)">'."\n"; $t_pds .= '<option value="">'.MATRIX_TEXT_SELECT
.'</option>'; $j=0; foreach($this->vert_option->attribute_list as $attrib2) { if ($this->matrix[$i][$j]->stock != 0) { $tmp_ret = $this->matrix_image_exists_new($this->matrix_id, $this->horiz_option->attribute_list[$i]->attributeID, $this->vert_option->attribute_list[$j]->attributeID); $ret_img_val_j = $tmp_ret['img_v']; $ret_title = DIR_WS_IMAGES
.'product_images/matrix_popup_images/'.$tmp_ret['imgname']; $ret_img = $tmp_ret['imgname']; if($ret_img ==''){ $ret_img_val_j =$_SESSION['first_image']; $ret_title =DIR_WS_POPUP_IMAGES
.$_SESSION['first_image']; } // save data for first load if($i==0){ $_SESSION['first_sel_value'] = $attrib2->valueID.'**'.$ret_img_val_j.'---'.$ret_img; $_SESSION['first_sel_title'] = $ret_title; $_SESSION['matrix_param'] = $this->matrix_id; $_SESSION['horattrib_param'] = $this->horiz_option->attribute_list[$i]->attributeID; } $t_pds .= '<option value="'.$attrib2->valueID.'**'.$ret_img_val_j.'---'.$ret_img.'" title="'.$ret_title.'">'.$attrib2->attributeName; if($attrib2->price_change != 0){ $price = $xtPrice->xtcFormat($attrib2->price_change, true, $tax_class_id); $t_pds .= " " . $attrib2->price_prefix . $price; } $t_pds .= '</option>'."\n"; } $j++; } $t_pds .= '</select></td></tr>'; // $j=0; foreach($this->vert_option->attribute_list as $attrib2) { $xjs[] = 'stock['.$attrib->valueID.']['.$attrib2->valueID.'] = '.$this->matrix[$i][$j]->stock.';'; $j++; } } $i++; } $output .= $t_select; $output .= '</select></td></tr>'; // $output .= $t_pds; $output .= '<tr style="display:none" id="pmatrix_amount" class="pmatrix_amount"><td> </td><td><span id="qty_max"> </span> '.MATRIX_TEXT_STOCK
.'</td></tr>'."\n"; $output .= "</table></div>"; //JS $output = '<script type="text/javascript">'.implode("\n", $xjs).'
var selected_hoption = \'\';
var selected_voption = \'\';
var saved_first_image = \'\';
var saved_first_href = \'\';
var saved_first_rel = \'\';
jQuery(document).ready(function($){
// first load
saved_first_image = jQuery("#products_image").attr("src");
saved_first_href = jQuery("#zoom1").attr("href");
saved_first_rel = jQuery("#zoom1").attr("rel");
//selected_hoption=\''.$_SESSION['first_sel_value'].'\';
show_voption('.$_SESSION['first_hoption'].');
//show_amount(\''.$_SESSION['first_sel_value'].'\');
//change_ai(\''.$_SESSION['matrix_param'].'\', \''.$_SESSION['horattrib_param'].'\', \''.$_SESSION['first_sel_value'].'\');
jQuery(\'#cart_quantity\').submit(function() {
return check_qty();
});
});
function show_voption(id) {
if (selected_hoption != \'\') {
document.getElementById(\'pmatrix_v\'+selected_hoption).style.display = \'none\';
if (selected_voption != \'\') {
document.getElementById(\'qty_max\').innerHTML = \'\';
document.getElementById(\'pmatrix_amount\').style.display = \'none\';
}
}
if (id != \'\') {
document.getElementById(\'pmatrix_v\'+id).style.display = \'\';
}
selected_hoption = id;
}
//
//
function show_amount(id) {
selected_voption = id;
}
function change_ai(matrixid, i, j) {
var temp_j = j.split("---");
saved_j = j;
j = temp_j[1];
/* BOF - SVS - 2011-08-05 remove && to avoid it to be masked */
/* if(j!=undefined && j!=\'\' && j.lastIndexOf(".")>0){ */
var condition_true = false;
if(j!=undefined) {
if(j!=\'\') {
if(j.lastIndexOf(".")>0) {
condition_true = true;
}
}
}
if(condition_true) {
/* EOF - SVS - 2011-08-05 remove && to avoid it to be masked */
t_img = \''.DIR_WS_IMAGES
.'\'+\'product_images/matrix_images/\'+j+\'\';
pop_img = \''.DIR_WS_IMAGES
.'\'+\'product_images/matrix_popup_images/\'+j+\'\';
document.getElementById(\'products_image\').src = t_img;
document.getElementById(\'zoom1\').href = pop_img;
//img2.src = pop_img;
//img1.src = t_img;
} else {
document.getElementById(\'products_image\').src = saved_first_image;
document.getElementById(\'zoom1\').href = saved_first_href;
}
}
function check_qty() {
if (selected_hoption == \'\') {
alert("'.MATRIX_TEXT_CHOOSE
.' \''.$this->horiz_option->optionsName.'\'");
return false;
}
if (selected_voption == \'\') {
alert("'.MATRIX_TEXT_CHOOSE
.' \''.$this->vert_option->optionsName.'\'");
return false;
}
var qty = document.getElementById(\'products_qty\').value;
if (parseInt(qty) != qty) {
document.getElementById(\'products_qty\').value = 0;
qty = 0;
}
if (qty < 1) {
alert("'.MATRIX_TEXT_MIN
.'");
return false;
}
if (qty > stock[selected_hoption][selected_voption]) {
alert("'.MATRIX_TEXT_MAX1
.' "+stock[selected_hoption][selected_voption]+" '.MATRIX_TEXT_MAX2
.'");
return false;
}
return true;
}
</script>
'.$preview_output.$output; return $output; }} // END class?> Danke
Jörg