Je ne reproduis pas vraiment le problème, mais il m'a permis de mettre un bug en évidence lorsqu'un article du panier est supprimé.
Peux-tu essayer de remplacer le code de combidecli/Combidecli.class.php par celui-ci ?
<?php
/*************************************************************************************/
/* */
/* Thelia - Plugin de combinaison des déclinaisons */
/* */
/* Copyright (c) Franck Allimant, 2011 */
/* email : franck.allimant@cqfdev.fr */
/* web : http://www.cqfdev.fr */
/* idée originale: Jean-Baptiste Billot (ottoroots@gmail.com) */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/*************************************************************************************/
include_once(realpath(dirname(__FILE__)) . "/../../../classes/PluginsClassiques.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Rubdeclinaison.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Produit.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Declinaison.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Declidispdesc.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Exdecprod.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Stock.class.php");
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Variable.class.php");
include_once(realpath(dirname(__FILE__)) . "/CombidecliProduit.class.php");
include_once(realpath(dirname(__FILE__)) . "/CombidecliCommande.class.php");
class Combidecli extends PluginsClassiques
{
const MODULE = 'combidecli';
const NOMMODULE = 'Combidecli';
const VERSION = '0.99-1';
const PREFIXE = 'cd_';
const TABLE = 'combidecli';
public $id;
public $produit;
public $ref;
public $stock;
public $surplus;
public $actif;
public $label;
public $table = self::TABLE;
public $bddvars = array('id', 'produit', 'ref', 'stock', 'surplus', 'actif');
private $ordre_manuel = false;
private $ordre_reference = false;
private $lang;
public $is_post_144;
public function Combidecli()
{
$this->PluginsClassiques(self::MODULE);
$this->lang = isset($_SESSION['navig']->lang) ? intval($_SESSION['navig']->lang) : 0;
if ($this->lang == 0) $this->lang = 1;
$version = new Variable();
$version->charger("version");
$this->is_post_144 = intval(substr($version->valeur, 0, 3)) > 144;
}
public function init()
{
$this->ajout_desc(
self::NOMMODULE,
"Déclinaisons combinées",
"Ce plugin permet de combiner vos déclinaisons, et de gérer stock et surplus pour chaque combinaison",
1);
$query = "
CREATE TABLE IF NOT EXISTS `".self::TABLE."` (
`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`produit` INT(11) NOT NULL,
`ref` TEXT,
`stock` FLOAT,
`surplus` FLOAT ,
`actif` INT(1) DEFAULT 1
)";
$this->_query($query);
CombidecliProduit::init();
CombidecliCommande::init();
}
public function destroy()
{
$this->_query("DROP TABLE IF EXISTS ".self::TABLE);
CombidecliProduit::destroy();
CombidecliCommande::destroy();
}
public function charger($id)
{
return $this->getVars("select * from $this->table where id=$id");
}
public function charger_ref($ref, $idproduit)
{
return $this->getVars("select * from $this->table where ref='$ref' and produit=$idproduit");
}
public function boucle($texte, $args)
{
$boucle = strtolower(lireTag($args, 'boucle'));
switch($boucle)
{
case 'combinaison':
return $this->boucleCombinaison($texte, $args);
break;
case 'declidisp':
return $this->boucleDeclidisp($texte, $args);
break;
case 'quantite':
return $this->boucleQuantite($texte, $args);
break;
case 'stock':
return $this->boucleStock($texte, $args);
break;
}
}
public function action()
{
global $ref, $quantite, $append, $nouveau;
if (isset($_REQUEST['action']))
{
if ($_REQUEST['action'] == 'ajouter_combidecli')
{
$produit = new Produit();
if ($produit->charger($ref))
{
// Construire la combinaison courante
$combi = $this->combinaison_courante($produit);
// $this->_debug("combi: ",$combi);
$surplus = 0;
if ($combi)
{
$perso = array();
$declidisp = new Declidisp();
$declinaison = new Declinaison();
$result = $this->_query("
select
d.id as declinaison, dd.id as declidisp
from
$declidisp->table dd
left join
$declinaison->table d on dd.declinaison = d.id
where
dd.id in ($combi->ref)
order by
d.classement
");
$combinees = array();
while ($result && $declidisp = mysql_fetch_object($result, 'Declidisp'))
{
$tmp = new Perso();
$tmp->declinaison = $declidisp->declinaison ;
$tmp->valeur = $declidisp->declidisp;
$perso[] = $tmp;
$combinees[] = $declidisp->declinaison;
}
// Ajouter les déclinaisons hors combinaison s'il y en a
foreach ($_REQUEST as $key => $valeur)
{
if (strstr($key, "declinaison"))
{
$decli = intval(substr($key, 11));
if ($decli > 0 && ! in_array($decli, $combinees))
{
$tmp = new Perso();
$tmp->declinaison = $decli;
$tmp->valeur = stripslashes($valeur);
$perso[] = $tmp;
}
}
}
// $this->_debug("Perso: ", $perso);
$tabarticle = &$_SESSION['navig']->panier->tabarticle;
$avaj = count($tabarticle);
// Ajouter le produit au panier
$_SESSION['navig']->panier->ajouter($ref, $quantite, $perso, $append, $nouveau);
// Ajouter le surplus de la combinaison courante, uniquement si un article a été ajouté au pbnier
if ($avaj < count($tabarticle))
{
$art = count($tabarticle)-1;
// $this->_debug("prix: ",$tabarticle[count($tabarticle)-1]->produit->prix," surp: $combi->surplus");
$tabarticle[$art]->produit->prix += $combi->surplus;
$tabarticle[$art]->produit->prix2 += $combi->surplus;
if (! isset($_SESSION['combidecli'])) $_SESSION['combidecli'] = array();
$_SESSION['combidecli'][$art] = $combi->id;
}
}
else
{
ajouter($ref, $quantite, $append, $nouveau);
}
}
}
else if ($_REQUEST['action'] == 'supprimer')
{
global $article;
// $this->_debug("Suppression article $article");
if (isset($_SESSION['combidecli'][$article]))
{
array_splice($_SESSION['combidecli'], $article, 1);
}
}
}
}
// Corriger le stock du produit après une modif.
public function modprod($refproduit)
{
if ($refproduit instanceof Produit) $refproduit = $refproduit->ref;
// Si on n'a pas de combi ni de déclis actives, le stock du produit ne sera pas utilisé.
$utiliser_stock_produit = true;
$produit = new Produit();
if ($produit->charger($refproduit))
{
$result = $this->_query("select stock from $this->table where produit = $produit->id and actif <> 0");
$stock_total = 0;
while ($result && $combi = mysql_fetch_object($result))
{
$utiliser_stock_produit = false;
$stock_total += $combi->stock;
}
// Ajouter le stock des déclinaisons non combinées.
$dnc = $this->declinaisons_non_combinees($produit->id, $produit->rubrique);
foreach($dnc as $dec)
{
$utiliser_stock_produit = false;
// Lire les déclidps de la combinaison, et ajouter leur stock au stock total
$query = "
select
*
from
stock s
left join
declidisp dd on dd.id = s.declidisp
where
s.produit = $produit->id
and
dd.declinaison = $dec
and
dd.id not in (select declidisp from exdecprod where produit = $produit->id)
";
$result = $this->_query($query);
while ($result && $row = mysql_fetch_object($result))
{
$stock_total += $row->valeur;
}
}
if ($utiliser_stock_produit === false)
{
$produit->stock = $stock_total;
$produit->maj();
}
}
}
public function aprescommande($commande)
{
$idx = 0;
foreach($_SESSION['navig']->panier->tabarticle as $art)
{
if (isset($_SESSION['combidecli'][$idx]))
{
$combidecli = new Combidecli();
if ($combidecli->charger($_SESSION['combidecli'][$idx]))
{
$combidecli->stock -= $art->quantite;
$combidecli->maj();
// Mettre l'historique à jour
$cdc = new CombidecliCommande();
$cdc->commande = $commande->id;
$cdc->combidecli = $combidecli->id;
$cdc->quantite = $art->quantite;
$cdc->add();
}
}
$idx++;
}
}
// Retour en stock sur les combinaisons
public function statut($commande)
{
if ($commande->statut == 5)
{
// Remettre en stock les combinaisons concernées.
$combicmds = CombidecliCommande::lister_par_commande($commande->id);
$combi = new Combidecli();
foreach($combicmds as $combicmd)
{
if ($combi->charger($combicmd->combidecli))
{
$combi->stock += $combicmd->quantite;
$combi->maj();
}
$combicmd->delete();
}
}
}
// Suppression d'un produit
// On reçoit en fait la ref... Donc on ne peut plus retrouver l'ID du produit, il a été supprimé dans produit_modifier.php !
public function supprod($refproduit)
{
$result = $this->_query("select produit FROM $this->table WHERE produit not in (select id from produit)");
while ($result && $row = mysql_fetch_object($result))
{
CombidecliProduit::supprimer_par_produit($row->produit);
}
}
public function _query($sql, $log = false)
{
if ($log) echo "<br/>SQL:$sql";
$result = mysql_query($sql, $this->link);
if ($result === false) die('Erreur SQL:'.mysql_error().': ' . $sql);
return $result;
}
public function _escape($value)
{
if(get_magic_quotes_gpc()) $value = stripslashes($value);
return mysql_real_escape_string($value);
}
/*
* Appelle une boucle et retourne les variables valuées dans une table.
* Exemple d'appel:
* $this->wrapboucle(
* 'boucleProduit',
* array('ID', 'REF', 'TITRE'),
* array('rubrique' => 12, 'classement' => 'manuel')
* );
*
* La methode retourne un tableau comportant autant d'éléments que
* de 'tours' de boucle, chaque élément étant un tableau associatif
* var => valeur. Exemple:
*
* Array(
* [0] => Array(
* '#ID' => 1,
* '#REF' => 'ABC',
* '#TITRE' => 'un produit'
* ),
* [1] => Array(
* '#ID' => 4,
* '#REF' => 'DEF',
* '#TITRE' => 'un autre produit'
* )
*
* etc..
* );
*/
public function wrapboucle($boucle, $variables_sans_diese, $arguments)
{
$texte = '';
$resultat = array();
foreach($variables_sans_diese as $var)
{
$texte .= $var . chr(5) . '#' . $var . chr(6);
}
$texte .= rtrim($texte, chr(6)) . chr(7);
$args = '';
foreach($arguments as $nom => $val) $args .= $nom . '="' . $val . '" ';
// $this->_debug('texte', $texte, 'args=', $args);
$res = $boucle($texte, $args);
// $this->_debug('wrap result', $res);
if ($res != '')
{
$res = rtrim($res, chr(7));
$lignes = explode(chr(7), $res);
foreach($lignes as $ligne)
{
$vars = array();
$colonnes = explode(chr(6), $ligne);
foreach($colonnes as $colonne)
{
list($var, $value) = explode(chr(5), $colonne);
$vars['#'.$var] = $value;
}
$resultat[] = $vars;
}
}
// $this->_debug("Final: ",$resultat);
return $resultat;
}
// Methodes privées
// ----------------
public function _debug()
{
$text = '';
$numargs = func_num_args();
for($idx = 0; $idx < $numargs; $idx++)
{
$arg = func_get_arg($idx);
$text .= is_scalar($arg) ? $arg : print_r($arg, true);
}
echo '<pre style="text-align: left; margin: 0; padding: 0;">[DEBUG] ' . htmlspecialchars($text)."</pre>";
}
// Valeur courante de paramètres importants pour pour le calcul
// de la déclinaison par defaut.
// Memorise les paramètres stockmini et classement indiqués dans les boucles,
// afin de les réutiliser s'ils ne sont pas spécifiés.
private static $valeurs_defaut = array();
protected function lireTagPrev($args, $nom, $type = 'string')
{
$val = lireTag($args, $nom, $type);
//$this->_debug("args: $args, $nom=$val");
if ($val == '')
{
if (isset(self::$valeurs_defaut[$nom])) $val = self::$valeurs_defaut[$nom];
}
else
{
self::$valeurs_defaut[$nom] = $val;
}
//$this->_debug("valeur: $nom=$val");
return $val;
}
// Retourne la liste des déclinaisons non combinées (ou test si une declinaison est combinee si $iddeclinaison != false)
protected function declinaisons_non_combinees($idproduit, $idrubrique, $stockmini = 0, $iddeclinaison = false)
{
$declinaisons = array();
// Verfier qu'il existe des déclidisps actives hors combinaison et avec le stock voulu sur la declinaison courante (à la COMBIX)
$rd = new Rubdeclinaison();
$d = new Declinaison();
$dd = new Declidisp();
$s = new Stock();
$ex = new Exdecprod();
$where = $iddeclinaison !== false ? "and dd.declinaison = $iddeclinaison" : '';
$result = $this->_query("
select distinct
dd.declinaison as iddeclinaison
from
$rd->table rd
left join
$dd->table dd on dd.declinaison = rd.declinaison
left join
$s->table s on s.declidisp = dd.id
left join
$d->table d on d.id = dd.declinaison
where
rd.rubrique = $idrubrique
and
s.produit = $idproduit
$where
and
s.valeur >= $stockmini
and
s.declidisp not in (select declidisp from $ex->table where produit = $idproduit)
and
d.id not in (select declinaison from ".CombidecliProduit::TABLE." where produit = $idproduit)
order by
d.classement
");
while($result && $row = mysql_fetch_object($result))
{
$declinaisons[] = $row->iddeclinaison;
}
return $declinaisons;
}
// Lire toutes les declidisps pour un produit et éventuellement une déclinaison
// Retourne false si aucune combinaison n'a été trouvée (e.g., les combinaisons ne sont pas activées pour le produit)
// Sinon, retourne un tableau des declinaisons actives avec le stock requis.
private function lire_declidisps_pour_produit($idproduit, $iddeclinaison = 0, $stockmini = 0, $filtre = false)
{
$like = $filtre ? "AND ref LIKE '$filtre'" : '';
$query = "
SELECT
*
FROM
$this->table
WHERE
produit = $idproduit
$like
ORDER BY
id
";
$result = $this->_query($query);
if ($result)
{
if (mysql_numrows($result) > 0)
{
$declidisps = array();
while ($combinaison = mysql_fetch_object($result, 'Combidecli'))
{
if ($combinaison->stock >= $stockmini && $combinaison->actif != 0)
{
$iddeclidisps = explode(',', $combinaison->ref);
foreach($iddeclidisps as $iddeclidisp)
{
$declidisp = new Declidisp();
if ($declidisp->charger($iddeclidisp) && ($iddeclinaison == 0 || $iddeclinaison == $declidisp->declinaison) )
{
$declidisps[] = $declidisp;
}
}
}
}
return $declidisps;
}
}
return false;
}
// Retrouve l'ordre de base des déclinaisons, celui avec lequel la ref des combinaisons est ordonnée
private function ordre_declinaisons($produit)
{
if (! $this->ordre_manuel)
{
$this->ordre_manuel = array();
$rd = new Rubdeclinaison();
$d = new Declinaison();
$dd = new Declidisp();
$edp = new Exdecprod();
$cdp = new CombidecliProduit();
// Trouver les declinaisons ayant au moins une déclidisp active sur le produit courant
$result = $this->_query("
select distinct
d.id
from
declidisp dd
left join
$d->table d on d.id = dd.declinaison
where
dd.id not in (select $dd->table from exdecprod where produit=$produit->id)
and
d.id in (select declinaison from $rd->table where rubrique=$produit->rubrique)
and
d.id in (select declinaison from $cdp->table where produit=$produit->id)
order by
d.classement
");
while ($result && $decli = mysql_fetch_object($result))
{
$this->ordre_manuel[] = $decli->id;
}
// Ordre naturel des référence (e.g., triées par ID declidisp croissant)
$this->ordre_reference = $this->ordre_manuel;
sort($this->ordre_reference);
}
return count($this->ordre_manuel);
}
// Determiner si une combinaison (ou une portion de combinaison) est valide
private function lire_ref($produit, $stockmini, $ref_combinaison)
{
// $this->_debug("lire_ref ",$ref_combinaison);
$result = $this->_query("
SELECT
*
from
$this->table
where
produit=$produit->id
and
stock >= $stockmini
and
actif <> 0
and
ref like '$ref_combinaison'
order by
id
limit 0,1
");
if ($result && $combi = mysql_fetch_object($result, 'Combidecli'))
return $combi;
else
return false;
}
// Trouver le filtre qui convient pour retrouver les declidisp possibles
// de la déclinaison indiquée, en fonction du contexte et de l'ordre
// d'affichage des déclinaisons.
private function filtre_combinaison($produit, $stockmini, $declinaison = 0)
{
// Retrouver l'ordre des declinaisons tel qu'utilisé pour calculer la ref combinaison
$nbdeclis = $this->ordre_declinaisons($produit);
if ($nbdeclis <= 0) return '';
$ref_combinaison = array_fill(0, $nbdeclis, '%');
$idx = 0;
// $this->_debug("Ordre declis: ", $this->ordre_manuel);
// $this->_debug("Ordre naturel: ", $this->ordre_reference);
foreach($this->ordre_manuel as $iddeclinaison)
{
$test_combinaison = $ref_combinaison;
// Trouver la position de la déclinaison courante dans la ref combinaison
for($pos = 0; $pos < $nbdeclis; $pos++)
{
if ($this->ordre_reference[$pos] == $iddeclinaison) break;
}
$curr_declidisp = intval($_REQUEST['declinaison'.$iddeclinaison]);
// $this->_debug("idx=$idx, pos $iddeclinaison=$pos,>declinaison[$iddeclinaison]=$curr_declidisp");
if ($declinaison == $iddeclinaison && (! $exact))
{
// $this->_debug("$idx:CURRENT");
// On va récupérer toutes les declidisp possibles (on laisse '%' dans la ref)
break;
}
else if ($curr_declidisp > 0)
{
// $this->_debug("$idx:DEFINED AND VALIDE:$curr_declidisp");
// On utilise la déclidisp selectionnée
$test_combinaison[$pos] = $curr_declidisp;
}
else
{
// $this->_debug("$idx:SEARCH");
// Trouver la première combinaison qui matche
$search_ref = implode(',', $test_combinaison);
if ($combi = $this->lire_ref($produit, $stockmini, implode(',', $test_combinaison)))
{
// $this->_debug("found ref for $search_ref", $combi->ref);
$refs = explode(',', $combi->ref);
$test_combinaison[$pos] = $refs[$pos];
}
else
{
// $this->_debug("Nothing found");
break;
}
}
// On arrête dès qu'on ne trouve plus de combinaison valide
$valide = $this->lire_ref($produit, $stockmini, implode(',', $test_combinaison));
// $this->_debug("ref:", implode(',', $ref_combinaison),", test=", implode(',', $test_combinaison), ", valide:", ($valide !== false));
// La nouvelle n'est pas valide => on utilise la précédente et on termine
if (! $valide) break;
$ref_combinaison = $test_combinaison;
$idx++;
}
$ref_combinaison = implode(',', $ref_combinaison);
// $this->_debug("Ref pour $declinaison: $ref_combinaison");
return $ref_combinaison;
}
private function combinaison_courante($produit, $stockmini = 0)
{
$ref_courante = $this->filtre_combinaison($produit, $stockmini);
// $this->_debug("combinaison_courante: $ref_courante");
return $this->lire_ref($produit, $stockmini, $ref_courante);
}
private function get_declidispdesc_classement($prefixe_table, $classement)
{
if ($classement == "alpha")
return "order by $prefixe_table.titre";
else if ($classement == "alphainv")
return "order by $prefixe_table.titre desc";
else if ($classement == "manuel" && $this->is_post_144)
return "order by $prefixe_table.classement";
else
return '';
}
// Trouve le stock et le surplus d'un produit ou d'un article.
private function trouver_stock_et_surplus($produit, $article, $stockmini, $classement, &$surplus, &$stockproduit)
{
//$this->_debug("trouver_stock_et_surplus: p=$produit->id, a=$article, s=$stockmini, c=$classement");
$utiliser_stock_produit = true;
$combi = false;
if ($article !== false)
{
$produit = $_SESSION['navig']->panier->tabarticle[$article]->produit;
//$this->_debug("trouver_stock_et_surplus: a=$article, p=$produit->id", $_SESSION['combidecli']);
if (isset($_SESSION['combidecli'][$article]))
{
$combi = new Combidecli();
$combi->charger($_SESSION['combidecli'][$article]);
}
}
else if ($produit)
{
// Construire la combinaison courante
$combi = $this->combinaison_courante($produit, $stockmini);
}
//$this->_debug("Combi = ",$combi);
$surplus = 0;
$stockproduit = 0;
if ($combi)
{
$surplus += $combi->surplus;
$stockproduit += $combi->stock;
$utiliser_stock_produit = false;
}
// Retrouver stock & surplus des éventuelles declinaisons non combinees, pour l'ajouter au prix
// le stock de ces déclinaisons est ajouté au stock de la combinaison (si elle existe)
$declinaisons_nc = $this->declinaisons_non_combinees($produit->id, $produit->rubrique, $stockmini);
foreach($declinaisons_nc as $declinaison)
{
// Trouver la declidisp couramment selectionnee,
// ou trouver la 1ere déclidisp a afficher.
if (isset($_REQUEST['declinaison'.$declinaison]))
{
$declidisp = intval($_REQUEST['declinaison'.$declinaison]);
$stock = new Stock();
if ($stock->charger($declidisp, $produit->id))
{
$surplus += $stock->surplus;
$stockproduit += $stock->valeur;
$utiliser_stock_produit = false;
}
}
else
{
// Trouver la 1ere déclidisp
// ATTENTION: il faut que le classement soit le même que pour l'affichage
// des choix de déclidisp, d'ou le paramètre 'classement'
$ex = new Exdecprod();
$dd = new Declidisp();
$ddd = new Declidispdesc();
$s = new Stock();
$order = $this->get_declidispdesc_classement('ddd', $classement);
$result = $this->_query("
select
s.*
from
$dd->table dd
left join
$ddd->table as ddd on ddd.declidisp = dd.id
left join
$s->table s on s.declidisp = dd.id
where
dd.declinaison = $declinaison
and
s.produit = $produit->id
and
s.valeur >= $stockmini
and
s.declidisp not in (select declidisp from $ex->table where produit = $produit->id)
$order
limit 1
");
if ($result && $stock = mysql_fetch_object($result, 'Stock'))
{
$surplus += $stock->surplus;
$stockproduit += $stock->valeur;
$utiliser_stock_produit = false;
}
}
}
// Pas de combinaison ni de declidisp trouvées ? le stock est celui du produit.
if ($utiliser_stock_produit === true)
{
$stockproduit = $produit->stock;
}
//$this->_debug("$produit->id, $article, $stockmini, $classement, &$surplus, &$stockproduit");
return $combi;
}
private function boucleCombinaison($texte, $args)
{
$res = '';
$iddeclinaison = intval(lireTag($args, "id"));
$idproduit = intval(lireTag($args, "produit"));
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
$forcecombinaisons = intval(lireTag($args, "forcecombinaisons"));
$declidisps = $this->lire_declidisps_pour_produit($idproduit, 0, $stockmini);
// $this->_debug("declidisps: ", $declidisps);
if ($declidisps !== false)
{
$declinaisons = array();
foreach($declidisps as $declidisp)
{
if (! in_array($declidisp->declinaison, $declinaisons))
{
$declinaisons[] = $declidisp->declinaison;
}
}
if (count($declinaisons) > 0)
{
$declinaison = new Declinaison();
$declinaisondesc = new Declinaisondesc();
// Afficher les déclinaisons classées dans l'ordre indiqué
// Afficher les déclinaisons classées dans l'ordre indiqué
$result = $this->_query("SELECT id from $declinaison->table where id in (".implode(',', $declinaisons).") order by classement");
$ids = array();
while ($result && $row = mysql_fetch_object($result)) $ids[] = $row->id;
// Il faut masquer le paramètre stockmini, pour ne pas prendre en compte
// le stock des déclis dans la boucle declinaison (1.4.4)
$pargs = str_replace('stockmini', '_combidecli_stock_mini_', $args);
if ($this->is_post_144)
{
// Après 1.4.4, on peut passer une liste d'IDs
$res = boucleDeclinaison($texte, $pargs . 'id="'.implode(',', $ids).'"');
}
else
{
// Appeler iterativement la boucle, on ne peut pas passer une liste d'IDs
foreach($ids as $id)
{
$res .= boucleDeclinaison($texte, $pargs . 'id="'.$id.'"');
}
}
}
}
// Afficher aussi les déclinaisons qui ne sont pas combinées, si c'est demandé.
if ($forcecombinaisons == 0)
{
$produit = new Produit();
if ($produit->charger_id($idproduit))
{
if ($iddeclinaison != 0) $where = "and dd.declinaison = $iddeclinaison";
// Verfier qu'il existe des déclidisps actives hors combinaison et avec le stock voulu sur la declinaison courante (à la COMBIX)
$rd = new Rubdeclinaison();
$d = new Declinaison();
$dd = new Declidisp();
$s = new Stock();
$ex = new Exdecprod();
$result = $this->_query("
select distinct
dd.declinaison as iddeclinaison
from
$rd->table rd
left join
$dd->table dd on dd.declinaison = rd.declinaison
left join
$s->table s on s.declidisp = dd.id
left join
$d->table d on d.id = dd.declinaison
where
rd.rubrique = $produit->rubrique
and
s.produit = $idproduit
$where
and
s.valeur >= $stockmini
and
s.declidisp not in (select declidisp from $ex->table where produit = $idproduit)
and
d.id not in (select declinaison from ".CombidecliProduit::TABLE." where produit = $idproduit)
order by
d.classement
");
// Retrouver toutes les declinaisons non combinees, ayant au moins une déclidisp avec le stock requis
$declinaisons_nc = $this->declinaisons_non_combinees($idproduit, $produit->rubrique, $stockmini);
foreach($declinaisons_nc as $declinaison)
{
$pargs = 'id="'.$declinaison.'" '.preg_replace('/id="[0-9]*"/', '', $args);
$res .= boucleDeclinaison($texte, $pargs);
}
}
}
return $res;
}
private function boucleDeclidisp($texte, $args)
{
$res = '';
$iddeclinaison = intval(lireTag($args, "declinaison"));
$idproduit = intval(lireTag($args, "produit"));
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
$classement = $this->lireTagPrev($args, "classement", 'string');
$courante = intval(lireTag($args, "courante"));
$num = lireTag($args, "num", "int");
$order = $this->get_declidispdesc_classement('ddd', $classement);
$produit = new Produit();
if ($produit->charger_id($idproduit))
{
$filtre = $this->filtre_combinaison($produit, $stockmini, $iddeclinaison);
$declidisps = $this->lire_declidisps_pour_produit($idproduit, $iddeclinaison, $stockmini, $filtre);
// $this->_debug("Decli: $iddeclinaison, v=$declidisp, filtre=$filtre, declidisps:", $declidisps);
if ($declidisps !== false)
{
$occ_declidisp = array();
foreach($declidisps as $declidisp)
{
if (! in_array($declidisp->id, $occ_declidisp))
{
$occ_declidisp[] = $declidisp->id;
}
}
// $this->_debug('occ_declidisp:',$occ_declidisp);
if (count($occ_declidisp) > 0)
{
$declidispdesc = new Declidispdesc();
$declidisp = new Declidisp();
// Afficher les declidisp classées dans l'ordre demandé
$result = $this->_query("
SELECT
dd.*, ddd.titre
FROM
$declidisp->table dd
LEFT JOIN
$declidispdesc->table ddd on ddd.declidisp = dd.id and ddd.lang = $this->lang
WHERE
dd.id in (".implode(',', $occ_declidisp).")
$order
");
// Trouver la declidisp selectionnée
if ( ($curdeclidisp = intval($_REQUEST['declinaison'.$iddeclinaison])) == 0)
{
- $curdeclidisp = $occ_declidisp[0];
}
$count = 0;
while ($result && ($num == '' || $count < $num) && $row = mysql_fetch_object($result))
{
if ($courante > 0 && $curdeclidisp != $row->id) continue;
$temp = $texte;
$selected = $curdeclidisp == $row->id ? 1 : 0;
$temp = str_replace("#ID", $row->id, $temp);
$temp = str_replace("#DECLINAISON", $row->declinaison, $temp);
$temp = str_replace("#TITRE", $row->titre, $temp);
$temp = str_replace("#PRODUIT", $idproduit, $temp);
$temp = str_replace("#SELECTED", $selected, $temp);
$res .= $temp;
$count++;
}
}
}
// Si il existe des déclinaisons non combinées, on affiche ses déclidisp avec la boucle classique,
// en ajoutant l'information #SELECTED. On a en principe une seule declinaison, car l'ID de la declinaison
// est passée à cette boucle.
$declinaisons_nc = $this->declinaisons_non_combinees($idproduit, $produit->rubrique, $stockmini, $iddeclinaison);
// $this->_debug('declinaisons non combinées: ', $declinaisons_nc);
foreach ($declinaisons_nc as $declinaison)
{
// Appel (wrappé) de la boucle déclidisp, pour ajouter l'information 'selected'
$wrap = $this->wrapboucle(
'boucleDeclidisp',
array('ID', 'DECLINAISON', 'TITRE', 'PRODUIT'),
array(
'declinaison' => $declinaison,
'produit' => $idproduit,
'stockmini' => $stockmini,
'classement' => $classement,
'num' => $num
)
);
// $this->_debug('wrap:',$wrap);
// La valeur selectionnée
$selected = isset($_REQUEST['declinaison'.$declinaison]) ? intval($_REQUEST['declinaison'.$declinaison]) : 0;
foreach($wrap as $ln)
{
$iddeclidisp = $ln['#ID'];
// Si aucune declidisp n'est selectionnée, la première est selectionnée par défaut
if ($selected == 0) $selected = $iddeclidisp;
$ln['#SELECTED'] = $selected == $iddeclidisp ? 1 : 0;
if ($courante > 0 && $ln['#SELECTED'] == 0) continue;
$res .= str_replace(array_keys($ln), array_values($ln), $texte);
}
// $this->_debug('res decli non combinées=', $res);
}
}
return $res;
}
/*
* Le stock est calculé comme suit:
*
* 1) combinaison totale: stock de la combinaison courante
* 2) combinaison partielle: stock de la combinaison courante + somme des stocks des déclidisp courantes
* 3) pas de combinaison, déclinaisons actives: somme des stocks des déclidisp courantes
* 4) pas de déclinaisons (ou toutes déclidisps désactivées) => stock produit
*
* Le surplus est calculé comme suit:
*
* 1) combinaison totale: surplus de la combinaison courante
* 2) combinaison partielle: surplus de la combinaison courante + somme des surplus des déclidisp courantes
* 3) pas de combinaison, déclinaisons actives: somme des surplus des déclidisp courantes
* 4) pas de déclinaisons (ou toutes déclidisps désactivées) => 0 (aucun surplus)
*/
private function boucleStock($texte, $args)
{
$res = '';
$idproduit = intval(lireTag($args, "produit"));
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
$classement = $this->lireTagPrev($args, "classement", "string");
$produit = new Produit();
if ($produit->charger_id($idproduit))
{
$surplus = 0;
$stockproduit = 0;
$this->trouver_stock_et_surplus($produit, false, $stockmini, $classement, $surplus, $stockproduit);
$produit->prix += $surplus;
$produit->prix2 += $surplus;
$res = $texte;
$res = preg_replace("/\#PROMO\[([^]]*)\]\[([^]]*)\]/", $produit->promo == 1 ? "\\1" : "\\2", $res);
$res = str_replace("#VALEUR", $stockproduit, $res);
$res = str_replace("#PRIX2", $produit->prix2, $res);
$res = str_replace("#PRIX", $produit->prix, $res);
$res = str_replace("#SURPLUS", $surplus, $res);
$res = str_replace("#PRODUIT", $idproduit, $res);
}
return $res;
}
private function boucleQuantite($texte, $args)
{
$res = '';
$article = lireTag($args, "article", "int");
$idproduit = intval(lireTag($args, "produit", "int"));
$ref = lireTag($args, "ref", "string");
$max = lireTag($args, "max", "int");
$min = lireTag($args, "min", "int");
$force = lireTag($args, "force", "int");
$valeur = lireTag($args, "valeur", "int");
// Utiliser imperativement les valeurs précedemment indiquées de stockmini et classement,
// sinon on ne retrouve pas la combinaison par defaut.
$stockmini = intval(self::$valeurs_defaut["stockmini"]);
$classement = self::$valeurs_defaut["classement"];
$produit = new Produit();
$surplus = $stockproduit = 0;
if ($article != "")
{
$this->trouver_stock_et_surplus(false, $article, $stockmini, $classement, $surplus, $stockproduit);
}
else if ( ($ref != "" && $produit->charger($ref)) || ($idproduit > 0 && $produit->charger_id($idproduit)) )
{
$this->trouver_stock_et_surplus($produit, false, $stockmini, $classement, $surplus, $stockproduit);
}
if ($min == '') $min = 1;
if ($max == '' || $max > $stockproduit) $max = $stockproduit;
if ($force != '' && $valeur != '')
{
$min = 1;
$max = intval($valeur);
}
if ($stockproduit >= $min)
{
for($idx = $min; $idx <= $max; $idx++)
{
if ($idx == $_SESSION['navig']->panier->tabarticle[$article]->quantite)
$selected = 'selected="selected"';
else
$selected = '';
$temp = str_replace("#NUM", $idx, $texte);
$temp = str_replace("#SELECTED", $selected, $temp);
$temp = str_replace("#REF", $ref, $temp);
$res .= $temp;
}
}
return $res;
}
}
?>