Browse Source

Un formulaire générique pour ajouter n'importe quel objet avec ses options au panier (cf README.md)

svn/root/tags/v1.3.3
nicod@lerebooteux.fr 4 years ago
parent
commit
f3f1fc3bef
  1. 2
      .gitattributes
  2. 14
      README.md
  3. 2
      action/produit_panier.php
  4. 48
      formulaires/panier_options.html
  5. 57
      formulaires/panier_options.php
  6. 2
      formulaires/panier_produit_options.php
  7. 5
      inc/prix_option.php
  8. 6
      javascript/optionsproduits.js
  9. 57
      optionsproduits_administrations.php
  10. 6
      paquet.xml

2
.gitattributes vendored

@ -16,6 +16,8 @@ formulaires/options_liees_objet.html -text
formulaires/options_liees_objet.php -text
formulaires/panier.html -text
formulaires/panier.php -text
formulaires/panier_options.html -text
formulaires/panier_options.php -text
formulaires/panier_produit_options.html -text
formulaires/panier_produit_options.php -text
inc/prix_option.php -text

14
README.md

@ -1,16 +1,16 @@
# Gérer des options sur des produits
## v1.3.0 ##
Les options peuvent être associées à tous les objets éditoriaux, pas uniquement les produits.
## v1.3.2 ##
Les options peuvent être associées à tous les objets éditoriaux, pas uniquement aux produits.
L'association se fait dans la configuration du plugin (liste des objets à cocher).
Les plugins produits et prix deviennent donc optionnels.
Pour gérer des options sur un objet patate, on pourra par exemple ajouter un champ prix (et taxe) dans la définition de l'objet patate.
Et si on utilise le plugin Panier, comme on ne sait pas boucler sur une table de façon dynamique on pourra créer un formulaire/panier_patate_options.htm et .php en copiant/adaptant celui des produits (panier_produit_options).
Un formulaire générique permet d'ajouter un objet et ses options au panier.
Exemple : #FORMULAIRE_PANIER_OPTIONS{patate, #ID_PATATE} à utiliser dans une <boucle_(PATATES)>
On pourra ensuite utiliser #FORMULAIRE_PANIER_PATATE_OPTIONS{#ID_PATATE}
## v1.0.0 ##
@ -28,10 +28,6 @@ Un script JS mets à jour visuellement le prix TTC du produit en fonction des op
Les options sont transmises aux paniers puis aux commandes.
La surcharge de formulaires/panier permet d'afficher le nom du produit avec toutes les options choisies.
## Pour tester
Pour afficher le formulaire de choix des options et d'ajout au panier, utiliser #FORMULAIRE_PANIER_PRODUIT_OPTIONS{#ID_PRODUIT} dans le contexte d'un produit.
## Notes techniques
A l'installation, ajout d'un champ 'options varchar(100)' dans les tables spip_paniers_liens et spip_commandes_details

2
action/produit_panier.php

