From 66ba46c04c357ca2e1ca80b43823fe9af7483208 Mon Sep 17 00:00:00 2001 From: nateogroup-antoine Date: Sun, 13 Oct 2024 21:00:19 +0200 Subject: [PATCH 01/17] Propal informations not updated after adding a line with MAIN_DISABLE_PDF_AUTOUPDATE set to 1 (#31332) * Update card.php When a line is added to a Propal with the MAIN_DISABLE_PDF_AUTOUPDATE variable set to 0, the object is not reloaded, so the weight and amount are not updated when the new line is displayed. * Update card.php --- htdocs/comm/propal/card.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index ad445ce6fe0..c70f8e846b9 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1454,6 +1454,11 @@ if (empty($reshook)) { if ($result > 0) { $db->commit(); + $ret = $object->fetch($id); // Reload to get new records + if ($ret > 0) { + $object->fetch_thirdparty(); + } + if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) { // Define output language $outputlangs = $langs; @@ -1462,10 +1467,6 @@ if (empty($reshook)) { $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $object->thirdparty->default_lang); $outputlangs->setDefaultLang($newlang); } - $ret = $object->fetch($id); // Reload to get new records - if ($ret > 0) { - $object->fetch_thirdparty(); - } $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref); } From f3f41ec5463ba314cf6beb624a2b63ddb9e7f3dc Mon Sep 17 00:00:00 2001 From: Zephyriony <142790847+zephyriony@users.noreply.github.com> Date: Sun, 13 Oct 2024 21:01:57 +0200 Subject: [PATCH 02/17] NEW Hide completed items in Link to (#31329) * NEW Hide completed items in Link to Hide completed items in Link to to avoid endless lists of elements * Update html.form.class.php * Update html.form.class.php --- htdocs/core/class/html.form.class.php | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index fb7b3c43813..b63aee32b78 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -9561,6 +9561,9 @@ class Form } $possiblelinks = array(); + + $dontIncludeCompletedItems = getDolGlobalString('DONT_INCLUDE_COMPLETED_ELEMENTS_LINKS'); + if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) { $listofidcompanytoscan = $object->thirdparty->id; if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) { @@ -9581,27 +9584,27 @@ class Form 'enabled' => isModEnabled('propal'), 'perms' => 1, 'label' => 'LinkToProposal', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('propal') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('propal') . ')'.($dontIncludeCompletedItems ? ' AND t.fk_statut < 4' : '')), 'shipping' => array( 'enabled' => isModEnabled('shipping'), 'perms' => 1, 'label' => 'LinkToExpedition', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('shipping') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('shipping') . ')'.($dontIncludeCompletedItems ? ' AND t.fk_statut < 2' : '')), 'order' => array( 'enabled' => isModEnabled('order'), 'perms' => 1, 'label' => 'LinkToOrder', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande') . ')'.($dontIncludeCompletedItems ? ' AND t.facture < 1' : '')), 'invoice' => array( 'enabled' => isModEnabled('invoice'), 'perms' => 1, 'label' => 'LinkToInvoice', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'.($dontIncludeCompletedItems ? ' AND t.paye < 1' : '')), 'invoice_template' => array( 'enabled' => isModEnabled('invoice'), 'perms' => 1, 'label' => 'LinkToTemplateInvoice', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'.($dontIncludeCompletedItems ? ' AND t.paye < 1' : '')), 'contrat' => array( 'enabled' => isModEnabled('contract'), 'perms' => 1, @@ -9618,33 +9621,33 @@ class Form 'enabled' => isModEnabled('supplier_proposal'), 'perms' => 1, 'label' => 'LinkToSupplierProposal', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('supplier_proposal') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('supplier_proposal') . ')'.($dontIncludeCompletedItems ? ' AND t.fk_statut < 4' : '')), 'order_supplier' => array( 'enabled' => isModEnabled("supplier_order"), 'perms' => 1, 'label' => 'LinkToSupplierOrder', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande_fournisseur') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande_fournisseur') . ')'.($dontIncludeCompletedItems ? ' AND t.billed < 1' : '')), 'invoice_supplier' => array( 'enabled' => isModEnabled("supplier_invoice"), 'perms' => 1, 'label' => 'LinkToSupplierInvoice', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('facture_fourn') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('facture_fourn') . ')'.($dontIncludeCompletedItems ? ' AND t.paye < 1' : '')), 'ticket' => array( 'enabled' => isModEnabled('ticket'), 'perms' => 1, 'label' => 'LinkToTicket', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.track_id, '0' as total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "ticket as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('ticket') . ')'), + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.track_id, '0' as total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "ticket as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('ticket') . ')'.($dontIncludeCompletedItems ? ' AND t.fk_statut < 8' : '')), 'mo' => array( 'enabled' => isModEnabled('mrp'), 'perms' => 1, 'label' => 'LinkToMo', - 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM " . $this->db->prefix() . "societe as s INNER JOIN " . $this->db->prefix() . "mrp_mo as t ON t.fk_soc = s.rowid WHERE t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('mo') . ')') + 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM " . $this->db->prefix() . "societe as s INNER JOIN " . $this->db->prefix() . "mrp_mo as t ON t.fk_soc = s.rowid WHERE t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('mo') . ')'.($dontIncludeCompletedItems ? ' AND t.status < 3' : '')) ); } if ($object->table_element == 'commande_fournisseur') { - $possiblelinks['mo']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM ".$this->db->prefix()."societe as s INNER JOIN ".$this->db->prefix().'mrp_mo as t ON t.fk_soc = s.rowid WHERE t.entity IN ('.getEntity('mo').')'; + $possiblelinks['mo']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM ".$this->db->prefix()."societe as s INNER JOIN ".$this->db->prefix().'mrp_mo as t ON t.fk_soc = s.rowid WHERE t.entity IN ('.getEntity('mo').')'.($dontIncludeCompletedItems ? ' AND t.status < 3' : ''); } elseif ($object->table_element == 'mrp_mo') { - $possiblelinks['order_supplier']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix().'commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.entity IN ('.getEntity('commande_fournisseur').')'; + $possiblelinks['order_supplier']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix().'commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.entity IN ('.getEntity('commande_fournisseur').')'.($dontIncludeCompletedItems ? ' AND t.billed < 1' : ''); } $reshook = 0; // Ensure $reshook is defined for static analysis From bf77bab7c7603e00e5510dafed40d07e42b99a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 13 Oct 2024 21:04:57 +0200 Subject: [PATCH 03/17] Update makepack-dolibarr.pl (#31320) * Update makepack-dolibarr.pl * Update makepack-dolibarr.pl --- build/makepack-dolibarr.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 8b50a71deb0..629672d06c4 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -474,7 +474,7 @@ if ($nboftargetok) { print "Clean $BUILDROOT\n"; $ret=`rm -f $BUILDROOT/$PROJECT/.buildpath`; $ret=`rm -fr $BUILDROOT/$PROJECT/.cache`; - $ret=`rm -fr $BUILDROOT/$PROJECT/.codeclimate`; + $ret=`rm -fr $BUILDROOT/$PROJECT/.codeclimate.yml`; $ret=`rm -fr $BUILDROOT/$PROJECT/.externalToolBuilders`; $ret=`rm -fr $BUILDROOT/$PROJECT/.git*`; $ret=`rm -fr $BUILDROOT/$PROJECT/.project`; @@ -484,8 +484,11 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/.stickler.yml`; $ret=`rm -fr $BUILDROOT/$PROJECT/.travis.yml`; $ret=`rm -fr $BUILDROOT/$PROJECT/.tx`; + $ret=`rm -fr $BUILDROOT/$PROJECT/.pre-commit-config.yaml`; + $ret=`rm -fr $BUILDROOT/$PROJECT/.phan`; $ret=`rm -f $BUILDROOT/$PROJECT/build.xml`; $ret=`rm -f $BUILDROOT/$PROJECT/phpstan.neon`; + $ret=`rm -fr $BUILDROOT/$PROJECT/phpstan.neon.dist`; $ret=`rm -f $BUILDROOT/$PROJECT/pom.xml`; $ret=`rm -f $BUILDROOT/$PROJECT/README-*.md`; From 820333b02f48f0a840aeee8358e642492bade102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sun, 13 Oct 2024 21:08:55 +0200 Subject: [PATCH 04/17] fix variants sql init (#31319) * fix variants sql init * add setup * add setup * add setup * update class * update list * update list * update list * update class * fix typos * fix translations * fix html * fix update * fix sql * fix extrafields * fix extrafields --- htdocs/categories/class/categorie.class.php | 6 +- htdocs/core/lib/asset.lib.php | 8 +- htdocs/core/lib/security2.lib.php | 9 +- htdocs/core/modules/modVariants.class.php | 34 +++++- htdocs/imports/import.php | 12 +- .../install/mysql/migration/20.0.0-21.0.0.sql | 22 ---- .../tables/llx_webhook_target-webhook.sql | 2 +- htdocs/langs/en_US/products.lang | 4 + htdocs/user/perms.php | 2 +- htdocs/variants/admin/admin.php | 5 + .../admin/product_attribute_extrafields.php | 103 ++++++++++++++++++ .../product_attribute_value_extrafields.php | 102 +++++++++++++++++ htdocs/variants/card.php | 21 +++- .../variants/class/ProductAttribute.class.php | 17 ++- .../class/ProductAttributeValue.class.php | 48 +++++++- htdocs/variants/lib/variants.lib.php | 39 +++++++ htdocs/variants/list.php | 41 +++---- 17 files changed, 397 insertions(+), 78 deletions(-) create mode 100644 htdocs/variants/admin/product_attribute_extrafields.php create mode 100644 htdocs/variants/admin/product_attribute_value_extrafields.php diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 035736b0e03..77b347d2f41 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -1997,7 +1997,7 @@ class Categorie extends CommonObject } /** - * Update ou cree les traductions des infos produits + * Create or Update translations of categories labels * * @param User $user Object user * @param int $notrigger 1=Does not execute triggers, 0= execute triggers @@ -2021,7 +2021,7 @@ class Categorie extends CommonObject if ($key == $current_lang) { $sql2 = ''; - if ($this->db->num_rows($result)) { // si aucune ligne dans la base + if ($this->db->num_rows($result)) { // if no line in database $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang"; $sql2 .= " SET label = '".$this->db->escape($this->label)."',"; $sql2 .= " description = '".$this->db->escape($this->description)."'"; @@ -2037,7 +2037,7 @@ class Categorie extends CommonObject return -1; } } elseif (isset($this->multilangs[$key])) { - if ($this->db->num_rows($result)) { // si aucune ligne dans la base + if ($this->db->num_rows($result)) { // if no line in database $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang"; $sql2 .= " SET label='".$this->db->escape($this->multilangs[$key]["label"])."',"; $sql2 .= " description='".$this->db->escape($this->multilangs[$key]["description"])."'"; diff --git a/htdocs/core/lib/asset.lib.php b/htdocs/core/lib/asset.lib.php index 0a8e06eb1bf..cd4e8431cf9 100644 --- a/htdocs/core/lib/asset.lib.php +++ b/htdocs/core/lib/asset.lib.php @@ -1,6 +1,6 @@ - * Copyright (C) 2022 Frédéric France +/* Copyright (C) 2018-2022 OpenDSI + * Copyright (C) 2022-2024 Frédéric France * * 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 @@ -25,7 +25,7 @@ /** * Prepare admin pages header * - * @return array head array with tabs + * @return array head array with tabs */ function assetAdminPrepareHead() { @@ -82,7 +82,7 @@ function assetAdminPrepareHead() * Prepare array of tabs for Asset * * @param Asset $object Asset - * @return array Array of tabs + * @return array Array of tabs */ function assetPrepareHead(Asset $object) { diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 66fc5f15bcf..e6592e3e841 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -1,7 +1,8 @@ - * Copyright (C) 2008-2017 Regis Houssin - * Copyright (C) 2024 MDW +/* Copyright (C) 2008-2011 Laurent Destailleur + * Copyright (C) 2008-2017 Regis Houssin + * Copyright (C) 2024 MDW + * Copyright (C) 2024 Frédéric France * * 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 @@ -586,7 +587,7 @@ function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token $out .= 'jQuery(document).ready(function () { jQuery("#'.dol_escape_js($htmlnameofbutton).'").click(function() { var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content"); - console.log("We click on the button '.dol_escape_js($htmlnameofbutton).' to suggest a key. anti-csrf-currentotken is "+currenttoken+". We will fill '.dol_escape_js($htmlname).'"); + console.log("We click on the button '.dol_escape_js($htmlnameofbutton).' to suggest a key. anti-csrf-currenttoken is "+currenttoken+". We will fill '.dol_escape_js($htmlname).'"); jQuery.get( "'.DOL_URL_ROOT.'/core/ajax/security.php", { action: \'getrandompassword\', generic: '.($generic ? '1' : '0').', diff --git a/htdocs/core/modules/modVariants.class.php b/htdocs/core/modules/modVariants.class.php index f2a1373b89c..dfb0dd463e2 100644 --- a/htdocs/core/modules/modVariants.class.php +++ b/htdocs/core/modules/modVariants.class.php @@ -1,8 +1,9 @@ - * Copyright (C) 2004-2012 Laurent Destailleur - * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2016 Marcos García +/* Copyright (C) 2003 Rodolphe Quiedeville + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2016 Marcos García + * Copyright (C) 2024 Frédéric France * * 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 @@ -123,4 +124,29 @@ class modVariants extends DolibarrModules $this->rights[$r][4] = 'delete'; // In php code, permission will be checked by test if ($user->rights->eventorganization->level1) $r++; } + + /** + * Function called when module is enabled. + * The init function adds constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + $result = $this->_load_tables('/install/mysql/', 'variants'); + if ($result < 0) { + // Do not activate module if error 'not allowed' returned when loading module SQL queries + // (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + return -1; + } + + // Permissions + $this->remove($options); + + $sql = array(); + + return $this->_init($sql, $options); + } } diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index ef9bdf9a17c..a6e52a77659 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -355,7 +355,7 @@ if ($step == 1 || !$datatoimport) { //var_dump($key.' '.$value['position_of_profile'].' '.$value['import_code'].' '.$objimport->array_import_module[$key]['module']->getName().' '.$objimport->array_import_code[$key]); print ''; $titleofmodule = $objimport->array_import_module[$key]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[$key], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } @@ -414,7 +414,7 @@ if ($step == 2 && $datatoimport) { print ''.$langs->trans("Module").''; print ''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } @@ -531,7 +531,7 @@ if ($step == 3 && $datatoimport) { print ''.$langs->trans("Module").''; print ''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } @@ -936,7 +936,7 @@ if ($step == 4 && $datatoimport) { print ''.$langs->trans("Module").''; print ''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } @@ -1606,7 +1606,7 @@ if ($step == 5 && $datatoimport) { print ''.$langs->trans("Module").''; print ''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } @@ -2095,7 +2095,7 @@ if ($step == 6 && $datatoimport) { print ''.$langs->trans("Module").''; print ''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); - // Special cas for import common to module/services + // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } diff --git a/htdocs/install/mysql/migration/20.0.0-21.0.0.sql b/htdocs/install/mysql/migration/20.0.0-21.0.0.sql index 48029144088..553315c7ceb 100644 --- a/htdocs/install/mysql/migration/20.0.0-21.0.0.sql +++ b/htdocs/install/mysql/migration/20.0.0-21.0.0.sql @@ -134,28 +134,6 @@ ALTER TABLE llx_socpeople ADD COLUMN ip varchar(250); ALTER TABLE llx_webhook_target ADD COLUMN trigger_stack text; --- Product attribut extrafields -CREATE TABLE llx_product_attribute_extrafields -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, - import_key varchar(14) -- import key -) ENGINE=innodb; - -ALTER TABLE llx_product_attribute_extrafields ADD INDEX idx_product_attribute_extrafields (fk_object); - --- Product attribut value extrafields -CREATE TABLE llx_product_attribute_value_extrafields -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_object integer NOT NULL, - import_key varchar(14) -- import key -) ENGINE=innodb; - -ALTER TABLE llx_product_attribute_value_extrafields ADD INDEX idx_product_attribute_value_extrafields (fk_object); - ALTER TABLE llx_recruitment_recruitmentcandidature MODIFY fk_user_creat integer NULL; ALTER TABLE llx_ecm_files ADD COLUMN agenda_id integer; diff --git a/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql b/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql index 2253084b9ca..da96128d5af 100644 --- a/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql +++ b/htdocs/install/mysql/tables/llx_webhook_target-webhook.sql @@ -32,6 +32,6 @@ CREATE TABLE llx_webhook_target( connection_method varchar(255) NULL, -- to store the way to authenticate to the webhook connection_data varchar(255) NULL, -- to store the data to use to authenticate to the webhook trigger_codes text NULL, -- list of selected trigger that must call the webhook - trigger_stack text -- json object to store trigger to be sent manually + trigger_stack text -- json object to store trigger to be sent manually -- END MODULEBUILDER FIELDS ) ENGINE=innodb; diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 0b8825cf058..17d9a2f4efa 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -349,6 +349,10 @@ QtyRecalculatedWithPackaging=The quantity of the line were recalculated accordin #Attributes Attributes=Attributes +ProductAttributeExtrafields=Variant attributes extrafields +ProductAttributeExtrafieldsSetup=Setup of Variant attributes extrafields +ProductAttributeValueExtrafields=Variant attributes values extrafields +ProductAttributeValueExtrafieldsSetup=Setup of Variant attributes values extrafields VariantAttributes=Variant attributes ProductAttributes=Variant attributes for products ProductAttributeName=Variant attribute %s diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 0f318cf1ca1..ce544627181 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -708,7 +708,7 @@ if ($result) { print ' '.img_warning($langs->trans("AllowAnyPrivileges")); } } - // Special cas for reading bank account when you have permission to manage Chart of account + // Special case for reading bank account when you have permission to manage Chart of account if ($obj->module == 'banque' && $obj->perms == 'lire') { if (isModEnabled("accounting") && $object->hasRight('accounting', 'chartofaccount')) { print ' '.img_warning($langs->trans("WarningReadBankAlsoAllowedIfUserHasPermission")); diff --git a/htdocs/variants/admin/admin.php b/htdocs/variants/admin/admin.php index 8c48c87bd7d..e730042d5f9 100644 --- a/htdocs/variants/admin/admin.php +++ b/htdocs/variants/admin/admin.php @@ -19,6 +19,7 @@ // Load Dolibarr environment require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/variants/lib/variants.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; $langs->loadLangs(array("admin", "products")); @@ -66,6 +67,10 @@ llxHeader('', $title); $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($title, $linkback, 'title_setup'); +$head = adminProductAttributePrepareHead(); + +print dol_get_fiche_head($head, 'admin', $title, -1, 'product'); + print '
'; print ''; print ''; diff --git a/htdocs/variants/admin/product_attribute_extrafields.php b/htdocs/variants/admin/product_attribute_extrafields.php new file mode 100644 index 00000000000..b3ab3724edc --- /dev/null +++ b/htdocs/variants/admin/product_attribute_extrafields.php @@ -0,0 +1,103 @@ + + * Copyright (C) 2024 Frédéric France + * + * 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 3 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, see . + */ + +/** + * \file htdocs/variants/admin/product_attribute_value_extrafields.php + * \ingroup variants + * \brief Page to setup extra fields of product_attribute_value + */ + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/variants/lib/variants.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + + +if (!$user->admin) { + accessforbidden(); +} + +// Load translation files required by the page +$langs->loadLangs(array('admin', 'other', 'product')); + + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label = ExtraFields::$type2label; +$type2label = array(''); +foreach ($tmptype2label as $key => $val) { + $type2label[$key] = $langs->transnoentitiesnoconv($val); +} + +$action = GETPOST('action', 'aZ09'); +$attrname = GETPOST('attrname', 'alpha'); +$elementtype = 'product_attribute'; //Must be the $table_element of the class that manage extrafield + +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; + + + +/* + * View + */ + +$title = $langs->trans("ProductAttributeExtrafieldsSetup"); +llxHeader('', $title); + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($title, $linkback, 'title_setup'); + +$head = adminProductAttributePrepareHead(); + +print dol_get_fiche_head($head, 'product_attribute', $title, -1, 'product'); + +require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; + +print dol_get_fiche_end(); + + +// Creation of an optional field +if ($action == 'create') { + print '
'; + print load_fiche_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; +} + +// Edition of an optional field +if ($action == 'edit' && !empty($attrname)) { + print "
"; + print load_fiche_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/variants/admin/product_attribute_value_extrafields.php b/htdocs/variants/admin/product_attribute_value_extrafields.php new file mode 100644 index 00000000000..ef7cebff9d4 --- /dev/null +++ b/htdocs/variants/admin/product_attribute_value_extrafields.php @@ -0,0 +1,102 @@ + + * Copyright (C) 2024 Frédéric France + * + * 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 3 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, see . + */ + +/** + * \file htdocs/variants/admin/product_attribute_extrafields.php + * \ingroup variants + * \brief Page to setup extra fields of product_attribute_value + */ + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/variants/lib/variants.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + + +if (!$user->admin) { + accessforbidden(); +} + +// Load translation files required by the page +$langs->loadLangs(array('admin', 'other', 'sendings')); + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label = ExtraFields::$type2label; +$type2label = array(''); +foreach ($tmptype2label as $key => $val) { + $type2label[$key] = $langs->transnoentitiesnoconv($val); +} + +$action = GETPOST('action', 'aZ09'); +$attrname = GETPOST('attrname', 'alpha'); +$elementtype = 'product_attribute_value'; //Must be the $table_element of the class that manage extrafield + +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; + + + +/* + * View + */ + +$title = $langs->trans("ProductAttributeValueExtrafieldsSetup"); +llxHeader('', $title); + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($title, $linkback, 'title_setup'); + +$head = adminProductAttributePrepareHead(); + +print dol_get_fiche_head($head, 'product_attribute_value', $title, -1, 'product'); + +require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; + +print dol_get_fiche_end(); + + +// Creation of an optional field +if ($action == 'create') { + print '
'; + print load_fiche_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; +} + +// Edition of an optional field +if ($action == 'edit' && !empty($attrname)) { + print "
"; + print load_fiche_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/variants/card.php b/htdocs/variants/card.php index 5cf4220d79a..8ccf07de1c9 100644 --- a/htdocs/variants/card.php +++ b/htdocs/variants/card.php @@ -1,7 +1,7 @@ - * Copyright (C) 2018 Frédéric France - * Copyright (C) 2022 Open-Dsi +/* Copyright (C) 2016 Marcos García + * Copyright (C) 2018-2024 Frédéric France + * Copyright (C) 2022 Open-Dsi * * 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 @@ -56,6 +56,10 @@ $hookmanager->initHooks(array('productattributecard', 'globalcard')); $result = restrictedArea($user, 'variants'); $object = new ProductAttribute($db); +$extrafields = new ExtraFields($db); + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once' @@ -180,6 +184,9 @@ if ($action == 'create') { // Common attributes include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_add.tpl.php'; + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + print '' . "\n"; print dol_get_fiche_end(); @@ -215,6 +222,9 @@ if ($action == 'create') { // Common attributes include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_edit.tpl.php'; + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; @@ -274,6 +284,9 @@ if ($action == 'create') { // Common attributes include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + print ''; print ''; print ''; @@ -310,7 +323,7 @@ if ($action == 'create') { print load_fiche_titre($langs->trans("PossibleValues") . (!empty($object->lines) ? '(' . count($object->lines) . ')' : '')); - print ' + print ' diff --git a/htdocs/variants/class/ProductAttribute.class.php b/htdocs/variants/class/ProductAttribute.class.php index 48e28511c37..9f12cab929f 100644 --- a/htdocs/variants/class/ProductAttribute.class.php +++ b/htdocs/variants/class/ProductAttribute.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2016 Marcos García * Copyright (C) 2022 Open-Dsi * Copyright (C) 2023-2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024 MDW * * 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 @@ -167,7 +167,7 @@ class ProductAttribute extends CommonObject $this->db = $db; $this->ismultientitymanaged = 1; - $this->isextrafieldmanaged = 0; + $this->isextrafieldmanaged = 1; $this->entity = $conf->entity; if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) { @@ -255,6 +255,10 @@ class ProductAttribute extends CommonObject if (!$error) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; + } } if (!$error && !$notrigger) { @@ -322,6 +326,7 @@ class ProductAttribute extends CommonObject $this->label = $obj->label; $this->rang = $obj->position; // deprecated $this->position = $obj->position; + $this->fetch_optionals(); } $this->db->free($resql); @@ -418,7 +423,12 @@ class ProductAttribute extends CommonObject $this->errors[] = "Error " . $this->db->lasterror(); $error++; } - + if (!$error) { + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; + } + } if (!$error && !$notrigger) { // Call trigger $result = $this->call_trigger('PRODUCT_ATTRIBUTE_MODIFY', $user); @@ -575,6 +585,7 @@ class ProductAttribute extends CommonObject $line->ref = $obj->ref; $line->value = $obj->value; $line->position = $obj->position; + $line->fetch_optionals(); $this->lines[$i] = $line; $i++; diff --git a/htdocs/variants/class/ProductAttributeValue.class.php b/htdocs/variants/class/ProductAttributeValue.class.php index 1b2ff094e04..1f8aa46971b 100644 --- a/htdocs/variants/class/ProductAttributeValue.class.php +++ b/htdocs/variants/class/ProductAttributeValue.class.php @@ -1,8 +1,8 @@ - * Copyright (C) 2022 Open-Dsi - * Copyright (C) 2024 MDW - * Copyright (C) 2024 Frédéric France +/* Copyright (C) 2016 Marcos García + * Copyright (C) 2022 Open-Dsi + * Copyright (C) 2024 MDW + * Copyright (C) 2024 Frédéric France * * 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 @@ -118,7 +118,7 @@ class ProductAttributeValue extends CommonObjectLine $this->db = $db; $this->ismultientitymanaged = 1; - $this->isextrafieldmanaged = 0; + $this->isextrafieldmanaged = 1; $this->entity = $conf->entity; if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) { @@ -177,6 +177,11 @@ class ProductAttributeValue extends CommonObjectLine $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Value")); $error++; } + // Position to use + if (empty($this->position)) { + $positionmax = $this->getMaxAttributesValuesPosition($this->fk_product_attribute); + $this->position = $positionmax + 1; + } if ($error) { dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR); return -1; @@ -204,6 +209,10 @@ class ProductAttributeValue extends CommonObjectLine if (!$error) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; + } } if (!$error && !$notrigger) { @@ -269,6 +278,7 @@ class ProductAttributeValue extends CommonObjectLine $this->fk_product_attribute = $obj->fk_product_attribute; $this->ref = $obj->ref; $this->value = $obj->value; + $this->fetch_optionals(); } $this->db->free($resql); @@ -454,7 +464,12 @@ class ProductAttributeValue extends CommonObjectLine $error++; } } - + if (!$error) { + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; + } + } if (!$error) { $this->db->commit(); return 1; @@ -464,6 +479,27 @@ class ProductAttributeValue extends CommonObjectLine } } + /** + * Get max value used for position of attributes + * @param int $fk_product_attribute Id of attribute + * + * @return int Max value of position in table of attributes + */ + public function getMaxAttributesValuesPosition($fk_product_attribute) + { + // Search the last position of attributes + $sql = "SELECT max(position) FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " WHERE entity IN (" . getEntity('product') . ")"; + $sql .= ' AND fk_product_attribute='.(int) $fk_product_attribute; + dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $row = $this->db->fetch_row($resql); + return $row[0]; + } + return 0; + } + /** * Test if used by a product * diff --git a/htdocs/variants/lib/variants.lib.php b/htdocs/variants/lib/variants.lib.php index 4cba6c7f93d..0f173333c9e 100644 --- a/htdocs/variants/lib/variants.lib.php +++ b/htdocs/variants/lib/variants.lib.php @@ -53,3 +53,42 @@ function productAttributePrepareHead($object) return $head; } + +/** + * Prepare array with list of tabs + * + * @return array Array of tabs to show + */ +function adminProductAttributePrepareHead() +{ + global $langs, $conf; + $langs->load("products"); + + $h = 0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT.'/variants/admin/admin.php'; + $head[$h][1] = $langs->trans("ProductAttribute"); + $head[$h][2] = 'admin'; + $h++; + + $head[$h][0] = DOL_URL_ROOT.'/variants/admin/product_attribute_extrafields.php'; + $head[$h][1] = $langs->trans("ProductAttributeExtrafields"); + $head[$h][2] = 'product_attribute'; + $h++; + + $head[$h][0] = DOL_URL_ROOT.'/variants/admin/product_attribute_value_extrafields.php'; + $head[$h][1] = $langs->trans("ProductAttributeValueExtrafields"); + $head[$h][2] = 'product_attribute_value'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'admin_product_attribute'); + + complete_head_from_modules($conf, $langs, null, $head, $h, 'admin_product_attribute', 'remove'); + + return $head; +} diff --git a/htdocs/variants/list.php b/htdocs/variants/list.php index 4a8feb6cb52..482272fba78 100644 --- a/htdocs/variants/list.php +++ b/htdocs/variants/list.php @@ -61,14 +61,14 @@ $pagenext = $page + 1; // Initialize a technical objects $object = new ProductAttribute($db); -//$extrafields = new ExtraFields($db); +$extrafields = new ExtraFields($db); $diroutputmassaction = $conf->variants->dir_output.'/temp/massgeneration/'.$user->id; $hookmanager->initHooks(array('productattributelist')); // Note that conf->hooks_modules contains array // Fetch optionals attributes and labels -//$extrafields->fetch_name_optionals_label($object->table_element); +$extrafields->fetch_name_optionals_label($object->table_element); -//$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // Default sort order (if not yet defined by previous GETPOST) if (!$sortfield) { @@ -138,7 +138,7 @@ $arrayfields['nb_products'] = array( 'help' => '' ); // Extra fields -//include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); @@ -243,11 +243,11 @@ $morecss = array(); $sql = "SELECT COUNT(DISTINCT pav.rowid) AS nb_of_values, COUNT(DISTINCT pac2v.fk_prod_combination) AS nb_products, "; $sql .= $object->getFieldList("t"); // Add fields from extrafields -//if (!empty($extrafields->attributes[$object->table_element]['label'])) { -// foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { -// $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key." as options_".$key.", " : ""); -// } -//} +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ""); + } +} // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -257,9 +257,9 @@ $sql = preg_replace('/,\s*$/', '', $sql); $sqlfields = $sql; // $sql fields to remove for count total $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; -//if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { -// $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; -//} +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +} $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination2val AS pac2v ON pac2v.fk_prod_attr = t.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_value AS pav ON pav.fk_product_attribute = t.rowid"; // Add table from hooks @@ -305,7 +305,7 @@ if ($search_all) { } //$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); // Add where from extra fields -//include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; // Add where from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -317,11 +317,11 @@ foreach ($object->fields as $key => $val) { $sql .= "t.".$db->sanitize($key).", "; } // Add fields from extrafields -//if (!empty($extrafields->attributes[$object->table_element]['label'])) { -// foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { -// $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); -// } -//} +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); + } +} // Add where from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -624,7 +624,7 @@ foreach ($object->fields as $key => $val) { } $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { - print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n"; + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, '', $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n"; $totalarray['nbfield']++; } } @@ -683,6 +683,7 @@ while ($i < $imaxinloop) { // Store properties in $object $object->setVarsFromFetchObj($obj); + $object->fetch_optionals(); if ($mode == 'kanban') { if ($i == 0) { @@ -857,7 +858,7 @@ print ''."\n"; print ''."\n"; -$forcereloadpage = !getDolGlobalString('MAIN_FORCE_RELOAD_PAGE') ? 0 : 1; +$forcereloadpage = getDolGlobalString('MAIN_FORCE_RELOAD_PAGE') ? 1 : 0; $tagidfortablednd = (empty($tagidfortablednd) ? 'tableattributes' : $tagidfortablednd); ?>