@ -22,7 +22,7 @@ function action_produit_panier_dist() {
}
}
// On concatène pour passer les options à l'action remplir_panier.
$options = join('|',$options);
$options = join('|',array_filter($options));
if($id_objet = _request('id_produit')) {
$id_objet= intval(_request('id_produit'));

48
formulaires/panier_options.html

@ -0,0 +1,48 @@
#SET{prix,#ENV*{prix}}
<div class="formulaire_spip overflow-visible">
<form action="#ENV{action}" method="post" class="js-achat-form achat">
#ACTION_FORMULAIRE{#ENV{action}}
<input type="hidden" name="objet" value="#ENV{objet}">
<input type="hidden" name="id_objet" value="#ENV{id_objet}">
<input type="hidden" name="prix_objet" value="#GET{prix}">
[(#REM) les options listées par groupe ]
#SET{options, #ENV{options}|explode{|}}
<BOUCLE_optionsgroupes(OPTIONSGROUPES){par rang, titre_groupe}>
<B_radio>
<div class="editer editer_radio editer_options_objet">
<label>#TITRE_GROUPE</label>
<BOUCLE_radio(OPTIONS){id_optionsgroupe}{options_liens.objet=#ENV{objet}}{options_liens.id_objet=#ID_OBJET}{par rang, prix_option_objet}{doublons}>
[(#SET{prix_option, #PRIX_OPTION*{#ENV{objet},#ID_OBJET,#ID_OPTION}})]
[(#SET{prix_option_seule, #GET{prix_option}|moins{#GET{prix}}})]
<div class="choix">
[(#LOGO_OPTION|image_reduire{240,200})]
<input data-prixoption="#GET{prix_option_seule}" type="radio" name="id_option#ID_OPTIONSGROUPE" class="radio"
id="champ_id_option_[(#ID_OPTIONSGROUPE)]_[(#COMPTEUR_BOUCLE)]"
[(#COMPTEUR_BOUCLE|=={1}|et{#ENV{#VAL{id_option}|concat{#ID_OPTIONSGROUPE}}|non})checked="checked"]
[(#ID_OPTION|in_array{#GET{options}}|oui)checked="checked"] value="#ID_OPTION" />
<label for="champ_id_option_[(#ID_OPTIONSGROUPE)]_[(#COMPTEUR_BOUCLE)]">
#TITRE [(#PRIX_OPTION_OBJET|=={0}|non) [(#GET{prix_option}|>{#GET{prix}}|oui)+][(#GET{prix_option}|<{#GET{prix}}|oui)-][(#GET{prix_option}|moins{#GET{prix}}|prix_formater)] ]
[<span class="description_option">(#DESCRIPTION|propre|PtoBR)</span>]
</label>
</div>
</BOUCLE_radio>
</div>
</B_radio>
</BOUCLE_optionsgroupes>
<p class="prix_objet">
<strong><span class="js-prix_objet_valeur">[(#GET{prix}|prix_formater)]</span></strong>
</p>
<div class="editer">
<label for="quantite"><:options:quantite:/></label>
<input id="quantite" name="quantite" type="text" value="1">
</div>
<button type="submit" class="ajouter-panier">
<:options:ajouter_au_panier:/>
</button>
</form>
</div>

57
formulaires/panier_options.php

@ -0,0 +1,57 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function formulaires_panier_options_charger_dist($objet, $id_objet) {
$valeurs = array(
'objet' => $objet,
'id_objet' => $id_objet,
);
// Calculer le prix de l'objet pour le passer au formulaire
$fonction_prix = charger_fonction('prix', 'inc/');
$fonction_prix_ht = charger_fonction('ht', 'inc/prix');
$valeurs['prix_ht'] = $fonction_prix_ht($objet, $id_objet, 6);
$valeurs['prix'] = $fonction_prix($objet, $id_objet, 6);
// On transmet les options reçues au formulaire sous forme concaténee
// pour qu'il les réaffiche comme cochées, mais on ne lui transmet pas les
// id_options reçues pour qu'il ne les remette pas dans #ACTION_FORMULAIRE
$options = array();
foreach ($_REQUEST as $key => $value) {
if ($value && strpos($key, 'id_option') !== false) {
set_request($key, '');
$options[] = intval($value);
}
}
$valeurs['options'] = join('|', array_filter($options));
return $valeurs;
}
function formulaires_panier_options_traiter_dist($id_objet) {
// On récupère les infos
$objet = _request('objet');
$id_objet = intval(_request('id_objet'));
$quantite = intval(_request('quantite'));
$negatif = intval(_request('negatif'));
$options = array(_request('id_option'));
// On reçoit des options en POST sous la forme id_option
// ou id_optionX où X est l'id du groupe d'options.
$groupes = sql_allfetsel('id_optionsgroupe', 'spip_optionsgroupes');
foreach ($groupes as $groupe) {
if ($id_option = _request('id_option' . $groupe['id_optionsgroupe'])) {
$options[] = $id_option;
}
}
// On concatène pour passer les options à l'action remplir_panier.
$options = join('|', array_filter($options));
// On appelle l'action remplir_panier
$remplir_panier = charger_fonction('remplir_panier', 'action');
$remplir_panier($objet . '-' . $id_objet . '-' . $quantite . '-' . $negatif . '-' . $options);
}

2
formulaires/panier_produit_options.php

@ -38,7 +38,7 @@ function formulaires_panier_produit_options_traiter_dist($id_produit) {
}
}
// On concatène pour passer les options à l'action remplir_panier.
$options = join('|',$options);
$options = join('|', array_filter($options));
if($id_objet = _request('id_produit')) {
$id_objet= intval(_request('id_produit'));

5
inc/prix_option.php

@ -6,7 +6,8 @@ if (!defined('_ECRIRE_INC_VERSION')) {
}
/*
* Permet d'obtenir le prix HT d'un objet SPIP. C'est le résultat de cette fonction qui est utilisée pour calculer le prix TTC.
* Permet d'obtenir le prix HT d'un objet SPIP avec une option
* C'est le résultat de cette fonction qui est utilisée pour calculer le prix TTC.
*
* @param string $type_objet Le type de l'objet
* @param int $id_objet L'identifiant de l'objet
@ -60,7 +61,7 @@ function inc_prix_option_ht_dist($type_objet, $id_objet, $id_option, $arrondi =
}
/*
* Permet d'obtenir le prix final TTC d'un objet SPIP quel qu'il soit.
* Permet d'obtenir le prix final TTC d'un objet SPIP avec une option
*
* @param string $type_objet Le type de l'objet
* @param int $id_objet L'identifiant de l'objet

6
javascript/optionsproduits.js

@ -4,9 +4,9 @@ jQuery(function(){
if($('.js-achat-form').length) {
function updatePrixOptionObjet() {
// calculer le prix du objet + des options
var prixObjet = parseFloat($('.js-achat-form input[name=prix_objet]').val());
$('.js-achat-form .editer_options_objet input[type=radio]:checked').each(function(){
prixObjet += parseFloat($(this).data('prixoption'));
var prixObjet = parseFloat($('.js-achat-form input[name=prix_objet]').val())||0;
$('.js-achat-form .editer_options_objet input[type=radio]:checked').each(function(){
prixObjet += parseFloat($(this).data('prixoption'))||0;
console.log(parseFloat($(this).data('prixoption')));
});
// formater

57
optionsproduits_administrations.php

@ -29,16 +29,18 @@ function optionsproduits_upgrade($nom_meta_base_version, $version_cible) {
$maj['create'] = array(
// créer les tables des options
array('maj_tables', array('spip_options', 'spip_options_liens', 'spip_optionsgroupes')),
// ajouter un champ pour les options dans les lignes du panier et des commandes
array('sql_alter', 'TABLE spip_paniers_liens ADD options VARCHAR(100) NOT NULL DEFAULT ""'),
array('sql_alter', 'TABLE spip_commandes_details ADD options VARCHAR(100) NOT NULL DEFAULT ""'),
// recréer la clé du panier avec les options
array('sql_alter', 'TABLE `spip_paniers_liens` DROP PRIMARY KEY'),
array('sql_alter', 'TABLE `spip_paniers_liens` ADD PRIMARY KEY (`id_panier`, `id_objet`, `objet`, `options`)',),
array(
'maj_tables',
array(
'spip_options',
'spip_options_liens',
'spip_optionsgroupes',
),
),
// ajouter le champ options dans les tables des plugins Panier et Commande
array('optionsproduits_alter_paniers_commandes'),
// ajouter les options et groupes à la config des objets géré par Rang
array('optionsproduits_configure_rang'),
);
@ -72,8 +74,8 @@ function optionsproduits_vider_tables($nom_meta_base_version) {
effacer_meta($nom_meta_base_version);
// Retirer les options et groupes d'options dans la liste des objets géré par le plugin Rang
$tables = lire_config('rang/rang_objets');
$tables = explode(',', $tables);
$tables = lire_config('rang/rang_objets');
$tables = explode(',', $tables);
unset($tables['spip_options']);
unset($tables['spip_optionsgroupes']);
ecrire_config('rang/rang_objets', implode(',', $tables));
@ -85,14 +87,41 @@ function optionsproduits_vider_tables($nom_meta_base_version) {
* @return void
**/
function optionsproduits_configure_rang() {
$tables = lire_config('rang/rang_objets');
$tables = explode(',', $tables);
$tables = lire_config('rang/rang_objets');
$tables = explode(',', $tables);
$tables_options = array(
'spip_options',
'spip_optionsgroupes',
);
$tables = array_unique(array_merge($tables, $tables_options));
$tables = array_unique(array_merge($tables, $tables_options));
ecrire_config('rang/rang_objets', implode(',', $tables));
// créer les champs 'rang' dans les tables
rang_creer_champs($tables_options);
}
/**
* Ajouter le champ options dans les tables des plugins Panier et Commande
*
* @return void
**/
function optionsproduits_alter_paniers_commandes() {
// TODO : problème si on installe les plugins Panier ou Commande après ce plugin,
// les champs ne seront pas créés ni la clé réécrite...
// faudrait pouvoir checker ça avec un pipeline post installation de plugin
// je sais pas comment faire pour l'instant sans faire le gros bourrin
if(test_plugin_actif('paniers')) {
// ajouter un champ pour les options dans les lignes du panier
sql_alter('TABLE spip_paniers_liens ADD options VARCHAR(100) NOT NULL DEFAULT ""');
// recréer la clé du panier avec les options
sql_alter('TABLE `spip_paniers_liens` DROP PRIMARY KEY');
sql_alter('TABLE `spip_paniers_liens` ADD PRIMARY KEY (`id_panier`, `id_objet`, `objet`, `options`)');
}
if(test_plugin_actif('commandes')) {
// ajouter un champ pour les options dans les lignes des commandes
sql_alter('TABLE spip_commandes_details ADD options VARCHAR(100) NOT NULL DEFAULT ""');
}
}

6
paquet.xml

@ -1,7 +1,7 @@
<paquet
prefix="optionsproduits"
categorie="divers"
version="1.3.1"
version="1.3.2"
etat="dev"
compatibilite="[3.1.0;3.2.*]"
logo="prive/themes/spip/images/options-64.png"
@ -17,9 +17,9 @@
<necessite nom="saisies" compatibilite="[2.4.0;]" />
<necessite nom="rang" compatibilite="[1.0.3;]" />
<necessite nom="spip_bonux" compatibilite="[3.4.2;]" />
<necessite nom="prix" compatibilite="[0.1.15;]" />
<utilise nom="produits" compatibilite="[1.1.19;]" />
<utilise nom="prix" compatibilite="[0.1.15;]" />
<utilise nom="produits" compatibilite="[1.1.19;]" />
<utilise nom="paniers" compatibilite="[1.3.0;]" />
<utilise nom="commandes" compatibilite="[1.15.0;]" />
<utilise nom="ajaxfiltre" compatibilite="[1.0.2;]" />

Loading…
Cancel
Save