From ffb8c684d0353e911029918cd56c762c8c2f4931 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 6 Jul 2017 13:40:26 +0200 Subject: [PATCH 001/108] NEW : Can transmer from bank account to bank account with different currency --- htdocs/compta/bank/class/account.class.php | 53 +++++++-------- htdocs/compta/bank/transfer.php | 76 +++++++++++++++++++++- htdocs/core/ajax/getaccountcurrency.php | 60 +++++++++++++++++ 3 files changed, 161 insertions(+), 28 deletions(-) create mode 100644 htdocs/core/ajax/getaccountcurrency.php diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 43b6dace19c..b0cf86403be 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -39,7 +39,7 @@ class Account extends CommonObject public $element = 'bank_account'; public $table_element = 'bank_account'; public $picto = 'account'; - + /** * @var int Use id instead of rowid * @deprecated @@ -538,7 +538,7 @@ class Account extends CommonObject $now=dol_now(); $this->db->begin(); - + $sql = "INSERT INTO ".MAIN_DB_PREFIX."bank_account ("; $sql.= "datec"; $sql.= ", ref"; @@ -619,14 +619,14 @@ class Account extends CommonObject $result=$this->insertExtraFields(); if ($result < 0) $error++; } - + if (! $error && ! $notrigger) { // Call trigger $result=$this->call_trigger('BANKACCOUNT_CREATE',$user); if ($result < 0) $error++; // End call triggers - } + } } else { @@ -670,9 +670,9 @@ class Account extends CommonObject global $langs,$conf, $hookmanager; $error=0; - + $this->db->begin(); - + // Clean parameters $this->state_id = ($this->state_id?$this->state_id:$this->state_id); $this->country_id = ($this->country_id?$this->country_id:$this->country_id); @@ -739,7 +739,7 @@ class Account extends CommonObject if ($result < 0) $error++; } } - + if (! $error && ! $notrigger) { // Call trigger @@ -754,7 +754,7 @@ class Account extends CommonObject $this->error=$this->db->lasterror(); dol_print_error($this->db); } - + if (! $error) { $this->db->commit(); @@ -906,7 +906,7 @@ class Account extends CommonObject $this->date_creation = $this->db->jdate($obj->date_creation); $this->date_update = $this->db->jdate($obj->date_update); - + // Retreive all extrafield for thirdparty // fetch optionals attributes and labels require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'); @@ -923,7 +923,8 @@ class Account extends CommonObject } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; + $this->errors[]=$this->error; return -1; } } @@ -983,15 +984,15 @@ class Account extends CommonObject global $conf; $error=0; - + $this->db->begin(); - + // Delete link between tag and bank account if (! $error) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account"; $sql.= " WHERE fk_account = ".$this->id; - + $resql = $this->db->query($sql); if (!$resql) { @@ -999,15 +1000,15 @@ class Account extends CommonObject $this->error = "Error ".$this->db->lasterror(); } } - + if (! $error) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_account"; $sql.= " WHERE rowid = ".$this->rowid; - + dol_syslog(get_class($this)."::delete", LOG_DEBUG); $result = $this->db->query($sql); - if ($result) + if ($result) { // Remove extrafields if ((empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used @@ -1020,13 +1021,13 @@ class Account extends CommonObject } } } - else + else { $error++; $this->error = "Error ".$this->db->lasterror(); - } + } } - + if (! $error) { $this->db->commit(); @@ -1433,7 +1434,7 @@ class Account extends CommonObject * - DeskCode * * Some countries show less or more bank account properties to the user - * + * * @param int $includeibanbic 1=Return also key for IBAN and BIC * @return array * @see useDetailedBBAN @@ -1554,7 +1555,7 @@ class AccountLine extends CommonObject var $element='bank'; var $table_element='bank'; var $picto = 'generic'; - + var $id; var $ref; var $datec; @@ -1842,7 +1843,7 @@ class AccountLine extends CommonObject function update_conciliation(User $user, $cat) { global $conf; - + $this->db->begin(); // Check statement field @@ -1854,7 +1855,7 @@ class AccountLine extends CommonObject return -1; } } - + $sql = "UPDATE ".MAIN_DB_PREFIX."bank SET"; $sql.= " rappro = 1"; $sql.= ", num_releve = '".$this->db->escape($this->num_releve)."'"; @@ -2042,7 +2043,7 @@ class AccountLine extends CommonObject return $result; } - + /** * Return label of status (activity, closed) * @@ -2053,7 +2054,7 @@ class AccountLine extends CommonObject { return $this->LibStatut($this->status,$mode); } - + /** * Renvoi le libelle d'un statut donne * @@ -2097,6 +2098,6 @@ class AccountLine extends CommonObject if ($statut==1) return $langs->trans("InActivity").' '.img_picto($langs->trans("InActivity"),'statut4', 'class="pictostatus"'); }*/ } - + } diff --git a/htdocs/compta/bank/transfer.php b/htdocs/compta/bank/transfer.php index 73e94a3d197..7c8d4a1826a 100644 --- a/htdocs/compta/bank/transfer.php +++ b/htdocs/compta/bank/transfer.php @@ -50,6 +50,7 @@ if ($action == 'add') $dateo = dol_mktime(12,0,0,GETPOST('remonth','int'),GETPOST('reday','int'),GETPOST('reyear','int')); $label = GETPOST('label','alpha'); $amount= GETPOST('amount'); + $amountto= GETPOST('amountto'); if (! $label) { @@ -71,6 +72,9 @@ if ($action == 'add') $error=1; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("TransferTo")), null, 'errors'); } + + + if (! $error) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; @@ -81,7 +85,18 @@ if ($action == 'add') $accountto=new Account($db); $accountto->fetch(GETPOST('account_to','int')); - if (($accountto->id != $accountfrom->id) && ($accountto->currency_code == $accountfrom->currency_code)) + if ($accountto->currency_code == $accountfrom->currency_code) { + $amountto=$amount; + } else { + if (! $amountto) + { + $error=1; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AmountTo")), null, 'errors'); + } + } + + + if (($accountto->id != $accountfrom->id) && empty($error)) { $db->begin(); @@ -102,7 +117,7 @@ if ($action == 'add') if (! $error) $bank_line_id_from = $accountfrom->addline($dateo, $typefrom, $label, -1*price2num($amount), '', '', $user); if (! ($bank_line_id_from > 0)) $error++; - if (! $error) $bank_line_id_to = $accountto->addline($dateo, $typeto, $label, price2num($amount), '', '', $user); + if (! $error) $bank_line_id_to = $accountto->addline($dateo, $typeto, $label, price2num($amountto), '', '', $user); if (! ($bank_line_id_to > 0)) $error++; if (! $error) $result=$accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.'/compta/bank/ligne.php?rowid=', '(banktransfert)', 'banktransfert'); @@ -137,6 +152,61 @@ if ($action == 'add') llxHeader(); + +print ' '; + + $form=new Form($db); $account_from=''; @@ -165,6 +235,7 @@ print ''; print ''; print ''; print ''; +print ''; print ''; $var=false; @@ -181,6 +252,7 @@ $form->select_date((! empty($dateo)?$dateo:''),'','','','','add'); print "\n"; print ''; print ''; +print ''; print "
'.$langs->trans("TransferFrom").''.$langs->trans("TransferTo").''.$langs->trans("Date").''.$langs->trans("Description").''.$langs->trans("Amount").'
"; diff --git a/htdocs/core/ajax/getaccountcurrency.php b/htdocs/core/ajax/getaccountcurrency.php new file mode 100644 index 00000000000..40e52672c0e --- /dev/null +++ b/htdocs/core/ajax/getaccountcurrency.php @@ -0,0 +1,60 @@ + + * + * 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/core/ajax/vatrates.php + * \brief File to load vat rates combobox + */ + +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); + +require '../../main.inc.php'; + +$id = GETPOST('id','int'); + +/* + * View + */ + +top_httphead(); + +//print ''."\n"; + +// Load original field value +if (! empty($id)) +{ + require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; + $account=new Account($db); + $result = $account->fetch($id); + if ($result<0) { + $return['value'] = ''; + $return['num'] = $result; + $return['error'] = $account->errors[0]; + } else { + $return['value'] = $account->currency_code; + $return['num'] = $result; + $return['error'] = ''; + } + + echo json_encode($return); +} + From 3825e7fd52870e39e94da7ca0899a4bdedf0e445 Mon Sep 17 00:00:00 2001 From: hguibourgdev Date: Sat, 15 Jul 2017 18:55:52 +0200 Subject: [PATCH 002/108] Update replenish.php FIX ">=" instead of ">" for alert test in order to work when negatif stock are allowed --- htdocs/product/stock/replenish.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index a3f4cb8ecaf..695cea9a9af 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -357,17 +357,17 @@ if ($usevirtualstock) if ($salert == 'on') // Option to see when stock is lower than alert { - $sql.= ' AND ('.$sqlalertstock.' > 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; + $sql.= ' AND ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.')))'; $alertchecked = 'checked'; } } else { - $sql.= ' HAVING (('.$sqldesiredtock.' > 0 AND ('.$sqldesiredtock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; - $sql.= ' OR ('.$sqlalertstock.' > 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").'))))'; + $sql.= ' HAVING (('.$sqldesiredtock.' >= 0 AND ('.$sqldesiredtock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql.= ' OR ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").'))))'; if ($salert == 'on') // Option to see when stock is lower than alert { - $sql.= ' AND ('.$sqlalertstock.' > 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql.= ' AND ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; $alertchecked = 'checked'; } } From 17da80832513e19d9efc40a4a7eec117aab45de4 Mon Sep 17 00:00:00 2001 From: Neil Orley Date: Fri, 8 Sep 2017 14:35:44 +0200 Subject: [PATCH 003/108] FIX wrong basePath in the swagger view Behind a reverse proxy the basePath seems to be in http. Forcing the basePath to DOL_MAIN_URL_ROOT fixes the problem. --- htdocs/api/class/api.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 40e00d01ffd..79793b0f8de 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -56,7 +56,7 @@ class DolibarrApi $this->db = $db; $production_mode = ( empty($conf->global->API_PRODUCTION_MODE) ? false : true ); $this->r = new Restler($production_mode, $refreshCache); - + $this->r->setBaseUrls(DOL_MAIN_URL_ROOT); $this->r->setAPIVersion(1); } From 681c2a67bd9c7d72554d976bc2d076a19410c4ca Mon Sep 17 00:00:00 2001 From: fappels Date: Mon, 11 Sep 2017 23:22:44 +0200 Subject: [PATCH 004/108] Fix batch required for lot product error message. --- htdocs/langs/en_US/errors.lang | 2 +- htdocs/product/stock/class/mouvementstock.class.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 8dfc02c49f1..47299634de3 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -156,7 +156,7 @@ ErrorPriceExpression22=Negative result '%s' ErrorPriceExpressionInternal=Internal error '%s' ErrorPriceExpressionUnknown=Unknown error '%s' ErrorSrcAndTargetWarehouseMustDiffers=Source and target warehouses must differs -ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without lot/serial information, on a product requiring lot/serial information +ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without lot/serial information, on product '%s' requiring lot/serial information ErrorCantSetReceptionToTotalDoneWithReceptionToApprove=All recorded receptions must first be verified (approved or denied) before being allowed to do this action ErrorCantSetReceptionToTotalDoneWithReceptionDenied=All recorded receptions must first be verified (approved) before being allowed to do this action ErrorGlobalVariableUpdater0=HTTP request failed with error '%s' diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 3e3eb4c28a7..25e0e9e7fce 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -96,6 +96,7 @@ class MouvementStock extends CommonObject require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; + $langs->load("errors"); $error = 0; dol_syslog(get_class($this)."::_create start userid=$user->id, fk_product=$fk_product, warehouse_id=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=".$datem.", eatby=".$eatby.", sellby=".$sellby.", batch=".$batch.", skip_batch=".$skip_batch); @@ -141,7 +142,7 @@ class MouvementStock extends CommonObject { if (empty($batch)) { - $this->errors[]=$langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $product->name); + $this->errors[]=$langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $product->ref); dol_syslog("Try to make a movement of a product with status_batch on without any batch data"); $this->db->rollback(); From f68d31d7c591da55f231e16ebdc65d171ea39572 Mon Sep 17 00:00:00 2001 From: Neil Orley Date: Tue, 12 Sep 2017 17:45:02 +0200 Subject: [PATCH 005/108] Add of $urlwithroot in the setBaseUrls function, to use Dolibarr external domain name in the configuration file --- htdocs/api/class/api.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 79793b0f8de..36eb7c1d7d2 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -56,7 +56,7 @@ class DolibarrApi $this->db = $db; $production_mode = ( empty($conf->global->API_PRODUCTION_MODE) ? false : true ); $this->r = new Restler($production_mode, $refreshCache); - $this->r->setBaseUrls(DOL_MAIN_URL_ROOT); + $this->r->setBaseUrls(DOL_MAIN_URL_ROOT, $urlwithroot); $this->r->setAPIVersion(1); } From 7f57f737b3fc194123e665b2d0bff7f227862d3d Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Fri, 15 Sep 2017 18:02:52 +0200 Subject: [PATCH 006/108] New: Ping ldap server before ldap_connect for avoid waiting --- htdocs/adherents/ldap.php | 8 +++--- htdocs/contact/ldap.php | 10 +++---- htdocs/core/class/ldap.class.php | 46 ++++++++++++++++++++++++-------- htdocs/user/group/ldap.php | 4 +-- htdocs/user/ldap.php | 4 +-- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/htdocs/adherents/ldap.php b/htdocs/adherents/ldap.php index 38e90663c0f..65aea951d76 100644 --- a/htdocs/adherents/ldap.php +++ b/htdocs/adherents/ldap.php @@ -1,6 +1,6 @@ - * Copyright (C) 2006 Regis Houssin +/* Copyright (C) 2006 Laurent Destailleur + * Copyright (C) 2006-2017 Regis Houssin * * 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 @@ -218,13 +218,11 @@ if ($result > 0) } else { - dol_print_error('',$ldap->error); + setEventMessages($ldap->error, $ldap->errors, 'errors'); } print ''; - llxFooter(); - $db->close(); diff --git a/htdocs/contact/ldap.php b/htdocs/contact/ldap.php index 16c00bf92cb..759831f7d57 100644 --- a/htdocs/contact/ldap.php +++ b/htdocs/contact/ldap.php @@ -1,6 +1,6 @@ - * Copyright (C) 2006-2012 Regis Houssin + * Copyright (C) 2006-2017 Regis Houssin * * 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 @@ -91,7 +91,7 @@ $head = contact_prepare_head($object); dol_fiche_head($head, 'ldap', $title, -1, 'contact'); dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', ''); - + print '
'; print '
'; @@ -196,15 +196,11 @@ if ($result > 0) } else { - dol_print_error('',$ldap->error); + setEventMessages($ldap->error, $ldap->errors, 'errors'); } print ''; - - - llxFooter(); - $db->close(); diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 7c6fc0c5a77..166fe466796 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -123,7 +123,7 @@ class Ldap $this->filter = $conf->global->LDAP_FILTER_CONNECTION; // Filter on user $this->filtermember = $conf->global->LDAP_MEMBER_FILTER; // Filter on member - + // Users $this->attr_login = $conf->global->LDAP_FIELD_LOGIN; //unix $this->attr_sambalogin = $conf->global->LDAP_FIELD_LOGIN_SAMBA; //samba, activedirectory @@ -176,34 +176,40 @@ class Ldap { if ($connected) break; if (empty($host)) continue; - + if (preg_match('/^ldap/',$host)) { - $this->connection = ldap_connect($host); + if ($this->serverPing($host) === true) { + $this->connection = ldap_connect($host); + } + else continue; } else { - $this->connection = ldap_connect($host,$this->serverPort); + if ($this->serverPing($host, $this->serverPort) === true) { + $this->connection = ldap_connect($host,$this->serverPort); + } + else continue; } - + if (is_resource($this->connection)) { // Begin TLS if requested by the configuration - if (! empty($conf->global->LDAP_SERVER_USE_TLS)) + if (! empty($conf->global->LDAP_SERVER_USE_TLS)) { - if (! ldap_start_tls($this->connection)) + if (! ldap_start_tls($this->connection)) { dol_syslog(get_class($this)."::connect_bind failed to start tls", LOG_WARNING); $connected = 0; $this->close(); } } - + // Execute the ldap_set_option here (after connect and before bind) $this->setVersion(); ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0); // no limit here. should return true. - - + + if ($this->serverType == "activedirectory") { $result=$this->setReferrals(); @@ -256,7 +262,7 @@ class Ldap } } } - + if (! $connected) $this->close(); } } @@ -662,6 +668,24 @@ class Ldap } } + /** + * Ping a server before ldap_connect for avoid waiting + * + * @param string $host Server host or address + * @param int $port Server port (default 389) + * @param int $timeout Timeout in second (default 1s) + * @return boolean true or false + */ + function serverPing($host, $port=389, $timeout=1) + { + $op = @fsockopen($host, $port, $errno, $errstr, $timeout); + if (!$op) return false; //DC is N/A + else { + fclose($opanak); //explicitly close open socket connection + return true; //DC is up & running, we can safely connect with ldap_connect + } + } + // Attribute methods ----------------------------------------------------- diff --git a/htdocs/user/group/ldap.php b/htdocs/user/group/ldap.php index c195136863e..b7b1597ea74 100644 --- a/htdocs/user/group/ldap.php +++ b/htdocs/user/group/ldap.php @@ -206,12 +206,10 @@ if ($result > 0) } else { - dol_print_error('',$ldap->error); + setEventMessages($ldap->error, $ldap->errors, 'errors'); } print ''; llxFooter(); - $db->close(); - diff --git a/htdocs/user/ldap.php b/htdocs/user/ldap.php index 49739fa7c77..001915a8004 100644 --- a/htdocs/user/ldap.php +++ b/htdocs/user/ldap.php @@ -1,6 +1,6 @@ - * Copyright (C) 2006-2015 Regis Houssin + * Copyright (C) 2006-2017 Regis Houssin * * 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 @@ -214,7 +214,7 @@ if ($result > 0) } else { - dol_print_error('',$ldap->error); + setEventMessages($ldap->error, $ldap->errors, 'errors'); } print ''; From 767240698f0d018202d613b24bfaa0e6c7538d87 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Fri, 15 Sep 2017 18:31:22 +0200 Subject: [PATCH 007/108] Fix: wrong var name --- htdocs/core/class/ldap.class.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 166fe466796..e06d472f326 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1,7 +1,7 @@ * Copyright (C) 2004 Benoit Mortier - * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2006-2015 Laurent Destailleur * * This program is free software; you can redistribute it and/or modify @@ -681,7 +681,7 @@ class Ldap $op = @fsockopen($host, $port, $errno, $errstr, $timeout); if (!$op) return false; //DC is N/A else { - fclose($opanak); //explicitly close open socket connection + fclose($op); //explicitly close open socket connection return true; //DC is up & running, we can safely connect with ldap_connect } } @@ -1435,5 +1435,3 @@ class Ldap return 0; } } - - From 9653280be950b8acdace160016534daf10dfa344 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 16 Sep 2017 10:54:20 +0200 Subject: [PATCH 008/108] New: big refactorization and uniformize code --- htdocs/adherents/card.php | 18 +- .../adherents/class/adherent_type.class.php | 386 ++++++++++++------ .../class/api_memberstypes.class.php | 1 - htdocs/adherents/index.php | 8 +- htdocs/adherents/list.php | 4 +- htdocs/adherents/type.php | 159 +++++--- htdocs/langs/en_US/members.lang | 5 + 7 files changed, 378 insertions(+), 203 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index bb67ec46468..aec9b6e4b92 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -2,7 +2,7 @@ /* Copyright (C) 2001-2004 Rodolphe Quiedeville * Copyright (C) 2002-2003 Jean-Louis Bergamo * Copyright (C) 2004-2012 Laurent Destailleur - * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2012 Marcos García * Copyright (C) 2012-2016 Philippe Grand * Copyright (C) 2015-2016 Alexandre Spangaro @@ -121,7 +121,16 @@ $hookmanager->initHooks(array('membercard','globalcard')); * Actions */ -if ($cancel) $action=''; +if ($cancel) { + + $action=''; + + if (! empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } +} $parameters=array('id'=>$id, 'rowid'=>$id, 'objcanvas'=>$objcanvas); $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks @@ -813,6 +822,7 @@ else print '
'; print ''; print ''; + if ($backtopage) print ''; dol_fiche_head(''); @@ -957,7 +967,7 @@ else print '
'; print ''; print '     '; - print ''; + print ''; print '
'; print "
\n"; @@ -1225,7 +1235,7 @@ else print '
'; print ''; print '     '; - print ''; + print ''; print '
'; print ''; diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index eec88a59c11..82753d08590 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2002 Rodolphe Quiedeville * Copyright (C) 2004-2008 Laurent Destailleur * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2016 Charlie Benke @@ -22,7 +22,6 @@ * \file htdocs/adherents/class/adherent_type.class.php * \ingroup member * \brief File of class to manage members types - * \author Rodolphe Quiedeville */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; @@ -64,140 +63,192 @@ class AdherentType extends CommonObject public $mail_valid; - /** + /** * Constructor * * @param DoliDB $db Database handler - */ - function __construct($db) - { - $this->db = $db; - $this->statut = 1; - } + */ + function __construct($db) + { + $this->db = $db; + $this->statut = 1; + } - /** - * Fonction qui permet de creer le status de l'adherent - * - * @param User $user User making creation - * @return int >0 if OK, < 0 if KO - */ - function create($user) - { - global $conf; + /** + * Fonction qui permet de creer le status de l'adherent + * + * @param User $user User making creation + * @param int $notrigger 1=do not execute triggers, 0 otherwise + * @return int >0 if OK, < 0 if KO + */ + function create($user,$notrigger=0) + { + global $conf; - $this->statut=(int) $this->statut; - $this->label=(!empty($this->libelle)?trim($this->libelle):trim($this->label)); + $error=0; - $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent_type ("; - $sql.= "libelle"; - $sql.= ", entity"; - $sql.= ") VALUES ("; - $sql.= "'".$this->db->escape($this->label)."'"; - $sql.= ", ".$conf->entity; - $sql.= ")"; + $this->statut=(int) $this->statut; + $this->label=trim($this->label); - dol_syslog("Adherent_type::create", LOG_DEBUG); - $result = $this->db->query($sql); - if ($result) - { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent_type"); - return $this->update($user); - } - else - { - $this->error=$this->db->error().' sql='.$sql; - return -1; - } - } + $this->db->begin(); + $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent_type ("; + $sql.= "libelle"; + $sql.= ", entity"; + $sql.= ") VALUES ("; + $sql.= "'".$this->db->escape($this->label)."'"; + $sql.= ", ".$conf->entity; + $sql.= ")"; - /** - * Met a jour en base donnees du type - * - * @param User $user Object user making change - * @return int >0 if OK, < 0 if KO - */ - function update($user) - { - global $hookmanager,$conf; + dol_syslog("Adherent_type::create", LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent_type"); - $error=0; + $result = $this->update($user,1); + if ($result < 0) + { + $this->db->rollback(); + return -3; + } - $this->label=(!empty($this->libelle)?trim($this->libelle):trim($this->label)); + if (! $notrigger) + { + // Call trigger + $result=$this->call_trigger('MEMBER_TYPE_CREATE',$user); + if ($result < 0) { $error++; } + // End call triggers + } - $sql = "UPDATE ".MAIN_DB_PREFIX."adherent_type "; - $sql.= "SET "; - $sql.= "statut = ".$this->statut.","; - $sql.= "libelle = '".$this->db->escape($this->label) ."',"; - $sql.= "subscription = '".$this->db->escape($this->subscription)."',"; - $sql.= "note = '".$this->db->escape($this->note)."',"; - $sql.= "vote = '".$this->db->escape($this->vote)."',"; - $sql.= "mail_valid = '".$this->db->escape($this->mail_valid)."'"; - $sql.= " WHERE rowid =".$this->id; + if (! $error) + { + $this->db->commit(); + return $this->id; + } + else + { + dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR); + $this->db->rollback(); + return -2; + } + } + else + { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } - $result = $this->db->query($sql); - if ($result) - { - $action='update'; + /** + * Met a jour en base donnees du type + * + * @param User $user Object user making change + * @param int $notrigger 1=do not execute triggers, 0 otherwise + * @return int >0 if OK, < 0 if KO + */ + function update($user,$notrigger=0) + { + global $conf, $hookmanager; - // Actions on extra fields (by external module or standard code) - $hookmanager->initHooks(array('membertypedao')); - $parameters=array('membertype'=>$this->id); - $reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks - if (empty($reshook)) - { - if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used - { - $result=$this->insertExtraFields(); - if ($result < 0) - { - $error++; - } - } - } - else if ($reshook < 0) $error++; + $error=0; + $this->label=trim($this->label); - return 1; - } - else - { - $this->error=$this->db->error().' sql='.$sql; - return -1; - } - } + $this->db->begin(); - /** - * Fonction qui permet de supprimer le status de l'adherent - * - * @param int $rowid Id of member type to delete - * @return int >0 if OK, 0 if not found, < 0 if KO - */ - function delete($rowid='') - { - if (empty($rowid)) $rowid=$this->id; + $sql = "UPDATE ".MAIN_DB_PREFIX."adherent_type "; + $sql.= "SET "; + $sql.= "statut = ".$this->statut.","; + $sql.= "libelle = '".$this->db->escape($this->label) ."',"; + $sql.= "subscription = '".$this->db->escape($this->subscription)."',"; + $sql.= "note = '".$this->db->escape($this->note)."',"; + $sql.= "vote = '".$this->db->escape($this->vote)."',"; + $sql.= "mail_valid = '".$this->db->escape($this->mail_valid)."'"; + $sql.= " WHERE rowid =".$this->id; - $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent_type WHERE rowid = ".$rowid; + $result = $this->db->query($sql); + if ($result) + { + $action='update'; - $resql=$this->db->query($sql); - if ($resql) - { - if ($this->db->affected_rows($resql)) - { - return 1; - } - else - { - return 0; - } - } - else - { - print "Err : ".$this->db->error(); - return 0; - } - } + // Actions on extra fields (by external module or standard code) + $hookmanager->initHooks(array('membertypedao')); + $parameters=array('membertype'=>$this->id); + $reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + if (empty($reshook)) + { + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used + { + $result=$this->insertExtraFields(); + if ($result < 0) + { + $error++; + } + } + } + else if ($reshook < 0) $error++; + + if (! $error && ! $notrigger) + { + // Call trigger + $result=$this->call_trigger('MEMBER_TYPE_MODIFY',$user); + if ($result < 0) { $error++; } + // End call triggers + } + + if (! $error) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR); + return -$error; + } + } + else + { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } + + /** + * Fonction qui permet de supprimer le status de l'adherent + * + * @return int >0 if OK, 0 if not found, < 0 if KO + */ + function delete() + { + global $user; + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent_type"; + $sql.= " WHERE rowid = ".$this->id; + + $resql=$this->db->query($sql); + if ($resql) + { + // Call trigger + $result=$this->call_trigger('MEMBER_TYPE_DELETE',$user); + if ($result < 0) { $error++; $this->db->rollback(); return -2; } + // End call triggers + + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + $this->error=$this->db->lasterror(); + return -1; + } + } /** * Fonction qui permet de recuperer le status de l'adherent @@ -223,7 +274,6 @@ class AdherentType extends CommonObject $this->id = $obj->rowid; $this->ref = $obj->rowid; $this->label = $obj->label; - $this->libelle = $obj->label; // For backward compatibility $this->statut = $obj->statut; $this->subscription = $obj->subscription; $this->mail_valid = $obj->mail_valid; @@ -250,7 +300,7 @@ class AdherentType extends CommonObject $adherenttypes = array(); - $sql = "SELECT rowid, libelle"; + $sql = "SELECT rowid, libelle as label"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type"; $sql.= " WHERE entity IN (".getEntity('adherent').")"; @@ -266,7 +316,7 @@ class AdherentType extends CommonObject { $obj = $this->db->fetch_object($resql); - $adherenttypes[$obj->rowid] = $langs->trans($obj->libelle); + $adherenttypes[$obj->rowid] = $langs->trans($obj->label); $i++; } } @@ -278,12 +328,11 @@ class AdherentType extends CommonObject return $adherenttypes; } - /** * Return clicable name (with picto eventually) * * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto - * @param int $maxlen length max libelle + * @param int $maxlen length max label * @return string String with URL */ function getNomUrl($withpicto=0,$maxlen=0) @@ -291,7 +340,7 @@ class AdherentType extends CommonObject global $langs; $result=''; - $label=$langs->trans("ShowTypeCard",$this->libelle); + $label=$langs->trans("ShowTypeCard",$this->label); $link = ''; $linkend=''; @@ -300,20 +349,101 @@ class AdherentType extends CommonObject if ($withpicto) $result.=($link.img_object($label, $picto, 'class="classfortooltip"').$linkend); if ($withpicto && $withpicto != 2) $result.=' '; - $result.=$link.($maxlen?dol_trunc($this->libelle,$maxlen):$this->libelle).$linkend; + $result.=$link.($maxlen?dol_trunc($this->label,$maxlen):$this->label).$linkend; return $result; } - /** * getLibStatut * * @return string Return status of a type of member */ - function getLibStatut() - { - return ''; - } + function getLibStatut() + { + return ''; + } + + /** + * Retourne chaine DN complete dans l'annuaire LDAP pour l'objet + * + * @param array $info Info array loaded by _load_ldap_info + * @param int $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb) + * 1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb) + * 2=Return key only (uid=qqq) + * @return string DN + */ + function _load_ldap_dn($info,$mode=0) + { + global $conf; + $dn=''; + if ($mode==0) $dn=$conf->global->LDAP_KEY_MEMBERS_TYPES."=".$info[$conf->global->LDAP_KEY_MEMBERS_TYPES].",".$conf->global->LDAP_MEMBER_TYPE_DN; + if ($mode==1) $dn=$conf->global->LDAP_MEMBER_TYPE_DN; + if ($mode==2) $dn=$conf->global->LDAP_KEY_MEMBERS_TYPES."=".$info[$conf->global->LDAP_KEY_MEMBERS_TYPES]; + return $dn; + } + + + /** + * Initialize the info array (array of LDAP values) that will be used to call LDAP functions + * + * @return array Tableau info des attributs + */ + function _load_ldap_info() + { + global $conf,$langs; + + $info=array(); + + // Object classes + $info["objectclass"]=explode(',',$conf->global->LDAP_MEMBER_TYPE_OBJECT_CLASS); + + // Champs + if ($this->label && ! empty($conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME)) $info[$conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME] = $this->label; + if ($this->note && ! empty($conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION)) $info[$conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION] = $this->note; + if (! empty($conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS)) + { + $valueofldapfield=array(); + foreach($this->members as $key=>$val) // This is array of users for group into dolibarr database. + { + $member=new Adherent($this->db); + $member->fetch($val->id); + $info2 = $member->_load_ldap_info(); + $valueofldapfield[] = $member->_load_ldap_dn($info2); + } + $info[$conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS] = (!empty($valueofldapfield)?$valueofldapfield:''); + } + return $info; + } + + /** + * Initialise an instance with random values. + * Used to build previews or test instances. + * id must be 0 if object instance is a specimen. + * + * @return void + */ + function initAsSpecimen() + { + global $conf, $user, $langs; + + // Initialise parametres + $this->id = 0; + $this->ref = 0; + $this->specimen=1; + + $this->label='MEMBERS TYPE SPECIMEN'; + $this->note='This is a note'; + $this->mail_valid='This is welcome email'; + $this->subscription=1; + $this->vote=0; + + $this->statut=1; + + // Members of this member type is just me + $this->members=array( + $user->id => $user + ); + } /** * getMailOnValid diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index ff8064d80fb..c6adaf50142 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -272,7 +272,6 @@ class MembersTypes extends DolibarrApi $object = parent::_cleanObjectDatas($object); unset($object->cotisation); - unset($object->libelle); unset($object->array_options); unset($object->linkedObjectsIds); diff --git a/htdocs/adherents/index.php b/htdocs/adherents/index.php index 2614a27d509..54779432a3b 100644 --- a/htdocs/adherents/index.php +++ b/htdocs/adherents/index.php @@ -59,7 +59,7 @@ $AdherentsResilies=array(); $AdherentType=array(); // Liste les adherents -$sql = "SELECT t.rowid, t.libelle, t.subscription,"; +$sql = "SELECT t.rowid, t.libelle as label, t.subscription,"; $sql.= " d.statut, count(d.rowid) as somme"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."adherent as d"; @@ -81,7 +81,7 @@ if ($result) $adhtype=new AdherentType($db); $adhtype->id=$objp->rowid; $adhtype->subscription=$objp->subscription; - $adhtype->libelle=$objp->libelle; + $adhtype->label=$objp->label; $AdherentType[$objp->rowid]=$adhtype; if ($objp->statut == -1) { $MemberToValidate[$objp->rowid]=$objp->somme; } @@ -273,7 +273,7 @@ $max=5; $sql = "SELECT a.rowid, a.statut, a.lastname, a.firstname, a.societe as company, a.fk_soc,"; $sql.= " a.tms as datem, datefin as date_end_subscription,"; -$sql.= " ta.rowid as typeid, ta.libelle, ta.subscription"; +$sql.= " ta.rowid as typeid, ta.libelle as label, ta.subscription"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a, ".MAIN_DB_PREFIX."adherent_type as ta"; $sql.= " WHERE a.entity IN (".getEntity('adherent').")"; $sql.= " AND a.fk_adherent_type = ta.rowid"; @@ -310,7 +310,7 @@ if ($resql) } $staticmember->ref=$staticmember->getFullName($langs); $statictype->id=$obj->typeid; - $statictype->libelle=$obj->libelle; + $statictype->label=$obj->label; print ''.$staticmember->getNomUrl(1,32).''; print ''.$statictype->getNomUrl(1,32).''; print ''.dol_print_date($db->jdate($obj->datem),'dayhour').''; diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 3dc5439f47f..783934deb34 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -315,7 +315,7 @@ if ($search_type > 0) { $membertype=new AdherentType($db); $result=$membertype->fetch(GETPOST("type",'int')); - $titre.=" (".$membertype->libelle.")"; + $titre.=" (".$membertype->label.")"; } $param=''; @@ -698,7 +698,7 @@ while ($i < min($num, $limit)) if (! empty($arrayfields['t.libelle']['checked'])) { $membertypestatic->id=$obj->type_id; - $membertypestatic->libelle=$obj->type; + $membertypestatic->label=$obj->type; print ''; print $membertypestatic->getNomUrl(1,32); print ''; diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index a0f36c409de..3d4fb786295 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2001-2002 Rodolphe Quiedeville * Copyright (C) 2003 Jean-Louis Bergamo * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2017 Regis Houssin @@ -37,6 +37,7 @@ $langs->load("members"); $rowid = GETPOST('rowid','int'); $action = GETPOST('action','alpha'); $cancel = GETPOST('cancel','alpha'); +$backtopage = GETPOST('backtopage','alpha'); $search_lastname = GETPOST('search_lastname','alpha'); $search_login = GETPOST('search_login','alpha'); @@ -64,6 +65,8 @@ $mail_valid=GETPOST("mail_valid"); // Security check $result=restrictedArea($user,'adherent',$rowid,'adherent_type'); +$object = new AdherentType($db); + $extrafields = new ExtraFields($db); // fetch optionals attributes and labels @@ -87,73 +90,95 @@ $hookmanager->initHooks(array('membertypecard','globalcard')); * Actions */ +if ($cancel) { + + $action=''; + + if (! empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } +} + if ($action == 'add' && $user->rights->adherent->configurer) { - if (! $cancel) + $object->label = trim($label); + $object->subscription = (int) trim($subscription); + $object->note = trim($comment); + $object->mail_valid = trim($mail_valid); + $object->vote = (boolean) trim($vote); + + // Fill array 'array_options' with data from add form + $ret = $extrafields->setOptionalsFromPost($extralabels,$object); + if ($ret < 0) $error++; + + if ($object->label) { - $object = new AdherentType($db); - - $object->label = trim($label); - $object->subscription = (int) trim($subscription); - $object->note = trim($comment); - $object->mail_valid = (boolean) trim($mail_valid); - $object->vote = (boolean) trim($vote); - - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost($extralabels,$object); - if ($ret < 0) $error++; - - if ($object->label) + $id=$object->create($user); + if ($id > 0) { - $id=$object->create($user); - if ($id > 0) - { - header("Location: ".$_SERVER["PHP_SELF"]); - exit; - } - else - { - $mesg=$object->error; - $action = 'create'; - } + header("Location: ".$_SERVER["PHP_SELF"]); + exit; } else { - $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")); + $mesg=$object->error; $action = 'create'; } } + else + { + $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")); + $action = 'create'; + } } if ($action == 'update' && $user->rights->adherent->configurer) { - if (! $cancel) + $object->fetch($rowid); + + $object->label = trim($label); + $object->subscription = (int) trim($subscription); + $object->note = trim($comment); + $object->mail_valid = trim($mail_valid); + $object->vote = (boolean) trim($vote); + + // Fill array 'array_options' with data from add form + $ret = $extrafields->setOptionalsFromPost($extralabels,$object); + if ($ret < 0) $error++; + + $ret=$object->update($user); + + if ($ret >= 0 && ! count($object->errors)) { - $object = new AdherentType($db); - $object->id = $rowid; - $object->label = trim($label); - $object->subscription = (int) trim($subscription); - $object->note = trim($comment); - $object->mail_valid = (boolean) trim($mail_valid); - $object->vote = (boolean) trim($vote); - - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost($extralabels,$object); - if ($ret < 0) $error++; - - $object->update($user); - - header("Location: ".$_SERVER["PHP_SELF"]."?rowid=".$_POST["rowid"]); - exit; + setEventMessages($langs->trans("MemberTypeModified"), null, 'mesgs'); } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } + + header("Location: ".$_SERVER["PHP_SELF"]."?rowid=".$object->id); + exit; } -if ($action == 'delete' && $user->rights->adherent->configurer) +if ($action == 'confirm_delete' && $user->rights->adherent->configurer) { - $object = new AdherentType($db); - $object->delete($rowid); - header("Location: ".$_SERVER["PHP_SELF"]); - exit; + $object->fetch($rowid); + $res=$object->delete(); + + if ($res > 0) + { + setEventMessages($langs->trans("MemberTypeDeleted"), null, 'mesgs'); + header("Location: ".$_SERVER["PHP_SELF"]); + exit; + } + else + { + setEventMessages($langs->trans("MemberTypeCanNotBeDeleted"), null, 'errors'); + $action=''; + } } @@ -308,7 +333,15 @@ if ($rowid > 0) { $object = new AdherentType($db); $object->fetch($rowid); - $object->fetch_optionals($rowid,$extralabels); + $object->fetch_optionals($object->id,$extralabels); + + /* + * Confirmation suppression + */ + if ($action == 'delete') + { + print $form->formconfirm($_SERVER['PHP_SELF']."?rowid=".$object->id,$langs->trans("DeleteAMemberType"),$langs->trans("ConfirmDeleteMemberType",$object->label),"confirm_delete", '',0,1); + } $head = member_type_prepare_head($object); @@ -337,15 +370,14 @@ if ($rowid > 0) print ''.$langs->trans("WelcomeEMail").''; print nl2br($object->mail_valid).""; - // Other attributes - include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; print ''; - print '
'; + print ''; dol_fiche_end(); - /* * Buttons */ @@ -359,7 +391,7 @@ if ($rowid > 0) } // Add - print ''; + print ''; // Delete if ($user->rights->adherent->configurer) @@ -459,7 +491,7 @@ if ($rowid > 0) $titre.=" (".$membertype->label.")"; } - $param="&rowid=".$rowid; + $param="&rowid=".$object->id; if (! empty($status)) $param.="&status=".$status; if (! empty($search_lastname)) $param.="&search_lastname=".$search_lastname; if (! empty($search_firstname)) $param.="&search_firstname=".$search_firstname; @@ -473,7 +505,7 @@ if ($rowid > 0) } print '
'; - print ''; + print ''; print '
'; print_barre_liste('',$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecords); @@ -593,12 +625,12 @@ if ($rowid > 0) print ''; if ($user->rights->adherent->creer) { - print ''.img_edit().''; + print ''.img_edit().''; } print ' '; if ($user->rights->adherent->supprimer) { - print ''.img_picto($langs->trans("Resiliate"),'disable.png').''; + print ''.img_picto($langs->trans("Resiliate"),'disable.png').''; } print ""; @@ -631,15 +663,14 @@ if ($rowid > 0) if ($action == 'edit') { $object = new AdherentType($db); - $object->id = $rowid; $object->fetch($rowid); - $object->fetch_optionals($rowid,$extralabels); + $object->fetch_optionals($object->id,$extralabels); $head = member_type_prepare_head($object); - print ''; + print ''; print ''; - print ''; + print ''; print ''; dol_fiche_head($head, 'card', $langs->trans("MemberType"), 0, 'group'); @@ -706,7 +737,7 @@ if ($rowid > 0) print '
'; print ''; print '     '; - print ''; + print ''; print '
'; print "
"; diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index 5e7ad30ec3f..dc25d792517 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -57,6 +57,11 @@ NewCotisation=New contribution PaymentSubscription=New contribution payment SubscriptionEndDate=Subscription's end date MembersTypeSetup=Members type setup +MemberTypeModified=Member type modified +DeleteAMemberType=Delete a member type +ConfirmDeleteMemberType=Are you sure you want to delete this member type? +MemberTypeDeleted=Member type deleted +MemberTypeCanNotBeDeleted=Member type can not be deleted NewSubscription=New subscription NewSubscriptionDesc=This form allows you to record your subscription as a new member of the foundation. If you want to renew your subscription (if already a member), please contact foundation board instead by email %s. Subscription=Subscription From 279988bd60a035a1fcca20a17161dd1b1ee16f1e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Sep 2017 12:45:54 +0200 Subject: [PATCH 009/108] Remove warning --- htdocs/core/modules/modFournisseur.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 017ffd1d121..39ebd275c67 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -272,12 +272,12 @@ class modFournisseur extends DolibarrModules $this->rights[$r][5] = 'approve2'; } - + // Menus //------- $this->menu = 1; // This module add menu entries. They are coded into menu manager. - - + + // Exports //-------- $r=0; @@ -435,7 +435,7 @@ class modFournisseur extends DolibarrModules // End add extra fields object $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'societe as s'; - if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid'; + if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe_commerciaux as sc ON sc.fk_soc = s.rowid'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'facture_fourn as f'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'projet as project on (f.fk_projet = project.rowid)'; @@ -444,7 +444,7 @@ class modFournisseur extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn as p ON pf.fk_paiementfourn = p.rowid'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid'; $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('supplier_invoice',1).')'; - if(!$user->rights->societe->client->voir) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id; + if (empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .=' AND sc.fk_user = '.$user->id; // Order $r++; From f584212700339675d8b17e233ea9caf790c35ef3 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 16 Sep 2017 16:06:34 +0200 Subject: [PATCH 010/108] Fix: use >0 instead !isnull --- htdocs/adherents/class/adherent.class.php | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 85665280275..a1b61358820 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -447,33 +447,33 @@ class Adherent extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET"; - $sql.= " civility = ".(!is_null($this->civility_id)?$this->db->escape($this->civility_id):"null"); + $sql.= " civility = ".($this->civility_id>0?$this->db->escape($this->civility_id):"null"); $sql.= ", firstname = ".($this->firstname?"'".$this->db->escape($this->firstname)."'":"null"); - $sql.= ", lastname=" .($this->lastname?"'".$this->db->escape($this->lastname)."'":"null"); - $sql.= ", login=" .($this->login?"'".$this->db->escape($this->login)."'":"null"); - $sql.= ", societe=" .($this->societe?"'".$this->db->escape($this->societe)."'":"null"); - $sql.= ", fk_soc=" .($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null"); - $sql.= ", address=" .($this->address?"'".$this->db->escape($this->address)."'":"null"); - $sql.= ", zip=" .($this->zip?"'".$this->db->escape($this->zip)."'":"null"); - $sql.= ", town=" .($this->town?"'".$this->db->escape($this->town)."'":"null"); - $sql.= ", country=".($this->country_id>0?$this->db->escape($this->country_id):"null"); - $sql.= ", state_id=".($this->state_id>0?$this->db->escape($this->state_id):"null"); - $sql.= ", email='".$this->db->escape($this->email)."'"; - $sql.= ", skype='".$this->db->escape($this->skype)."'"; - $sql.= ", phone=" .($this->phone?"'".$this->db->escape($this->phone)."'":"null"); - $sql.= ", phone_perso=" .($this->phone_perso?"'".$this->db->escape($this->phone_perso)."'":"null"); - $sql.= ", phone_mobile=" .($this->phone_mobile?"'".$this->db->escape($this->phone_mobile)."'":"null"); - $sql.= ", note_private=" .($this->note_private?"'".$this->db->escape($this->note_private)."'":"null"); - $sql.= ", note_public=" .($this->note_public?"'".$this->db->escape($this->note_public)."'":"null"); - $sql.= ", photo=" .($this->photo?"'".$this->db->escape($this->photo)."'":"null"); - $sql.= ", public='".$this->db->escape($this->public)."'"; - $sql.= ", statut=" .$this->statut; - $sql.= ", fk_adherent_type=".$this->typeid; - $sql.= ", morphy='".$this->db->escape($this->morphy)."'"; - $sql.= ", birth=" .($this->birth?"'".$this->db->idate($this->birth)."'":"null"); - if ($this->datefin) $sql.= ", datefin='".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription - if ($this->datevalid) $sql.= ", datevalid='".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member - $sql.= ", fk_user_mod=".($user->id>0?$user->id:'null'); // Can be null because member can be create by a guest + $sql.= ", lastname = ".($this->lastname?"'".$this->db->escape($this->lastname)."'":"null"); + $sql.= ", login = ".($this->login?"'".$this->db->escape($this->login)."'":"null"); + $sql.= ", societe = ".($this->societe?"'".$this->db->escape($this->societe)."'":"null"); + $sql.= ", fk_soc = ".($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null"); + $sql.= ", address = ".($this->address?"'".$this->db->escape($this->address)."'":"null"); + $sql.= ", zip = ".($this->zip?"'".$this->db->escape($this->zip)."'":"null"); + $sql.= ", town = ".($this->town?"'".$this->db->escape($this->town)."'":"null"); + $sql.= ", country = ".($this->country_id>0?$this->db->escape($this->country_id):"null"); + $sql.= ", state_id = ".($this->state_id>0?$this->db->escape($this->state_id):"null"); + $sql.= ", email = '".$this->db->escape($this->email)."'"; + $sql.= ", skype = '".$this->db->escape($this->skype)."'"; + $sql.= ", phone = ".($this->phone?"'".$this->db->escape($this->phone)."'":"null"); + $sql.= ", phone_perso = ".($this->phone_perso?"'".$this->db->escape($this->phone_perso)."'":"null"); + $sql.= ", phone_mobile = ".($this->phone_mobile?"'".$this->db->escape($this->phone_mobile)."'":"null"); + $sql.= ", note_private = ".($this->note_private?"'".$this->db->escape($this->note_private)."'":"null"); + $sql.= ", note_public = ".($this->note_public?"'".$this->db->escape($this->note_public)."'":"null"); + $sql.= ", photo = ".($this->photo?"'".$this->db->escape($this->photo)."'":"null"); + $sql.= ", public = '".$this->db->escape($this->public)."'"; + $sql.= ", statut = ".$this->statut; + $sql.= ", fk_adherent_type = ".$this->typeid; + $sql.= ", morphy = '".$this->db->escape($this->morphy)."'"; + $sql.= ", birth = ".($this->birth?"'".$this->db->idate($this->birth)."'":"null"); + if ($this->datefin) $sql.= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription + if ($this->datevalid) $sql.= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member + $sql.= ", fk_user_mod = ".($user->id>0?$user->id:'null'); // Can be null because member can be create by a guest $sql.= " WHERE rowid = ".$this->id; dol_syslog(get_class($this)."::update update member", LOG_DEBUG); From 4ab1f68102df45a099d10c8c4bd8212c4f715705 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 16 Sep 2017 17:12:51 +0200 Subject: [PATCH 011/108] Fix: check connectivity for avoid ldap errors --- htdocs/core/class/ldap.class.php | 18 +- ...interface_50_modLdap_Ldapsynchro.class.php | 928 +++++++++--------- 2 files changed, 471 insertions(+), 475 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index e06d472f326..58eedc0ad9d 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -195,15 +195,15 @@ class Ldap if (is_resource($this->connection)) { // Begin TLS if requested by the configuration - if (! empty($conf->global->LDAP_SERVER_USE_TLS)) - { - if (! ldap_start_tls($this->connection)) - { - dol_syslog(get_class($this)."::connect_bind failed to start tls", LOG_WARNING); - $connected = 0; - $this->close(); - } - } + if (! empty($conf->global->LDAP_SERVER_USE_TLS)) + { + if (! ldap_start_tls($this->connection)) + { + dol_syslog(get_class($this)."::connect_bind failed to start tls", LOG_WARNING); + $connected = 0; + $this->close(); + } + } // Execute the ldap_set_option here (after connect and before bind) $this->setVersion(); diff --git a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php index 561ba330694..9c5112dd68a 100644 --- a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php +++ b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php @@ -1,6 +1,7 @@ - * Copyright (C) 2014 Marcos García +/* Copyright (C) 2005-2012 Laurent Destailleur + * Copyright (C) 2005-2017 Regis Houssin + * Copyright (C) 2014 Marcos García * * 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 @@ -49,553 +50,548 @@ class InterfaceLdapsynchro extends DolibarrTriggers * @return int <0 if KO, 0 if no triggered ran, >0 if OK */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) - { - if (empty($conf->ldap->enabled)) return 0; // Module not active, we do nothing + { + if (empty($conf->ldap->enabled)) return 0; // Module not active, we do nothing - if (! function_exists('ldap_connect')) - { - dol_syslog("Warning, module LDAP is enabled but LDAP functions not available in this PHP", LOG_WARNING); - return 0; - } + if (! function_exists('ldap_connect')) + { + dol_syslog("Warning, module LDAP is enabled but LDAP functions not available in this PHP", LOG_WARNING); + return 0; + } - // Users - if ($action == 'USER_CREATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); + $result=0; - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); + // Users + if ($action == 'USER_CREATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $result=$ldap->add($dn,$info,$user); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->add($dn,$info,$user); } - return $result; - } - } - elseif ($action == 'USER_MODIFY') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - if (empty($object->oldcopy) || ! is_object($object->oldcopy)) - { - dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); - $object->oldcopy = clone $object; - } + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'USER_MODIFY') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $oldinfo=$object->oldcopy->_load_ldap_info(); - $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); - $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; - } - } - elseif ($action == 'USER_NEW_PASSWORD') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - if (empty($object->oldcopy) || ! is_object($object->oldcopy)) - { - dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); - $object->oldcopy = clone $object; - } + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'USER_NEW_PASSWORD') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $oldinfo=$object->oldcopy->_load_ldap_info(); - $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); - $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; - } - } - elseif ($action == 'USER_ENABLEDISABLE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - } - elseif ($action == 'USER_DELETE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->delete($dn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; - } - } - elseif ($action == 'USER_SETINGROUP') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - // Must edit $object->newgroupid - $usergroup=new UserGroup($this->db); - if ($object->newgroupid > 0) - { - $usergroup->fetch($object->newgroupid); + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'USER_ENABLEDISABLE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + } + elseif ($action == 'USER_DELETE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $oldinfo=$usergroup->_load_ldap_info(); - $olddn=$usergroup->_load_ldap_dn($oldinfo); + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); - // Verify if entry exist - $container=$usergroup->_load_ldap_dn($oldinfo,1); - $search = "(".$usergroup->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } + $result=$ldap->delete($dn); + } - $info=$usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) - $dn=$usergroup->_load_ldap_dn($info); + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'USER_SETINGROUP') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - } - return $result; - } - } - elseif ($action == 'USER_REMOVEFROMGROUP') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); + if ($result > 0) + { + // Must edit $object->newgroupid + $usergroup=new UserGroup($this->db); + if ($object->newgroupid > 0) + { + $usergroup->fetch($object->newgroupid); - // Must edit $object->newgroupid - $usergroup=new UserGroup($this->db); - if ($object->oldgroupid > 0) - { - $usergroup->fetch($object->oldgroupid); + $oldinfo=$usergroup->_load_ldap_info(); + $olddn=$usergroup->_load_ldap_dn($oldinfo); - $oldinfo=$usergroup->_load_ldap_info(); - $olddn=$usergroup->_load_ldap_dn($oldinfo); + // Verify if entry exist + $container=$usergroup->_load_ldap_dn($oldinfo,1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } - // Verify if entry exist - $container=$usergroup->_load_ldap_dn($oldinfo,1); - $search = "(".$usergroup->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } + $info=$usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$usergroup->_load_ldap_dn($info); - $info=$usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) - $dn=$usergroup->_load_ldap_dn($info); + $result=$ldap->update($dn,$info,$user,$olddn); + } + } - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - } - return $result; - } - } + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'USER_REMOVEFROMGROUP') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + // Must edit $object->newgroupid + $usergroup=new UserGroup($this->db); + if ($object->oldgroupid > 0) + { + $usergroup->fetch($object->oldgroupid); + + $oldinfo=$usergroup->_load_ldap_info(); + $olddn=$usergroup->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$usergroup->_load_ldap_dn($oldinfo,1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$usergroup->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } // Groupes - elseif ($action == 'GROUP_CREATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); + elseif ($action == 'GROUP_CREATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - // Get a gid number for objectclass PosixGroup - if(in_array('posixGroup',$info['objectclass'])) - $info['gidNumber'] = $ldap->getNextGroupGid(); - - $result=$ldap->add($dn,$info,$user); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + // Get a gid number for objectclass PosixGroup + if (in_array('posixGroup',$info['objectclass'])) { + $info['gidNumber'] = $ldap->getNextGroupGid(); + } + + $result=$ldap->add($dn,$info,$user); } - return $result; - } - } - elseif ($action == 'GROUP_MODIFY') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - if (empty($object->oldcopy) || ! is_object($object->oldcopy)) - { - dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); - $object->oldcopy = clone $object; - } - - $oldinfo=$object->oldcopy->_load_ldap_info(); - $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); - $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; - } - } - elseif ($action == 'GROUP_DELETE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->delete($dn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; - } - } - - // Contacts - elseif ($action == 'CONTACT_CREATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->add($dn,$info,$user); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; - } - } - elseif ($action == 'CONTACT_MODIFY') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - if (empty($object->oldcopy) || ! is_object($object->oldcopy)) - { - dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); - $object->oldcopy = clone $object; - } - - $oldinfo=$object->oldcopy->_load_ldap_info(); - $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); - $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; - } - } - elseif ($action == 'CONTACT_DELETE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->delete($dn); - if ($result < 0) - { - $this->error="ErrorLDAP ".$ldap->error; - } - return $result; + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } - } + } + elseif ($action == 'GROUP_MODIFY') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - // Members - elseif ($action == 'MEMBER_CREATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { - $ldap=new Ldap(); - $ldap->connect_bind(); - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->add($dn,$info,$user); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; - } - } - elseif ($action == 'MEMBER_VALIDATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'GROUP_DELETE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->delete($dn); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + + // Contacts + elseif ($action == 'CONTACT_CREATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->add($dn,$info,$user); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'CONTACT_MODIFY') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'CONTACT_DELETE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_CONTACT_ACTIVE)) + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->delete($dn); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + + // Members + elseif ($action == 'MEMBER_CREATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->add($dn,$info,$user); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'MEMBER_VALIDATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { // If status field is setup to be synchronized if (! empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) { $ldap=new Ldap(); - $ldap->connect_bind(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - $olddn=$dn; // We know olddn=dn as we change only status - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + $olddn=$dn; // We know olddn=dn as we change only status + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } } - } - elseif ($action == 'MEMBER_SUBSCRIPTION') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { + } + elseif ($action == 'MEMBER_SUBSCRIPTION') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { // If subscriptions fields are setup to be synchronized if ($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE - || $conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT - || $conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE - || $conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT - || $conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION) + || $conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT + || $conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE + || $conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT + || $conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION) { $ldap=new Ldap(); - $ldap->connect_bind(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - $olddn=$dn; // We know olddn=dn as we change only subscriptions - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + $olddn=$dn; // We know olddn=dn as we change only subscriptions + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } } - } - elseif ($action == 'MEMBER_MODIFY') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { - $ldap=new Ldap(); - $ldap->connect_bind(); + } + elseif ($action == 'MEMBER_MODIFY') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); - if (empty($object->oldcopy) || ! is_object($object->oldcopy)) - { - dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); - $object->oldcopy = clone $object; - } - - $oldinfo=$object->oldcopy->_load_ldap_info(); - $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); - $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; - } - } - elseif ($action == 'MEMBER_NEW_PASSWORD') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'MEMBER_NEW_PASSWORD') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { // If password field is setup to be synchronized if ($conf->global->LDAP_FIELD_PASSWORD || $conf->global->LDAP_FIELD_PASSWORD_CRYPTED) { $ldap=new Ldap(); - $ldap->connect_bind(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - $olddn=$dn; // We know olddn=dn as we change only password - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + $olddn=$dn; // We know olddn=dn as we change only password + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } } } - elseif ($action == 'MEMBER_RESILIATE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') - { + elseif ($action == 'MEMBER_RESILIATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') + { // If status field is setup to be synchronized if (! empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) { $ldap=new Ldap(); - $ldap->connect_bind(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - $olddn=$dn; // We know olddn=dn as we change only status - - $result=$ldap->update($dn,$info,$user,$olddn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + $olddn=$dn; // We know olddn=dn as we change only status + + $result=$ldap->update($dn,$info,$user,$olddn); } - return $result; + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } } - } - elseif ($action == 'MEMBER_DELETE') - { - dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + } + elseif ($action == 'MEMBER_DELETE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); if (! empty($conf->global->LDAP_MEMBER_ACTIVE) && (string) $conf->global->LDAP_MEMBER_ACTIVE == '1') { $ldap=new Ldap(); - $ldap->connect_bind(); + $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - - $result=$ldap->delete($dn); - if ($result < 0) + if ($result > 0) { - $this->error="ErrorLDAP ".$ldap->error; + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->delete($dn); } - return $result; + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } } - // If not found -/* - else - { - dol_syslog("Trigger '".$this->name."' for action '$action' was ran by ".__FILE__." but no handler found for this action."); - return -1; - } -*/ - return 0; + return $result; } } From 87b81fb2fda13f2bf507b4a1f8dc521b776626ee Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 16 Sep 2017 17:51:18 +0200 Subject: [PATCH 012/108] NEW add members types ldap group management --- htdocs/adherents/class/adherent.class.php | 171 +++++----- .../adherents/class/adherent_type.class.php | 301 +++++++++++------- htdocs/adherents/type.php | 24 +- htdocs/adherents/type_ldap.php | 189 +++++++++++ htdocs/admin/ldap.php | 15 +- htdocs/admin/ldap_groups.php | 5 +- htdocs/admin/ldap_members_types.php | 252 +++++++++++++++ htdocs/core/class/conf.class.php | 1 + htdocs/core/class/ldap.class.php | 7 +- htdocs/core/lib/ldap.lib.php | 8 + htdocs/core/lib/member.lib.php | 10 + ...interface_50_modLdap_Ldapsynchro.class.php | 200 +++++++++++- htdocs/langs/en_US/admin.lang | 12 +- htdocs/langs/en_US/errors.lang | 1 + htdocs/langs/en_US/ldap.lang | 2 + htdocs/user/group/ldap.php | 23 +- 16 files changed, 989 insertions(+), 232 deletions(-) create mode 100644 htdocs/adherents/type_ldap.php create mode 100644 htdocs/admin/ldap_members_types.php diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index a1b61358820..47bf219216c 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -714,109 +714,108 @@ class Adherent extends CommonObject * Fonction qui supprime l'adherent et les donnees associees * * @param int $rowid Id of member to delete - * @param User $user User object + * @param User $user User object * @param int $notrigger 1=Does not execute triggers, 0= execute triggers * @return int <0 if KO, 0=nothing to do, >0 if OK */ - function delete($rowid, $user, $notrigger=0) - { - global $conf, $langs; + function delete($rowid, $user, $notrigger=0) + { + global $conf, $langs; - $result = 0; + $result = 0; $error=0; $errorflag=0; // Check parameters if (empty($rowid)) $rowid=$this->id; - $this->db->begin(); + $this->db->begin(); - if (! $error && ! $notrigger) - { - // Call trigger - $result=$this->call_trigger('MEMBER_DELETE',$user); - if ($result < 0) $error++; - // End call triggers - } + // Remove category + $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".$rowid; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-1; + } - // Remove category - $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".$rowid; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); - $resql=$this->db->query($sql); - if (! $resql) - { - $error++; - $this->error .= $this->db->lasterror(); - $errorflag=-1; + // Remove subscription + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".$rowid; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-2; + } + } - } + // Remove linked user + if (! $error) + { + $ret=$this->setUserId(0); + if ($ret < 0) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-3; + } + } - // Remove subscription - if (! $error) - { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".$rowid; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); - $resql=$this->db->query($sql); - if (! $resql) - { - $error++; - $this->error .= $this->db->lasterror(); - $errorflag=-2; - } - } + // Removed extrafields + if (! $error) + { + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used + { + $result=$this->deleteExtraFields(); + if ($result < 0) + { + $error++; + $errorflag=-4; + dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR); + } + } + } - // Remove linked user - if (! $error) - { - $ret=$this->setUserId(0); - if ($ret < 0) - { - $error++; - $this->error .= $this->db->lasterror(); - $errorflag=-3; - } - } + // Remove adherent + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".$rowid; + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag=-5; + } + } - // Removed extrafields - if (! $error) - { - if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used - { - $result=$this->deleteExtraFields(); - if ($result < 0) - { - $error++; - $errorflag=-4; - dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR); - } - } - } + if (! $error && ! $notrigger) + { + // Call trigger + $result=$this->call_trigger('MEMBER_DELETE',$user); + if ($result < 0) $error++; + // End call triggers + } - // Remove adherent - if (! $error) - { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".$rowid; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); - $resql=$this->db->query($sql); - if (! $resql) - { - $error++; - $this->error .= $this->db->lasterror(); - $errorflag=-5; - } - } - - if (! $error) - { - $this->db->commit(); - return 1; - } - else - { - $this->db->rollback(); - return $errorflag; - } - } + if (! $error) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return $errorflag; + } + } /** diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 82753d08590..7293fd10e90 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -61,6 +61,8 @@ class AdherentType extends CommonObject public $vote; /** @var bool Email sent during validation */ public $mail_valid; + /** @var array Array of members */ + public $members=array(); /** @@ -250,83 +252,137 @@ class AdherentType extends CommonObject } } - /** - * Fonction qui permet de recuperer le status de l'adherent - * - * @param int $rowid Id of member type to load - * @return int <0 if KO, >0 if OK - */ - function fetch($rowid) - { - $sql = "SELECT d.rowid, d.libelle as label, d.statut, d.subscription, d.mail_valid, d.note, d.vote"; - $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; - $sql .= " WHERE d.rowid = ".$rowid; + /** + * Fonction qui permet de recuperer le status de l'adherent + * + * @param int $rowid Id of member type to load + * @param bool $load_members Load members or not + * @return int <0 if KO, >0 if OK + */ + function fetch($rowid, $load_members = true) + { + $sql = "SELECT d.rowid, d.libelle as label, d.statut, d.subscription, d.mail_valid, d.note, d.vote"; + $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; + $sql .= " WHERE d.rowid = ".$rowid; - dol_syslog("Adherent_type::fetch", LOG_DEBUG); + dol_syslog("Adherent_type::fetch", LOG_DEBUG); - $resql=$this->db->query($sql); - if ($resql) - { - if ($this->db->num_rows($resql)) - { - $obj = $this->db->fetch_object($resql); + $resql=$this->db->query($sql); + if ($resql) + { + if ($this->db->num_rows($resql)) + { + $obj = $this->db->fetch_object($resql); - $this->id = $obj->rowid; - $this->ref = $obj->rowid; - $this->label = $obj->label; - $this->statut = $obj->statut; - $this->subscription = $obj->subscription; - $this->mail_valid = $obj->mail_valid; - $this->note = $obj->note; - $this->vote = $obj->vote; - } - return 1; - } - else - { - $this->error=$this->db->lasterror(); - return -1; - } - } + $this->id = $obj->rowid; + $this->ref = $obj->rowid; + $this->label = $obj->label; + $this->statut = $obj->statut; + $this->subscription = $obj->subscription; + $this->mail_valid = $obj->mail_valid; + $this->note = $obj->note; + $this->vote = $obj->vote; - /** - * Return list of members' type - * - * @return array List of types of members - */ - function liste_array() - { - global $conf,$langs; + if ($load_members) { + $this->members=$this->listMembersForMemberType(); + } + } - $adherenttypes = array(); + return 1; + } + else + { + $this->error=$this->db->lasterror(); + return -1; + } + } - $sql = "SELECT rowid, libelle as label"; - $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type"; - $sql.= " WHERE entity IN (".getEntity('adherent').")"; + /** + * Return list of members' type + * + * @return array List of types of members + */ + function liste_array() + { + global $conf,$langs; - $resql=$this->db->query($sql); - if ($resql) - { - $nump = $this->db->num_rows($resql); + $adherenttypes = array(); - if ($nump) - { - $i = 0; - while ($i < $nump) - { - $obj = $this->db->fetch_object($resql); + $sql = "SELECT rowid, libelle as label"; + $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type"; + $sql.= " WHERE entity IN (".getEntity('adherent').")"; - $adherenttypes[$obj->rowid] = $langs->trans($obj->label); - $i++; - } - } - } - else - { - print $this->db->error(); - } - return $adherenttypes; - } + $resql=$this->db->query($sql); + if ($resql) + { + $nump = $this->db->num_rows($resql); + + if ($nump) + { + $i = 0; + while ($i < $nump) + { + $obj = $this->db->fetch_object($resql); + + $adherenttypes[$obj->rowid] = $langs->trans($obj->label); + $i++; + } + } + } + else + { + print $this->db->error(); + } + return $adherenttypes; + } + + /** + * Return array of Member objects for member type this->id (or all if this->id not defined) + * + * @param string $excludefilter Filter to exclude + * @param int $mode 0=Return array of member instance, 1=Return array of members id only + * @return mixed Array of members or -1 on error + */ + function listMembersForMemberType($excludefilter='', $mode=0) + { + global $conf, $user; + + $ret=array(); + + $sql = "SELECT a.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a"; + $sql.= " WHERE a.entity IN (".getEntity('member').")"; + $sql.= " AND a.fk_adherent_type = ".$this->id; + if (! empty($excludefilter)) $sql.=' AND ('.$excludefilter.')'; + + dol_syslog(get_class($this)."::listUsersForGroup", LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) + { + while ($obj = $this->db->fetch_object($resql)) + { + if (! array_key_exists($obj->rowid, $ret)) + { + if ($mode != 1) + { + $memberstatic=new Adherent($this->db); + $memberstatic->fetch($obj->rowid); + $ret[$obj->rowid]=$memberstatic; + } + else $ret[$obj->rowid]=$obj->rowid; + } + } + + $this->db->free($resql); + + return $ret; + } + else + { + $this->error=$this->db->lasterror(); + return -1; + } + } /** * Return clicable name (with picto eventually) @@ -445,60 +501,63 @@ class AdherentType extends CommonObject ); } - /** - * getMailOnValid - * - * @return string Return mail model - */ - function getMailOnValid() - { - global $conf; + /** + * getMailOnValid + * + * @return string Return mail model + */ + function getMailOnValid() + { + global $conf; - if (! empty($this->mail_valid) && trim(dol_htmlentitiesbr_decode($this->mail_valid))) - { - return $this->mail_valid; - } - else - { - return $conf->global->ADHERENT_MAIL_VALID; - } - } + if (! empty($this->mail_valid) && trim(dol_htmlentitiesbr_decode($this->mail_valid))) + { + return $this->mail_valid; + } + else + { + return $conf->global->ADHERENT_MAIL_VALID; + } + } - /** - * getMailOnSubscription - * - * @return string Return mail model - */ - function getMailOnSubscription() - { - global $conf; - // mail_subscription not defined so never used - if (! empty($this->mail_subscription) && trim(dol_htmlentitiesbr_decode($this->mail_subscription))) // Property not yet defined - { - return $this->mail_subscription; - } - else - { - return $conf->global->ADHERENT_MAIL_COTIS; - } - } + /** + * getMailOnSubscription + * + * @return string Return mail model + */ + function getMailOnSubscription() + { + global $conf; + + // mail_subscription not defined so never used + if (! empty($this->mail_subscription) && trim(dol_htmlentitiesbr_decode($this->mail_subscription))) // Property not yet defined + { + return $this->mail_subscription; + } + else + { + return $conf->global->ADHERENT_MAIL_COTIS; + } + } + + /** + * getMailOnResiliate + * + * @return string Return mail model + */ + function getMailOnResiliate() + { + global $conf; + + // NOTE mail_resiliate not defined so never used + if (! empty($this->mail_resiliate) && trim(dol_htmlentitiesbr_decode($this->mail_resiliate))) // Property not yet defined + { + return $this->mail_resiliate; + } + else + { + return $conf->global->ADHERENT_MAIL_RESIL; + } + } - /** - * getMailOnResiliate - * - * @return string Return mail model - */ - function getMailOnResiliate() - { - global $conf; - // NOTE mail_resiliate not defined so never used - if (! empty($this->mail_resiliate) && trim(dol_htmlentitiesbr_decode($this->mail_resiliate))) // Property not yet defined - { - return $this->mail_resiliate; - } - else - { - return $conf->global->ADHERENT_MAIL_RESIL; - } - } } diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 3d4fb786295..b59d8b7530d 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -113,7 +113,24 @@ if ($action == 'add' && $user->rights->adherent->configurer) $ret = $extrafields->setOptionalsFromPost($extralabels,$object); if ($ret < 0) $error++; - if ($object->label) + if (empty($object->label)) { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")), null, 'errors'); + } + else { + $sql = "SELECT libelle FROM ".MAIN_DB_PREFIX."adherent_type WHERE libelle='".$db->escape($object->label)."'"; + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + } + if ($num) { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorLabelAlreadyExists",$login), null, 'errors'); + } + } + + if (! $error) { $id=$object->create($user); if ($id > 0) @@ -123,13 +140,12 @@ if ($action == 'add' && $user->rights->adherent->configurer) } else { - $mesg=$object->error; + setEventMessages($object->error, $object->errors, 'errors'); $action = 'create'; } } else { - $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")); $action = 'create'; } } @@ -138,6 +154,8 @@ if ($action == 'update' && $user->rights->adherent->configurer) { $object->fetch($rowid); + $object->oldcopy = clone $object; + $object->label = trim($label); $object->subscription = (int) trim($subscription); $object->note = trim($comment); diff --git a/htdocs/adherents/type_ldap.php b/htdocs/adherents/type_ldap.php new file mode 100644 index 00000000000..e610f651df5 --- /dev/null +++ b/htdocs/adherents/type_ldap.php @@ -0,0 +1,189 @@ + + * Copyright (C) 2006-2017 Regis Houssin + * + * 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/adherents/type_ldap.php + * \ingroup ldap + * \brief Page fiche LDAP members types + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/ldap.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/ldap.lib.php'; + +$langs->load("members"); +$langs->load("admin"); +$langs->load("ldap"); + +$id = GETPOST('rowid', 'int'); +$action = GETPOST('action','alpha'); + +// Security check +$result=restrictedArea($user,'adherent',$id,'adherent_type'); + +$object = new AdherentType($db); +$object->fetch($id); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('membertypeldapcard','globalcard')); + +/* + * Actions + */ + + +$parameters=array(); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + if ($action == 'dolibarr2ldap') + { + $ldap = new Ldap(); + $result = $ldap->connect_bind(); + + if ($result > 0) + { + $info = $object->_load_ldap_info(); + $dn = $object->_load_ldap_dn($info); + $olddn = $dn; // We can say that old dn = dn as we force synchro + + $result = $ldap->update($dn, $info, $user, $olddn); + } + + if ($result >= 0) { + setEventMessages($langs->trans("MemberTypeSynchronized"), null, 'mesgs'); + } + else { + setEventMessages($ldap->error, $ldap->errors, 'errors'); + } + } +} + +/* + * View + */ + +llxHeader(); + +$form = new Form($db); + +$head = member_type_prepare_head($object); + +dol_fiche_head($head, 'ldap', $langs->trans("MemberType"), -1, 'group'); + +$linkback = ''.$langs->trans("BackToList").''; + +dol_banner_tab($object, 'rowid', $linkback); + +print '
'; +print '
'; + +print ''; + +// LDAP DN +print '\n"; + +// LDAP Cle +print '\n"; + +// LDAP Server +print '\n"; +print '\n"; +print '\n"; +print '\n"; +print '\n"; + +print '
LDAP '.$langs->trans("LDAPMemberTypeDn").''.$conf->global->LDAP_MEMBER_TYPE_DN."
LDAP '.$langs->trans("LDAPNamingAttribute").''.$conf->global->LDAP_KEY_MEMBERS_TYPES."
LDAP '.$langs->trans("Type").''.$conf->global->LDAP_SERVER_TYPE."
LDAP '.$langs->trans("Version").''.$conf->global->LDAP_SERVER_PROTOCOLVERSION."
LDAP '.$langs->trans("LDAPPrimaryServer").''.$conf->global->LDAP_SERVER_HOST."
LDAP '.$langs->trans("LDAPSecondaryServer").''.$conf->global->LDAP_SERVER_HOST_SLAVE."
LDAP '.$langs->trans("LDAPServerPort").''.$conf->global->LDAP_SERVER_PORT."
'; + +print '
'; + +dol_fiche_end(); + +/* + * Barre d'actions + */ + +print '
'; + +if ($conf->global->LDAP_MEMBER_TYPE_ACTIVE == 1) +{ + print ''.$langs->trans("ForceSynchronize").''; +} + +print "
\n"; + +if ($conf->global->LDAP_MEMBER_TYPE_ACTIVE == 1) print "
\n"; + + + +// Affichage attributs LDAP +print load_fiche_titre($langs->trans("LDAPInformationsForThisMemberType")); + +print ''; + +print ''; +print ''; +print ''; +print ''; + +// Lecture LDAP +$ldap=new Ldap(); +$result=$ldap->connect_bind(); +if ($result > 0) +{ + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info,1); + $search = "(".$object->_load_ldap_dn($info,2).")"; + $records = $ldap->getAttribute($dn,$search); + + //print_r($records); + + // Affichage arbre + if ((! is_numeric($records) || $records != 0) && (! isset($records['count']) || $records['count'] > 0)) + { + if (! is_array($records)) + { + print ''; + } + else + { + $result=show_ldap_content($records,0,$records['count'],true); + } + } + else + { + print ''; + } + + $ldap->unbind(); + $ldap->close(); +} +else +{ + setEventMessages($ldap->error, $ldap->errors, 'errors'); +} + +print '
'.$langs->trans("LDAPAttributes").''.$langs->trans("Value").'
'.$langs->trans("ErrorFailedToReadLDAP").'
'.$langs->trans("LDAPRecordNotFound").' (dn='.$dn.' - search='.$search.')
'; + +llxFooter(); +$db->close(); diff --git a/htdocs/admin/ldap.php b/htdocs/admin/ldap.php index d5720835f3c..77fdf6fc579 100644 --- a/htdocs/admin/ldap.php +++ b/htdocs/admin/ldap.php @@ -68,6 +68,7 @@ if (empty($reshook)) if (! dolibarr_set_const($db, 'LDAP_SYNCHRO_ACTIVE',GETPOST("activesynchro"),'chaine',0,'',$conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_CONTACT_ACTIVE',GETPOST("activecontact"),'chaine',0,'',$conf->entity)) $error++; if (! dolibarr_set_const($db, 'LDAP_MEMBER_ACTIVE',GETPOST("activemembers"),'chaine',0,'',$conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_ACTIVE',GETPOST("activememberstypes"),'chaine',0,'',$conf->entity)) $error++; if (! $error) { @@ -135,7 +136,6 @@ print ''; // Synchro contact active if (! empty($conf->societe->enabled)) { - print ''.$langs->trans("LDAPDnContactActive").''; $arraylist=array(); $arraylist['0']=$langs->trans("No"); @@ -147,7 +147,6 @@ if (! empty($conf->societe->enabled)) // Synchro member active if (! empty($conf->adherent->enabled)) { - print ''.$langs->trans("LDAPDnMemberActive").''; $arraylist=array(); $arraylist['0']=$langs->trans("No"); @@ -157,6 +156,18 @@ if (! empty($conf->adherent->enabled)) print ''.$langs->trans("LDAPDnMemberActiveExample").''; } +// Synchro member type active +if (! empty($conf->adherent->enabled)) +{ + print ''.$langs->trans("LDAPDnMemberTypeActive").''; + $arraylist=array(); + $arraylist['0']=$langs->trans("No"); + $arraylist['1']=$langs->trans("DolibarrToLDAP"); + //$arraylist['ldap2dolibarr']=$langs->trans("LDAPToDolibarr").' ('.$langs->trans("SupportedForLDAPImportScriptOnly").')'; + print $form->selectarray('activememberstypes',$arraylist,$conf->global->LDAP_MEMBER_TYPE_ACTIVE); + print ''.$langs->trans("LDAPDnMemberTypeActiveExample").''; +} + // Fields from hook $parameters=array(); $reshook=$hookmanager->executeHooks('addAdminLdapOptions',$parameters); // Note that $action and $object may have been modified by hook diff --git a/htdocs/admin/ldap_groups.php b/htdocs/admin/ldap_groups.php index fc68d815439..d431a7aaf30 100644 --- a/htdocs/admin/ldap_groups.php +++ b/htdocs/admin/ldap_groups.php @@ -220,8 +220,9 @@ if (function_exists("ldap_connect")) $dn=$object->_load_ldap_dn($info); // Get a gid number for objectclass PosixGroup - if(in_array('posixGroup',$info['objectclass'])) - $info['gidNumber'] = $ldap->getNextGroupGid(); + if (in_array('posixGroup',$info['objectclass'])) { + $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_GROUPS'); + } $result1=$ldap->delete($dn); // To be sure to delete existing records $result2=$ldap->add($dn,$info,$user); // Now the test diff --git a/htdocs/admin/ldap_members_types.php b/htdocs/admin/ldap_members_types.php new file mode 100644 index 00000000000..47286dc98da --- /dev/null +++ b/htdocs/admin/ldap_members_types.php @@ -0,0 +1,252 @@ + + * Copyright (C) 2004 Sebastien Di Cintio + * Copyright (C) 2004 Benoit Mortier + * Copyright (C) 2005-2017 Regis Houssin + * Copyright (C) 2006-2011 Laurent Destailleur + * Copyright (C) 2011-2013 Juanjo Menent + * + * 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/admin/ldap_members_types.php + * \ingroup ldap + * \brief Page to setup LDAP synchronization for members types + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/ldap.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/ldap.lib.php'; + +$langs->load("admin"); +$langs->load("errors"); + +if (!$user->admin) + accessforbidden(); + +$action = GETPOST('action','aZ09'); + + +/* + * Actions + */ + +if ($action == 'setvalue' && $user->admin) +{ + $error=0; + $db->begin(); + + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_DN',GETPOST("membertype"),'chaine',0,'',$conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_OBJECT_CLASS',GETPOST("objectclass"),'chaine',0,'',$conf->entity)) $error++; + + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_FIELD_FULLNAME',GETPOST("fieldfullname"),'chaine',0,'',$conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_FIELD_DESCRIPTION',GETPOST("fielddescription"),'chaine',0,'',$conf->entity)) $error++; + if (! dolibarr_set_const($db, 'LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS',GETPOST("fieldmembertypemembers"),'chaine',0,'',$conf->entity)) $error++; + + // This one must be after the others + $valkey=''; + $key=GETPOST("key"); + if ($key) $valkey=$conf->global->$key; + if (! dolibarr_set_const($db, 'LDAP_KEY_MEMBERS_TYPES',$valkey,'chaine',0,'',$conf->entity)) $error++; + + if (! $error) + { + $db->commit(); + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } + else + { + $db->rollback(); + dol_print_error($db); + } +} + + + +/* + * View + */ + +llxHeader('',$langs->trans("LDAPSetup"),'EN:Module_LDAP_En|FR:Module_LDAP|ES:Módulo_LDAP'); +$linkback=''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans("LDAPSetup"),$linkback,'title_setup'); + +$head = ldap_prepare_head(); + +// Test si fonction LDAP actives +if (! function_exists("ldap_connect")) +{ + setEventMessages($langs->trans("LDAPFunctionsNotAvailableOnPHP"), null, 'errors'); +} + +dol_fiche_head($head, 'memberstypes', $langs->trans("LDAPSetup"), -1); + + +print $langs->trans("LDAPDescMembersTypes").'
'; +print '
'; + + +print '
'; +print ''; + +$form=new Form($db); + +print ''; +$var=true; + +print ''; +print ''; +print "\n"; + +// DN pour les types de membres + +print ''; +print ''; +print ''; + +// List of object class used to define attributes in structure + +print ''; +print ''; +print ''; + +print '
'.$langs->trans("LDAPSynchronizeMembersTypes").'
'.$langs->trans("LDAPMemberTypeDn").''; +print ''; +print ''.$langs->trans("LDAPMemberTypepDnExample").' 
'.$langs->trans("LDAPMemberTypeObjectClassList").''; +print ''; +print ''.$langs->trans("LDAPMemberTypeObjectClassListExample").' 
'; +print '
'; +print ''; +$var=true; + +print ''; +print ''; +print ''; +print ''; +print "\n"; + +// Filtre + +// Common name + +print ''; +print '"; +print ''; + +// Description + +print ''; +print '"; +print ''; + +// User group + +print ''; +print '"; +print ''; + +print '
'.$langs->trans("LDAPDolibarrMapping").''.$langs->trans("LDAPLdapMapping").''.$langs->trans("LDAPNamingAttribute").'
'.$langs->trans("LDAPFieldName").''; +print ''; +print ''.$langs->trans("LDAPFieldCommonNameExample").'global->LDAP_KEY_MEMBERS_TYPES && $conf->global->LDAP_KEY_MEMBERS_TYPES==$conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME)?' checked':'').">
'.$langs->trans("LDAPFieldDescription").''; +print ''; +print ''.$langs->trans("LDAPFieldDescriptionExample").'global->LDAP_KEY_MEMBERS_TYPES && $conf->global->LDAP_KEY_MEMBER_TYPES==$conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION)?' checked':'').">
'.$langs->trans("LDAPFieldGroupMembers").''; +print ''; +print ''.$langs->trans("LDAPFieldGroupMembersExample").'global->LDAP_KEY_MEMBERS_TYPES && $conf->global->LDAP_KEY_MEMBERS_TYPES==$conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS)?' checked':'').">
'; + +print info_admin($langs->trans("LDAPDescValues")); + +dol_fiche_end(); + +print '
'; + +print '
'; + + +/* + * Test de la connexion + */ +if ($conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') +{ + $butlabel=$langs->trans("LDAPTestSynchroMemberType"); + $testlabel='testmembertype'; + $key=$conf->global->LDAP_KEY_MEMBERS_TYPES; + $dn=$conf->global->LDAP_MEMBER_TYPE_DN; + $objectclass=$conf->global->LDAP_MEMBER_TYPE_OBJECT_CLASS; + + show_ldap_test_button($butlabel,$testlabel,$key,$dn,$objectclass); +} + +if (function_exists("ldap_connect")) +{ + if ($_GET["action"] == 'testmembertype') + { + // Creation objet + $object=new AdherentType($db); + $object->initAsSpecimen(); + + // Test synchro + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + // Get a gid number for objectclass PosixGroup + if (in_array('posixGroup',$info['objectclass'])) { + $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_MEMBERS_TYPES'); + } + + $result1=$ldap->delete($dn); // To be sure to delete existing records + $result2=$ldap->add($dn,$info,$user); // Now the test + $result3=$ldap->delete($dn); // Clean what we did + + if ($result2 > 0) + { + print img_picto('','info').' '; + print ''.$langs->trans("LDAPSynchroOK").'
'; + } + else + { + print img_picto('','error').' '; + print ''.$langs->trans("LDAPSynchroKOMayBePermissions"); + print ': '.$ldap->error; + print '
'; + print $langs->trans("ErrorLDAPMakeManualTest",$conf->ldap->dir_temp).'
'; + } + + print "
\n"; + print "LDAP input file used for test:

\n"; + print nl2br($ldap->dump_content($dn,$info)); + print "\n
"; + } + else + { + print img_picto('','error').' '; + print ''.$langs->trans("LDAPSynchroKO"); + print ': '.$ldap->error; + print '
'; + print $langs->trans("ErrorLDAPMakeManualTest",$conf->ldap->dir_temp).'
'; + } + } +} + +llxFooter(); +$db->close(); diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index ad224fec97d..8dba7f0e8c5 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -254,6 +254,7 @@ class Conf if (! isset($this->global->LDAP_KEY_GROUPS)) $this->global->LDAP_KEY_GROUPS=$this->global->LDAP_FIELD_FULLNAME; if (! isset($this->global->LDAP_KEY_CONTACTS)) $this->global->LDAP_KEY_CONTACTS=$this->global->LDAP_FIELD_FULLNAME; if (! isset($this->global->LDAP_KEY_MEMBERS)) $this->global->LDAP_KEY_MEMBERS=$this->global->LDAP_FIELD_FULLNAME; + if (! isset($this->global->LDAP_KEY_MEMBERS_TYPES)) $this->global->LDAP_KEY_MEMBERS_TYPES=$this->global->LDAP_FIELD_FULLNAME; // Load translation object with current language if (empty($this->global->MAIN_LANG_DEFAULT)) $this->global->MAIN_LANG_DEFAULT="en_US"; diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 58eedc0ad9d..790772a9803 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1411,13 +1411,16 @@ class Ldap /** * Return available value of group GID * + * @param string Key of group * @return int gid number */ - function getNextGroupGid() + function getNextGroupGid($keygroup='LDAP_KEY_GROUPS') { global $conf; - $search='('.$conf->global->LDAP_KEY_GROUPS.'=*)'; + if (empty($keygroup)) $keygroup='LDAP_KEY_GROUPS'; + + $search='('.$conf->global->$keygroup.'=*)'; $result = $this->search($this->groups,$search); if($result) { diff --git a/htdocs/core/lib/ldap.lib.php b/htdocs/core/lib/ldap.lib.php index f684af594e5..3db36723b32 100644 --- a/htdocs/core/lib/ldap.lib.php +++ b/htdocs/core/lib/ldap.lib.php @@ -75,6 +75,14 @@ function ldap_prepare_head() $h++; } + if (! empty($conf->adherent->enabled) && ! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE)) + { + $head[$h][0] = DOL_URL_ROOT."/admin/ldap_members_types.php"; + $head[$h][1] = $langs->trans("LDAPMembersTypesSynchro"); + $head[$h][2] = 'memberstypes'; + $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 diff --git a/htdocs/core/lib/member.lib.php b/htdocs/core/lib/member.lib.php index 472c040e450..7e5e5e0c604 100644 --- a/htdocs/core/lib/member.lib.php +++ b/htdocs/core/lib/member.lib.php @@ -124,6 +124,16 @@ function member_type_prepare_head(AdherentType $object) $head[$h][2] = 'card'; $h++; + if (! empty($conf->ldap->enabled) && ! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE)) + { + $langs->load("ldap"); + + $head[$h][0] = DOL_URL_ROOT.'/adherents/type_ldap.php?rowid='.$object->id; + $head[$h][1] = $langs->trans("LDAPCard"); + $head[$h][2] = 'ldap'; + $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 diff --git a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php index 9c5112dd68a..05a9a5a1b20 100644 --- a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php +++ b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php @@ -271,7 +271,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers // Get a gid number for objectclass PosixGroup if (in_array('posixGroup',$info['objectclass'])) { - $info['gidNumber'] = $ldap->getNextGroupGid(); + $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_GROUPS'); } $result=$ldap->add($dn,$info,$user); @@ -429,6 +429,33 @@ class InterfaceLdapsynchro extends DolibarrTriggers $dn=$object->_load_ldap_dn($info); $result=$ldap->add($dn,$info,$user); + + // For member type + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + $membertype=new AdherentType($this->db); + if ($object->typeid > 0) + { + $membertype->fetch($object->typeid); + + $oldinfo=$membertype->_load_ldap_info(); + $olddn=$membertype->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$membertype->_load_ldap_dn($oldinfo,1); + $search = "(".$membertype->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$membertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$membertype->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + } } if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; @@ -518,6 +545,59 @@ class InterfaceLdapsynchro extends DolibarrTriggers $dn=$object->_load_ldap_dn($info); $result=$ldap->update($dn,$info,$user,$olddn); + + // For member type + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + if ($object->oldcopy->typeid != $object->typeid) + { + /* + * Add member in new member type + */ + $newmembertype=new AdherentType($this->db); + $newmembertype->fetch($object->typeid); + + $oldinfo=$newmembertype->_load_ldap_info(); + $olddn=$newmembertype->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$newmembertype->_load_ldap_dn($oldinfo,1); + $search = "(".$newmembertype->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$newmembertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$newmembertype->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + + /* + * Remove member in old member type + */ + $oldmembertype=new AdherentType($this->db); + $oldmembertype->fetch($object->oldcopy->typeid); + + $oldinfo=$oldmembertype->_load_ldap_info(); + $olddn=$oldmembertype->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$oldmembertype->_load_ldap_dn($oldinfo,1); + $search = "(".$oldmembertype->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$oldmembertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$oldmembertype->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + } } if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; @@ -585,13 +665,125 @@ class InterfaceLdapsynchro extends DolibarrTriggers $dn=$object->_load_ldap_dn($info); $result=$ldap->delete($dn); + + // For member type + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + if ($object->typeid > 0) + { + /* + * Remove member in member type + */ + $membertype=new AdherentType($this->db); + $membertype->fetch($object->typeid); + + $oldinfo=$membertype->_load_ldap_info(); + $olddn=$membertype->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$membertype->_load_ldap_dn($oldinfo,1); + $search = "(".$membertype->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$membertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$membertype->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + } } if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; } - } + } - return $result; - } + // Members types + elseif ($action == 'MEMBER_TYPE_CREATE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + // Get a gid number for objectclass PosixGroup + if (in_array('posixGroup',$info['objectclass'])) { + $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_MEMBERS_TYPE'); + } + + $result=$ldap->add($dn,$info,$user); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'MEMBER_TYPE_MODIFY') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + if (empty($object->oldcopy) || ! is_object($object->oldcopy)) + { + dol_syslog("Trigger ".$action." was called by a function that did not set previously the property ->oldcopy onto object", LOG_WARNING); + $object->oldcopy = clone $object; + } + + $oldinfo=$object->oldcopy->_load_ldap_info(); + $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$object->oldcopy->_load_ldap_dn($oldinfo,1); + $search = "(".$object->oldcopy->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + elseif ($action == 'MEMBER_TYPE_DELETE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') + { + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + $info=$object->_load_ldap_info(); + $dn=$object->_load_ldap_dn($info); + + $result=$ldap->delete($dn); + } + + if ($result < 0) $this->error="ErrorLDAP ".$ldap->error; + } + } + + return $result; + } } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 0fe1040b389..759e7402515 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1253,6 +1253,7 @@ LDAPUsersSynchro=Users LDAPGroupsSynchro=Groups LDAPContactsSynchro=Contacts LDAPMembersSynchro=Members +LDAPMembersTypesSynchro=Members types LDAPSynchronization=LDAP synchronisation LDAPFunctionsNotAvailableOnPHP=LDAP functions are not available on your PHP LDAPToDolibarr=LDAP -> Dolibarr @@ -1261,7 +1262,8 @@ LDAPNamingAttribute=Key in LDAP LDAPSynchronizeUsers=Organization of users in LDAP LDAPSynchronizeGroups=Organization of groups in LDAP LDAPSynchronizeContacts=Organization of contacts in LDAP -LDAPSynchronizeMembers=Organization of foundation's members in LDAP +LDAPSynchronizeMembers=Organization of foundation's members in LDAP +LDAPSynchronizeMembersTypes=Organization of foundation's members types in LDAP LDAPPrimaryServer=Primary server LDAPSecondaryServer=Secondary server LDAPServerPort=Server port @@ -1285,12 +1287,18 @@ LDAPDnContactActive=Contacts' synchronization LDAPDnContactActiveExample=Activated/Unactivated synchronization LDAPDnMemberActive=Members' synchronization LDAPDnMemberActiveExample=Activated/Unactivated synchronization +LDAPDnMemberTypeActive=Members types' synchronization +LDAPDnMemberTypeActiveExample=Activated/Unactivated synchronization LDAPContactDn=Dolibarr contacts' DN LDAPContactDnExample=Complete DN (ex: ou=contacts,dc=example,dc=com) LDAPMemberDn=Dolibarr members DN LDAPMemberDnExample=Complete DN (ex: ou=members,dc=example,dc=com) LDAPMemberObjectClassList=List of objectClass LDAPMemberObjectClassListExample=List of objectClass defining record attributes (ex: top,inetOrgPerson or top,user for active directory) +LDAPMemberTypeDn=Dolibarr members types DN +LDAPMemberTypepDnExample=Complete DN (ex: ou=memberstypes,dc=example,dc=com) +LDAPMemberTypeObjectClassList=List of objectClass +LDAPMemberTypeObjectClassListExample=List of objectClass defining record attributes (ex: top,groupOfUniqueNames) LDAPUserObjectClassList=List of objectClass LDAPUserObjectClassListExample=List of objectClass defining record attributes (ex: top,inetOrgPerson or top,user for active directory) LDAPGroupObjectClassList=List of objectClass @@ -1302,6 +1310,7 @@ LDAPTestSynchroContact=Test contacts synchronization LDAPTestSynchroUser=Test user synchronization LDAPTestSynchroGroup=Test group synchronization LDAPTestSynchroMember=Test member synchronization +LDAPTestSynchroMemberType=Test member type synchronization LDAPTestSearch= Test a LDAP search LDAPSynchroOK=Synchronization test successful LDAPSynchroKO=Failed synchronization test @@ -1367,6 +1376,7 @@ LDAPDescContact=This page allows you to define LDAP attributes name in LDAP tree LDAPDescUsers=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr users. LDAPDescGroups=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr groups. LDAPDescMembers=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr members module. +LDAPDescMembersTypes=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr members types. LDAPDescValues=Example values are designed for OpenLDAP with following loaded schemas: core.schema, cosine.schema, inetorgperson.schema). If you use thoose values and OpenLDAP, modify your LDAP config file slapd.conf to have all thoose schemas loaded. ForANonAnonymousAccess=For an authenticated access (for a write access for example) PerfDolibarr=Performance setup/optimizing report diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 003eedeac8a..a4777f3ae09 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -104,6 +104,7 @@ ErrorForbidden2=Permission for this login can be defined by your Dolibarr admini ErrorForbidden3=It seems that Dolibarr is not used through an authenticated session. Take a look at Dolibarr setup documentation to know how to manage authentications (htaccess, mod_auth or other...). ErrorNoImagickReadimage=Class Imagick is not found in this PHP. No preview can be available. Administrators can disable this tab from menu Setup - Display. ErrorRecordAlreadyExists=Record already exists +ErrorLabelAlreadyExists=This label already exists ErrorCantReadFile=Failed to read file '%s' ErrorCantReadDir=Failed to read directory '%s' ErrorBadLoginPassword=Bad value for login or password diff --git a/htdocs/langs/en_US/ldap.lang b/htdocs/langs/en_US/ldap.lang index 42e699de311..d6360f3e540 100644 --- a/htdocs/langs/en_US/ldap.lang +++ b/htdocs/langs/en_US/ldap.lang @@ -6,6 +6,7 @@ LDAPInformationsForThisContact=Information in LDAP database for this contact LDAPInformationsForThisUser=Information in LDAP database for this user LDAPInformationsForThisGroup=Information in LDAP database for this group LDAPInformationsForThisMember=Information in LDAP database for this member +LDAPInformationsForThisMemberType=Information in LDAP database for this member type LDAPAttributes=LDAP attributes LDAPCard=LDAP card LDAPRecordNotFound=Record not found in LDAP database @@ -20,6 +21,7 @@ LDAPFieldSkypeExample=Example : skypeName UserSynchronized=User synchronized GroupSynchronized=Group synchronized MemberSynchronized=Member synchronized +MemberTypeSynchronized=Member type synchronized ContactSynchronized=Contact synchronized ForceSynchronize=Force synchronizing Dolibarr -> LDAP ErrorFailedToReadLDAP=Failed to read LDAP database. Check LDAP module setup and database accessibility. diff --git a/htdocs/user/group/ldap.php b/htdocs/user/group/ldap.php index b7b1597ea74..ae0d974be9a 100644 --- a/htdocs/user/group/ldap.php +++ b/htdocs/user/group/ldap.php @@ -63,30 +63,31 @@ $object->getrights(); if ($action == 'dolibarr2ldap') { - $db->begin(); - $ldap=new Ldap(); $result=$ldap->connect_bind(); - $info=$object->_load_ldap_info(); - // Get a gid number for objectclass PosixGroup - if(in_array('posixGroup',$info['objectclass'])) - $info['gidNumber'] = $ldap->getNextGroupGid(); + if ($result > 0) + { + $info=$object->_load_ldap_info(); - $dn=$object->_load_ldap_dn($info); - $olddn=$dn; // We can say that old dn = dn as we force synchro + // Get a gid number for objectclass PosixGroup + if (in_array('posixGroup',$info['objectclass'])) { + $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_GROUPS'); + } - $result=$ldap->update($dn,$info,$user,$olddn); + $dn=$object->_load_ldap_dn($info); + $olddn=$dn; // We can say that old dn = dn as we force synchro + + $result=$ldap->update($dn,$info,$user,$olddn); + } if ($result >= 0) { setEventMessages($langs->trans("GroupSynchronized"), null, 'mesgs'); - $db->commit(); } else { setEventMessages($ldap->error, $ldap->errors, 'errors'); - $db->rollback(); } } From d9b3a4e45673667a8d4a32cebef1c44fdf455607 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 16 Sep 2017 21:58:05 +0200 Subject: [PATCH 013/108] Fix: phpcs --- htdocs/core/class/ldap.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 790772a9803..64e6f9fd5ef 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1411,8 +1411,8 @@ class Ldap /** * Return available value of group GID * - * @param string Key of group - * @return int gid number + * @param string $keygroup Key of group + * @return int gid number */ function getNextGroupGid($keygroup='LDAP_KEY_GROUPS') { From 1f88e624c26d95ec8abbdb87b2c9c97acffd4f9c Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sun, 17 Sep 2017 10:42:00 +0200 Subject: [PATCH 014/108] Fix: add ldap import/export script --- htdocs/admin/ldap.php | 2 +- .../sync_members_types_dolibarr2ldap.php | 131 +++++++++++ .../sync_members_types_ldap2dolibarr.php | 221 ++++++++++++++++++ test/phpunit/AdherentTest.php | 4 +- 4 files changed, 355 insertions(+), 3 deletions(-) create mode 100755 scripts/members/sync_members_types_dolibarr2ldap.php create mode 100755 scripts/members/sync_members_types_ldap2dolibarr.php diff --git a/htdocs/admin/ldap.php b/htdocs/admin/ldap.php index 77fdf6fc579..f9b863e487e 100644 --- a/htdocs/admin/ldap.php +++ b/htdocs/admin/ldap.php @@ -163,7 +163,7 @@ if (! empty($conf->adherent->enabled)) $arraylist=array(); $arraylist['0']=$langs->trans("No"); $arraylist['1']=$langs->trans("DolibarrToLDAP"); - //$arraylist['ldap2dolibarr']=$langs->trans("LDAPToDolibarr").' ('.$langs->trans("SupportedForLDAPImportScriptOnly").')'; + $arraylist['ldap2dolibarr']=$langs->trans("LDAPToDolibarr").' ('.$langs->trans("SupportedForLDAPImportScriptOnly").')'; print $form->selectarray('activememberstypes',$arraylist,$conf->global->LDAP_MEMBER_TYPE_ACTIVE); print ''.$langs->trans("LDAPDnMemberTypeActiveExample").''; } diff --git a/scripts/members/sync_members_types_dolibarr2ldap.php b/scripts/members/sync_members_types_dolibarr2ldap.php new file mode 100755 index 00000000000..939a98c8728 --- /dev/null +++ b/scripts/members/sync_members_types_dolibarr2ldap.php @@ -0,0 +1,131 @@ +#!/usr/bin/env php + + * Copyright (C) 2006 Laurent Destailleur + * Copyright (C) 2017 Regis Houssin + * + * 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 scripts/user/sync_members_types_dolibarr2ldap.php + * \ingroup ldap core + * \brief Script de mise a jour des types de membres dans LDAP depuis base Dolibarr + */ + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path=dirname(__FILE__).'/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; + exit(-1); +} + +if (! isset($argv[1]) || ! $argv[1]) { + print "Usage: ".$script_file." now\n"; + exit(-1); +} +$now=$argv[1]; + +require_once($path."../../htdocs/master.inc.php"); +require_once(DOL_DOCUMENT_ROOT."/core/class/ldap.class.php"); +require_once(DOL_DOCUMENT_ROOT."/adherents/class/adherent_type.class.php"); + +// Global variables +$version=DOL_VERSION; +$error=0; + + +/* + * Main + */ + +@set_time_limit(0); +print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." *****\n"; +dol_syslog($script_file." launched with arg ".join(',',$argv)); + +/* +if (! $conf->global->LDAP_SYNCHRO_ACTIVE) +{ + print $langs->trans("LDAPSynchronizationNotSetupInDolibarr"); + exit(-1); +} +*/ + +$sql = "SELECT rowid"; +$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type"; + +$resql = $db->query($sql); +if ($resql) +{ + $num = $db->num_rows($resql); + $i = 0; + + $ldap=new Ldap(); + $result=$ldap->connect_bind(); + + if ($result > 0) + { + while ($i < $num) + { + $ldap->error=""; + + $obj = $db->fetch_object($resql); + + $membertype = new AdherentType($db); + $membertype->id = $obj->rowid; + $membertype->fetch($membertype->id); + + print $langs->trans("UpdateMemberType")." rowid=".$membertype->id." ".$membertype-label; + + $oldobject=$membertype; + + $oldinfo=$membertype->_load_ldap_info(); + $olddn=$membertype->_load_ldap_dn($oldinfo); + + $info=$membertype->_load_ldap_info(); + $dn=$membertype->_load_ldap_dn($info); + + $result=$ldap->add($dn,$info,$user); // Wil fail if already exists + $result=$ldap->update($dn,$info,$user,$olddn); + if ($result > 0) + { + print " - ".$langs->trans("OK"); + } + else + { + $error++; + print " - ".$langs->trans("KO").' - '.$ldap->error; + } + print "\n"; + + $i++; + } + + $ldap->unbind(); + $ldap->close(); + } + else { + print $ldap->error; + } +} +else +{ + dol_print_error($db); +} + +exit($error); diff --git a/scripts/members/sync_members_types_ldap2dolibarr.php b/scripts/members/sync_members_types_ldap2dolibarr.php new file mode 100755 index 00000000000..fb8fb160d36 --- /dev/null +++ b/scripts/members/sync_members_types_ldap2dolibarr.php @@ -0,0 +1,221 @@ +#!/usr/bin/env php + + * Copyright (C) 2006-2012 Laurent Destailleur + * Copyright (C) 2013 Maxime Kohlhaas + * Copyright (C) 2017 Regis Houssin + * + * 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 scripts/user/sync_members_types_ldap2dolibarr.php + * \ingroup ldap member + * \brief Script to update members types into Dolibarr from LDAP + */ + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path=dirname(__FILE__).'/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; + exit(-1); +} + +require_once($path."../../htdocs/master.inc.php"); +require_once(DOL_DOCUMENT_ROOT."/core/lib/date.lib.php"); +require_once(DOL_DOCUMENT_ROOT."/core/class/ldap.class.php"); +require_once(DOL_DOCUMENT_ROOT."/adherents/class/adherent_type.class.php"); + +$langs->load("main"); +$langs->load("errors"); + + +// Global variables +$version=DOL_VERSION; +$error=0; +$forcecommit=0; +$confirmed=0; + + +/* + * Main + */ + +@set_time_limit(0); +print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." *****\n"; +dol_syslog($script_file." launched with arg ".join(',',$argv)); + +// List of fields to get from LDAP +$required_fields = array( + $conf->global->LDAP_KEY_MEMBERS_TYPES, + $conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME, + $conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION, + $conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS +); + +// Remove from required_fields all entries not configured in LDAP (empty) and duplicated +$required_fields=array_unique(array_values(array_filter($required_fields, "dolValidElement"))); + + +if (! isset($argv[1])) { + //print "Usage: $script_file (nocommitiferror|commitiferror) [id_group]\n"; + print "Usage: $script_file (nocommitiferror|commitiferror) [--server=ldapserverhost] [--excludeuser=user1,user2...] [-y]\n"; + exit(-1); +} + +foreach($argv as $key => $val) +{ + if ($val == 'commitiferror') $forcecommit=1; + if (preg_match('/--server=([^\s]+)$/',$val,$reg)) $conf->global->LDAP_SERVER_HOST=$reg[1]; + if (preg_match('/--excludeuser=([^\s]+)$/',$val,$reg)) $excludeuser=explode(',',$reg[1]); + if (preg_match('/-y$/',$val,$reg)) $confirmed=1; +} + +print "Mails sending disabled (useless in batch mode)\n"; +$conf->global->MAIN_DISABLE_ALL_MAILS=1; // On bloque les mails +print "\n"; +print "----- Synchronize all records from LDAP database:\n"; +print "host=".$conf->global->LDAP_SERVER_HOST."\n"; +print "port=".$conf->global->LDAP_SERVER_PORT."\n"; +print "login=".$conf->global->LDAP_ADMIN_DN."\n"; +print "pass=".preg_replace('/./i','*',$conf->global->LDAP_ADMIN_PASS)."\n"; +print "DN to extract=".$conf->global->LDAP_MEMBER_TYPE_DN."\n"; +print 'Filter=('.$conf->global->LDAP_KEY_MEMBERS_TYPES.'=*)'."\n"; +print "----- To Dolibarr database:\n"; +print "type=".$conf->db->type."\n"; +print "host=".$conf->db->host."\n"; +print "port=".$conf->db->port."\n"; +print "login=".$conf->db->user."\n"; +print "database=".$conf->db->name."\n"; +print "----- Options:\n"; +print "commitiferror=".$forcecommit."\n"; +print "Mapped LDAP fields=".join(',',$required_fields)."\n"; +print "\n"; + +if (! $confirmed) +{ + print "Hit Enter to continue or CTRL+C to stop...\n"; + $input = trim(fgets(STDIN)); +} + +if (empty($conf->global->LDAP_MEMBER_TYPE_DN)) +{ + print $langs->trans("Error").': '.$langs->trans("LDAP setup for members types not defined inside Dolibarr"); + exit(-1); +} + + +$ldap = new Ldap(); +$result = $ldap->connect_bind(); +if ($result >= 0) +{ + $justthese=array(); + + + // We disable synchro Dolibarr-LDAP + $conf->global->LDAP_MEMBER_TYPE_ACTIVE=0; + + $ldaprecords = $ldap->getRecords('*',$conf->global->LDAP_MEMBER_TYPE_DN, $conf->global->LDAP_KEY_MEMBERS_TYPES, $required_fields, 0, array($conf->global->LDAP_MEMBER_TYPE_FIELD_GROUPMEMBERS)); + if (is_array($ldaprecords)) + { + $db->begin(); + + // Warning $ldapuser has a key in lowercase + foreach ($ldaprecords as $key => $ldapgroup) + { + $membertype = new AdherentType($db); + $membertype->fetch('', $ldapgroup[$conf->global->LDAP_KEY_MEMBERS_TYPES]); + $membertype->label = $ldapgroup[$conf->global->LDAP_MEMBER_TYPE_FIELD_FULLNAME]; + $membertype->description = $ldapgroup[$conf->global->LDAP_MEMBER_TYPE_FIELD_DESCRIPTION]; + $membertype->entity = $conf->entity; + + //print_r($ldapgroup); + + if ($membertype->id > 0) { // Member type update + print $langs->transnoentities("MemberTypeUpdate").' # '.$key.': name='.$membertype->label; + $res=$membertype->update($user); + + if ($res > 0) + { + print ' --> Updated member type id='.$membertype->id.' name='.$membertype->label; + } + else + { + $error++; + print ' --> '.$res.' '.$membertype->error; + } + print "\n"; + } else { // Member type creation + print $langs->transnoentities("MemberTypeCreate").' # '.$key.': name='.$membertype->label; + $res=$membertype->create($user); + + if ($res > 0) + { + print ' --> Created member type id='.$membertype->id.' name='.$membertype->label; + } + else + { + $error++; + print ' --> '.$res.' '.$membertype->error; + } + print "\n"; + } + + //print_r($membertype); + } + + if (! $error || $forcecommit) + { + if (! $error) print $langs->transnoentities("NoErrorCommitIsDone")."\n"; + else print $langs->transnoentities("ErrorButCommitIsDone")."\n"; + $db->commit(); + } + else + { + print $langs->transnoentities("ErrorSomeErrorWereFoundRollbackIsDone",$error)."\n"; + $db->rollback(); + } + print "\n"; + } + else + { + dol_print_error('',$ldap->error); + $error++; + } +} +else +{ + dol_print_error('',$ldap->error); + $error++; +} + + +exit($error); + + +/** + * Function to say if a value is empty or not + * + * @param string $element Value to test + * @return boolean True of false + */ +function dolValidElement($element) +{ + return (trim($element) != ''); +} + diff --git a/test/phpunit/AdherentTest.php b/test/phpunit/AdherentTest.php index 34ec0a80917..357ae3744e9 100644 --- a/test/phpunit/AdherentTest.php +++ b/test/phpunit/AdherentTest.php @@ -138,8 +138,8 @@ class AdherentTest extends PHPUnit_Framework_TestCase $localobject=new AdherentType($this->savdb); $localobject->statut=1; - $localobject->libelle='Adherent type test'; - $localobject->cotisation=1; + $localobject->label='Adherent type test'; + $localobject->subscription=1; $localobject->vote=1; $result=$localobject->create($user); print __METHOD__." result=".$result."\n"; From 4043141ae3f3dfbb45c2d89f93fcb758f95a3636 Mon Sep 17 00:00:00 2001 From: TuxGasy Date: Mon, 18 Sep 2017 14:11:21 +0200 Subject: [PATCH 015/108] Allow create shipping if STOCK_SUPPORTS_SERVICES option is enabled --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 4d8bc4335e5..9de9ffed222 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2541,7 +2541,7 @@ if ($action == 'create' && $user->rights->commande->creer) if (! empty($conf->expedition->enabled)) { $numshipping = $object->nb_expedition(); - if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfProductsLines() > 0) { + if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES))) { if (($conf->expedition_bon->enabled && $user->rights->expedition->creer) || ($conf->livraison_bon->enabled && $user->rights->expedition->livraison->creer)) { if ($user->rights->expedition->creer) { print ''; From 4c97f5514db91f78e08b087ec3d25582c9822792 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Sep 2017 15:25:04 +0200 Subject: [PATCH 016/108] FIX #7366 renaming table with pgsql --- htdocs/install/mysql/migration/4.0.0-5.0.0.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql index cd535c5c119..42389a5c2dd 100644 --- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql +++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql @@ -4,6 +4,7 @@ -- when current version is 4.0.0 or higher. -- -- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- -- VPGSQL8.2 ALTER SEQUENCE IF EXISTS llx_table_rowid_seq RENAME TO llx_table_new_rowid_seq; -- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; -- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); -- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; @@ -120,6 +121,8 @@ create table llx_expensereport_extrafields ALTER TABLE llx_expensereport_extrafields ADD INDEX idx_expensereport_extrafields (fk_object); ALTER TABLE llx_cotisation RENAME TO llx_subscription; +-- VPGSQL8.2 ALTER SEQUENCE IF EXISTS llx_cotisation_rowid_seq RENAME TO llx_subscription_rowid_seq; + ALTER TABLE llx_subscription ADD UNIQUE INDEX uk_subscription (fk_adherent,dateadh); ALTER TABLE llx_subscription CHANGE COLUMN cotisation subscription real; ALTER TABLE llx_adherent_type CHANGE COLUMN cotisation subscription varchar(3) NOT NULL DEFAULT '1'; From 278bcfa8da6fd13becd9cfeff8a32b359794acae Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Sep 2017 15:31:22 +0200 Subject: [PATCH 017/108] FIX #7148 --- htdocs/admin/multicurrency.php | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index b03872a8fbd..9ae20ac06d7 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -61,7 +61,7 @@ if (preg_match('/set_(.*)/',$action,$reg)) dol_print_error($db); } } - + if (preg_match('/del_(.*)/',$action,$reg)) { $code=$reg[1]; @@ -79,7 +79,7 @@ if (preg_match('/del_(.*)/',$action,$reg)) if ($action == 'add_currency') { $langs->loadCacheCurrencies(''); - + $code = GETPOST('code', 'alpha'); $rate = GETPOST('rate', 'alpha'); $currency = new MultiCurrency($db); @@ -96,23 +96,23 @@ if ($action == 'add_currency') elseif ($action == 'update_currency') { $submit = GETPOST('submit', 'alpha'); - + if ($submit == $langs->trans('Modify')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); - $rate = GETPOST('rate', 'float'); + $rate = price2num(GETPOST('rate', 'alpha')); $currency = new MultiCurrency($db); - + if ($currency->fetch($fk_multicurrency) > 0) { $currency->updateRate($rate); - } + } } elseif ($submit == $langs->trans('Delete')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); $currency = new MultiCurrency($db); - + if ($currency->fetch($fk_multicurrency) > 0) { if ($currency->delete() > 0) setEventMessages($langs->trans('RecordDeleted'), array()); @@ -120,14 +120,14 @@ elseif ($action == 'update_currency') } } } -elseif ($action == 'synchronize') +elseif ($action == 'synchronize') { $response = GETPOST('response'); $response = json_decode($response); - + if ($response->success) { - MultiCurrency::syncRates($response); + MultiCurrency::syncRates($response); } else { @@ -226,7 +226,7 @@ print ''; print ''; */ -/* TODO uncomment when the functionality will integrated +/* TODO uncomment when the functionality will integrated $var=!$var; print ''; print ''.$langs->transnoentitiesnoconv("multicurrency_modifyRateApplication").''; @@ -259,8 +259,8 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print $langs->trans("Value").' '; print ''; print ''; - - + + $var=!$var; print ''; print ''.$langs->transnoentitiesnoconv("multicurrency_appId").''; @@ -273,7 +273,7 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''; print ''; print ''; - + $var=!$var; print ''; print ''.$langs->transnoentitiesnoconv("multicurrency_appCurrencySource").''; @@ -286,7 +286,7 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''; print ''; print ''; - + $var=!$var; print ''; print ''.$langs->transnoentitiesnoconv("multicurrency_alternateCurrencySource").''; @@ -299,7 +299,7 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''; print ''; print ''; - + print ''; print '
'; } @@ -334,7 +334,7 @@ print ''; foreach ($TCurrency as &$currency) { if($currency->code == $conf->currency) continue; - + $var=!$var; print ''; print ''.$currency->code.' - '.$currency->name.''; @@ -363,7 +363,7 @@ print ' { $("#bt_sync").attr("disabled", true); var url_sync = "http://apilayer.net/api/live?access_key='.$conf->global->MULTICURRENCY_APP_ID.'&format=1'.(!empty($conf->global->MULTICURRENCY_APP_SOURCE) ? '&source='.$conf->global->MULTICURRENCY_APP_SOURCE : '').'"; - + $.ajax({ url: url_sync, dataType: "jsonp" From f5bc9c08b124b50f9661304c4c4a102d6c2e8ec9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Sep 2017 11:38:28 +0200 Subject: [PATCH 018/108] Missing css --- htdocs/theme/eldy/style.css.php | 6 ++++++ htdocs/theme/md/style.css.php | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 90bcb8522de..6c07c9fa734 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -586,6 +586,12 @@ div.myavailability { text-overflow: ellipsis; white-space: nowrap; } +.tdoverflowmax200 { /* For tdoverflow, the max-midth become a minimum ! */ + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} .tdoverflowmax300 { /* For tdoverflow, the max-midth become a minimum ! */ max-width: 300px; overflow: hidden; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 60c52e8683f..ff217042b23 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -564,6 +564,12 @@ div.myavailability { text-overflow: ellipsis; white-space: nowrap; } +.tdoverflowmax200 { /* For tdoverflow, the max-midth become a minimum ! */ + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} .tdoverflowmax300 { max-width: 300px; overflow: hidden; From 815d0aff900af35cc5d9e819c143df1862a5ad90 Mon Sep 17 00:00:00 2001 From: atm-quentin Date: Tue, 19 Sep 2017 15:10:18 +0200 Subject: [PATCH 019/108] FIX for free line select unit was wrong --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a684cff7165..32480e5cf15 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3274,7 +3274,7 @@ class Form $return= ''; print ''; print ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) +{ + $ret = $object->fetch_all('', '', 0, 0, $filter); + if($ret == -1) { + dol_print_error($db,$object->error); + exit; + } else { + $nbtotalofrecords = $ret; + } +} + +// Load object list +$ret = $object->fetch_all($sortorder, $sortfield, $limit, $offset, $filter); +if($ret == -1) { + dol_print_error($db,$object->error); + exit; +} else { + print_barre_liste($pagetitle, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $ret+1, $nbtotalofrecords,'title_generic.png', 0, '', '', $limit); +} + $moreforfilter = ''; print '
'; From 296e678c1be26500c87a56bc46fbe0db84573b7b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Sep 2017 12:02:46 +0200 Subject: [PATCH 037/108] Solve url too long with paybox --- htdocs/public/payment/newpayment.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 52aa5950a92..1862a5b8a47 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -143,12 +143,11 @@ if (! empty($FULLTAG)) $urlok.='fulltag='.urlencode($FULLTAG).'&'; $urlko.='fulltag='.urlencode($FULLTAG).'&'; } -/* This make url too long. Seems not required into the back url if (! empty($SECUREKEY)) { $urlok.='securekey='.urlencode($SECUREKEY).'&'; $urlko.='securekey='.urlencode($SECUREKEY).'&'; -}*/ +} if (! empty($entity)) { $urlok.='e='.urlencode($entity).'&'; @@ -336,6 +335,10 @@ if ($action == 'dopayment') $origfulltag=GETPOST("fulltag",'alpha'); + // Securekey into back url useless for back url and we need an url lower than 150. + $urlok = preg_replace('/securekey=[^&]+/', '', $urlok); + $urlko = preg_replace('/securekey=[^&]+/', '', $urlko); + $mesg=''; if (empty($PRICE) || ! is_numeric($PRICE)) $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Amount")); elseif (empty($email)) $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("YourEMail")); From 76c3fe1260cd5cd50f16b6f50997381543183401 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Thu, 21 Sep 2017 12:06:43 +0200 Subject: [PATCH 038/108] Fix: Stripe not working on live mode --- htdocs/stripe/config.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/stripe/config.php b/htdocs/stripe/config.php index 0cc15c7fb60..9aaed7cf0b9 100644 --- a/htdocs/stripe/config.php +++ b/htdocs/stripe/config.php @@ -1,6 +1,7 @@ * Copyright (C) 2017 Saasprov + * Copyright (C) 2017 Ferran Marcet * * 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 @@ -32,7 +33,7 @@ global $conf; //use \includes\stripe as stripe; $stripe = array(); -if (empty($conf->global->SKYPE_LIVE)) +if (empty($conf->global->STRIPE_LIVE)) { $stripe = array( "secret_key" => $conf->global->STRIPE_TEST_SECRET_KEY, From 01f9d59e759d6daef533521f08a0508877169467 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 21 Sep 2017 12:16:01 +0200 Subject: [PATCH 039/108] Fix: use another method --- htdocs/adherents/class/adherent.class.php | 18 +++---- .../adherents/class/adherent_type.class.php | 9 ++-- htdocs/adherents/type.php | 4 ++ htdocs/adherents/type_ldap.php | 2 + ...interface_50_modLdap_Ldapsynchro.class.php | 54 +++++++++++-------- 5 files changed, 49 insertions(+), 38 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 47bf219216c..ffeb68c9445 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -729,7 +729,15 @@ class Adherent extends CommonObject // Check parameters if (empty($rowid)) $rowid=$this->id; - $this->db->begin(); + $this->db->begin(); + + if (! $error && ! $notrigger) + { + // Call trigger + $result=$this->call_trigger('MEMBER_DELETE',$user); + if ($result < 0) $error++; + // End call triggers + } // Remove category $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".$rowid; @@ -797,14 +805,6 @@ class Adherent extends CommonObject } } - if (! $error && ! $notrigger) - { - // Call trigger - $result=$this->call_trigger('MEMBER_DELETE',$user); - if ($result < 0) $error++; - // End call triggers - } - if (! $error) { $this->db->commit(); diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 7293fd10e90..30c85618bfa 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -256,10 +256,9 @@ class AdherentType extends CommonObject * Fonction qui permet de recuperer le status de l'adherent * * @param int $rowid Id of member type to load - * @param bool $load_members Load members or not * @return int <0 if KO, >0 if OK */ - function fetch($rowid, $load_members = true) + function fetch($rowid) { $sql = "SELECT d.rowid, d.libelle as label, d.statut, d.subscription, d.mail_valid, d.note, d.vote"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; @@ -282,10 +281,6 @@ class AdherentType extends CommonObject $this->mail_valid = $obj->mail_valid; $this->note = $obj->note; $this->vote = $obj->vote; - - if ($load_members) { - $this->members=$this->listMembersForMemberType(); - } } return 1; @@ -375,6 +370,8 @@ class AdherentType extends CommonObject $this->db->free($resql); + $this->members=$ret; + return $ret; } else diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index b59d8b7530d..ee9f9b2f3c8 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -154,6 +154,10 @@ if ($action == 'update' && $user->rights->adherent->configurer) { $object->fetch($rowid); + if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') { + $object->listMembersForMemberType(); + } + $object->oldcopy = clone $object; $object->label = trim($label); diff --git a/htdocs/adherents/type_ldap.php b/htdocs/adherents/type_ldap.php index e610f651df5..d4de1a2afdb 100644 --- a/htdocs/adherents/type_ldap.php +++ b/htdocs/adherents/type_ldap.php @@ -63,6 +63,8 @@ if (empty($reshook)) if ($result > 0) { + $object->listMembersForMemberType(); + $info = $object->_load_ldap_info(); $dn = $object->_load_ldap_dn($info); $olddn = $dn; // We can say that old dn = dn as we force synchro diff --git a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php index 05a9a5a1b20..a906ec821ed 100644 --- a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php +++ b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php @@ -437,6 +437,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers if ($object->typeid > 0) { $membertype->fetch($object->typeid); + $membertype->listMembersForMemberType(); $oldinfo=$membertype->_load_ldap_info(); $olddn=$membertype->_load_ldap_dn($oldinfo); @@ -549,36 +550,38 @@ class InterfaceLdapsynchro extends DolibarrTriggers // For member type if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') { + /* + * Change member info + */ + $newmembertype=new AdherentType($this->db); + $newmembertype->fetch($object->typeid); + $newmembertype->listMembersForMemberType(); + + $oldinfo=$newmembertype->_load_ldap_info(); + $olddn=$newmembertype->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container=$newmembertype->_load_ldap_dn($oldinfo,1); + $search = "(".$newmembertype->_load_ldap_dn($oldinfo,2).")"; + $records=$ldap->search($container,$search); + if (count($records) && $records['count'] == 0) + { + $olddn = ''; + } + + $info=$newmembertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn=$newmembertype->_load_ldap_dn($info); + + $result=$ldap->update($dn,$info,$user,$olddn); + if ($object->oldcopy->typeid != $object->typeid) { - /* - * Add member in new member type - */ - $newmembertype=new AdherentType($this->db); - $newmembertype->fetch($object->typeid); - - $oldinfo=$newmembertype->_load_ldap_info(); - $olddn=$newmembertype->_load_ldap_dn($oldinfo); - - // Verify if entry exist - $container=$newmembertype->_load_ldap_dn($oldinfo,1); - $search = "(".$newmembertype->_load_ldap_dn($oldinfo,2).")"; - $records=$ldap->search($container,$search); - if (count($records) && $records['count'] == 0) - { - $olddn = ''; - } - - $info=$newmembertype->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) - $dn=$newmembertype->_load_ldap_dn($info); - - $result=$ldap->update($dn,$info,$user,$olddn); - /* * Remove member in old member type */ $oldmembertype=new AdherentType($this->db); $oldmembertype->fetch($object->oldcopy->typeid); + $oldmembertype->listMembersForMemberType(); $oldinfo=$oldmembertype->_load_ldap_info(); $olddn=$oldmembertype->_load_ldap_dn($oldinfo); @@ -676,6 +679,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers */ $membertype=new AdherentType($this->db); $membertype->fetch($object->typeid); + $membertype->listMembersForMemberType('a.rowid != ' . $object->id); // remove deleted member from the list $oldinfo=$membertype->_load_ldap_info(); $olddn=$membertype->_load_ldap_dn($oldinfo); @@ -742,6 +746,8 @@ class InterfaceLdapsynchro extends DolibarrTriggers $object->oldcopy = clone $object; } + $object->oldcopy->listMembersForMemberType(); + $oldinfo=$object->oldcopy->_load_ldap_info(); $olddn=$object->oldcopy->_load_ldap_dn($oldinfo); @@ -754,6 +760,8 @@ class InterfaceLdapsynchro extends DolibarrTriggers $olddn = ''; } + $object->listMembersForMemberType(); + $info=$object->_load_ldap_info(); $dn=$object->_load_ldap_dn($info); From 71fc5a99d6c08758f80c394122aa88be7c86ae0d Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 21 Sep 2017 12:19:14 +0200 Subject: [PATCH 040/108] Fix: list already load in trigger --- htdocs/adherents/type.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index ee9f9b2f3c8..b59d8b7530d 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -154,10 +154,6 @@ if ($action == 'update' && $user->rights->adherent->configurer) { $object->fetch($rowid); - if (! empty($conf->global->LDAP_MEMBER_TYPE_ACTIVE) && (string) $conf->global->LDAP_MEMBER_TYPE_ACTIVE == '1') { - $object->listMembersForMemberType(); - } - $object->oldcopy = clone $object; $object->label = trim($label); From 8f19ffd097f695f10c45f8d44cf7d654a626741e Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 21 Sep 2017 12:22:10 +0200 Subject: [PATCH 041/108] Fix contract class for date --- htdocs/contrat/class/contrat.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 24b51e835a2..52bc7efd860 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -872,7 +872,7 @@ class Contrat extends CommonObject $sql.= " fk_commercial_signature, fk_commercial_suivi, fk_projet,"; $sql.= " ref, entity, note_private, note_public, ref_customer, ref_supplier, ref_ext)"; $sql.= " VALUES ('".$this->db->idate($now)."',".$this->socid.",".$user->id; - $sql.= ", '".$this->db->idate($this->date_contrat)."'"; + $sql.= ", ".(dol_strlen($this->date_contrat)!=0 ? "'".$this->db->idate($this->date_contrat)."'" : "NULL"); $sql.= ",".($this->commercial_signature_id>0?$this->commercial_signature_id:"NULL"); $sql.= ",".($this->commercial_suivi_id>0?$this->commercial_suivi_id:"NULL"); $sql.= ",".($this->fk_project>0?$this->fk_project:"NULL"); From 96efe43e3cbcc8c8f7a94b5187be927cbc679068 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Sep 2017 12:48:07 +0200 Subject: [PATCH 042/108] NEW Provide a way to download a file from a public URL. --- htdocs/document.php | 37 ++++++++++++++++++++++++++--- htdocs/ecm/class/ecmfiles.class.php | 15 +++++++++--- htdocs/ecm/docfile.php | 30 ++++++++++++++--------- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/htdocs/document.php b/htdocs/document.php index d35021005e6..c09441ea0ed 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -59,24 +59,28 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $encoding = ''; $action=GETPOST('action','alpha'); -$original_file=GETPOST('file','alpha'); // Do not use urldecode here ($_GET are already decoded by PHP). +$original_file=GETPOST('file','alpha'); // Do not use urldecode here ($_GET are already decoded by PHP). +$hashn=GETPOST('hashn','aZ09'); +$hashc=GETPOST('hashc','aZ09'); $modulepart=GETPOST('modulepart','alpha'); $urlsource=GETPOST('urlsource','alpha'); $entity=GETPOST('entity','int')?GETPOST('entity','int'):$conf->entity; // Security check -if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart'); +if (empty($modulepart)) accessforbidden('Bad link. Bad value for parameter modulepart',0,0,1); +if (empty($original_file) && empty($hashn) && empty($hashc)) accessforbidden('Bad link. Missing identification to find file (original_file, hasn or hashc)',0,0,1); if ($modulepart == 'fckeditor') $modulepart='medias'; // For backward compatibility $socid=0; if ($user->societe_id > 0) $socid = $user->societe_id; // For some module part, dir may be privates -if (in_array($modulepart,array('facture_paiement','unpaid'))) +if (in_array($modulepart, array('facture_paiement','unpaid'))) { if (! $user->rights->societe->client->voir || $socid) $original_file='private/'.$user->id.'/'.$original_file; // If user has no permission to see all, output dir is specific to user } + /* * Action */ @@ -99,6 +103,33 @@ if (preg_match('/\.(html|htm)$/i',$original_file)) $attachment = false; if (isset($_GET["attachment"])) $attachment = GETPOST("attachment",'alpha')?true:false; if (! empty($conf->global->MAIN_DISABLE_FORCE_SAVEAS)) $attachment=false; +// If we have a hash (hashc or hashn), we guess the original_file. Note: using hashn is not reliable. +if (! empty($hashn) || ! empty($hashc)) +{ + include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; + $ecmfile=new EcmFiles($db); + $result = $ecmfile->fetch(0, $hashn, '', $hashc); + if ($result > 0) + { + $tmp = explode('/', $ecmfile->filepath, 2); // $ecmfile->filepatch is relative to document directory + $moduleparttocheck = $tmp[0]; + if ($moduleparttocheck == $modulepart) + { + $original_file = (($tmp[1]?$tmp[1].'/':'').$ecmfile->filename); // this is relative to module dir + //var_dump($original_file); exit; + } + else + { + accessforbidden('Bad link. File owns to another module part.',0,0,1); + } + } + else + { + accessforbidden('Bad link. File was not found or removed recently.',0,0,1); + } +} + + // Security: Delete string ../ into $original_file $original_file = str_replace("../","/", $original_file); diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index abe5c403462..77fa294aeed 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -157,6 +157,7 @@ class EcmFiles //extends CommonObject // Insert request $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '('; + $sql.= 'ref,'; $sql.= 'label,'; $sql.= 'entity,'; $sql.= 'filename,'; @@ -174,6 +175,7 @@ class EcmFiles //extends CommonObject $sql.= 'fk_user_m,'; $sql.= 'acl'; $sql .= ') VALUES ('; + $sql .= " '".dol_hash($this->filepath.'/'.$this->filename, 3)."', "; $sql .= ' '.(! isset($this->label)?'NULL':"'".$this->db->escape($this->label)."'").','; $sql .= ' '.(! isset($this->entity)?$conf->entity:$this->entity).','; $sql .= ' '.(! isset($this->filename)?'NULL':"'".$this->db->escape($this->filename)."'").','; @@ -232,11 +234,12 @@ class EcmFiles //extends CommonObject * Load object in memory from the database * * @param int $id Id object - * @param string $ref Not used yet. Will contains a hash id from filename+filepath + * @param string $ref Hash of file name (filename+filepath). Not always defined on some version. * @param string $relativepath Relative path of file from document directory. Example: path/path2/file + * @param string $hashoffile Hash of file content. Take the first one found if same file is at different places. This hash will also change if file content is changed. * @return int <0 if KO, 0 if not found, >0 if OK */ - public function fetch($id, $ref = null, $relativepath = '') + public function fetch($id, $ref = '', $relativepath = '', $hashoffile='') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -268,11 +271,16 @@ class EcmFiles //extends CommonObject if ($relativepath) { $sql .= " AND t.filepath = '" . $this->db->escape(dirname($relativepath)) . "' AND t.filename = '".$this->db->escape(basename($relativepath))."'"; } - elseif (null !== $ref) { + elseif (! empty($ref)) { $sql .= " AND t.ref = '".$this->db->escape($ref)."'"; + } + elseif (! empty($hashoffile)) { + $sql .= " AND t.label = '".$this->db->escape($hashoffile)."'"; } else { $sql .= ' AND t.rowid = ' . $id; } + $this->db->plimit(1); + $this->db->order('t.rowid', 'ASC'); // When we search on hash of content, we take the first one. $resql = $this->db->query($sql); if ($resql) { @@ -484,6 +492,7 @@ class EcmFiles //extends CommonObject // Update request $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET'; + $sql .= ' ref = '.dol_hash($this->filepath.'/'.$this->filename, 3); $sql .= ' label = '.(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").','; $sql .= ' entity = '.(isset($this->entity)?$this->entity:$conf->entity).','; $sql .= ' filename = '.(isset($this->filename)?"'".$this->db->escape($this->filename)."'":"null").','; diff --git a/htdocs/ecm/docfile.php b/htdocs/ecm/docfile.php index 045c3ebda8b..aa708a85f24 100644 --- a/htdocs/ecm/docfile.php +++ b/htdocs/ecm/docfile.php @@ -287,17 +287,25 @@ print ' '.$langs->trans("Download").''; print ''; print ''.$langs->trans("DirectDownloadLink").''; -$modulepart='ecm'; -$forcedownload=1; -$rellink='/document.php?modulepart='.$modulepart; -if ($forcedownload) $rellink.='&attachment=1'; -if (! empty($object->entity)) $rellink.='&entity='.$object->entity; -$rellink.='&file='.urlencode($filepath); -$fulllink=$urlwithroot.$rellink; -// TODO -//print img_picto('','object_globe.png').' '; -//print ''; -//print ' '.$langs->trans("Download").''; +if (! empty($ecmfile->ref) || ! empty($ecmfile->label)) +{ + $modulepart='ecm'; + $forcedownload=1; + $rellink='/document.php?modulepart='.$modulepart; + if ($forcedownload) $rellink.='&attachment=1'; + if (! empty($object->entity)) $rellink.='&entity='.$object->entity; + //$rellink.='&file='.urlencode($filepath); // No need of name of file for public link, we will use the hash + $fulllink=$urlwithroot.$rellink; + if (! empty($ecmfile->ref)) $fulllink.='&hashn='.$ecmfile->ref; // Hash of file path + elseif (! empty($ecmfile->label)) $fulllink.='&hashc='.$ecmfile->label; // Hash of file content + print img_picto('','object_globe.png').' '; + print ''; + print ' '.$langs->trans("Download").''; +} +else +{ + print img_warning().' '.$langs->trans("FileNotYetIndexedInDatabase"); +} print ''; print ''; From 57358f0ce5d5a626f38ae87385c493b5fde641fe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Sep 2017 14:02:42 +0200 Subject: [PATCH 043/108] NEW Provide a way to download a file from a public URL for files in ECM --- htdocs/document.php | 11 +- htdocs/ecm/class/ecmfiles.class.php | 43 ++++- htdocs/ecm/docfile.php | 162 +++++++++++------- .../install/mysql/migration/6.0.0-7.0.0.sql | 5 + htdocs/install/mysql/tables/llx_ecm_files.sql | 5 +- htdocs/langs/en_US/ecm.lang | 5 +- htdocs/langs/en_US/main.lang | 3 +- htdocs/langs/en_US/website.lang | 2 +- 8 files changed, 158 insertions(+), 78 deletions(-) diff --git a/htdocs/document.php b/htdocs/document.php index c09441ea0ed..590d47d2c13 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -60,15 +60,14 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $encoding = ''; $action=GETPOST('action','alpha'); $original_file=GETPOST('file','alpha'); // Do not use urldecode here ($_GET are already decoded by PHP). -$hashn=GETPOST('hashn','aZ09'); -$hashc=GETPOST('hashc','aZ09'); +$hashp=GETPOST('hashp','aZ09'); $modulepart=GETPOST('modulepart','alpha'); $urlsource=GETPOST('urlsource','alpha'); $entity=GETPOST('entity','int')?GETPOST('entity','int'):$conf->entity; // Security check if (empty($modulepart)) accessforbidden('Bad link. Bad value for parameter modulepart',0,0,1); -if (empty($original_file) && empty($hashn) && empty($hashc)) accessforbidden('Bad link. Missing identification to find file (original_file, hasn or hashc)',0,0,1); +if (empty($original_file) && empty($hashp)) accessforbidden('Bad link. Missing identification to find file (original_file or hashp)',0,0,1); if ($modulepart == 'fckeditor') $modulepart='medias'; // For backward compatibility $socid=0; @@ -103,12 +102,12 @@ if (preg_match('/\.(html|htm)$/i',$original_file)) $attachment = false; if (isset($_GET["attachment"])) $attachment = GETPOST("attachment",'alpha')?true:false; if (! empty($conf->global->MAIN_DISABLE_FORCE_SAVEAS)) $attachment=false; -// If we have a hash (hashc or hashn), we guess the original_file. Note: using hashn is not reliable. -if (! empty($hashn) || ! empty($hashc)) +// If we have a hash public (hashp), we guess the original_file. +if (! empty($hashp)) { include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; $ecmfile=new EcmFiles($db); - $result = $ecmfile->fetch(0, $hashn, '', $hashc); + $result = $ecmfile->fetch(0, '', '', '', $hashp); if ($result > 0) { $tmp = explode('/', $ecmfile->filepath, 2); // $ecmfile->filepatch is relative to document directory diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 77fa294aeed..0035b18d3c7 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -46,7 +46,9 @@ class EcmFiles //extends CommonObject /** */ - public $label; // hash of file md5_file(dol_osencode($destfull)), so MD5 of file content + public $ref; // hash of file path + public $label; // hash of file content (md5_file(dol_osencode($destfull)) + public $share; // hash for file sharing. empty by default public $entity; public $filename; public $filepath; @@ -94,10 +96,15 @@ class EcmFiles //extends CommonObject $error = 0; // Clean parameters - + if (isset($this->ref)) { + $this->ref = trim($this->ref); + } if (isset($this->label)) { $this->label = trim($this->label); } + if (isset($this->share)) { + $this->share = trim($this->share); + } if (isset($this->entity)) { $this->entity = trim($this->entity); } @@ -136,6 +143,10 @@ class EcmFiles //extends CommonObject } if (empty($this->date_c)) $this->date_c = dol_now(); + // If ref not defined + if (empty($ref)) $ref = dol_hash($this->filepath.'/'.$this->filename, 3); + + $maxposition=0; if (empty($this->position)) // Get max used { @@ -159,6 +170,7 @@ class EcmFiles //extends CommonObject $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '('; $sql.= 'ref,'; $sql.= 'label,'; + $sql.= 'share,'; $sql.= 'entity,'; $sql.= 'filename,'; $sql.= 'filepath,'; @@ -175,8 +187,9 @@ class EcmFiles //extends CommonObject $sql.= 'fk_user_m,'; $sql.= 'acl'; $sql .= ') VALUES ('; - $sql .= " '".dol_hash($this->filepath.'/'.$this->filename, 3)."', "; + $sql .= " '".$ref."', "; $sql .= ' '.(! isset($this->label)?'NULL':"'".$this->db->escape($this->label)."'").','; + $sql .= ' '.(! isset($this->share)?'NULL':"'".$this->db->escape($this->share)."'").','; $sql .= ' '.(! isset($this->entity)?$conf->entity:$this->entity).','; $sql .= ' '.(! isset($this->filename)?'NULL':"'".$this->db->escape($this->filename)."'").','; $sql .= ' '.(! isset($this->filepath)?'NULL':"'".$this->db->escape($this->filepath)."'").','; @@ -237,9 +250,10 @@ class EcmFiles //extends CommonObject * @param string $ref Hash of file name (filename+filepath). Not always defined on some version. * @param string $relativepath Relative path of file from document directory. Example: path/path2/file * @param string $hashoffile Hash of file content. Take the first one found if same file is at different places. This hash will also change if file content is changed. + * @param string $hashforshare Hash of file sharing. * @return int <0 if KO, 0 if not found, >0 if OK */ - public function fetch($id, $ref = '', $relativepath = '', $hashoffile='') + public function fetch($id, $ref = '', $relativepath = '', $hashoffile='', $hashforshare='') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -247,6 +261,7 @@ class EcmFiles //extends CommonObject $sql .= ' t.rowid,'; $sql .= " t.ref,"; $sql .= " t.label,"; + $sql .= " t.share,"; $sql .= " t.entity,"; $sql .= " t.filename,"; $sql .= " t.filepath,"; @@ -276,11 +291,15 @@ class EcmFiles //extends CommonObject } elseif (! empty($hashoffile)) { $sql .= " AND t.label = '".$this->db->escape($hashoffile)."'"; + } + elseif (! empty($hashforshare)) { + $sql .= " AND t.share = '".$this->db->escape($hashforshare)."'"; } else { $sql .= ' AND t.rowid = ' . $id; } + // When we search on hash of content, we take the first one. Solve also hash conflict. $this->db->plimit(1); - $this->db->order('t.rowid', 'ASC'); // When we search on hash of content, we take the first one. + $this->db->order('t.rowid', 'ASC'); $resql = $this->db->query($sql); if ($resql) { @@ -291,6 +310,7 @@ class EcmFiles //extends CommonObject $this->id = $obj->rowid; $this->ref = $obj->ref; $this->label = $obj->label; + $this->share = $obj->share; $this->entity = $obj->entity; $this->filename = $obj->filename; $this->filepath = $obj->filepath; @@ -352,6 +372,7 @@ class EcmFiles //extends CommonObject $sql = 'SELECT'; $sql .= ' t.rowid,'; $sql .= " t.label,"; + $sql .= " t.share,"; $sql .= " t.entity,"; $sql .= " t.filename,"; $sql .= " t.filepath,"; @@ -401,8 +422,9 @@ class EcmFiles //extends CommonObject $line = new EcmfilesLine(); $line->id = $obj->rowid; - + $line->ref = $obj->ref; $line->label = $obj->label; + $line->share = $obj->share; $line->entity = $obj->entity; $line->filename = $obj->filename; $line->filepath = $obj->filepath; @@ -446,9 +468,15 @@ class EcmFiles //extends CommonObject // Clean parameters + if (isset($this->ref)) { + $this->ref = trim($this->ref); + } if (isset($this->label)) { $this->label = trim($this->label); } + if (isset($this->share)) { + $this->share = trim($this->share); + } if (isset($this->entity)) { $this->entity = trim($this->entity); } @@ -492,8 +520,9 @@ class EcmFiles //extends CommonObject // Update request $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET'; - $sql .= ' ref = '.dol_hash($this->filepath.'/'.$this->filename, 3); + $sql .= " ref = '".dol_hash($this->filepath.'/'.$this->filename, 3)."',"; $sql .= ' label = '.(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").','; + $sql .= ' share = '.(! empty($this->share)?"'".$this->db->escape($this->share)."'":"null").','; $sql .= ' entity = '.(isset($this->entity)?$this->entity:$conf->entity).','; $sql .= ' filename = '.(isset($this->filename)?"'".$this->db->escape($this->filename)."'":"null").','; $sql .= ' filepath = '.(isset($this->filepath)?"'".$this->db->escape($this->filepath)."'":"null").','; diff --git a/htdocs/ecm/docfile.php b/htdocs/ecm/docfile.php index aa708a85f24..a856ab22c36 100644 --- a/htdocs/ecm/docfile.php +++ b/htdocs/ecm/docfile.php @@ -39,6 +39,9 @@ $langs->load("bills"); $langs->load("contracts"); $langs->load("categories"); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'alpha'); + if (!$user->rights->ecm->setup) accessforbidden(); // Get parameters @@ -61,8 +64,6 @@ $pagenext = $page + 1; if (! $sortorder) $sortorder="ASC"; if (! $sortfield) $sortfield="label"; -$cancel=GETPOST('cancel','alpha'); -$action=GETPOST('action','aZ09'); $section=GETPOST("section"); if (! $section) { @@ -87,19 +88,25 @@ if (! $result > 0) $relativepath=$ecmdir->getRelativePath(); $upload_dir = $conf->ecm->dir_output.'/'.$relativepath; +$fullpath=$conf->ecm->dir_output.'/'.$relativepath.$urlfile; -/* -$ecmfile = new ECMFile($db); -if (! empty($_GET["fileid"])) +$file = new stdClass(); +$file->section_id=$ecmdir->id; +$file->label=$urlfile; + +$relativetodocument = 'ecm/'.$relativepath; // $relativepath is relative to ECM dir, we need relative to document +$filepath=$relativepath.$file->label; +$filepathtodocument=$relativetodocument.$file->label; + +// Try to load object from index +$object = new ECMFiles($db); +$result=$object->fetch(0, '', $filepathtodocument); +if (! ($result >= 0)) { - $result=$ecmfile->fetch($_GET["fileid"]); - if (! $result > 0) - { - dol_print_error($db,$ecmfile->error); - exit; - } + dol_print_error($db, $object->error, $object->errors); + exit; } -*/ + @@ -107,7 +114,7 @@ if (! empty($_GET["fileid"])) * Actions */ -if ($action == 'cancel') +if ($cancel) { $action =''; if ($backtourl) @@ -117,7 +124,7 @@ if ($action == 'cancel') } else { - header("Location: ".DOL_URL_ROOT.'/ecm/index.php?action=file_manager§ion='.$section); + header("Location: ".DOL_URL_ROOT.'/ecm/docfile.php?urlfile='.$urlfile.'§ion='.$section); exit; } } @@ -127,8 +134,9 @@ if ($action == 'update') { $error=0; - $oldlabel=GETPOST('urlfile'); - $newlabel=GETPOST('label'); + $oldlabel=GETPOST('urlfile', 'alpha'); + $newlabel=GETPOST('label', 'alpha'); + $shareenabled = GETPOST('shareenabled', 'alpha'); //$db->begin(); @@ -142,7 +150,7 @@ if ($action == 'update') //print $oldfile.' - '.$newfile; if ($newlabel != $oldlabel) { - $result=dol_move($oldfile, $newfile); + $result=dol_move($oldfile, $newfile); // This include update of database if (! $result) { $langs->load('errors'); @@ -151,14 +159,39 @@ if ($action == 'update') } } + // Now we update index of file + $db->begin(); + if (! $error) { - //$db->commit(); + if (is_object($object)) + { + if ($shareenabled) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + $object->share = getRandomPassword(true); + } + else + { + $object->share = ''; + } + $result = $object->update($user); + if ($result < 0) + { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } + } + } + + if (!$error) + { + $db->commit(); $urlfile=$newlabel; } else { - //$db->rollback(); + $db->rollback(); } } @@ -168,25 +201,20 @@ if ($action == 'update') * View */ -llxHeader(); - $form=new Form($db); -$fullpath=$conf->ecm->dir_output.'/'.$relativepath.$urlfile; - -$file = new stdClass(); -$file->section_id=$ecmdir->id; -$file->label=$urlfile; +llxHeader(); $head = ecm_file_prepare_head($file); -if ($_GET["action"] == 'edit') +if ($action == 'edit') { print '
'; print ''; print ''; print ''; print ''; + print ''; } dol_fiche_head($head, 'card', $langs->trans("File"), 0, 'generic'); @@ -217,11 +245,11 @@ while ($tmpecmdir && $result > 0) print img_picto('','object_dir').' '.$langs->trans("ECMRoot").' -> '; print $s; print ' -> '; -if (GETPOST('action','aZ09') == 'edit') print ''; +if ($action == 'edit') print ''; else print $urlfile; print ''; /*print ''.$langs->trans("Description").''; -if ($_GET["action"] == 'edit') +if ($action == 'edit') { print ''; + } + else + { + print ''; + } + print ''; print ''; } print ''."\n"; @@ -292,7 +304,7 @@ if ($action == 'create') // Part to edit record if (($id || $ref) && $action == 'edit') { - print load_fiche_titre($langs->trans("MyModule")); + print load_fiche_titre($langs->trans("MyObject")); print ''; print ''; @@ -308,9 +320,21 @@ if (($id || $ref) && $action == 'edit') print ''.$langs->trans($val['label']).''; - print ''; + print ''; + if ($val['type'] == 'text') + { + print ''; + } + else + { + print ''; + } + print ''; print ''; } print ''; @@ -326,6 +350,7 @@ if (($id || $ref) && $action == 'edit') + // Part to show record if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { diff --git a/htdocs/websites/index.php b/htdocs/websites/index.php index 35731bc3bb0..96947035113 100644 --- a/htdocs/websites/index.php +++ b/htdocs/websites/index.php @@ -275,11 +275,11 @@ if ($action == 'add') } else { - $objectpage->title = GETPOST('WEBSITE_TITLE'); - $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME'); - $objectpage->description = GETPOST('WEBSITE_DESCRIPTION'); - $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS'); - $objectpage->lang = GETPOST('WEBSITE_LANG'); + $objectpage->title = GETPOST('WEBSITE_TITLE','alpha'); + $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME','alpha'); + $objectpage->description = GETPOST('WEBSITE_DESCRIPTION','alpha'); + $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS','alpha'); + $objectpage->lang = GETPOST('WEBSITE_LANG','alpha'); } if (! $error) @@ -392,7 +392,7 @@ if ($action == 'updatecss') // $htmlheadercontent.= "header('Content-type: text/html');\n"; // Not required. htmlheader.html is never call as a standalone page $htmlheadercontent.= "// END PHP ?>\n";*/ - $htmlheadercontent.= preg_replace(array('/\n*/ims','/<\/html>\n*/ims'),array('',''),GETPOST('WEBSITE_HTML_HEADER')); + $htmlheadercontent.= preg_replace(array('/\n*/ims','/<\/html>\n*/ims'),array('',''),GETPOST('WEBSITE_HTML_HEADER', 'none')); /*$htmlheadercontent.= "\n".'\n"; - $csscontent.= GETPOST('WEBSITE_CSS_INLINE'); + $csscontent.= GETPOST('WEBSITE_CSS_INLINE', 'none'); $csscontent.= "\n".'\n";*/ - $robotcontent.= GETPOST('WEBSITE_ROBOT'); + $robotcontent.= GETPOST('WEBSITE_ROBOT', 'none'); /*$robotcontent.= "\n".'\n";*/ - $htaccesscontent.= GETPOST('WEBSITE_HTACCESS'); + $htaccesscontent.= GETPOST('WEBSITE_HTACCESS', 'none'); /*$robotcontent.= "\n".'old_object = clone $objectpage; - $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME'); - $objectpage->title = GETPOST('WEBSITE_TITLE'); - $objectpage->description = GETPOST('WEBSITE_DESCRIPTION'); - $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS'); - $objectpage->lang = GETPOST('WEBSITE_LANG'); + $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha'); + $objectpage->title = GETPOST('WEBSITE_TITLE', 'alpha'); + $objectpage->description = GETPOST('WEBSITE_DESCRIPTION', 'alpha'); + $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS', 'alpha'); + $objectpage->lang = GETPOST('WEBSITE_LANG', 'alpha'); $res = $objectpage->update($user); if (! $res > 0) From e1b4788bc232433ccad802fb8bba966937ed8dee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 01:52:14 +0200 Subject: [PATCH 063/108] Update vat rates --- htdocs/install/mysql/data/llx_c_tva.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index cce279d79da..b4389ca8397 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -88,6 +88,8 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 9 -- CYPRUS (id country=78) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (781, 78, '19','0','VAT standard rate',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (782, 78, '9','0','VAT Rate 9',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (783, 78, '5','0','VAT Rate 5',1); insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (784, 78, '0','0','VAT Rate 0',1); -- DANMERK (id country=80) From 2ca5f2e27e001ea58209569d615f031f86023771 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 01:52:49 +0200 Subject: [PATCH 064/108] Prepare 6.0.2 --- htdocs/filefunc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index cbec259b2aa..394686cc5e4 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -31,7 +31,7 @@ */ if (! defined('DOL_APPLICATION_TITLE')) define('DOL_APPLICATION_TITLE','Dolibarr'); -if (! defined('DOL_VERSION')) define('DOL_VERSION','6.0.1'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c +if (! defined('DOL_VERSION')) define('DOL_VERSION','6.0.2'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c if (! defined('EURO')) define('EURO',chr(128)); From a94f2b07e1c6a759a8888d02c1bccc83a12b8263 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 02:46:33 +0200 Subject: [PATCH 065/108] Fix css --- htdocs/core/boxes/modules_boxes.php | 2 +- htdocs/theme/eldy/style.css.php | 9 +++++---- htdocs/theme/md/style.css.php | 9 +++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 9c496964942..93b8fa3d9d2 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -286,7 +286,7 @@ class ModeleBoxes // Can't be abtract as it is instantiated to build "empty" if (isset($contents[$i])) { // TR - if (isset($contents[$i][0]['tr'])) $out.= ''; + if (isset($contents[$i][0]['tr'])) $out.= ''; else $out.= ''; // Loop on each TD diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index e6bf4d8233a..2cf1f276d24 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -52,7 +52,7 @@ $colortexttitlenotab='100,60,20'; $colortexttitle='0,0,0'; $colortext='0,0,0'; $colortextlink='0,0,100'; -$fontsize='13'; +$fontsize='14'; $fontsizesmaller='12'; if (defined('THEME_ONLY_CONSTANT')) return; @@ -118,7 +118,7 @@ if (empty($conf->global->THEME_ELDY_ENABLE_PERSONALIZED)) $conf->global->THEME_ELDY_BACKTABCARD1='255,255,255'; // card $conf->global->THEME_ELDY_BACKTABACTIVE='234,234,234'; $conf->global->THEME_ELDY_TEXT='0,0,0'; - $conf->global->THEME_ELDY_FONT_SIZE1='13'; + $conf->global->THEME_ELDY_FONT_SIZE1='14'; $conf->global->THEME_ELDY_FONT_SIZE2='12'; } @@ -3025,11 +3025,12 @@ div.warning { color: #302020; padding: 0.3em 0.3em 0.3em 0.3em; margin: 0.5em 0em 0.5em 0em; - border: 1px solid #e0d0b0; + /* border: 1px solid #e0d0b0; */ + border: 2px solid #805000; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; - background: #EFDF9A; + /* background: #EFDF9A; */ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 64210218799..a3bc638aec1 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -53,7 +53,7 @@ $colortexttitlenotab='90,90,90'; $colortexttitle='20,20,20'; $colortext='0,0,0'; $colortextlink='0,0,120'; -$fontsize='13'; +$fontsize='14'; $fontsizesmaller='11'; if (defined('THEME_ONLY_CONSTANT')) return; @@ -120,7 +120,7 @@ if (empty($conf->global->THEME_ELDY_ENABLE_PERSONALIZED)) $conf->global->THEME_ELDY_BACKTABCARD1='255,255,255'; // card $conf->global->THEME_ELDY_BACKTABACTIVE='234,234,234'; $conf->global->THEME_ELDY_TEXT='0,0,0'; - $conf->global->THEME_ELDY_FONT_SIZE1='13'; + $conf->global->THEME_ELDY_FONT_SIZE1='14'; $conf->global->THEME_ELDY_FONT_SIZE2='11'; } @@ -3124,11 +3124,12 @@ div.warning { color: #302020; padding: 0.3em 0.3em 0.3em 0.3em; margin: 0.5em 0em 0.5em 0em; - border: 1px solid #e0d0b0; + /* border: 1px solid #e0d0b0; */ + border: 2px solid #805000 -moz-border-radius:3px; -webkit-border-radius: 3px; border-radius: 3px; - background: #EFDF9A; + /* background: #EFDF9A; */ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } From 839f3ca41dd39d37e870fc2cf57aa810315887fa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 03:22:48 +0200 Subject: [PATCH 066/108] NEW Can use an url like $conf->global>-MYPARAM for menu urls --- htdocs/core/menus/standard/auguria.lib.php | 7 +++++++ htdocs/core/menus/standard/eldy.lib.php | 7 +++++++ htdocs/theme/eldy/style.css.php | 4 ++-- htdocs/theme/md/style.css.php | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/htdocs/core/menus/standard/auguria.lib.php b/htdocs/core/menus/standard/auguria.lib.php index 5fc0ab2c516..9119afc7696 100644 --- a/htdocs/core/menus/standard/auguria.lib.php +++ b/htdocs/core/menus/standard/auguria.lib.php @@ -73,6 +73,13 @@ function print_auguria_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0,$m $showmode=dol_auguria_showmenu($type_user,$newTabMenu[$i],$listofmodulesforexternal); if ($showmode == 1) { + // $menu_array[$i]['url'] can be a relative url, a full external url or a dynamic value like '$conf->global->APARAM) + if (preg_match('/^\$conf->global->([^\?]+)/', $newTabMenu[$i]['url'], $reg)) + { + $keyforsconst=$reg[1]; + $newTabMenu[$i]['url'] = $conf->global->$keyforsconst; + } + $url = $shorturl = $newTabMenu[$i]['url']; if (! preg_match("/^(http:\/\/|https:\/\/)/i",$newTabMenu[$i]['url'])) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 8c03d0c1ffc..013b6ea74ae 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1598,6 +1598,13 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu } } + // $menu_array[$i]['url'] can be a relative url, a full external url or a dynamic value like '$conf->global->APARAM) + if (preg_match('/^\$conf->global->([^\?]+)/', $menu_array[$i]['url'], $reg)) + { + $keyforsconst=$reg[1]; + $menu_array[$i]['url'] = $conf->global->$keyforsconst; + } + $url = $shorturl = $menu_array[$i]['url']; if (! preg_match("/^(http:\/\/|https:\/\/)/i",$menu_array[$i]['url'])) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 2cf1f276d24..5226cb266e5 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -52,7 +52,7 @@ $colortexttitlenotab='100,60,20'; $colortexttitle='0,0,0'; $colortext='0,0,0'; $colortextlink='0,0,100'; -$fontsize='14'; +$fontsize='13'; $fontsizesmaller='12'; if (defined('THEME_ONLY_CONSTANT')) return; @@ -118,7 +118,7 @@ if (empty($conf->global->THEME_ELDY_ENABLE_PERSONALIZED)) $conf->global->THEME_ELDY_BACKTABCARD1='255,255,255'; // card $conf->global->THEME_ELDY_BACKTABACTIVE='234,234,234'; $conf->global->THEME_ELDY_TEXT='0,0,0'; - $conf->global->THEME_ELDY_FONT_SIZE1='14'; + $conf->global->THEME_ELDY_FONT_SIZE1='13'; $conf->global->THEME_ELDY_FONT_SIZE2='12'; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index a3bc638aec1..283f1aad16f 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -53,7 +53,7 @@ $colortexttitlenotab='90,90,90'; $colortexttitle='20,20,20'; $colortext='0,0,0'; $colortextlink='0,0,120'; -$fontsize='14'; +$fontsize='13'; $fontsizesmaller='11'; if (defined('THEME_ONLY_CONSTANT')) return; @@ -120,7 +120,7 @@ if (empty($conf->global->THEME_ELDY_ENABLE_PERSONALIZED)) $conf->global->THEME_ELDY_BACKTABCARD1='255,255,255'; // card $conf->global->THEME_ELDY_BACKTABACTIVE='234,234,234'; $conf->global->THEME_ELDY_TEXT='0,0,0'; - $conf->global->THEME_ELDY_FONT_SIZE1='14'; + $conf->global->THEME_ELDY_FONT_SIZE1='13'; $conf->global->THEME_ELDY_FONT_SIZE2='11'; } From 35d00fd2ec45cf7939eec3ca0da40a00916f4dc0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 09:28:31 +0200 Subject: [PATCH 067/108] Fix wrap on lites_total --- htdocs/core/boxes/box_activity.php | 2 +- htdocs/theme/eldy/style.css.php | 16 +++++++++------- htdocs/theme/md/style.css.php | 21 ++++++++++++--------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php index 71a9a4e3125..d3059daba53 100644 --- a/htdocs/core/boxes/box_activity.php +++ b/htdocs/core/boxes/box_activity.php @@ -435,7 +435,7 @@ class box_activity extends ModeleBoxes } // Add the sum in the bottom of the boxes - $this->info_box_contents[$line][0] = array('tr' => 'class="liste_total"'); + $this->info_box_contents[$line][0] = array('tr' => 'class="liste_total_wrap"'); $this->info_box_contents[$line][1] = array('td' => 'align="left" class="liste_total" ', 'text' => $langs->trans("Total")." ".$textHead); $this->info_box_contents[$line][2] = array('td' => 'align="right" class="liste_total" ', 'text' => $totalnb); $this->info_box_contents[$line][3] = array('td' => 'align="right" class="liste_total" ', 'text' => ''); diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 5226cb266e5..4451135830c 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -863,11 +863,11 @@ div.fiche>form>div.div-table-responsive { .minwidth500imp { min-width: 250px !important; } } -/* Force values for small screen 570 */ +/* Force values for small screen 767 */ @media only screen and (max-width: 767px) { body { - font-size: px; + font-size: px; } } @@ -875,7 +875,7 @@ div.fiche>form>div.div-table-responsive { @media only screen and (max-width: 570px) { body { - font-size: px; + font-size: px; } .divmainbodylarge { margin-left: 20px !important; margin-right: 20px !important; } @@ -2749,14 +2749,16 @@ input.liste_titre { line-height: 24px; } -.noborder tr.liste_total, .noborder tr.liste_total td, tr.liste_total, form.liste_total { - /* height: 32px; */ -} -.noborder tr.liste_total td, tr.liste_total td, form.liste_total div { +.noborder tr.liste_total td, tr.liste_total td, form.liste_total div, .noborder tr.liste_total_wrap td, tr.liste_total_wrap td, form.liste_total_wrap div { color: #551188; font-weight: normal; +} +.noborder tr.liste_total td, tr.liste_total td, form.liste_total div { white-space: nowrap; } +.noborder tr.liste_total_wrap td, tr.liste_total_wrap td, form.liste_total_wrap div { + white-space: normal; +} form.liste_total div { border-top: 1px solid #DDDDDD; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 283f1aad16f..13aca2545dd 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -865,11 +865,11 @@ div.fiche>form>div.div-table-responsive { .minwidth500imp { min-width: 100px !important; } } -/* Force values for small screen 570 */ +/* Force values for small screen 767 */ @media only screen and (max-width: 767px) { body { - font-size: px; + font-size: px; } } @@ -877,7 +877,7 @@ div.fiche>form>div.div-table-responsive { @media only screen and (max-width: 570px) { body { - font-size: px; + font-size: px; } .divmainbodylarge { margin-left: 20px; margin-right: 20px; } @@ -2865,16 +2865,19 @@ input.liste_titre { border: 0px; } -.noborder tr.liste_total, .noborder tr.liste_total td, tr.liste_total, form.liste_total { - /* height: 32px; */ -} -.noborder tr.liste_total td, tr.liste_total td, form.liste_total div { - /* border-top: 1px solid #f4f4f4; */ +.noborder tr.liste_total td, tr.liste_total td, form.liste_total div, .noborder tr.liste_total_wrap td, tr.liste_total_wrap td, form.liste_total_wrap div { color: #332266; font-weight: normal; - white-space: nowrap; padding: 4px; } +.noborder tr.liste_total td, tr.liste_total td, form.liste_total div { + white-space: nowrap; +} +.noborder tr.liste_total_wrap td, tr.liste_total_wrap td, form.liste_total_wrap div { + white-space: normal; +} + + tr.liste_sub_total, tr.liste_sub_total td { border-bottom: 2px solid #aaa; } From 91beb3a4d6fed9dfa6b9faf78e7a72041e0c9ba7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 11:39:09 +0200 Subject: [PATCH 068/108] Debug modulebuilder --- htdocs/modulebuilder/index.php | 193 +++++++++++++++++---------------- 1 file changed, 101 insertions(+), 92 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 43f679541ab..31514435cd7 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -967,12 +967,14 @@ elseif (! empty($module)) $linktoenabledisable.=img_picto($langs->trans("Disabled"),'switch_off'); $linktoenabledisable.="\n"; } - - $modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive", $urltomodulesetup); - if (! empty($conf->$module->enabled)) + if (! empty($conf->$modulelowercase->enabled)) { $modulestatusinfo=img_warning().' '.$langs->trans("ModuleIsLive"); } + else + { + $modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive", $urltomodulesetup); + } $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread?'@'.$dirread:''); $head2[$h][1] = $langs->trans("Description"); @@ -1308,12 +1310,12 @@ elseif (! empty($module)) //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']); $objectname = $reg[1]; if (empty($firstobjectname)) $firstobjectname = $objectname; - } - $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname; - $head3[$h][1] = $objectname; - $head3[$h][2] = $objectname; - $h++; + $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname; + $head3[$h][1] = $objectname; + $head3[$h][2] = $objectname; + $h++; + } } $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj=deleteobject'; @@ -1483,98 +1485,105 @@ elseif (! empty($module)) print ''; print ''; - // Line to add a property - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - $properties = dol_sort_array($tmpobjet->fields, 'position'); - foreach($properties as $propkey => $propval) + if (! empty($properties)) { - /* If from Reflection - if ($propval->class == $tabobj) - { - $propname=$propval->getName(); - $comment=$propval->getDocComment(); - $type=gettype($tmpobjet->$propname); - $default=$propdefault[$propname]; - // Discard generic properties - if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'isnolinkedbythird', 'ismultientitymanaged'))) continue; + // Line to add a property + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; - // Keep or not lines - if (in_array($propname, array('fk_element', 'lines'))) continue; - }*/ + foreach($properties as $propkey => $propval) + { + /* If from Reflection + if ($propval->class == $tabobj) + { + $propname=$propval->getName(); + $comment=$propval->getDocComment(); + $type=gettype($tmpobjet->$propname); + $default=$propdefault[$propname]; + // Discard generic properties + if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'isnolinkedbythird', 'ismultientitymanaged'))) continue; - $propname=$propkey; - $proplabel=$propval['label']; - $proptype=$propval['type']; - $propnotnull=$propval['notnull']; - $propsearchall=$propval['searchall']; - //$propdefault=$propval['default']; - $propindex=$propval['index']; - $propposition=$propval['position']; - $propenabled=$propval['enabled']; - $propvisible=$propval['visible']; - $propisameasure=$propval['isameasure']; - $propcomment=$propval['comment']; + // Keep or not lines + if (in_array($propname, array('fk_element', 'lines'))) continue; + }*/ - print ''; + $propname=$propkey; + $proplabel=$propval['label']; + $proptype=$propval['type']; + $propnotnull=$propval['notnull']; + $propsearchall=$propval['searchall']; + //$propdefault=$propval['default']; + $propindex=$propval['index']; + $propposition=$propval['position']; + $propenabled=$propval['enabled']; + $propvisible=$propval['visible']; + $propisameasure=$propval['isameasure']; + $propcomment=$propval['comment']; - print ''; - print $propname; - print ''; - print ''; - print $proplabel; - print ''; - print ''; - print $proptype; - print ''; - print ''; - print $propnotnull; - print ''; - /*print ''; - print $propdefault; - print '';*/ - print ''; - print $propindex?'X':''; - print ''; - print ''; - print $propposition; - print ''; - print ''; - print $propenabled?$propenabled:''; - print ''; - print ''; - print $propvisible?$propvisible:''; - print ''; - print ''; - print $propisameasure?$propisameasure:''; - print ''; - print ''; - print $propsearchall?'X':''; - print ''; - print ''; - print $propcomment; - print ''; - print ''; - print ''.img_delete().''; - print ''; + print ''; - print ''; + print ''; + print $propname; + print ''; + print ''; + print $proplabel; + print ''; + print ''; + print $proptype; + print ''; + print ''; + print $propnotnull; + print ''; + /*print ''; + print $propdefault; + print '';*/ + print ''; + print $propindex?'X':''; + print ''; + print ''; + print $propposition; + print ''; + print ''; + print $propenabled?$propenabled:''; + print ''; + print ''; + print $propvisible?$propvisible:''; + print ''; + print ''; + print $propisameasure?$propisameasure:''; + print ''; + print ''; + print $propsearchall?'X':''; + print ''; + print ''; + print $propcomment; + print ''; + print ''; + print ''.img_delete().''; + print ''; + + print ''; + } + } + else + { + print ''.$langs->trans('Property $field not found into the class. The class was probably not generated by modulebuilder.').''; } print ''; print '
'; From 414f633e750d892269e4fc027a81d9ff4ce794dd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 12:59:49 +0200 Subject: [PATCH 069/108] Fix css --- htdocs/core/class/html.form.class.php | 4 +- htdocs/core/class/html.formactions.class.php | 107 ++++++++++-------- htdocs/langs/en_US/modulebuilder.lang | 10 +- htdocs/modulebuilder/index.php | 32 +++++- .../template/doc/Specifications.asciidoc | 4 +- .../modulebuilder/template/myobject_card.php | 4 +- htdocs/theme/eldy/style.css.php | 4 +- 7 files changed, 103 insertions(+), 62 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index ed318bbd900..931c3c5d1ce 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5551,8 +5551,8 @@ class Form { $nbofdifferenttypes = count($object->linkedObjects); - print '
'; - print load_fiche_titre($langs->trans('RelatedObjects'), $morehtmlright, ''); + print ''; + print load_fiche_titre($langs->trans('RelatedObjects'), $morehtmlright, '', 0, 0, 'showlinkedobjectblock'); print '
'; diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index b93083d9a9f..84c7ab389f3 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -187,20 +187,22 @@ class FormActions elseif ($typeelement == 'project') $title=$langs->trans('LatestLinkedEvents', $max?$max:''); elseif ($typeelement == 'task') $title=$langs->trans('LatestLinkedEvents', $max?$max:''); elseif ($typeelement == 'member') $title=$langs->trans('LatestLinkedEvents', $max?$max:''); - else $title=$langs->trans("Actions"); + else $title=$langs->trans("LatestLinkedEvents", $max?$max:''); $urlbacktopage=$_SERVER['PHP_SELF'].'?id='.$object->id.($moreparambacktopage?'&'.$moreparambacktopage:''); $buttontoaddnewevent = ''; $buttontoaddnewevent.= $langs->trans("AddEvent"); $buttontoaddnewevent.= ''; + + print ''."\n"; print load_fiche_titre($title, $buttontoaddnewevent, ''); $page=0; $param=''; $total = 0; - print '
'; + print '
'; print ''; print ''; print getTitleFieldOfList('Ref', 0, $_SERVER["PHP_SELF"], '', $page, $param, '', $sortfield, $sortorder, '', 1); @@ -214,63 +216,70 @@ class FormActions $userstatic = new User($this->db); - $cursorevent = 0; - foreach($listofactions as $action) + if (count($listofactions)) { - if ($max && $cursorevent >= $max) break; + $cursorevent = 0; + foreach($listofactions as $action) + { + if ($max && $cursorevent >= $max) break; - $ref=$action->getNomUrl(1,-1); - $label=$action->getNomUrl(0,38); + $ref=$action->getNomUrl(1,-1); + $label=$action->getNomUrl(0,38); - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; - print ''; - print ''; - print ''; + print $action->type; + print ''; + print ''; + print ''; + print ''; + print ''; - $cursorevent++; + $cursorevent++; + } + } + else + { + print ''; } if ($max && $num > $max) { - print ''; + print ''; } print '
'.$ref.''.$label.''; - if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) - { - if ($action->type_picto) print img_picto('', $action->type_picto); - else { - if ($action->type_code == 'AC_RDV') print img_picto('', 'object_group').' '; - if ($action->type_code == 'AC_TEL') print img_picto('', 'object_phoning').' '; - if ($action->type_code == 'AC_FAX') print img_picto('', 'object_phoning_fax').' '; - if ($action->type_code == 'AC_EMAIL') print img_picto('', 'object_email').' '; - } - } - print $action->type; - print ''.dol_print_date($action->datep,'dayhour'); - if ($action->datef) - { - $tmpa=dol_getdate($action->datep); - $tmpb=dol_getdate($action->datef); - if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) + print '
'.$ref.''.$label.''; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes'] && $tmpa['seconds'] != $tmpb['seconds']) print '-'.dol_print_date($action->datef,'hour'); + if ($action->type_picto) print img_picto('', $action->type_picto); + else { + if ($action->type_code == 'AC_RDV') print img_picto('', 'object_group').' '; + if ($action->type_code == 'AC_TEL') print img_picto('', 'object_phoning').' '; + if ($action->type_code == 'AC_FAX') print img_picto('', 'object_phoning_fax').' '; + if ($action->type_code == 'AC_EMAIL') print img_picto('', 'object_email').' '; + } } - else print '-'.dol_print_date($action->datef,'dayhour'); - } - print ''; - if (! empty($action->userownerid)) - { - $userstatic->fetch($action->userownerid); // TODO Introduce a cache on users fetched - print $userstatic->getNomUrl(-1, '', 0, 0, 16, 0, '', ''); - } - print ''; - if (! empty($action->author->id)) - { - print $action->getLibStatut(3); - } - print '
'.dol_print_date($action->datep,'dayhour'); + if ($action->datef) + { + $tmpa=dol_getdate($action->datep); + $tmpb=dol_getdate($action->datef); + if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) + { + if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes'] && $tmpa['seconds'] != $tmpb['seconds']) print '-'.dol_print_date($action->datef,'hour'); + } + else print '-'.dol_print_date($action->datef,'dayhour'); + } + print ''; + if (! empty($action->userownerid)) + { + $userstatic->fetch($action->userownerid); // TODO Introduce a cache on users fetched + print $userstatic->getNomUrl(-1, '', 0, 0, 16, 0, '', ''); + } + print ''; + if (! empty($action->author->id)) + { + print $action->getLibStatut(3); + } + print '
'.$langs->trans("None").'
'.$langs->trans("More").'...
'.$langs->trans("More").'...
'; diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 732514de9c1..081f67fb022 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -64,8 +64,14 @@ IsAMeasure=Is a measure DirScanned=Directory scanned NoTrigger=No trigger NoWidget=No widget +ListOfPermissionsDefined=List of defined permissions EnabledDesc=Condition to have this field active (Examples: 1 or $conf->global->MYMODULE_MYOPTION) -VisibleDesc=Is field is visible in list (-1 means not shown by default but can be added into list to be viewed) +VisibleDesc=Is the field visible into list ? (Examples: 0=not visible, 1=visible by default on list, -1=not shown by default on list but can be added into list to be viewed) +IsAMeasureDesc=Can the value of field be cumulated to get a total into list ? (Examples: 1 or 0) +SearchAllDesc=Is the field used to make a search from the quick search tool ? (Examples: 1 or 0) +SpecDefDesc=Enter here all documentation you want to provide with your module that is not already defined by other tabs. You can use .md or better, the rich .asciidoc syntax. +LanguageDefDesc=Enter in this files, all the key and the translation for each language file. MenusDefDesc=Define here the menus provided by your module (once defined, they are visible into the menu editor %s) PermissionsDefDesc=Define here the new permissions provided by your module (once defined, they are visible into the default permissions setup %s) -ListOfPermissionsDefined=List of defined permissions +HooksDefDesc=Define in the module_parts['hooks'] property in the module descriptor the context of hooks you want to manage (list of contexts can be found by a search on 'initHooks(' in core code).
Edit the hook file to add code of your hooked functions (hookable functions can be found by a search on 'executeHooks' in core code). +TriggerDefDesc=Define in the trigger file the code you want to execute for each business event executed diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 31514435cd7..145d68f7c2f 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1194,6 +1194,9 @@ elseif (! empty($module)) { if ($action != 'editfile' || empty($file)) { + print $langs->trans("SpecDefDesc").'
'; + print '
'; + $specs=dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$'); foreach ($specs as $spec) @@ -1241,6 +1244,9 @@ elseif (! empty($module)) { if ($action != 'editfile' || empty($file)) { + print $langs->trans("LanguageDefDesc").'
'; + print '
'; + $langfiles=dol_dir_list(dol_buildpath($modulelowercase.'/langs', 0), 'files', 1, '\.lang$'); foreach ($langfiles as $langfile) @@ -1419,11 +1425,14 @@ elseif (! empty($module)) print '
'; print '
'; + $urloflist = dol_buildpath(strtolower($module).'/'.strtolower($tabobj).'_list.php', 1); + $urlofcard = dol_buildpath(strtolower($module).'/'.strtolower($tabobj).'_card.php', 1); + print '
'; - print ' '.$langs->trans("PageForList").' : '.$pathtolist.''; + print ' '.$langs->trans("PageForList").' : '.$pathtolist.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("PageForCreateEditView").' : '.$pathtocard.''; + print ' '.$langs->trans("PageForCreateEditView").' : '.$pathtocard.'?action=create'; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForAgendaTab").' : '.$pathtoagenda.''; @@ -1479,8 +1488,8 @@ elseif (! empty($module)) print ''.$langs->trans("Position").''; print ''.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc")).''; print ''.$form->textwithpicto($langs->trans("Visible"), $langs->trans("VisibleDesc")).''; - print ''.$langs->trans("IsAMeasure").''; - print ''.$langs->trans("SearchAll").''; + print ''.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).''; + print ''.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).''; print ''.$langs->trans("Comment").''; print ''; print ''; @@ -1885,8 +1894,16 @@ elseif (! empty($module)) { if ($action != 'editfile' || empty($file)) { - $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; - print ' '.$langs->trans("HooksFile").' : '.$pathtohook.''; + print $langs->trans("HooksDefDesc").'
'; + print '
'; + + $pathtofile = $modulelowercase.'/core/modules/mod'.$module.'.class.php'; + print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + + $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; + print ' '.$langs->trans("HooksFile").' : '.$pathtohook.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } @@ -1926,6 +1943,9 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { + print $langs->trans("TriggerDefDesc").'
'; + print '
'; + if (! empty($triggers)) { foreach ($triggers as $trigger) diff --git a/htdocs/modulebuilder/template/doc/Specifications.asciidoc b/htdocs/modulebuilder/template/doc/Specifications.asciidoc index 7b1711cf514..d2150c0865d 100644 --- a/htdocs/modulebuilder/template/doc/Specifications.asciidoc +++ b/htdocs/modulebuilder/template/doc/Specifications.asciidoc @@ -1 +1,3 @@ -# SPECIFICATIONS OF MODULE MYMODULE FOR DOLIBARR ERP CRM \ No newline at end of file +# SPECIFICATIONS OF MODULE MYMODULE FOR DOLIBARR ERP CRM + +There is no detailed specification available yet. diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 9aa0f8cd361..97662c150da 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -534,10 +534,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; + $MAXEVENT = 10; + // List of actions on element include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, 'myobject', $socid, 1); + $somethingshown = $formactions->showactions($object, 'myobject', $socid, 1, '', $MAXEVENT); print '
'; } diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 4451135830c..1fbd4e44037 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -719,7 +719,9 @@ div.myavailability { margin-top: 6px; margin-bottom: 12px; } - +#builddoc_form ~ .showlinkedobjectblock { + margin-top: 20px; +} /* For the long description of module */ .moduledesclong p img, .moduledesclong p a img { From 7d580105c81c4dc65ae9065f3cdac5ad94839654 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 13:02:25 +0200 Subject: [PATCH 070/108] Fix css --- htdocs/theme/md/style.css.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 13aca2545dd..4d46f2e781e 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -730,7 +730,9 @@ div.myavailability { margin-top: 6px; margin-bottom: 12px; } - +#builddoc_form ~ .showlinkedobjectblock { + margin-top: 20px; +} /* For the long description of module */ .moduledesclong p img,.moduledesclong p a img { From bee94b32d9c98e14a761eac75522664f3eddca53 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 15:12:25 +0200 Subject: [PATCH 071/108] Debug modulebuilder --- htdocs/core/lib/functions.lib.php | 4 +- htdocs/langs/en_US/modulebuilder.lang | 1 + htdocs/modulebuilder/index.php | 325 ++++++++++++++------------ 3 files changed, 180 insertions(+), 150 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index c995c1269ad..41cd039d1e6 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -601,8 +601,8 @@ function dol_include_once($relpath, $classname='') * * @param string $path Relative path to file (if mode=0) or relative url (if mode=1). Ie: mydir/myfile, ../myfile * @param int $type 0=Used for a Filesystem path, 1=Used for an URL path (output relative), 2=Used for an URL path (output full path using same host that current url), 3=Used for an URL path (output full path using host defined into $dolibarr_main_url_root of conf file) - * @param int $returnemptyifnotfound If file was not found, do not return default path but an empty string - * @return string Full filesystem path (if mode=0), Full url path (if mode=1) + * @param int $returnemptyifnotfound If path==0 and if file was not found, do not return default path but an empty string + * @return string Full filesystem path (if path=0), Full url path (if mode=1) */ function dol_buildpath($path, $type=0, $returnemptyifnotfound=0) { diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 081f67fb022..0f62870b299 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -64,6 +64,7 @@ IsAMeasure=Is a measure DirScanned=Directory scanned NoTrigger=No trigger NoWidget=No widget +GoToApiExplorer=Go to API explorer ListOfPermissionsDefined=List of defined permissions EnabledDesc=Condition to have this field active (Examples: 1 or $conf->global->MYMODULE_MYOPTION) VisibleDesc=Is the field visible into list ? (Examples: 0=not visible, 1=visible by default on list, -1=not shown by default on list but can be added into list to be viewed) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 145d68f7c2f..48bfb1731ae 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1395,53 +1395,66 @@ elseif (! empty($module)) $pathtosql = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.sql'; $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($tabobj).'_extrafields.sql'; $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.key.sql'; + + $realpathtoclass = dol_buildpath($pathtoclass, 0, 1); + $realpathtoapi = dol_buildpath($pathtoapi, 0, 1); + $realpathtoagenda = dol_buildpath($pathtoagenda, 0, 1); + $realpathtocard = dol_buildpath($pathtocard, 0, 1); + $realpathtodocument = dol_buildpath($pathtodocument, 0, 1); + $realpathtolist = dol_buildpath($pathtolist, 0, 1); + $realpathtonote = dol_buildpath($pathtonote, 0, 1); + $realpathtophpunit = dol_buildpath($pathtophpunit, 0, 1); + $realpathtosql = dol_buildpath($pathtosql, 0, 1); + $realpathtosqlextra = dol_buildpath($pathtosqlextra, 0, 1); + $realpathtosqlkey = dol_buildpath($pathtosqlkey, 0, 1); + print '
'; - print ' '.$langs->trans("ClassFile").' : '.$pathtoclass.''; + print ' '.$langs->trans("ClassFile").' : '.($realpathtoclass?'':'').$pathtoclass.($realpathtoclass?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("ApiClassFile").' : '.$pathtoapi.''; + print ' '.$langs->trans("ApiClassFile").' : '.($realpathtoapi?'':'').$pathtoapi.($realpathtoapi?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '   '.$langs->trans("GoToApiExplorer").''; print '
'; - print ' '.$langs->trans("TestClassFile").' : '.$pathtophpunit.''; + print ' '.$langs->trans("TestClassFile").' : '.($realpathtophpunit?'':'').$pathtophpunit.($realpathtophpunit?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; - print ' '.$langs->trans("SqlFile").' : '.$pathtosql.''; + print ' '.$langs->trans("SqlFile").' : '.($realpathtosql?'':'').$pathtosql.($realpathtosql?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '   '.$langs->trans("DropTableIfEmpty").''; - print '   '.$langs->trans("RunSql").''; + //print '   '.$langs->trans("RunSql").''; print '
'; - print ' '.$langs->trans("SqlFileExtraFields").' : '.$pathtosqlextra.''; + print ' '.$langs->trans("SqlFileExtraFields").' : '.($realpathtosqlextra?'':'').$pathtosqlextra.($realpathtosqlextra?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '   '.$langs->trans("RunSql").''; + //print '   '.$langs->trans("RunSql").''; print '
'; - print ' '.$langs->trans("SqlFileKey").' : '.$pathtosqlkey.''; + print ' '.$langs->trans("SqlFileKey").' : '.($realpathtosqlkey?'':'').$pathtosqlkey.($realpathtosqlkey?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '   '.$langs->trans("RunSql").''; + //print '   '.$langs->trans("RunSql").''; print '
'; print '
'; print '
'; - $urloflist = dol_buildpath(strtolower($module).'/'.strtolower($tabobj).'_list.php', 1); - $urlofcard = dol_buildpath(strtolower($module).'/'.strtolower($tabobj).'_card.php', 1); + $urloflist = dol_buildpath($pathtolist, 1); + $urlofcard = dol_buildpath($pathtocard, 1); print '
'; - print ' '.$langs->trans("PageForList").' : '.$pathtolist.''; + print ' '.$langs->trans("PageForList").' : '.($realpathtosql?'':'').$pathtolist.($realpathtosql?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("PageForCreateEditView").' : '.$pathtocard.'?action=create'; + print ' '.$langs->trans("PageForCreateEditView").' : '.($realpathtocard?'':'').$pathtocard.($realpathtocard?'':'').'?action=create'; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("PageForAgendaTab").' : '.$pathtoagenda.''; + print ' '.$langs->trans("PageForAgendaTab").' : '.($realpathtoagenda?'':'').$pathtoagenda.($realpathtoagenda?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("PageForDocumentTab").' : '.$pathtodocument.''; + print ' '.$langs->trans("PageForDocumentTab").' : '.($realpathtodocument?'':'').$pathtodocument.($realpathtodocument?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; - print ' '.$langs->trans("PageForNoteTab").' : '.$pathtonote.''; + print ' '.$langs->trans("PageForNoteTab").' : '.($realpathtonote?'':'').$pathtonote.($realpathtonote?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -1455,149 +1468,165 @@ elseif (! empty($module)) { $result = @include_once($dirread.'/'.$pathtoclass); } - if (class_exists($tabobj)) $tmpobjet = new $tabobj($db); - - $reflector = new ReflectionClass($tabobj); - $properties = $reflector->getProperties(); // Can also use get_object_vars - $propdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars - //$propstat = $reflector->getStaticProperties(); - - print load_fiche_titre($langs->trans("Properties"), '', ''); - - print ''; - - print ''; - print ''; - print ''; - print ''; - print ''; - - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - - $properties = dol_sort_array($tmpobjet->fields, 'position'); - - if (! empty($properties)) + if (class_exists($tabobj)) { - // Line to add a property - print ''; - print ''; - print ''; - print ''; - print ''; - //print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + try { + $tmpobjet = @new $tabobj($db); + } + catch(Exception $e) + { + dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); + } + } - foreach($properties as $propkey => $propval) + if (! empty($tmpobjet)) + { + $reflector = new ReflectionClass($tabobj); + $properties = $reflector->getProperties(); // Can also use get_object_vars + $propdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars + //$propstat = $reflector->getStaticProperties(); + + print load_fiche_titre($langs->trans("Properties"), '', ''); + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + print '
'.$langs->trans("Property"); - print ' ('.$langs->trans("Example").')'; - print ''; - print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")); - print ''.$langs->trans("Type").''.$langs->trans("NotNull").''.$langs->trans("DefaultValue").''.$langs->trans("DatabaseIndex").''.$langs->trans("Position").''.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc")).''.$form->textwithpicto($langs->trans("Visible"), $langs->trans("VisibleDesc")).''.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).''.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).''.$langs->trans("Comment").'
'; - print ''; - print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $properties = dol_sort_array($tmpobjet->fields, 'position'); + + if (! empty($properties)) { - /* If from Reflection - if ($propval->class == $tabobj) - { - $propname=$propval->getName(); - $comment=$propval->getDocComment(); - $type=gettype($tmpobjet->$propname); - $default=$propdefault[$propname]; - // Discard generic properties - if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'isnolinkedbythird', 'ismultientitymanaged'))) continue; + // Line to add a property + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; - // Keep or not lines - if (in_array($propname, array('fk_element', 'lines'))) continue; - }*/ + foreach($properties as $propkey => $propval) + { + /* If from Reflection + if ($propval->class == $tabobj) + { + $propname=$propval->getName(); + $comment=$propval->getDocComment(); + $type=gettype($tmpobjet->$propname); + $default=$propdefault[$propname]; + // Discard generic properties + if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'isnolinkedbythird', 'ismultientitymanaged'))) continue; - $propname=$propkey; - $proplabel=$propval['label']; - $proptype=$propval['type']; - $propnotnull=$propval['notnull']; - $propsearchall=$propval['searchall']; - //$propdefault=$propval['default']; - $propindex=$propval['index']; - $propposition=$propval['position']; - $propenabled=$propval['enabled']; - $propvisible=$propval['visible']; - $propisameasure=$propval['isameasure']; - $propcomment=$propval['comment']; + // Keep or not lines + if (in_array($propname, array('fk_element', 'lines'))) continue; + }*/ - print ''; + $propname=$propkey; + $proplabel=$propval['label']; + $proptype=$propval['type']; + $propnotnull=$propval['notnull']; + $propsearchall=$propval['searchall']; + //$propdefault=$propval['default']; + $propindex=$propval['index']; + $propposition=$propval['position']; + $propenabled=$propval['enabled']; + $propvisible=$propval['visible']; + $propisameasure=$propval['isameasure']; + $propcomment=$propval['comment']; - print ''; - print ''; - print ''; - print ''; - /*print '';*/ - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + /*print '';*/ + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + } } + else + { + print ''; + } + print '
'.$langs->trans("Property"); + print ' ('.$langs->trans("Example").')'; + print ''; + print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")); + print ''.$langs->trans("Type").''.$langs->trans("NotNull").''.$langs->trans("DefaultValue").''.$langs->trans("DatabaseIndex").''.$langs->trans("Position").''.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc")).''.$form->textwithpicto($langs->trans("Visible"), $langs->trans("VisibleDesc")).''.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).''.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).''.$langs->trans("Comment").'
'; + print ''; + print '
'; - print $propname; - print ''; - print $proplabel; - print ''; - print $proptype; - print ''; - print $propnotnull; - print ''; - print $propdefault; - print ''; - print $propindex?'X':''; - print ''; - print $propposition; - print ''; - print $propenabled?$propenabled:''; - print ''; - print $propvisible?$propvisible:''; - print ''; - print $propisameasure?$propisameasure:''; - print ''; - print $propsearchall?'X':''; - print ''; - print $propcomment; - print ''; - print ''.img_delete().''; - print '
'; + print $propname; + print ''; + print $proplabel; + print ''; + print $proptype; + print ''; + print $propnotnull; + print ''; + print $propdefault; + print ''; + print $propindex?'X':''; + print ''; + print $propposition; + print ''; + print $propenabled?$propenabled:''; + print ''; + print $propvisible?$propvisible:''; + print ''; + print $propisameasure?$propisameasure:''; + print ''; + print $propsearchall?'X':''; + print ''; + print $propcomment; + print ''; + print ''.img_delete().''; + print '
'.$langs->trans('Property $field not found into the class. The class was probably not generated by modulebuilder.').'
'; + print '
'; + + print ''; } else - { - print ''.$langs->trans('Property $field not found into the class. The class was probably not generated by modulebuilder.').''; - } - print ''; - print '
'; - - print ''; + { + print ''.$langs->trans('Failed to init the object with the new.').''; + } } catch(Exception $e) { From b4e461e7ea9f73fd3687e51d1df8e0a1fbbfe2be Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 18:17:34 +0200 Subject: [PATCH 072/108] Debug modulebuilder --- htdocs/core/lib/modulebuilder.lib.php | 67 ++++++++++++--- htdocs/langs/en_US/modulebuilder.lang | 2 + htdocs/modulebuilder/index.php | 85 +++++++++++-------- .../template/class/myobject.class.php | 14 +-- .../modulebuilder/template/myobject_card.php | 21 ++++- 5 files changed, 129 insertions(+), 60 deletions(-) diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 282a02835c3..23d6597b227 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -34,7 +34,7 @@ * @param string $readdir Directory source (use $destdir when not defined) * @param string $addfieldentry Array of the field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure') * @param string $delfieldentry Id of field to remove - * @return int <=0 if KO, >0 if OK + * @return int|object <=0 if KO, Object if OK */ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir='', $addfieldentry=array() ,$delfieldentry='') { @@ -43,6 +43,12 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' if (empty($objectname)) return -1; if (empty($readdir)) $readdir=$destdir; + if (! empty($addfieldentry['arrayofkeyval']) && ! is_array($addfieldentry['arrayofkeyval'])) + { + dol_print_error('', 'Bad parameter addfieldentry with a property arrayofkeyval defined but that is not an array.'); + return -1; + } + // Check parameters if (count($addfieldentry) > 0) { @@ -92,8 +98,9 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' { if (is_array($addfieldentry) && count($addfieldentry)) { - $name=$addfieldentry['name']; + $name=$addfieldentry['name']; unset($addfieldentry['name']); + $object->fields[$name]=$addfieldentry; } if (! empty($delfieldentry)) @@ -114,6 +121,7 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' if (count($object->fields)) { + foreach($object->fields as $key => $val) { $i++; @@ -127,11 +135,24 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' if ($val['comment']) $texttoinsert.= " 'comment'=>'".$val['comment']."',"; if ($val['isameasure']) $texttoinsert.= " 'isameasure'=>'".$val['isameasure']."',"; if ($val['help']) $texttoinsert.= " 'help'=>'".$val['help']."',"; + if ($val['arrayofkeyval']) + { + $texttoinsert.= " 'arrayofkeyval'=>array("; + $i=0; + foreach($val['arrayofkeyval'] as $key2 => $val2) + { + if ($i) $texttoinsert.=", "; + $texttoinsert.="'".$key2."'=>'".$val2."'"; + $i++; + } + $texttoinsert.= ")"; + } $texttoinsert.= "),\n"; } } $texttoinsert.= "\t".');'."\n"; + //print ($texttoinsert);exit; if (count($object->fields)) { @@ -162,7 +183,7 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); @chmod($pathoffiletoedittarget, octdec($newmask)); - return 1; + return $object; } catch(Exception $e) { @@ -179,12 +200,15 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir=' * @param string $objectname Name of object * @param string $newmask New mask * @param string $readdir Directory source (use $destdir when not defined) + * @param Object $object If object was already loaded/known, it is pass to avaoid another include and new. * @return int <=0 if KO, >0 if OK */ -function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='') +function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='', $object=null) { global $db, $langs; + $error = 0; + if (empty($objectname)) return -1; if (empty($readdir)) $readdir=$destdir; @@ -200,11 +224,15 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='') return -1; } + // Load object from myobject.class.php try { - include_once $pathoffiletoclasssrc; - if (class_exists($objectname)) $object=new $objectname($db); - else return -1; + if (! is_object($object)) + { + include_once $pathoffiletoclasssrc; + if (class_exists($objectname)) $object=new $objectname($db); + else return -1; + } } catch(Exception $e) { @@ -235,9 +263,15 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='') $contentsql = preg_replace('/-- BEGIN MODULEBUILDER FIELDS.*END MODULEBUILDER FIELDS/ims', $texttoinsert, $contentsql); - file_put_contents($pathoffiletoedittarget, $contentsql); - @chmod($pathoffiletoedittarget, octdec($newmask)); - + $result = file_put_contents($pathoffiletoedittarget, $contentsql); + if ($result) + { + @chmod($pathoffiletoedittarget, octdec($newmask)); + } + else + { + $error++; + } // Edit .key.sql file $pathoffiletoeditsrc=$destdir.'/sql/llx_'.strtolower($objectname).'.key.sql'; @@ -265,10 +299,17 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='') dol_mkdir(dirname($pathoffiletoedittarget)); - file_put_contents($pathoffiletoedittarget, $contentsql); - @chmod($pathoffiletoedittarget, octdec($newmask)); + $result2 = file_put_contents($pathoffiletoedittarget, $contentsql); + if ($result) + { + @chmod($pathoffiletoedittarget, octdec($newmask)); + } + else + { + $error++; + } - return 1; + return $error ? -1 : 1; } diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 0f62870b299..891faa8e134 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -51,6 +51,8 @@ DatabaseIndex=Database index FileAlreadyExists=File %s already exists TriggersFile=File for triggers code HooksFile=File for hooks code +ArrayOfKeyValues=Array of key-val +ArrayOfKeyValuesDesc=Array of keys and values if field is a combo list with fixed values WidgetFile=Widget file ReadmeFile=Readme file ChangeLog=ChangeLog file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 48bfb1731ae..5ff69549182 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -337,13 +337,13 @@ if ($dirins && $action == 'initobject' && $module && $objectname) if (! $error) { // Edit the class file to write properties - $result=rebuildObjectClass($destdir, $module, $objectname, $newmask); - if ($result < 0) $error++; + $object=rebuildObjectClass($destdir, $module, $objectname, $newmask); + if (is_numeric($object) && $object < 0) $error++; } if (! $error) { // Edit sql with new properties - $result=rebuildObjectSql($destdir, $module, $objectname, $newmask); + $result=rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object); if ($result < 0) $error++; } @@ -362,25 +362,28 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) dol_mkdir($destdir); $addfieldentry = array( - 'name'=>GETPOST('propname','aZ09'),'type'=>GETPOST('proptype','alpha'),'label'=>GETPOST('proplabel','alpha'),'visible'=>GETPOST('propvisible','int'),'enabled'=>GETPOST('propenabled','int'), + 'name'=>GETPOST('propname','aZ09'),'label'=>GETPOST('proplabel','alpha'),'type'=>GETPOST('proptype','alpha'), + 'arrayofkeyval'=>GETPOST('proparrayofkeyval','none'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}' + 'visible'=>GETPOST('propvisible','int'),'enabled'=>GETPOST('propenabled','int'), 'position'=>GETPOST('propposition','int'),'notnull'=>GETPOST('propnotnull','int'),'index'=>GETPOST('propindex','int'),'searchall'=>GETPOST('propsearchall','int'), 'isameasure'=>GETPOST('propisameasure','int'), 'comment'=>GETPOST('propcomment','alpha'),'help'=>GETPOST('prophelp')); + if (! empty($addfieldentry['arrayofkeyval']) && ! is_array($addfieldentry['arrayofkeyval'])) + { + $addfieldentry['arrayofkeyval'] = dol_json_decode($addfieldentry['arrayofkeyval'], true); + } + // Edit the class file to write properties if (! $error) { - $result=rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry); - // var_dump($result);exit; - if ($result <= 0) - { - $error++; - } + $object=rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry); + if (is_numeric($result) && $result <= 0) $error++; } // Edit sql with new properties if (! $error) { - $result=rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir); + $result=rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object); if ($result <= 0) { $error++; @@ -412,14 +415,14 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) // Edit the class file to write properties if (! $error) { - $result=rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey); - if ($result <= 0) $error++; + $object=rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey); + if (is_numeric($object) && $object <= 0) $error++; } // Edit sql with new properties if (! $error) { - $result=rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir); + $result=rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object); if ($result <= 0) $error++; } @@ -1410,28 +1413,28 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("ClassFile").' : '.($realpathtoclass?'':'').$pathtoclass.($realpathtoclass?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("ApiClassFile").' : '.($realpathtoapi?'':'').$pathtoapi.($realpathtoapi?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '   '.$langs->trans("GoToApiExplorer").''; print '
'; print ' '.$langs->trans("TestClassFile").' : '.($realpathtophpunit?'':'').$pathtophpunit.($realpathtophpunit?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print ' '.$langs->trans("SqlFile").' : '.($realpathtosql?'':'').$pathtosql.($realpathtosql?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '   '.$langs->trans("DropTableIfEmpty").''; //print '   '.$langs->trans("RunSql").''; print '
'; print ' '.$langs->trans("SqlFileExtraFields").' : '.($realpathtosqlextra?'':'').$pathtosqlextra.($realpathtosqlextra?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; //print '   '.$langs->trans("RunSql").''; print '
'; print ' '.$langs->trans("SqlFileKey").' : '.($realpathtosqlkey?'':'').$pathtosqlkey.($realpathtosqlkey?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; //print '   '.$langs->trans("RunSql").''; print '
'; @@ -1443,19 +1446,19 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("PageForList").' : '.($realpathtosql?'':'').$pathtolist.($realpathtosql?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForCreateEditView").' : '.($realpathtocard?'':'').$pathtocard.($realpathtocard?'':'').'?action=create'; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForAgendaTab").' : '.($realpathtoagenda?'':'').$pathtoagenda.($realpathtoagenda?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForDocumentTab").' : '.($realpathtodocument?'':'').$pathtodocument.($realpathtodocument?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForNoteTab").' : '.($realpathtonote?'':'').$pathtonote.($realpathtonote?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '


'; @@ -1506,6 +1509,7 @@ elseif (! empty($module)) print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")); print ''; print ''.$langs->trans("Type").''; + print ''.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).''; print ''.$langs->trans("NotNull").''; //print ''.$langs->trans("DefaultValue").''; print ''.$langs->trans("DatabaseIndex").''; @@ -1524,18 +1528,19 @@ elseif (! empty($module)) { // Line to add a property print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + print ''; //print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; print ''; print ''; print ''; @@ -1559,6 +1564,7 @@ elseif (! empty($module)) $propname=$propkey; $proplabel=$propval['label']; $proptype=$propval['type']; + $proparrayofkeyval=$propval['arrayofkeyval']; $propnotnull=$propval['notnull']; $propsearchall=$propval['searchall']; //$propdefault=$propval['default']; @@ -1580,6 +1586,12 @@ elseif (! empty($module)) print ''; print $proptype; print ''; + print ''; + if ($proparrayofkeyval) + { + print json_encode($proparrayofkeyval); + } + print ''; print ''; print $propnotnull; print ''; @@ -1652,6 +1664,7 @@ elseif (! empty($module)) print ''; print ''; print ''; + print ''; print ''; $doleditor=new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%'); diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 546c404eb49..259db698024 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -78,19 +78,19 @@ class MyObject extends CommonObject * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. */ public $fields=array( - 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), - 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), - 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'index'=>1, 'position'=>20), + 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), + 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), + 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'index'=>1, 'position'=>20), 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1), 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Amount'), - 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>1, 'position'=>1000), - 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), - 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), + 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), //'date_valid' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>500), - 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), + 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-1, 'notnull'=>-1, 'position'=>500), //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValid', 'enabled'=>1, 'visible'=>-1, 'position'=>500), 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'notnull'=>-1, 'index'=>1, 'position'=>1000), + 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>1, 'position'=>1000, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Active', -1=>'Cancel')), ); public $rowid; diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 97662c150da..c4826cf2792 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -270,22 +270,30 @@ if ($action == 'create') foreach($object->fields as $key => $val) { if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; - print ''; + print ''.$langs->trans($val['label']).''; + print '>'; + print $langs->trans($val['label']); + print ''; print ''; if ($val['type'] == 'text') { print ''; + } + elseif (is_array($val['arrayofkeyval'])) + { + print $form->selectarray($key, $val['arrayofkeyval'], GETPOST($key, 'int')); } else { - print ''; + $cssforinput = 'minwidth100'; + print ''; } print ''; print ''; @@ -329,10 +337,15 @@ if (($id || $ref) && $action == 'edit') print ''; + } + elseif (is_array($val['arrayofkeyval'])) + { + print $form->selectarray($key, $val['arrayofkeyval'], GETPOST($key, 'int')); } else { - print ''; + $cssforinput = 'minwidth100'; + print ''; } print ''; print ''; From b9f2a53b3672eb80815fc29813c7445f3a8cb53e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Sep 2017 23:51:49 +0200 Subject: [PATCH 073/108] Debug modulebuilder --- htdocs/modulebuilder/index.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 5ff69549182..02150274fda 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1398,6 +1398,8 @@ elseif (! empty($module)) $pathtosql = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.sql'; $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($tabobj).'_extrafields.sql'; $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.key.sql'; + $pathtolib = strtolower($module).'/lib/'.strtolower($tabobj).'.lib.php'; + $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png'; $realpathtoclass = dol_buildpath($pathtoclass, 0, 1); $realpathtoapi = dol_buildpath($pathtoapi, 0, 1); @@ -1410,6 +1412,8 @@ elseif (! empty($module)) $realpathtosql = dol_buildpath($pathtosql, 0, 1); $realpathtosqlextra = dol_buildpath($pathtosqlextra, 0, 1); $realpathtosqlkey = dol_buildpath($pathtosqlkey, 0, 1); + $realpathtolib = dol_buildpath($pathtolib, 0, 1); + $realpathtopicto = dol_buildpath($pathtopicto, 0, 1); print '
'; print ' '.$langs->trans("ClassFile").' : '.($realpathtoclass?'':'').$pathtoclass.($realpathtoclass?'':'').''; @@ -1459,6 +1463,16 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("PageForNoteTab").' : '.($realpathtonote?'':'').$pathtonote.($realpathtonote?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + + print '
'; + + print ' '.$langs->trans("PageForLib").' : '.($realpathtolib?'':'').$pathtolib.($realpathtodocument?'':'').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + print ' '.$langs->trans("PageForPicto").' : '.($realpathtopicto?'':'').$pathtopicto.($realpathtopicto?'':'').''; + //print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; print '


'; From 91d303465dca47d1f2ca67f23ed6b0122aa15786 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 01:36:20 +0200 Subject: [PATCH 074/108] NEW Can add html content on right of tabs --- htdocs/admin/dolistore/ajax/image.php | 3 ++- htdocs/admin/ihm.php | 14 ++++++------- htdocs/compta/bank/bankentries.php | 2 +- htdocs/compta/facture/card.php | 4 ++-- htdocs/core/class/html.form.class.php | 4 ++-- htdocs/core/lib/functions.lib.php | 19 +++++++++++------- htdocs/core/search_page.php | 2 +- htdocs/core/tpl/objectline_create.tpl.php | 2 +- htdocs/core/tpl/objectline_edit.tpl.php | 8 ++++---- htdocs/fourn/facture/card.php | 4 ++-- htdocs/langs/en_US/modulebuilder.lang | 3 ++- htdocs/modulebuilder/index.php | 20 +++++++++++-------- .../product/class/html.formproduct.class.php | 3 +-- htdocs/projet/element.php | 2 -- htdocs/theme/eldy/style.css.php | 4 +++- htdocs/theme/md/style.css.php | 8 ++++++-- 16 files changed, 57 insertions(+), 45 deletions(-) diff --git a/htdocs/admin/dolistore/ajax/image.php b/htdocs/admin/dolistore/ajax/image.php index 6d63dd3e08b..14d05a036e8 100644 --- a/htdocs/admin/dolistore/ajax/image.php +++ b/htdocs/admin/dolistore/ajax/image.php @@ -64,4 +64,5 @@ try { if ($trace[0]['args'][0] == 404) die('Bad ID'); else if ($trace[0]['args'][0] == 401) die('Bad auth key'); else die('Can not access to '.$conf->global->MAIN_MODULE_DOLISTORE_API_SRV); -} \ No newline at end of file +} + diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index 7a336e6d4e7..2322ae7a057 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -230,14 +230,14 @@ if ($action == 'edit') // Edit print ''; // Default language - print ''.$langs->trans("DefaultLanguage").''; + print ''.$langs->trans("DefaultLanguage").''; print $formadmin->select_language($conf->global->MAIN_LANG_DEFAULT, 'MAIN_LANG_DEFAULT', 1, 0, 0, 0, 0, 'minwidth300'); print ''; print ' '; print ''; // Multilingual GUI - print ''.$langs->trans("EnableMultilangInterface").''; + print ''.$langs->trans("EnableMultilangInterface").''; print $form->selectyesno('MAIN_MULTILANGS',$conf->global->MAIN_MULTILANGS,1); print ''; print ' '; @@ -349,9 +349,8 @@ if ($action == 'edit') // Edit print ''; // Message of the day on home page - $substitutionarray=getCommonSubstitutionArray($langs, 0, array('object')); + $substitutionarray=getCommonSubstitutionArray($langs, 0, array('object','objectamount')); complete_substitutions_array($substitutionarray, $langs); - $substitutionarray['__(AnyTranslationKey)__']=$langs->trans('TranslationKey'); print ''; $texthelp=$langs->trans("FollowingConstantsWillBeSubstituted").'
'; @@ -359,7 +358,7 @@ if ($action == 'edit') // Edit { $texthelp.=$key.'
'; } - print $form->textwithpicto($langs->trans("MessageOfDay"), $texthelp, 1, 'help', '', 0, 2, ''); + print $form->textwithpicto($langs->trans("MessageOfDay"), $texthelp, 1, 'help', '', 0, 2, 'tooltipmessageofday'); print ''; @@ -379,16 +378,15 @@ if ($action == 'edit') // Edit print ''; // Message on login page - $substitutionarray=getCommonSubstitutionArray($langs, 0, array('object','user')); + $substitutionarray=getCommonSubstitutionArray($langs, 0, array('object','objectamount','user')); complete_substitutions_array($substitutionarray, $langs); - $substitutionarray['__(AnyTranslationKey)__']=$langs->trans('TranslationKey'); print ''; $texthelp=$langs->trans("FollowingConstantsWillBeSubstituted").'
'; foreach($substitutionarray as $key => $val) { $texthelp.=$key.'
'; } - print $form->textwithpicto($langs->trans("MessageLogin"), $texthelp, 1, 'help', '', 0, 2, ''); + print $form->textwithpicto($langs->trans("MessageLogin"), $texthelp, 1, 'help', '', 0, 2, 'tooltipmessagelogin'); print ''; $doleditor = new DolEditor('main_home', (isset($conf->global->MAIN_HOME)?$conf->global->MAIN_HOME:''), '', 142, 'dolibarr_notes', 'In', false, true, true, ROWS_4, '90%'); $doleditor->Create(); diff --git a/htdocs/compta/bank/bankentries.php b/htdocs/compta/bank/bankentries.php index cd4d659d743..40d2f5c8ffc 100644 --- a/htdocs/compta/bank/bankentries.php +++ b/htdocs/compta/bank/bankentries.php @@ -743,7 +743,7 @@ if ($resql) // Title $bankcateg=new BankCateg($db); - $morehtml='
'; + $morehtml='
'; $morehtml.= ' "; // ' Page '; $morehtml.=''; $morehtml.='/'.$nbtotalofpages.' '; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index b3a21f9af31..8006a120996 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2550,8 +2550,8 @@ if ($action == 'create') print $desc; print '
'; - print '    0 ? 'checked':'').' /> "; - print '
    0 ? 'checked':'').' /> "; + print '    0 ? 'checked':'').' /> "; + print '
    0 ? 'checked':'').' /> "; print '
'; print '
'; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 931c3c5d1ce..f2427056fb5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -544,7 +544,7 @@ class Form $disabled=0; $ret='
'; - $ret.=''; // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks. $parameters=array(); @@ -561,7 +561,7 @@ class Form $ret.=''; // Warning: if you set submit button to disabled, post using 'Enter' will no more work. - $ret.=''; + $ret.=''; $ret.='
'; if (! empty($conf->use_javascript_ajax)) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 41cd039d1e6..f5b4b755b8d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1016,11 +1016,12 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename=' * @param int $notab -1 or 0=Add tab header, 1=no tab header. If you set this to 1, using dol_fiche_end() to close tab is not required. * @param string $picto Add a picto on tab title * @param int $pictoisfullpath If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto. + * @param string $morehtmlright Add more html content on right of tabs title * @return void */ -function dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0) +function dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='') { - print dol_get_fiche_head($links, $active, $title, $notab, $picto, $pictoisfullpath); + print dol_get_fiche_head($links, $active, $title, $notab, $picto, $pictoisfullpath, $morehtmlright); } /** @@ -1032,14 +1033,17 @@ function dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto * @param int $notab -1 or 0=Add tab header, 1=no tab header. If you set this to 1, using dol_fiche_end() to close tab is not required. * @param string $picto Add a picto on tab title * @param int $pictoisfullpath If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto. + * @param string $morehtmlright Add more html content on right of tabs title * @return string */ -function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0) +function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='') { global $conf, $langs, $hookmanager; $out="\n".'
'."\n"; + if ($morehtmlright) $out.='
'.$morehtmlright.'
'; // Output right area first so when space is missing, text is in front of tabs and not under. + // Show title $showtitle=1; if (! empty($conf->dol_optimize_smallscreen)) $showtitle=0; @@ -1060,6 +1064,8 @@ function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $pi if (count($keys)) $maxkey=max($keys); } + //$conf->global->MAIN_MAXTABS_IN_CARD=3; + // Show tabs $bactive=false; // if =0 we don't use the feature @@ -1147,7 +1153,7 @@ function dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $pi { $tabsname=str_replace("@", "", $picto); $out.='\n"; @@ -5213,9 +5219,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob if (empty($exclude) || ! in_array('system', $exclude)) { - $substitutionarray=array_merge($substitutionarray, array( - '__DOL_MAIN_URL_ROOT__'=>DOL_MAIN_URL_ROOT - )); + $substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationKey'); + $substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT; } if (empty($exclude) || ! in_array('mycompany', $exclude)) { diff --git a/htdocs/core/search_page.php b/htdocs/core/search_page.php index 494dddbdff3..61d39af045e 100644 --- a/htdocs/core/search_page.php +++ b/htdocs/core/search_page.php @@ -73,7 +73,7 @@ if ($conf->use_javascript_ajax && 1 == 2) // select2 is ko with jmobile { if (! is_object($form)) $form=new Form($db); $selected=-1; - $searchform.='

'.$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, 'data-role="none"', '', 0, 1, 'minwidth300', 1, $langs->trans("Search"), 0); + $searchform.='

'.$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'minwidth300', 1, $langs->trans("Search"), 0); } else { diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 9969740ff35..84b2413f396 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -317,7 +317,7 @@ else { product->enabled) || ! empty($conf->service->enabled)) { ?> - + "> diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 2f839e06281..de1649225ee 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -179,7 +179,7 @@ $coldisplay=-1; // We remove first td product->enabled) || ! empty($conf->service->enabled)) { ?> - + @@ -266,21 +266,21 @@ jQuery(document).ready(function() if (event.which != 9 && (event.which < 37 ||event.which > 40) && jQuery("#price_ht").val() != '') { jQuery("#price_ttc").val(''); jQuery("#multicurrency_subprice").val(''); - } + } }); jQuery("#price_ttc").keyup(function(event) { // console.log(event.which); // discard event tag and arrows if (event.which != 9 && (event.which < 37 || event.which > 40) && jQuery("#price_ttc").val() != '') { jQuery("#price_ht").val(''); jQuery("#multicurrency_subprice").val(''); - } + } }); jQuery("#multicurrency_subprice").keyup(function(event) { // console.log(event.which); // discard event tag and arrows if (event.which != 9 && (event.which < 37 || event.which > 40) && jQuery("#price_ttc").val() != '') { jQuery("#price_ht").val(''); jQuery("#price_ttc").val(''); - } + } }); '; - print '    0 ? 'checked':'').' /> "; - print '
    0 ? 'checked':'').' /> "; + print '    0 ? 'checked':'').' /> "; + print '
    0 ? 'checked':'').' /> "; print '
'; print '
'; diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 891faa8e134..e5e662a7852 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -3,7 +3,8 @@ ModuleBuilderDesc=This tools must be used by experienced users or developers. It EnterNameOfModuleDesc=Enter name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) EnterNameOfObjectDesc=Enter name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. ModuleBuilderDesc2=Path where modules are generated/edited (first alternative directory defined into %s): %s -ModuleBuilderDesc3=Generated/editable modules found: %s (they are detected as editable when the file %s exists in root of module directory). +ModuleBuilderDesc3=Generated/editable modules found: %s +ModuleBuilderDesc4=A module is detected as 'editable' when the file %s exists in root of module directory NewModule=New module NewObject=New object ModuleKey=Module key diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 02150274fda..da5bbfaf1cd 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -851,7 +851,8 @@ if ($message) print $message; } -print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'
'; +//print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'
'; +$infomodulesfound = '
'.$form->textwithpicto($langs->trans("ModuleBuilderDesc3", count($listofmodules)), $langs->trans("ModuleBuilderDesc4", $FILEFLAG)).'
'; // Load module descriptor @@ -911,7 +912,7 @@ $head[$h][2] = 'deletemodule'; $h++; -dol_fiche_head($head, $module, $langs->trans("Modules"), -1, 'generic'); // Modules +dol_fiche_head($head, $module, $langs->trans("Modules"), -1, 'generic', 0, $infomodulesfound); // Modules if ($module == 'initmodule') { @@ -1427,6 +1428,15 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + print '
'; + + print ' '.$langs->trans("PageForLib").' : '.($realpathtolib?'':'').$pathtolib.($realpathtodocument?'':'').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + print ' '.$langs->trans("PageForPicto").' : '.($realpathtopicto?'':'').$pathtopicto.($realpathtopicto?'':'').''; + //print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + print '
'; print ' '.$langs->trans("SqlFile").' : '.($realpathtosql?'':'').$pathtosql.($realpathtosql?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; @@ -1467,12 +1477,6 @@ elseif (! empty($module)) print '
'; - print ' '.$langs->trans("PageForLib").' : '.($realpathtolib?'':'').$pathtolib.($realpathtodocument?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '
'; - print ' '.$langs->trans("PageForPicto").' : '.($realpathtopicto?'':'').$pathtopicto.($realpathtopicto?'':'').''; - //print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print ''; print '


'; diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index 1c4c3249791..8d4ddc4705d 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -219,10 +219,9 @@ class FormProduct include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; $comboenhancement = ajax_combobox($htmlname, $events); $out.= $comboenhancement; - $nodatarole=($comboenhancement?' data-role="none"':''); } - $out.=''; if ($empty) $out.=''; foreach($this->cache_warehouses as $id => $arraytypes) { diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index f76b6f9f0cc..8dd7f6bbed5 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -1133,13 +1133,11 @@ foreach ($listofreferent as $key => $value) } // Enhance with select2 -$nodatarole=''; if ($conf->use_javascript_ajax) { include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; $comboenhancement = ajax_combobox('.elementselect'); $out.=$comboenhancement; - $nodatarole=($comboenhancement?' data-role="none"':''); print $comboenhancement; } diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 1fbd4e44037..fa85d0825e7 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -2039,7 +2039,9 @@ div.tabs { div.tabsElem { margin-top: 1px; } /* To avoid overlap of tabs when not browser */ - +div.tabsElem a { + font-weight: normal !important; +} div.tabBar { color: #; padding-top: 16px; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 4d46f2e781e..1273d819f3c 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -2064,8 +2064,12 @@ div.tabs { clear:both; height:100%; } -div.tabsElem { margin-top: 6px; } /* To avoid overlap of tabs when not browser */ - +div.tabsElem { + margin-top: 6px; +} /* To avoid overlap of tabs when not browser */ +div.tabsElem a { + font-weight: normal !important; +} div.tabBar { color: #; padding-top: 16px; From 87a75a0ad73b4c5436eccda96a0ff32dd187c62c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 01:46:00 +0200 Subject: [PATCH 075/108] CSS not bold on jnotify messages --- htdocs/theme/eldy/style.css.php | 6 ++++++ htdocs/theme/md/style.css.php | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index fa85d0825e7..505038023ca 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -3991,6 +3991,12 @@ div#ecm-layout-center { padding-left: 10px !important; padding-right: 10px !important; } +.jnotify-container .jnotify-notification .jnotify-message { + font-weight: normal; +} +.jnotify-container .jnotify-notification-warning .jnotify-close, .jnotify-container .jnotify-notification-warning .jnotify-message { + color: #a28918 !important; +} /* use or not ? */ div.jnotify-background { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 1273d819f3c..64d852b0395 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4043,6 +4043,12 @@ div#ecm-layout-center { padding-left: 10px !important; padding-right: 10px !important; } +.jnotify-container .jnotify-notification .jnotify-message { + font-weight: normal; +} +.jnotify-container .jnotify-notification-warning .jnotify-close, .jnotify-container .jnotify-notification-warning .jnotify-message { + color: #a28918 !important; +} /* use or not ? */ div.jnotify-background { From 97ece5fda949292c37f438e3df9ea82895fd7a15 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 01:49:59 +0200 Subject: [PATCH 076/108] CSS --- htdocs/theme/eldy/style.css.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 505038023ca..c1841f6cb9a 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -3138,12 +3138,11 @@ td.legendLabel { padding: 2px 2px 2px 0 !important; } div.titre { font-family: ; font-size: 14px; - font-weight: bold; + /* font-weight: bold; */ color: rgb(); text-decoration: none; padding-top: 5px; padding-bottom: 5px; - /* text-shadow: 1px 1px 2px #FFFFFF; */ } #dolpaymenttable { min-width: 310px; font-size: 16px; } /* Width must have min to make stripe input area visible */ From f4b35a304b4d552be8607e7425e3650dea83507c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 02:32:21 +0200 Subject: [PATCH 077/108] Update doc --- .../template/doc/Specifications.asciidoc | 128 +++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/template/doc/Specifications.asciidoc b/htdocs/modulebuilder/template/doc/Specifications.asciidoc index d2150c0865d..adfaeb4e9b5 100644 --- a/htdocs/modulebuilder/template/doc/Specifications.asciidoc +++ b/htdocs/modulebuilder/template/doc/Specifications.asciidoc @@ -1,3 +1,127 @@ -# SPECIFICATIONS OF MODULE MYMODULE FOR DOLIBARR ERP CRM += MYMODULE = +Copyright (C) ---Put here your own copyright and developer email--- +:subtitle: MYMODULE SPECIFICATIONS + + + +== Topic of document + +This document was build from following input: + +* Date 1 +... + +* Date 2 +... + + +The document includes an introductory chapter of functional specifications, presenting the different actors involved in the rebuild of the definitions +of business terms that will be used (some of which may be new or different). +The main following chapter will present the entire process, also known as *uses cases*, according to a principle of a description, in chronological sequence if possible, +to present the actor and the action performed, as in the following example: + +* *X* Actor realizes Action A. +* *Y* Actor communicates Info B to Actor *Z* +* *Automaton* performs update of data for... +* Etc ... + +Functional requirements are complemented by a chapter of technical requirements. +The chapter on data lists key information specific to Presto that were identified at the time of writing specification. It will be enriched as +iterations occurs. + +Finally, in the Appendix, the documents known when writing this document are centralized to illustrate the existing document or inspire the new expected one. +These documents have their content directly integrated in this specification or have a reference to +external documents stored in the *Appendices* directory accompanying this document. + + + +*Log of versions* + +[options="header",format="csv"] +|=== +Author, Date, Version +John Doe, Date YYY-MM-DD, Version 1.0 +|=== + + + +<<< + + +== BUSINESS SPECIFICATIONS - INTRODUCTION + +=== List of actors [[actors]] + +Actors are physical people or moral entities working on at least one process. +The following chart prensts list of actors or partners identified by the project for the defined scope of project. We will use then the name defined into first column to speak about roles in the rest of documents. + +[options="header",format="csv"] +|=== +Actor/profil/role, Description of role, Access to system or not, Example of actor +Customer Service, Receive and create Sales orders (SO), Yes, Mr Smith +Purchase, Make puchase order (PO), Yes, 5 people +Administrator - IT, Administration of users/groups and IT services, Yes, John Doe +Automaton, Execute automatic data processing, Yes, NA +|=== + + +=== Definitions [[definitions]] + +To understand the descriptions of the target process, it was necessary to define or redefine some vocabulary concepts. We must see these definitions as defined in the +new system. Indeed, some terms are already being used but have either not a definition in line with standards, or even differs between services. To bring everyone, +and to consolidate the process, these terms are redefined here, and with their definition in the target objective. + +*Definition ABC* + +... + +*Definition DEF* + +... + + +[NOTE] +============== +Important information will be noticed with a notice like this one. + +* Main information 1 +* Main information 2 +============== + + + +== BUSINESS SPECIFICATION - PROCESS + +Specifications were cut into different business process. We call a business process a workflow with a starting situation and ending situation. Between start and end, we will find actions +done by actors to bring the value of the company. This actions are described using the syntax rule: +*Actor X* do action Y, *Actor Z* do action W. + +_Each process/use case is described into a separate chapter._ + + +=== Use case / Process 1 [[process_1]] + +==== Title and goals + +... + +==== Actors or roles + +* Members of group *...* + +==== Standard flow + +* Members of Groupe *...*: Do ... +* Members of Groupe *...*: Do ... +* Members of Groupe *...*: Do ... + +==== Alternative flow + +* A user without role *...*: Can't do ... + +==== Business rules + +* Business rule 1 +* Business rule 2 + -There is no detailed specification available yet. From fac4ebec22bad9b7f550e72f5bb6ff7f4e404008 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 10:26:43 +0200 Subject: [PATCH 078/108] Code comment --- htdocs/modulebuilder/template/myobject_card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index c4826cf2792..515768b8011 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -27,8 +27,8 @@ //if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); //if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); //if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test done when option MAIN_SECURITY_CSRF_WITH_TOKEN is on. //if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data //if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test //if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu From c65f794f87b8804d57a7eafdc4a20b391aef59d4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 10:29:48 +0200 Subject: [PATCH 079/108] Code comment --- htdocs/modulebuilder/index.php | 2 +- htdocs/modulebuilder/template/myobject_list.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index da5bbfaf1cd..dade8847aa6 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -23,7 +23,7 @@ * \brief Home page for module builder module */ -if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti SQL+XSS injection attack test require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index ad8c8b317eb..475716114fa 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -27,8 +27,8 @@ //if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); //if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); //if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test done when option MAIN_SECURITY_CSRF_WITH_TOKEN is on. //if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data //if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test //if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu From 0cdca6f3ebae336a29398e463856529ba9c6d910 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sun, 24 Sep 2017 11:10:33 +0200 Subject: [PATCH 080/108] Fix: phpcs error --- htdocs/core/class/html.form.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f2427056fb5..dd9e643e74c 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2987,12 +2987,12 @@ class Form * Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want. * See instead to force the default value by the caller. * - * @param int $selected Id of payment term to preselect by default - * @param string $htmlname Nom de la zone select - * @param int $filtertype Not used + * @param int $selected Id of payment term to preselect by default + * @param string $htmlname Nom de la zone select + * @param int $filtertype Not used * @param int $addempty Add an empty entry - * @param int $noadmininfo 0=Add admin info, 1=Disable admin info - * @param string $morecss Add more CSS on select tag + * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info + * @param string $morecss Add more CSS on select tag * @return void */ function select_conditions_paiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='') From b48fe684d358c9cecaa793b51c51a95dde0eed60 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sun, 24 Sep 2017 17:43:01 +0200 Subject: [PATCH 081/108] Fix: wrong return when cancel --- htdocs/adherents/card.php | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 479af36a134..0ef0a4e3dc3 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -121,17 +121,6 @@ $hookmanager->initHooks(array('membercard','globalcard')); * Actions */ -if ($cancel) { - - $action=''; - - if (! empty($backtopage)) - { - header("Location: ".$backtopage); - exit; - } -} - $parameters=array('id'=>$id, 'rowid'=>$id, 'objcanvas'=>$objcanvas); $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -986,11 +975,18 @@ else dol_fiche_end(); - print '
'; - print ''; - print '     '; - print ''; - print '
'; + print '
'; + print ''; + print '  '; + if (! empty($backtopage)) + { + print ''; + } + else + { + print ''; + } + print '
'; print "\n"; } From 49e9326a6d4b81e446b40b2143b47af145b23145 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 19:50:32 +0200 Subject: [PATCH 082/108] Code comment --- htdocs/core/lib/security2.lib.php | 2 +- htdocs/main.inc.php | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 3876dc0e2cd..4d79b87122e 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -184,7 +184,7 @@ function dol_loginfunction($langs,$conf,$mysoc) // Set cookie for timeout management $prefix=dol_getprefix(); $sessiontimeout='DOLSESSTIMEOUT_'.$prefix; - if (! empty($conf->global->MAIN_SESSION_TIMEOUT)) setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", '', 0); + if (! empty($conf->global->MAIN_SESSION_TIMEOUT)) setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", null, false, true); if (GETPOST('urlfrom','alpha')) $_SESSION["urlfrom"]=GETPOST('urlfrom','alpha'); else unset($_SESSION["urlfrom"]); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 675c82aa499..27168349f22 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -179,7 +179,9 @@ if (! empty($_SERVER['DOCUMENT_ROOT']) && substr($_SERVER['DOCUMENT_ROOT'], -6) // Include the conf.php and functions.lib.php require_once 'filefunc.inc.php'; -// If there is a POST parameter to tell to save automatically some POST parameters into cookies, we do it +// If there is a POST parameter to tell to save automatically some POST parameters into cookies, we do it. +// This is used for example by form of boxes to save personalization of some options. +// DOL_AUTOSET_COOKIE=cookiename:val1,val2 and cookiename_val1=aaa cookiename_val2=bbb will set cookie_name with value json_encode(array('val1'=> , )) if (! empty($_POST["DOL_AUTOSET_COOKIE"])) { $tmpautoset=explode(':',$_POST["DOL_AUTOSET_COOKIE"],2); @@ -194,7 +196,7 @@ if (! empty($_POST["DOL_AUTOSET_COOKIE"])) $cookiename=$tmpautoset[0]; $cookievalue=json_encode($cookiearrayvalue); //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue); - setcookie($cookiename, empty($cookievalue)?'':$cookievalue, empty($cookievalue)?0:(time()+(86400*354)), '/'); // keep cookie 1 year + setcookie($cookiename, empty($cookievalue)?'':$cookievalue, empty($cookievalue)?0:(time()+(86400*354)), '/', null, false, true); // keep cookie 1 year and add tag httponly if (empty($cookievalue)) unset($_COOKIE[$cookiename]); } @@ -204,7 +206,7 @@ $sessionname='DOLSESSID_'.$prefix; $sessiontimeout='DOLSESSTIMEOUT_'.$prefix; if (! empty($_COOKIE[$sessiontimeout])) ini_set('session.gc_maxlifetime',$_COOKIE[$sessiontimeout]); session_name($sessionname); -session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie +session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start. // This create lock released until session_write_close() or end of page. // We need this lock as long as we read/write $_SESSION ['vars']. We can close released when finished. if (! defined('NOSESSION')) From 4246cf24f3ea4b296647f57267dbd5b417691d57 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 20:36:27 +0200 Subject: [PATCH 083/108] Perf enhancement: Remove one include of js. --- htdocs/core/class/html.form.class.php | 11 +++-- htdocs/core/js/lib_head.js.php | 29 ++++++++++++ htdocs/core/js/select2_locale.js.php | 67 --------------------------- htdocs/core/lib/ajax.lib.php | 5 +- htdocs/main.inc.php | 3 +- 5 files changed, 39 insertions(+), 76 deletions(-) delete mode 100644 htdocs/core/js/select2_locale.js.php diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f2427056fb5..d5ada748c1f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5215,15 +5215,16 @@ class Form */ static function selectArrayAjax($htmlname, $url, $id='', $moreparam='', $moreparamtourl='', $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0) { - global $langs; + global $conf, $langs; global $delayedhtmlcontent; - $tmpplugin='select2'; + // TODO Use an internal dolibarr component instead of select2 + if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ! defined('REQUIRE_JQUERY_MULTISELECT')) return ''; $out=''; - // TODO Use an internal dolibarr component instead of select2 - $outdelayed=' + $tmpplugin='select2'; + $outdelayed="\n".' '."\n"; - print ''."\n"; } } @@ -1321,7 +1320,7 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs // Global js function print ''."\n"; - print ''."\n"; + print ''."\n"; // Add datepicker default options /*if (! defined('DISABLE_DATE_PICKER')) From 3482b1293321e134a7b45afdab6ad5a9fae7cf3f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 20:55:48 +0200 Subject: [PATCH 084/108] Comment deprecated js code --- htdocs/core/js/lib_head.js.php | 157 +++++++++++++++++---------------- 1 file changed, 81 insertions(+), 76 deletions(-) diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 46219f1b50e..57a6c4f7005 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -82,6 +82,7 @@ else header('Cache-Control: no-cache'); * SimpleDateFormat a utiliser pour retour * ================================================================== */ + /* function showDP(base,dateFieldID,format,codelang) { // check to see if another box is already showing @@ -165,7 +166,7 @@ function resetDP(base,dateFieldID,format,codelang) function loadMonth(base,month,year,ymd,codelang) { - /* showDP.box.innerHTML="Loading..."; */ + // showDP.box.innerHTML="Loading..."; // alert(codelang); var theURL=base+"datepicker.php?cm=shw&lang="+codelang; theURL+="&m="+encodeURIComponent(month); @@ -192,37 +193,6 @@ function closeDPBox() showDP.datefieldID=null; } -function dpChangeDay(dateFieldID,format) -{ - showDP.datefieldID=dateFieldID; - console.log("Call dpChangeDay, we save date into detailed fields."); - - var thefield=getObjectFromID(showDP.datefieldID); - var thefieldday=getObjectFromID(showDP.datefieldID+"day"); - var thefieldmonth=getObjectFromID(showDP.datefieldID+"month"); - var thefieldyear=getObjectFromID(showDP.datefieldID+"year"); - - var date=getDateFromFormat(thefield.value,format); - if (date) - { - thefieldday.value=date.getDate(); - if(thefieldday.onchange) thefieldday.onchange.call(thefieldday); - thefieldmonth.value=date.getMonth()+1; - if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth); - thefieldyear.value=date.getFullYear(); - if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear); - } - else - { - thefieldday.value=''; - if(thefieldday.onchange) thefieldday.onchange.call(thefieldday); - thefieldmonth.value=''; - if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth); - thefieldyear.value=''; - if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear); - } -} - function dpClickDay(year,month,day,format) { var thefield=getObjectFromID(showDP.datefieldID); @@ -250,16 +220,6 @@ function dpHighlightDay(year,month,day,months){ displayinfo.innerHTML=months[month-1]+" "+day+", "+year; } -// Returns an object given an id -function getObjectFromID(id){ - var theObject; - if(document.getElementById) - theObject=document.getElementById(id); - else - theObject=document.all[id]; - return theObject; -} - // This Function returns the top position of an object function getTop(theitem){ var offsetTrail = theitem; @@ -286,6 +246,85 @@ function getLeft(theitem){ return offsetLeft; } +// To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and +// not put popup completely on the front) +// Used only bu popup calendar +function hideSelectBoxes() { + var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10); + if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1) + { + for(var i = 0; i < document.all.length; i++) + { + if(document.all[i].tagName) + if(document.all[i].tagName == "SELECT") + document.all[i].style.visibility="hidden"; + } + } +} +// To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and +// not put popup completely on the front) +// Used only bu popup calendar +function displaySelectBoxes() { + var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10); + if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1) + { + for(var i = 0; i < document.all.length; i++) + { + if(document.all[i].tagName) + if(document.all[i].tagName == "SELECT") + document.all[i].style.visibility="visible"; + } + } +} + +*/ + + +// Returns an object given an id +function getObjectFromID(id){ + var theObject; + if(document.getElementById) + theObject=document.getElementById(id); + else + theObject=document.all[id]; + return theObject; +} + +// Called after selection of a date to save details into detailed fields +function dpChangeDay(dateFieldID,format) +{ + //showDP.datefieldID=dateFieldID; + console.log("Call dpChangeDay, we save date into detailed fields."); + + var thefield=getObjectFromID(dateFieldID); + var thefieldday=getObjectFromID(dateFieldID+"day"); + var thefieldmonth=getObjectFromID(dateFieldID+"month"); + var thefieldyear=getObjectFromID(dateFieldID+"year"); + + var date=getDateFromFormat(thefield.value,format); + if (date) + { + thefieldday.value=date.getDate(); + if(thefieldday.onchange) thefieldday.onchange.call(thefieldday); + thefieldmonth.value=date.getMonth()+1; + if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth); + thefieldyear.value=date.getFullYear(); + if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear); + } + else + { + thefieldday.value=''; + if(thefieldday.onchange) thefieldday.onchange.call(thefieldday); + thefieldmonth.value=''; + if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth); + thefieldyear.value=''; + if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear); + } +} + + + + // Create XMLHttpRequest object and load url // Used by calendar or other ajax processes @@ -345,40 +384,6 @@ function loadXMLDoc(url,readyStateFunction,async) return req; } -/* To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and - * not put popup completely on the front) - * Used only bu popup calendar - */ -function hideSelectBoxes() { - var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10); - if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1) - { - for(var i = 0; i < document.all.length; i++) - { - if(document.all[i].tagName) - if(document.all[i].tagName == "SELECT") - document.all[i].style.visibility="hidden"; - } - } -} -/* To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and - * not put popup completely on the front) - * Used only bu popup calendar - */ -function displaySelectBoxes() { - var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10); - if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1) - { - for(var i = 0; i < document.all.length; i++) - { - if(document.all[i].tagName) - if(document.all[i].tagName == "SELECT") - document.all[i].style.visibility="visible"; - } - } -} - - /* * ================================================================= From 2e511badf99f321ecd1a9c86b0dbb05662cb3fd6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 21:02:20 +0200 Subject: [PATCH 085/108] Code comment --- htdocs/core/js/lib_head.js.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 57a6c4f7005..7ed49d004d2 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -44,7 +44,7 @@ top_httphead('text/javascript; charset=UTF-8'); if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate'); else header('Cache-Control: no-cache'); ?> - +// Javascript libraries for Dolibarr ERP CRM (https://www.dolibarr.org) /** From 7a6180858e9d37a2d8442a9a72d9428554b95514 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 21:12:50 +0200 Subject: [PATCH 086/108] Fix phpunit --- test/phpunit/AdherentTest.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/phpunit/AdherentTest.php b/test/phpunit/AdherentTest.php index 34ec0a80917..b29f8508a8e 100644 --- a/test/phpunit/AdherentTest.php +++ b/test/phpunit/AdherentTest.php @@ -196,7 +196,6 @@ class AdherentTest extends PHPUnit_Framework_TestCase $result=$localobject->fetch($id); print __METHOD__." id=".$id." result=".$result."\n"; $this->assertLessThan($result, 0); - return $localobject; } @@ -318,14 +317,13 @@ class AdherentTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; - $template = '%DOL_MAIN_URL_ROOT%,%ID%,%CIVILITY%,%FIRSTNAME%,%LASTNAME%,%FULLNAME%,%COMPANY%,'. - '%ADDRESS%,%ZIP%,%TOWN%,%COUNTRY%,%EMAIL%,%BIRTH%,%PHOTO%,%LOGIN%,%PASSWORD%,%PRENOM%,'. - '%NOM%,%SOCIETE%,%ADDRESS%,%ZIP%,%TOWN%,%COUNTRY%'; + $template = '__CIVILITY__,__FIRSTNAME__,__LASTNAME__,__FULLNAME__,__COMPANY__,'. + '__ADDRESS__,__ZIP__,__TOWN__,__COUNTRY__,__EMAIL__,__BIRTH__,__PHOTO__,__LOGIN__'; // If option to store clear password has been set, we get 'dolibspec' into PASSWORD field. - $expected = DOL_MAIN_URL_ROOT.','.$localobject->id.',,New firstname,New name,New firstname New name,'. + $expected = ',New firstname,New name,New firstname New name,'. 'New company,New address,New zip,New town,Belgium,newemail@newemail.com,'.dol_print_date($localobject->birth,'day').',,'. - 'newlogin,dolibspec,New firstname,New name,New company,New address,New zip,New town,Belgium'; + 'newlogin'; $result = $localobject->makeSubstitution($template); print __METHOD__." result=".$result."\n"; From 971e59395c78e2527510d35d76627a50e917eebf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 21:46:14 +0200 Subject: [PATCH 087/108] Fix phpcs --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d5ada748c1f..b75cde6d9e3 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2991,7 +2991,7 @@ class Form * @param string $htmlname Nom de la zone select * @param int $filtertype Not used * @param int $addempty Add an empty entry - * @param int $noadmininfo 0=Add admin info, 1=Disable admin info + * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info * @param string $morecss Add more CSS on select tag * @return void */ From 5776a948c44309402f9c462a85766084c0e2e833 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 21:54:26 +0200 Subject: [PATCH 088/108] Update card.php --- htdocs/holiday/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 6d6eb15e856..51ad2277ab5 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/holiday/common.inc.php'; $myparam = GETPOST("myparam"); $action=GETPOST('action', 'alpha'); $id=GETPOST('id', 'int'); -$fuserid = (GETPOST('fuserid')?:$user->id); +$fuserid = (GETPOST('fuserid','int')?GETPOST('fuserid','int'):$user->id); // Protection if external user if ($user->societe_id > 0) accessforbidden(); From 1bb5408d837feea388d9abd1959a1df33fd9cb70 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 22:18:10 +0200 Subject: [PATCH 089/108] FIX #7464 --- htdocs/install/mysql/migration/5.0.0-6.0.0.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index 3a5810d19e4..cd955b0416b 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -338,6 +338,7 @@ UPDATE llx_const SET value = __ENCRYPT('moono-lisa')__ WHERE value = __ENCRYPT DELETE FROM llx_document_model where nom = 'fsfe.fr.php' and type='donation'; ALTER TABLE llx_product_price ADD COLUMN default_vat_code varchar(10) AFTER tva_tx; +ALTER TABLE llx_product_customer_price ADD COLUMN default_vat_code varchar(10) AFTER tva_tx; ALTER TABLE llx_product_fournisseur_price ADD COLUMN default_vat_code varchar(10) AFTER tva_tx; ALTER TABLE llx_user ADD COLUMN model_pdf varchar(255); From 3a7aea48d76d82f2a4de61785b13caa014d641be Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 22:38:18 +0200 Subject: [PATCH 090/108] FIX #7475 --- htdocs/comm/propal/class/propal.class.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index f007cbdbf81..359695d883b 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -3366,8 +3366,8 @@ class Propal extends CommonObject $this->lines = array(); $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,'; - $sql.= ' pt.qty, pt.vat_src_code, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,'; - $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,'; + $sql.= ' pt.qty, pt.vat_src_code, pt.tva_tx, pt.localtax1_tx, pt.localtax2_tx, pt.remise_percent, pt.subprice, pt.info_bits,'; + $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.total_localtax1, pt.total_localtax2, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code,'; $sql.= ' pt.date_start, pt.date_end, pt.product_type, pt.rang, pt.fk_parent_line,'; $sql.= ' pt.fk_unit,'; $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.description as product_desc, p.tobatch as product_tobatch,'; @@ -3411,11 +3411,15 @@ class Propal extends CommonObject $this->lines[$i]->vat_src_code = $obj->vat_src_code; $this->lines[$i]->tva_tx = $obj->tva_tx; + $this->lines[$i]->localtax1_tx = $obj->localtax1_tx; + $this->lines[$i]->localtax2_tx = $obj->localtax2_tx; $this->lines[$i]->info_bits = $obj->info_bits; $this->lines[$i]->total_ht = $obj->total_ht; $this->lines[$i]->total_tva = $obj->total_tva; $this->lines[$i]->total_ttc = $obj->total_ttc; - $this->lines[$i]->fk_fournprice = $obj->fk_fournprice; + $this->lines[$i]->total_localtax1 = $obj->total_localtax1; + $this->lines[$i]->total_localtax2 = $obj->total_localtax2; + $this->lines[$i]->fk_fournprice = $obj->fk_fournprice; $marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht); $this->lines[$i]->pa_ht = $marginInfos[0]; $this->lines[$i]->marge_tx = $marginInfos[1]; From adb3827d1eeb3c6ce963155b776b35f922f2417d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 22:55:27 +0200 Subject: [PATCH 091/108] FIX #7475 --- htdocs/comm/propal/class/propal.class.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 359695d883b..f2ecb877a9a 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1404,7 +1404,7 @@ class Propal extends CommonObject { $this->lines=array(); - $sql = 'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,'; + $sql = 'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,'; $sql.= ' d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,'; $sql.= ' d.fk_unit,'; $sql.= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,'; @@ -1443,6 +1443,8 @@ class Propal extends CommonObject $line->tva_tx = $objp->tva_tx; $line->localtax1_tx = $objp->localtax1_tx; $line->localtax2_tx = $objp->localtax2_tx; + $line->localtax1_type = $objp->localtax1_type; + $line->localtax2_type = $objp->localtax2_type; $line->subprice = $objp->subprice; $line->fk_remise_except = $objp->fk_remise_except; $line->remise_percent = $objp->remise_percent; @@ -3366,7 +3368,7 @@ class Propal extends CommonObject $this->lines = array(); $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,'; - $sql.= ' pt.qty, pt.vat_src_code, pt.tva_tx, pt.localtax1_tx, pt.localtax2_tx, pt.remise_percent, pt.subprice, pt.info_bits,'; + $sql.= ' pt.qty, pt.vat_src_code, pt.tva_tx, pt.localtax1_tx, pt.localtax2_tx, pt.localtax1_type, pt.localtax2_type, pt.remise_percent, pt.subprice, pt.info_bits,'; $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.total_localtax1, pt.total_localtax2, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code,'; $sql.= ' pt.date_start, pt.date_end, pt.product_type, pt.rang, pt.fk_parent_line,'; $sql.= ' pt.fk_unit,'; @@ -3413,6 +3415,8 @@ class Propal extends CommonObject $this->lines[$i]->tva_tx = $obj->tva_tx; $this->lines[$i]->localtax1_tx = $obj->localtax1_tx; $this->lines[$i]->localtax2_tx = $obj->localtax2_tx; + $this->lines[$i]->localtax1_type = $obj->localtax1_type; + $this->lines[$i]->localtax2_type = $obj->localtax2_type; $this->lines[$i]->info_bits = $obj->info_bits; $this->lines[$i]->total_ht = $obj->total_ht; $this->lines[$i]->total_tva = $obj->total_tva; From 270aba99faabfd561fddfa8f7e94a8b413db2508 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 23:28:48 +0200 Subject: [PATCH 092/108] FIX #7471 --- .../class/fournisseur.commande.class.php | 9 +++- .../fourn/class/fournisseur.facture.class.php | 4 +- htdocs/fourn/commande/card.php | 52 ++++++++++++------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 528e32fd4a4..d328a66cef3 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -279,11 +279,12 @@ class CommandeFournisseur extends CommonOrder $this->fetchObjectLinked(); + //$result=$this->fetch_lines(); $this->lines=array(); $sql = "SELECT l.rowid, l.ref as ref_supplier, l.fk_product, l.product_type, l.label, l.description, l.qty,"; $sql.= " l.vat_src_code, l.tva_tx, l.remise_percent, l.subprice,"; - $sql.= " l.localtax1_tx, l. localtax2_tx, l.total_localtax1, l.total_localtax2,"; + $sql.= " l.localtax1_tx, l. localtax2_tx, l.localtax1_type, l. localtax2_type, l.total_localtax1, l.total_localtax2,"; $sql.= " l.total_ht, l.total_tva, l.total_ttc, l.special_code, l.fk_parent_line, l.rang,"; $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.description as product_desc,"; $sql.= " l.fk_unit,"; @@ -315,6 +316,8 @@ class CommandeFournisseur extends CommonOrder $line->tva_tx = $objp->tva_tx; $line->localtax1_tx = $objp->localtax1_tx; $line->localtax2_tx = $objp->localtax2_tx; + $line->localtax1_type = $objp->localtax1_type; + $line->localtax2_type = $objp->localtax2_type; $line->subprice = $objp->subprice; $line->pu_ht = $objp->subprice; $line->remise_percent = $objp->remise_percent; @@ -2977,7 +2980,7 @@ class CommandeFournisseurLigne extends CommonOrderLine public function fetch($rowid) { $sql = 'SELECT cd.rowid, cd.fk_commande, cd.fk_product, cd.product_type, cd.description, cd.qty, cd.tva_tx,'; - $sql.= ' cd.localtax1_tx, cd.localtax2_tx, cd.ref,'; + $sql.= ' cd.localtax1_tx, cd.localtax2_tx, cd.localtax1_type, cd.localtax2_type, cd.ref,'; $sql.= ' cd.remise, cd.remise_percent, cd.subprice,'; $sql.= ' cd.info_bits, cd.total_ht, cd.total_tva, cd.total_ttc,'; $sql.= ' cd.total_localtax1, cd.total_localtax2,'; @@ -3003,6 +3006,8 @@ class CommandeFournisseurLigne extends CommonOrderLine $this->tva_tx = $objp->tva_tx; $this->localtax1_tx = $objp->localtax1_tx; $this->localtax2_tx = $objp->localtax2_tx; + $this->localtax1_type = $objp->localtax1_type; + $this->localtax2_type = $objp->localtax2_type; $this->remise = $objp->remise; $this->remise_percent = $objp->remise_percent; $this->fk_product = $objp->fk_product; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 022b5f7c15d..6e5e7fce66a 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -640,7 +640,7 @@ class FactureFournisseur extends CommonInvoice function fetch_lines() { $sql = 'SELECT f.rowid, f.ref as ref_supplier, f.description, f.pu_ht, f.pu_ttc, f.qty, f.remise_percent, f.vat_src_code, f.tva_tx'; - $sql.= ', f.localtax1_tx, f.localtax2_tx, f.total_localtax1, f.total_localtax2, f.fk_facture_fourn '; + $sql.= ', f.localtax1_tx, f.localtax2_tx, f.localtax1_type, f.localtax2_type, f.total_localtax1, f.total_localtax2, f.fk_facture_fourn '; $sql.= ', f.total_ht, f.tva as total_tva, f.total_ttc, f.fk_product, f.product_type, f.info_bits, f.rang, f.special_code, f.fk_parent_line, f.fk_unit'; $sql.= ', p.rowid as product_id, p.ref as product_ref, p.label as label, p.description as product_desc'; $sql.= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_subprice, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc'; @@ -681,6 +681,8 @@ class FactureFournisseur extends CommonInvoice $line->tva_tx = $obj->tva_tx; $line->localtax1_tx = $obj->localtax1_tx; $line->localtax2_tx = $obj->localtax2_tx; + $line->localtax1_type = $obj->localtax1_type; + $line->localtax2_type = $obj->localtax2_type; $line->qty = $obj->qty; $line->remise_percent = $obj->remise_percent; $line->tva = $obj->total_tva; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 48a2e72661b..43ce10ba2f6 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -544,19 +544,7 @@ if (empty($reshook)) */ if ($action == 'updateline' && $user->rights->fournisseur->commande->creer && ! GETPOST('cancel')) { - $tva_tx = GETPOST('tva_tx'); - - if (GETPOST('price_ht') != '') - { - $price_base_type = 'HT'; - $ht = price2num(GETPOST('price_ht')); - } - else - { - $ttc = price2num(GETPOST('price_ttc')); - $ht = $ttc / (1 + ($tva_tx / 100)); - $price_base_type = 'HT'; - } + $vat_rate=(GETPOST('tva_tx')?GETPOST('tva_tx'):0); if ($lineid) { @@ -568,10 +556,36 @@ if (empty($reshook)) $date_start=dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear')); $date_end=dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); - $localtax1_tx=get_localtax($tva_tx,1,$mysoc,$object->thirdparty); - $localtax2_tx=get_localtax($tva_tx,2,$mysoc,$object->thirdparty); + // Define info_bits + $info_bits = 0; + if (preg_match('/\*/', $vat_rate)) + $info_bits |= 0x01; - $pu_ht_devise = GETPOST('multicurrency_subprice'); + // Define vat_rate + $vat_rate = str_replace('*', '', $vat_rate); + $localtax1_rate = get_localtax($vat_rate, 1, $mysoc, $object->thirdparty); + $localtax2_rate = get_localtax($vat_rate, 2, $mysoc, $object->thirdparty); + + if (GETPOST('price_ht') != '') + { + $price_base_type = 'HT'; + $ht = price2num(GETPOST('price_ht')); + } + else + { + $vatratecleaned = $vat_rate; + if (preg_match('/^(.*)\s*\((.*)\)$/', $vat_rate, $reg)) // If vat is "xx (yy)" + { + $vatratecleaned = trim($reg[1]); + $vatratecode = $reg[2]; + } + + $ttc = price2num(GETPOST('price_ttc')); + $ht = $ttc / (1 + ($vatratecleaned / 100)); + $price_base_type = 'HT'; + } + + $pu_ht_devise = GETPOST('multicurrency_subprice'); // Extrafields Lines $extrafieldsline = new ExtraFields($db); @@ -590,9 +604,9 @@ if (empty($reshook)) $ht, $_POST['qty'], $_POST['remise_percent'], - $tva_tx, - $localtax1_tx, - $localtax2_tx, + $vat_rate, + $localtax1_rate, + $localtax2_rate, $price_base_type, 0, isset($_POST["type"])?$_POST["type"]:$line->product_type, From af384f14ae5833b1cb914d740dd0ce963f009727 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 23:40:42 +0200 Subject: [PATCH 093/108] FIX #7477 --- htdocs/compta/facture/fiche-rec.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index 58fed19d103..66c964212db 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -360,7 +360,7 @@ if (empty($reshook)) // For triggers $line->id = $lineid; - if ($line->delete() > 0) + if ($line->delete($user) > 0) { $result=$object->update_price(1); From 4b92e2a705f4b25c8dc2e6c89aa8518d619fbafb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Sep 2017 23:55:44 +0200 Subject: [PATCH 094/108] Fix localtax --- htdocs/contrat/class/contrat.class.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 52bc7efd860..937cce82474 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -728,7 +728,7 @@ class Contrat extends CommonObject } // Selectionne les lignes contrat liees a aucun produit - $sql = "SELECT d.rowid, d.fk_contrat, d.statut, d.qty, d.description, d.price_ht, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.rowid, d.remise_percent, d.subprice,"; + $sql = "SELECT d.rowid, d.fk_contrat, d.statut, d.qty, d.description, d.price_ht, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.rowid, d.remise_percent, d.subprice,"; $sql.= " d.total_ht,"; $sql.= " d.total_tva,"; $sql.= " d.total_localtax1,"; @@ -766,6 +766,8 @@ class Contrat extends CommonObject $line->tva_tx = $objp->tva_tx; $line->localtax1_tx = $objp->localtax1_tx; $line->localtax2_tx = $objp->localtax2_tx; + $line->localtax1_type = $objp->localtax1_type; + $line->localtax2_type = $objp->localtax2_type; $line->subprice = $objp->subprice; $line->remise_percent = $objp->remise_percent; $line->price_ht = $objp->price_ht; @@ -2628,6 +2630,8 @@ class ContratLigne extends CommonObjectLine $sql.= " t.vat_src_code,"; $sql.= " t.localtax1_tx,"; $sql.= " t.localtax2_tx,"; + $sql.= " t.localtax1_type,"; + $sql.= " t.localtax2_type,"; $sql.= " t.qty,"; $sql.= " t.remise_percent,"; $sql.= " t.remise,"; @@ -2681,6 +2685,8 @@ class ContratLigne extends CommonObjectLine $this->vat_src_code = $obj->vat_src_code; $this->localtax1_tx = $obj->localtax1_tx; $this->localtax2_tx = $obj->localtax2_tx; + $this->localtax1_type = $obj->localtax1_type; + $this->localtax2_type = $obj->localtax2_type; $this->qty = $obj->qty; $this->remise_percent = $obj->remise_percent; $this->remise = $obj->remise; From cef7b9c92dd42ab468b51a3ef9b89c3cff452ee3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 00:08:26 +0200 Subject: [PATCH 095/108] FIX #7435 Can't add payment term --- htdocs/admin/dict.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 52e90b21956..ce87f507cc6 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -600,7 +600,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($value == 'localtax2' && empty($_POST['localtax2_type'])) continue; if ($value == 'color' && empty($_POST['color'])) continue; if ($value == 'formula' && empty($_POST['formula'])) continue; - if ((! isset($_POST[$value]) || $_POST[$value]=='') + if ($value == 'sortorder') continue; // For a column name 'sortorder', we use the field name 'position' + if ((! isset($_POST[$value]) || $_POST[$value]=='') && (! in_array($listfield[$f], array('decalage','module','accountancy_code','accountancy_code_sell','accountancy_code_buy')) // Fields that are not mandatory && (! ($id == 10 && $listfield[$f] == 'code')) // Code is mandatory fir table 10 ) @@ -715,7 +716,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $_POST[$listfieldvalue[$i]] = $conf->entity; } if ($i) $sql.=","; - if ($_POST[$listfieldvalue[$i]] == '' && ! ($listfieldvalue[$i] == 'code' && $id == 10)) $sql.="null"; // For vat, we want/accept code = '' + if ($listfieldvalue[$i] == 'sortorder') // For column name 'sortorder', we use the field name 'position' + { + $sql.="'".(int) $db->escape($_POST['position'])."'"; + } + elseif ($_POST[$listfieldvalue[$i]] == '' && ! ($listfieldvalue[$i] == 'code' && $id == 10)) $sql.="null"; // For vat, we want/accept code = '' else $sql.="'".$db->escape($_POST[$listfieldvalue[$i]])."'"; $i++; } @@ -764,7 +769,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) } if ($i) $sql.=","; $sql.= $field."="; - if ($_POST[$listfieldvalue[$i]] == '' && ! ($listfieldvalue[$i] == 'code' && $id == 10)) $sql.="null"; // For vat, we want/accept code = '' + if ($listfieldvalue[$i] == 'sortorder') // For column name 'sortorder', we use the field name 'position' + { + $sql.="'".(int) $db->escape($_POST['position'])."'"; + } + elseif ($_POST[$listfieldvalue[$i]] == '' && ! ($listfieldvalue[$i] == 'code' && $id == 10)) $sql.="null"; // For vat, we want/accept code = '' else $sql.="'".$db->escape($_POST[$listfieldvalue[$i]])."'"; $i++; } @@ -1839,6 +1848,8 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='') } else { + if ($fieldlist[$field]=='sortorder') $fieldlist[$field]='position'; + $classtd=''; $class=''; if ($fieldlist[$field]=='code') $classtd='width100'; if ($fieldlist[$field]=='affect') $class='maxwidth50'; From e3da4188e2fabb92b8e3302f081aab275aa86ff0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 00:16:52 +0200 Subject: [PATCH 096/108] GETPOST must not clean data for text input. --- htdocs/comm/action/card.php | 2 +- htdocs/comm/propal/card.php | 10 +++++----- htdocs/comm/remx.php | 2 +- htdocs/commande/card.php | 6 +++--- htdocs/compta/facture/card.php | 2 +- htdocs/compta/facture/class/facture.class.php | 4 ++-- htdocs/compta/facture/fiche-rec.php | 10 +++++----- htdocs/compta/paiement/card.php | 2 +- htdocs/contrat/card.php | 2 +- htdocs/cron/card.php | 4 ++-- htdocs/expedition/card.php | 4 ++-- htdocs/expensereport/card.php | 8 ++++---- htdocs/fichinter/card.php | 10 +++++----- htdocs/fourn/commande/card.php | 8 ++++---- htdocs/fourn/commande/orderstoinvoice.php | 4 ++-- htdocs/fourn/facture/card.php | 12 ++++++------ htdocs/fourn/paiement/card.php | 2 +- htdocs/loan/card.php | 4 ++-- htdocs/loan/payment/payment.php | 4 ++-- htdocs/product/card.php | 12 ++++++------ htdocs/public/members/new.php | 2 +- htdocs/supplier_proposal/card.php | 8 ++++---- htdocs/user/note.php | 2 +- 23 files changed, 62 insertions(+), 62 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index b491c9007cb..02a16af3c17 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -824,7 +824,7 @@ if ($action == 'create') // Description print ''.$langs->trans("Description").''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('note',(GETPOST('note')?GETPOST('note'):$object->note),'',180,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_5,'90%'); + $doleditor=new DolEditor('note',(GETPOST('note','none')?GETPOST('note','none'):$object->note),'',180,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_5,'90%'); $doleditor->Create(); print ''; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 8fb2a102c22..4fc1eebb66d 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -358,8 +358,8 @@ if (empty($reshook)) $object->fk_project = GETPOST('projectid'); $object->modelpdf = GETPOST('model'); $object->author = $user->id; // deprecated - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->statut = Propal::STATUS_DRAFT; $object->fk_incoterms = GETPOST('incoterm_id', 'int'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); @@ -386,8 +386,8 @@ if (empty($reshook)) $object->fk_project = GETPOST('projectid'); $object->modelpdf = GETPOST('model'); $object->author = $user->id; // deprecated - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->fk_incoterms = GETPOST('incoterm_id', 'int'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); @@ -979,7 +979,7 @@ if (empty($reshook)) $info_bits |= 0x01; // Clean parameters - $description = dol_htmlcleanlastbr(GETPOST('product_desc')); + $description = dol_htmlcleanlastbr(GETPOST('product_desc','none')); // Define vat_rate $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index 332181922d2..7a34d1a3a76 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -292,7 +292,7 @@ if ($socid > 0) print $form->load_tva('tva_tx',GETPOST('tva_tx'),$mysoc,$object); print ''; print ''.$langs->trans("NoteReason").''; - print ''; + print ''; print ""; } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index eb510b53333..53082499a9a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -256,8 +256,8 @@ if (empty($reshook)) $db->begin(); $object->date_commande = $datecommande; - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->source = GETPOST('source_id'); $object->fk_project = GETPOST('projectid'); $object->ref_client = GETPOST('ref_client'); @@ -927,7 +927,7 @@ if (empty($reshook)) $date_end=''; $date_start=dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear')); $date_end=dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); - $description=dol_htmlcleanlastbr(GETPOST('product_desc')); + $description=dol_htmlcleanlastbr(GETPOST('product_desc','none')); $pu_ht=GETPOST('price_ht'); $vat_rate=(GETPOST('tva_tx')?GETPOST('tva_tx'):0); $pu_ht_devise = GETPOST('multicurrency_subprice'); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 949e36f8ec3..2535d8e7442 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1816,7 +1816,7 @@ if (empty($reshook)) $date_end = ''; $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear')); $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); - $description = dol_htmlcleanlastbr(GETPOST('product_desc') ? GETPOST('product_desc') : GETPOST('desc')); + $description = dol_htmlcleanlastbr(GETPOST('product_desc','none') ? GETPOST('product_desc','none') : GETPOST('desc','none')); $pu_ht = GETPOST('price_ht'); $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); $qty = GETPOST('qty'); diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 41cc8042144..b6d294c6e18 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -293,8 +293,8 @@ class Facture extends CommonInvoice // Fields coming from GUI (priority on template). TODO Value of template should be used as default value on GUI so we can use here always value from GUI $this->fk_project = GETPOST('projectid','int') > 0 ? GETPOST('projectid','int') : $_facrec->fk_project; - $this->note_public = GETPOST('note_public') ? GETPOST('note_public') : $_facrec->note_public; - $this->note_private = GETPOST('note_private') ? GETPOST('note_private') : $_facrec->note_private; + $this->note_public = GETPOST('note_public','none') ? GETPOST('note_public','none') : $_facrec->note_public; + $this->note_private = GETPOST('note_private','none') ? GETPOST('note_private','none') : $_facrec->note_private; $this->modelpdf = GETPOST('model') ? GETPOST('model') : $_facrec->modelpdf; $this->cond_reglement_id = GETPOST('cond_reglement_id') > 0 ? GETPOST('cond_reglement_id') : $_facrec->cond_reglement_id; $this->mode_reglement_id = GETPOST('mode_reglement_id') > 0 ? GETPOST('mode_reglement_id') : $_facrec->mode_reglement_id; diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index 66c964212db..80912bffbad 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -209,8 +209,8 @@ if (empty($reshook)) if (! $error) { $object->titre = GETPOST('titre', 'alpha'); - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->usenewprice = GETPOST('usenewprice'); $object->frequency = $frequency; @@ -723,7 +723,7 @@ if (empty($reshook)) $date_end = ''; //$date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear')); //$date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); - $description = dol_htmlcleanlastbr(GETPOST('product_desc') ? GETPOST('product_desc') : GETPOST('desc')); + $description = dol_htmlcleanlastbr(GETPOST('product_desc','none') ? GETPOST('product_desc','none') : GETPOST('desc','none')); $pu_ht = GETPOST('price_ht'); $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); $qty = GETPOST('qty'); @@ -965,8 +965,8 @@ if ($action == 'create') print ''.$langs->trans("Customer").''.$object->thirdparty->getNomUrl(1,'customer').''; print ''; - $note_public=GETPOST('note_public')?GETPOST('note_public'):$object->note_public; - $note_private=GETPOST('note_private')?GETPOST('note_private'):$object->note_private; + $note_public=GETPOST('note_public','none')?GETPOST('note_public','none'):$object->note_public; + $note_private=GETPOST('note_private','none')?GETPOST('note_private','none'):$object->note_private; // Help of substitution key $substitutionarray=array( diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index 523d5256816..da38e9fb47a 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -60,7 +60,7 @@ if ($action == 'setnote' && $user->rights->facture->paiement) $db->begin(); $object->fetch($id); - $result = $object->update_note(GETPOST('note')); + $result = $object->update_note(GETPOST('note','none')); if ($result > 0) { $db->commit(); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 6d2181886a0..46fa2b3ca87 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -676,7 +676,7 @@ if (empty($reshook)) $fk_unit = GETPOST('unit', 'alpha'); - $objectline->description=GETPOST('product_desc'); + $objectline->description=GETPOST('product_desc','none'); $objectline->price_ht=GETPOST('elprice'); $objectline->subprice=GETPOST('elprice'); $objectline->qty=GETPOST('elqty'); diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index a1255954014..8e540c799fe 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -148,7 +148,7 @@ if ($action=='add') $object->params=GETPOST('params'); $object->md5params=GETPOST('md5params'); $object->module_name=GETPOST('module_name','alpha'); - $object->note=GETPOST('note'); + $object->note=GETPOST('note','none'); $object->datestart=dol_mktime(GETPOST('datestarthour','int'), GETPOST('datestartmin','int'), 0, GETPOST('datestartmonth','int'), GETPOST('datestartday','int'), GETPOST('datestartyear','int')); $object->dateend=dol_mktime(GETPOST('dateendhour','int'), GETPOST('dateendmin','int'), 0, GETPOST('dateendmonth','int'), GETPOST('dateendday','int'), GETPOST('dateendyear','int')); $object->datenextrun=dol_mktime(GETPOST('datenextrunhour','int'), GETPOST('datenextrunmin','int'), 0, GETPOST('datenextrunmonth','int'), GETPOST('datenextrunday','int'), GETPOST('datenextrunyear','int')); @@ -184,7 +184,7 @@ if ($action=='update') $object->params=GETPOST('params'); $object->md5params=GETPOST('md5params'); $object->module_name=GETPOST('module_name','alpha'); - $object->note=GETPOST('note'); + $object->note=GETPOST('note','none'); $object->datestart=dol_mktime(GETPOST('datestarthour','int'), GETPOST('datestartmin','int'), 0, GETPOST('datestartmonth','int'), GETPOST('datestartday','int'), GETPOST('datestartyear','int')); $object->dateend=dol_mktime(GETPOST('dateendhour','int'), GETPOST('dateendmin','int'), 0, GETPOST('dateendmonth','int'), GETPOST('dateendday','int'), GETPOST('dateendyear','int')); $object->datenextrun=dol_mktime(GETPOST('datenextrunhour','int'), GETPOST('datenextrunmin','int'), 0, GETPOST('datenextrunmonth','int'), GETPOST('datenextrunday','int'), GETPOST('datenextrunyear','int')); diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index e8748d3a9af..17777e6e228 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -219,8 +219,8 @@ if (empty($reshook)) $object->shipping_method_id = GETPOST('shipping_method_id','int'); $object->tracking_number = GETPOST('tracking_number','alpha'); $object->ref_int = GETPOST('ref_int','alpha'); - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->fk_incoterms = GETPOST('incoterm_id', 'int'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 561f1ecd082..1460d97323c 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -213,8 +213,8 @@ if (empty($reshook)) $object->fk_statut = 1; $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); $object->fk_user_validator = GETPOST('fk_user_validator','int'); - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); // Fill array 'array_options' with data from add form if (! $error) { @@ -264,8 +264,8 @@ if (empty($reshook)) } $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); $object->fk_user_modif = $user->id; $result = $object->update($user); diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 32fcf3c9973..680ab2b6a7e 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -64,7 +64,7 @@ $confirm = GETPOST('confirm','alpha'); $mesg = GETPOST('msg','alpha'); $origin=GETPOST('origin','alpha'); $originid=(GETPOST('originid','int')?GETPOST('originid','int'):GETPOST('origin_id','int')); // For backward compatibility -$note_public = GETPOST('note_public'); +$note_public = GETPOST('note_public','none'); $lineid = GETPOST('line_id','int'); //PDF @@ -208,8 +208,8 @@ if (empty($reshook)) $object->description = GETPOST('description'); $object->ref = $ref; $object->modelpdf = GETPOST('model','alpha'); - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); if ($object->socid > 0) { @@ -877,8 +877,8 @@ if ($action == 'create') $soc = $objectsrc->client; - $note_private = (! empty($objectsrc->note) ? $objectsrc->note : (! empty($objectsrc->note_private) ? $objectsrc->note_private : GETPOST('note_private'))); - $note_public = (! empty($objectsrc->note_public) ? $objectsrc->note_public : GETPOST('note_public')); + $note_private = (! empty($objectsrc->note) ? $objectsrc->note : (! empty($objectsrc->note_private) ? $objectsrc->note_private : GETPOST('note_private','none'))); + $note_public = (! empty($objectsrc->note_public) ? $objectsrc->note_public : GETPOST('note_public','none')); // Object source contacts list $srccontactslist = $objectsrc->liste_contact(-1,'external',1); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index ffe55f1315e..210e93adf14 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -988,8 +988,8 @@ if (empty($reshook)) $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->date_livraison = $datelivraison; $object->fk_incoterms = GETPOST('incoterm_id', 'int'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); @@ -1534,7 +1534,7 @@ if ($action=='create') print ''.$langs->trans('NotePublic').''; print ''; - $doleditor = new DolEditor('note_public', isset($note_public) ? $note_public : GETPOST('note_public'), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); + $doleditor = new DolEditor('note_public', isset($note_public) ? $note_public : GETPOST('note_public','none'), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); print $doleditor->Create(1); print ''; //print ''; @@ -1542,7 +1542,7 @@ if ($action=='create') print ''.$langs->trans('NotePrivate').''; print ''; - $doleditor = new DolEditor('note_private', isset($note_private) ? $note_private : GETPOST('note_private'), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); + $doleditor = new DolEditor('note_private', isset($note_private) ? $note_private : GETPOST('note_private','none'), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); print $doleditor->Create(1); print ''; //print ''; diff --git a/htdocs/fourn/commande/orderstoinvoice.php b/htdocs/fourn/commande/orderstoinvoice.php index b1a8c0c08c1..012574915ab 100644 --- a/htdocs/fourn/commande/orderstoinvoice.php +++ b/htdocs/fourn/commande/orderstoinvoice.php @@ -155,8 +155,8 @@ if (($action == 'create' || $action == 'add') && ! $error) { $object->libelle = GETPOST('libelle'); $object->date = $datefacture; $object->date_echeance = $datedue; - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $projectid = GETPOST('projectid'); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index d632081fd9e..9f747b07197 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -443,8 +443,8 @@ if (empty($reshook)) $object->libelle = GETPOST('label'); $object->date = $datefacture; $object->date_echeance = $datedue; - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); @@ -507,8 +507,8 @@ if (empty($reshook)) $object->libelle = $_POST['label']; $object->date = $datefacture; $object->date_echeance = $datedue; - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); @@ -616,8 +616,8 @@ if (empty($reshook)) $object->libelle = $_POST['label']; $object->date = $datefacture; $object->date_echeance = $datedue; - $object->note_public = GETPOST('note_public'); - $object->note_private = GETPOST('note_private'); + $object->note_public = GETPOST('note_public','none'); + $object->note_private = GETPOST('note_private','none'); $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); $object->fk_account = GETPOST('fk_account', 'int'); diff --git a/htdocs/fourn/paiement/card.php b/htdocs/fourn/paiement/card.php index f42cc1db110..a1104eeaceb 100644 --- a/htdocs/fourn/paiement/card.php +++ b/htdocs/fourn/paiement/card.php @@ -57,7 +57,7 @@ if ($action == 'setnote' && $user->rights->fournisseur->facture->creer) $db->begin(); $object->fetch($id); - $result = $object->update_note(GETPOST('note')); + $result = $object->update_note(GETPOST('note','none')); if ($result > 0) { $db->commit(); diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 4f61aa833bf..1f76d705305 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -133,8 +133,8 @@ if (empty($reshook)) $object->dateend = $dateend; $object->nbterm = GETPOST('nbterm'); $object->rate = $rate; - $object->note_private = GETPOST('note_private'); - $object->note_public = GETPOST('note_public'); + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); $object->fk_project = GETPOST('projectid','int'); $accountancy_account_capital = GETPOST('accountancy_account_capital'); diff --git a/htdocs/loan/payment/payment.php b/htdocs/loan/payment/payment.php index dc927035954..bea15f288a0 100644 --- a/htdocs/loan/payment/payment.php +++ b/htdocs/loan/payment/payment.php @@ -101,8 +101,8 @@ if ($action == 'add_payment') $payment->amount_interest = GETPOST('amount_interest'); $payment->paymenttype = GETPOST('paymenttype'); $payment->num_payment = GETPOST('num_payment'); - $payment->note_private = GETPOST('note_private'); - $payment->note_public = GETPOST('note_public'); + $payment->note_private = GETPOST('note_private','none'); + $payment->note_public = GETPOST('note_public','none'); if (! $error) { diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 143b375f5b3..f5e6c906e7d 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -281,9 +281,9 @@ if (empty($reshook)) $object->barcode_type_coder = $stdobject->barcode_type_coder; $object->barcode_type_label = $stdobject->barcode_type_label; - $object->description = dol_htmlcleanlastbr(GETPOST('desc')); + $object->description = dol_htmlcleanlastbr(GETPOST('desc','none')); $object->url = GETPOST('url'); - $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private')); + $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private','none')); $object->note = $object->note_private; // deprecated $object->customcode = GETPOST('customcode'); $object->country_id = GETPOST('country_id'); @@ -370,11 +370,11 @@ if (empty($reshook)) $object->ref = $ref; $object->label = GETPOST('label'); - $object->description = dol_htmlcleanlastbr(GETPOST('desc')); + $object->description = dol_htmlcleanlastbr(GETPOST('desc','none')); $object->url = GETPOST('url'); if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { - $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private')); + $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private','none')); $object->note = $object->note_private; } $object->customcode = GETPOST('customcode'); @@ -977,7 +977,7 @@ else // Description (used in invoice, propal...) print ''.$langs->trans("Description").''; - $doleditor = new DolEditor('desc', GETPOST('desc'), '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%'); + $doleditor = new DolEditor('desc', GETPOST('desc','none'), '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%'); $doleditor->Create(); print ""; @@ -1092,7 +1092,7 @@ else print ''.$langs->trans("NoteNotVisibleOnBill").''; // We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF. - $doleditor = new DolEditor('note_private', GETPOST('note_private'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_8, '90%'); + $doleditor = new DolEditor('note_private', GETPOST('note_private','none'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_8, '90%'); $doleditor->Create(); print ""; diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index 2869d2254e7..6a5fcbdfc62 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -572,7 +572,7 @@ foreach($extrafields->attribute_label as $key=>$value) // Comments print ''; print ''.$langs->trans("Comments").''; -print ''; +print ''; print ''."\n"; // Add specific fields used by Dolibarr foundation for example diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 1b3857fdbf1..a997b5f4b96 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -268,7 +268,7 @@ if (empty($reshook)) $object->fk_project = GETPOST('projectid'); $object->modelpdf = GETPOST('model'); $object->author = $user->id; // deprecated - $object->note = GETPOST('note'); + $object->note = GETPOST('note','none'); $object->statut = SupplierProposal::STATUS_DRAFT; $id = $object->create_from($user); @@ -286,7 +286,7 @@ if (empty($reshook)) $object->fk_project = GETPOST('projectid'); $object->modelpdf = GETPOST('model'); $object->author = $user->id; // deprecated - $object->note = GETPOST('note'); + $object->note = GETPOST('note','none'); $object->origin = GETPOST('origin'); $object->origin_id = GETPOST('originid'); @@ -465,7 +465,7 @@ if (empty($reshook)) } else { // prevent browser refresh from closing proposal several times if ($object->statut == SupplierProposal::STATUS_VALIDATED) { - $object->cloture($user, GETPOST('statut'), GETPOST('note')); + $object->cloture($user, GETPOST('statut'), GETPOST('note','none')); } } } @@ -774,7 +774,7 @@ if (empty($reshook)) $info_bits |= 0x01; // Clean parameters - $description = dol_htmlcleanlastbr(GETPOST('product_desc')); + $description = dol_htmlcleanlastbr(GETPOST('product_desc','none')); // Define vat_rate $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); diff --git a/htdocs/user/note.php b/htdocs/user/note.php index 1734e7286d4..78fe25adfe9 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -65,7 +65,7 @@ if (empty($reshook)) { if ($action == 'update' && $user->rights->user->user->creer && !$_POST["cancel"]) { $db->begin(); - $res = $object->update_note(dol_html_entity_decode(GETPOST('note_private'), ENT_QUOTES)); + $res = $object->update_note(dol_html_entity_decode(GETPOST('note_private','none'), ENT_QUOTES)); if ($res < 0) { $mesg = '
'.$adh->error.'
'; $db->rollback(); From 6ee15f1c45dcf13a36c1ff39688207c23f12cb70 Mon Sep 17 00:00:00 2001 From: dolibarr95 Date: Mon, 25 Sep 2017 09:01:47 +0200 Subject: [PATCH 097/108] Fix 7470 php warning when MAIN_MODULE_xxxxx_DIR exists but the module does not have a directory. --- htdocs/core/class/conf.class.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index ad224fec97d..1b8709f1330 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -287,15 +287,18 @@ class Conf { foreach($this->modules_parts['dir'] as $module => $dirs) { - foreach($dirs as $type => $name) + if (! empty($this->$module->enabled)) { - $subdir=($type=='temp'?'/temp':''); - // For multicompany sharings - $varname = 'multidir_'.$type; - $this->$module->$varname = array($this->entity => $rootfordata."/".$name.$subdir); - // For backward compatibility - $varname = 'dir_'.$type; - $this->$module->$varname = $rootfordata."/".$name.$subdir; + foreach($dirs as $type => $name) + { + $subdir=($type=='temp'?'/temp':''); + // For multicompany sharings + $varname = 'multidir_'.$type; + $this->$module->$varname = array($this->entity => $rootfordata."/".$name.$subdir); + // For backward compatibility + $varname = 'dir_'.$type; + $this->$module->$varname = $rootfordata."/".$name.$subdir; + } } } } From d3d6fca350ed1ac4e3c07fc1d1a754748c346468 Mon Sep 17 00:00:00 2001 From: Inovea Conseil Date: Mon, 25 Sep 2017 10:49:56 +0200 Subject: [PATCH 098/108] Missing space in request Fix bug in request --- htdocs/core/boxes/box_services_contracts.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_services_contracts.php b/htdocs/core/boxes/box_services_contracts.php index 1795f7c6f2f..0cc4e68682b 100644 --- a/htdocs/core/boxes/box_services_contracts.php +++ b/htdocs/core/boxes/box_services_contracts.php @@ -2,6 +2,7 @@ /* Copyright (C) 2003 Rodolphe Quiedeville * Copyright (C) 2005-2017 Laurent Destailleur * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2017 Nicolas Zabouri * * 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 @@ -91,7 +92,7 @@ class box_services_contracts extends ModeleBoxes $sql.= " INNER JOIN ".MAIN_DB_PREFIX."contrat as c ON s.rowid = c.fk_soc"; $sql.= " INNER JOIN ".MAIN_DB_PREFIX."contratdet as cd ON c.rowid = cd.fk_contrat"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; - if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= "INNER JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " INNER JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; $sql.= ")"; $sql.= " WHERE c.entity = ".$conf->entity; if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; From a9fabf117ee3be11b9ed84814330403dc069db4c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 11:42:59 +0200 Subject: [PATCH 099/108] Code comment --- htdocs/core/class/html.form.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9ebcb295792..009f1f0dcd3 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1256,6 +1256,7 @@ class Form * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param bool $options_only Return options only (for ajax treatment) * @return int <0 if KO, Nb of contact in list if OK + * @deprected You can use selectcontacts directly (warning order of param was changed) */ function select_contacts($socid,$selected='',$htmlname='contactid',$showempty=0,$exclude='',$limitto='',$showfunction=0, $moreclass='', $showsoc=0, $forcecombo=0, $events=array(), $options_only=false) { @@ -1264,7 +1265,8 @@ class Form } /** - * Return list of all contacts (for a third party or all) + * Return HTML code of the SELECT of list of all contacts (for a third party or all). + * This also set the number of contacts found into $this->num * * @param int $socid Id ot third party or 0 for all * @param string $selected Id contact pre-selectionne From 0ffffa3019b51e92fc1c6b20a6b98a055a900c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Peccatte?= Date: Mon, 25 Sep 2017 12:05:12 +0200 Subject: [PATCH 100/108] Add a parameter to specify variant identifier separator --- htdocs/variants/admin/admin.php | 13 +++++++++++++ htdocs/variants/class/ProductCombination.class.php | 10 +++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/htdocs/variants/admin/admin.php b/htdocs/variants/admin/admin.php index eedacb086b3..f3752469538 100644 --- a/htdocs/variants/admin/admin.php +++ b/htdocs/variants/admin/admin.php @@ -37,6 +37,12 @@ if ($_POST) { setEventMessage($langs->trans('CoreErrorMessage'), 'errors'); } + if (dolibarr_set_const($db, 'PRODUIT_ATTRIBUTES_SEPARATOR', GETPOST('PRODUIT_ATTRIBUTES_SEPARATOR'), 'chaine', 0, '', $conf->entity)) { + setEventMessage($langs->trans('RecordSaved')); + } else { + setEventMessage($langs->trans('CoreErrorMessage'), 'errors'); + } + } $title = $langs->trans('ModuleSetup').' '.$langs->trans('ProductAttributes'); @@ -55,6 +61,13 @@ print ''.$langs->trans("Value").''."\n"; print ' '."\n"; print ''.$langs->trans('HideProductCombinations').''; print $form->selectyesno("PRODUIT_ATTRIBUTES_HIDECHILD",$conf->global->PRODUIT_ATTRIBUTES_HIDECHILD,1).''; +print ''.$langs->trans('CombinationsSeparator').''; +if(isset($conf->global->PRODUIT_ATTRIBUTES_SEPARATOR)) { + $separator = $conf->global->PRODUIT_ATTRIBUTES_SEPARATOR; +} else { + $separator = "_"; +} +print ''; print ''; print '
'; print ''; diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index d3e6964aea6..04b987192e1 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -476,7 +476,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; */ public function createProductCombination(Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false) { - global $db, $user; + global $db, $user, $conf; require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php'; require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.class.php'; @@ -542,7 +542,11 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $price_impact += (float) price2num($variations[$currcombattr][$currcombval]['price']); } - $newproduct->ref .= '_'.$prodattrval->ref; + if (isset($conf->global->PRODUIT_ATTRIBUTES_SEPARATOR)) { + $newproduct->ref .= $conf->global->PRODUIT_ATTRIBUTES_SEPARATOR . $prodattrval->ref; + } else { + $newproduct->ref .= '_'.$prodattrval->ref; + } //The first one should not contain a linebreak if ($newproduct->description) { @@ -660,4 +664,4 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; return 1; } -} \ No newline at end of file +} From 35ae0e435d8ace1670af9981a6074c4568dc6e3b Mon Sep 17 00:00:00 2001 From: Inovea Conseil Date: Mon, 25 Sep 2017 16:14:14 +0200 Subject: [PATCH 101/108] Fix quote in input Delete a quote in input field --- htdocs/core/class/extrafields.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 6a7659cd925..b539a02654f 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -8,6 +8,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2015 Charles-Fr BENKE * Copyright (C) 2016 Raphaël Doursenaud + * Copyright (C) 2017 Nicolas ZABOURI * * 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 @@ -832,7 +833,7 @@ class ExtraFields { $tmp=explode(',',$size); $newsize=$tmp[0]; - $out=''; + $out=''; } elseif ($type == 'varchar') { From 16941f1d9d65f6c67aea354035c4e292b84519c0 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 25 Sep 2017 16:46:13 +0200 Subject: [PATCH 102/108] Fix: uniformize code --- htdocs/product/inventory/card.php | 40 ++++------------------------- htdocs/product/inventory/list.php | 42 +++++-------------------------- 2 files changed, 11 insertions(+), 71 deletions(-) diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php index c5eca27b348..7ef847855e5 100644 --- a/htdocs/product/inventory/card.php +++ b/htdocs/product/inventory/card.php @@ -1,6 +1,5 @@ - * Copyright (C) ---Put here your own copyright and developer email--- * * 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 @@ -17,43 +16,14 @@ */ /** - * \file product/inventory/card.php + * \file htdocs/product/inventory/card.php * \ingroup inventory - * \brief This file is an example of a php page - * Put here some comments + * \brief Inventory card */ -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); -//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); -//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test -//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data -//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test -//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu -//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php -//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library -//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) - -// Load Dolibarr environment -$res=0; -// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) -if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); -// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME -$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; -while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } -if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); -if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); -// Try main.inc.php using relative path -if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); -if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); -if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); -if (! $res) die("Include of main fails"); - -include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); -dol_include_once('/inventory/class/inventory.class.php'); +require '../../main.inc.php'; +include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +include_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; // Load traductions files requiredby by page $langs->loadLangs(array("inventory","other")); diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index 6f443324f6b..a8ce9c404e6 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -1,6 +1,5 @@ - * Copyright (C) ---Put here your own copyright and developer email--- * * 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 @@ -17,45 +16,16 @@ */ /** - * \file product/inventory/list.php + * \file htdocs/product/inventory/list.php * \ingroup inventory - * \brief List page for monmodule + * \brief List page for inventory */ -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); -//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); -//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test -//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data -//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test -//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu -//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php -//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library -//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) - - -// Load Dolibarr environment -$res=0; -// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) -if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); -// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME -$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; -while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } -if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); -if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); -// Try main.inc.php using relative path -if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); -if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); -if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); -if (! $res) die("Include of main fails"); - -require_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; -dol_include_once('/inventory/class/inventory.class.php'); +require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; // Load traductions files requiredby by page $langs->loadLangs(array("inventory","other")); @@ -177,7 +147,7 @@ if (empty($reshook)) $permtoread = $user->rights->inventory->read; $permtodelete = $user->rights->inventory->delete; $uploaddir = $conf->inventory->dir_output; - include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + //include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; // TODO to fix for product module } From dc362fcd30d6484e098ad50df8005f7de79c07cc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 18:11:03 +0200 Subject: [PATCH 103/108] NEW Can show currency in list of bank accounts --- htdocs/compta/bank/bankentries.php | 10 ++--- htdocs/compta/bank/index.php | 63 +++++++++++++++++---------- htdocs/compta/bank/transfer.php | 11 +++-- htdocs/core/class/html.form.class.php | 18 ++++---- htdocs/langs/en_US/multicurrency.lang | 1 + 5 files changed, 61 insertions(+), 42 deletions(-) diff --git a/htdocs/compta/bank/bankentries.php b/htdocs/compta/bank/bankentries.php index 40d2f5c8ffc..8cb5b878dc0 100644 --- a/htdocs/compta/bank/bankentries.php +++ b/htdocs/compta/bank/bankentries.php @@ -104,9 +104,9 @@ if (! $sortfield) $sortfield='b.datev, b.dateo, b.rowid'; $mode_balance_ok=false; //if (($sortfield == 'b.datev' || $sortfield == 'b.datev, b.dateo, b.rowid')) // TODO Manage balance when account not selected -if (($sortfield == 'b.datev' || $sortfield == 'b.datev, b.dateo, b.rowid')) +if (($sortfield == 'b.datev' || $sortfield == 'b.datev,b.dateo,b.rowid')) { - $sortfield = 'b.datev, b.dateo, b.rowid'; + $sortfield = 'b.datev,b.dateo,b.rowid'; if ($id > 0 || ! empty($ref) || $account > 0) $mode_balance_ok = true; } if (strtolower($sortorder) == 'desc') $mode_balance_ok = false; @@ -887,7 +887,7 @@ if ($resql) if (! empty($arrayfields['b.rowid']['checked'])) print_liste_field_titre($arrayfields['b.rowid']['label'],$_SERVER['PHP_SELF'],'b.rowid','',$param,'',$sortfield,$sortorder); if (! empty($arrayfields['description']['checked'])) print_liste_field_titre($arrayfields['description']['label'],$_SERVER['PHP_SELF'],'','',$param,'',$sortfield,$sortorder); if (! empty($arrayfields['b.dateo']['checked'])) print_liste_field_titre($arrayfields['b.dateo']['label'],$_SERVER['PHP_SELF'],'b.dateo','',$param,'align="center"',$sortfield,$sortorder); - if (! empty($arrayfields['b.datev']['checked'])) print_liste_field_titre($arrayfields['b.datev']['label'],$_SERVER['PHP_SELF'],'b.datev, b.dateo, b.rowid','',$param,'align="center"',$sortfield,$sortorder); + if (! empty($arrayfields['b.datev']['checked'])) print_liste_field_titre($arrayfields['b.datev']['label'],$_SERVER['PHP_SELF'],'b.datev,b.dateo,b.rowid','',$param,'align="center"',$sortfield,$sortorder); if (! empty($arrayfields['type']['checked'])) print_liste_field_titre($arrayfields['type']['label'],$_SERVER['PHP_SELF'],'','',$param,'align="center"',$sortfield,$sortorder); if (! empty($arrayfields['b.num_chq']['checked'])) print_liste_field_titre($arrayfields['b.num_chq']['label'],$_SERVER['PHP_SELF'],'b.num_chq','',$param,'align="center"',$sortfield,$sortorder); if (! empty($arrayfields['bu.label']['checked'])) print_liste_field_titre($arrayfields['bu.label']['label'],$_SERVER['PHP_SELF'],'bu.label','',$param,'',$sortfield,$sortorder); @@ -1065,7 +1065,7 @@ if ($resql) $bankstatic->id=$banklinestatic->fk_account; $bankstatic->label=$banklinestatic->bank_account_ref; print ' ('.$langs->trans("TransferFrom").' '; - print $bankstatic->getNomUrl(1,'transactions'); + print $bankstatic->getNomUrl(1); print ' '.$langs->trans("toward").' '; $bankstatic->id=$objp->bankid; $bankstatic->label=$objp->bankref; @@ -1082,7 +1082,7 @@ if ($resql) $banklinestatic->fetch($links[$key]['url_id']); $bankstatic->id=$banklinestatic->fk_account; $bankstatic->label=$banklinestatic->bank_account_ref; - print $bankstatic->getNomUrl(1,'transactions'); + print $bankstatic->getNomUrl(1); print ')'; } //var_dump($links); diff --git a/htdocs/compta/bank/index.php b/htdocs/compta/bank/index.php index 5a0ab062b29..4485680a4e9 100644 --- a/htdocs/compta/bank/index.php +++ b/htdocs/compta/bank/index.php @@ -92,7 +92,8 @@ $arrayfields=array( 'b.account_number'=>array('label'=>$langs->trans("AccountAccounting"), 'checked'=>$conf->accountancy->enabled), 'b.fk_accountancy_journal'=>array('label'=>$langs->trans("AccountancyJournal"), 'checked'=>$conf->accountancy->enabled), 'toreconcile'=>array('label'=>$langs->trans("TransactionsToConciliate"), 'checked'=>1), - 'b.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), + 'b.currency_code'=>array('label'=>$langs->trans("Currency"), 'checked'=>0), + 'b.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), 'b.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), 'b.clos'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), 'balance'=>array('label'=>$langs->trans("Balance"), 'checked'=>1, 'position'=>1010), @@ -121,7 +122,7 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; // Purge search criteria -if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All test are required to be compatible with all browsers +if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers { $search_ref=''; $search_label=''; @@ -142,7 +143,7 @@ $title=$langs->trans('BankAccounts'); // Load array of financial accounts (opened by default) $accounts = array(); -$sql = "SELECT rowid, label, courant, rappro, account_number, fk_accountancy_journal, datec as date_creation, tms as date_update"; +$sql = "SELECT rowid, label, courant, rappro, account_number, fk_accountancy_journal, currency_code, datec as date_creation, tms as date_update"; // Add fields from extrafields foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : ''); // Add fields from hooks @@ -337,6 +338,12 @@ if (! empty($arrayfields['toreconcile']['checked'])) print ''; print ''; } +// Currency +if (! empty($arrayfields['b.currency_code']['checked'])) +{ + print ''; + print ''; +} // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { @@ -407,6 +414,7 @@ if (! empty($arrayfields['accountype']['checked'])) print_liste_field_titr if (! empty($arrayfields['b.number']['checked'])) print_liste_field_titre($arrayfields['b.number']['label'],$_SERVER["PHP_SELF"],'b.number','',$param,'',$sortfield,$sortorder); if (! empty($arrayfields['b.account_number']['checked'])) print_liste_field_titre($arrayfields['b.account_number']['label'],$_SERVER["PHP_SELF"],'b.account_number','',$param,'',$sortfield,$sortorder); if (! empty($arrayfields['b.fk_accountancy_journal']['checked'])) print_liste_field_titre($arrayfields['b.fk_accountancy_journal']['label'],$_SERVER["PHP_SELF"],'b.fk_accountancy_journal','',$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['b.currency_code']['checked'])) print_liste_field_titre($arrayfields['b.currency_code']['label'],$_SERVER["PHP_SELF"],'','',$param,'align="center"',$sortfield,$sortorder); if (! empty($arrayfields['toreconcile']['checked'])) print_liste_field_titre($arrayfields['toreconcile']['label'],$_SERVER["PHP_SELF"],'','',$param,'align="center"',$sortfield,$sortorder); // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) @@ -442,19 +450,19 @@ foreach ($accounts as $key=>$type) $found++; - $acc = new Account($db); - $acc->fetch($key); + $obj = new Account($db); + $obj->fetch($key); $var = !$var; - $solde = $acc->solde(1); + $solde = $obj->solde(1); - if (! empty($lastcurrencycode) && $lastcurrencycode != $acc->currency_code) + if (! empty($lastcurrencycode) && $lastcurrencycode != $obj->currency_code) { $lastcurrencycode='various'; // We found several different currencies } if ($lastcurrencycode != 'various') { - $lastcurrencycode=$acc->currency_code; + $lastcurrencycode=$obj->currency_code; } print ''; @@ -462,14 +470,14 @@ foreach ($accounts as $key=>$type) // Ref if (! empty($arrayfields['b.ref']['checked'])) { - print ''.$acc->getNomUrl(1).''; + print ''.$obj->getNomUrl(1).''; if (! $i) $totalarray['nbfield']++; } // Label if (! empty($arrayfields['b.label']['checked'])) { - print ''.$acc->label.''; + print ''.$obj->label.''; if (! $i) $totalarray['nbfield']++; } @@ -477,7 +485,7 @@ foreach ($accounts as $key=>$type) if (! empty($arrayfields['accountype']['checked'])) { print ''; - print $acc->type_lib[$acc->type]; + print $obj->type_lib[$obj->type]; print ''; if (! $i) $totalarray['nbfield']++; } @@ -485,7 +493,7 @@ foreach ($accounts as $key=>$type) // Number if (! empty($arrayfields['b.number']['checked'])) { - print ''.$acc->number.''; + print ''.$obj->number.''; if (! $i) $totalarray['nbfield']++; } @@ -496,12 +504,12 @@ foreach ($accounts as $key=>$type) if (! empty($conf->accounting->enabled)) { $accountingaccount = new AccountingAccount($db); - $accountingaccount->fetch('',$acc->account_number); + $accountingaccount->fetch('',$obj->account_number); print $accountingaccount->getNomUrl(0,1,1,'',1); } else { - print $acc->account_number; + print $obj->account_number; } print ''; if (! $i) $totalarray['nbfield']++; @@ -514,7 +522,7 @@ foreach ($accounts as $key=>$type) if (! empty($conf->accounting->enabled)) { $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($acc->fk_accountancy_journal); + $accountingjournal->fetch($obj->fk_accountancy_journal); print $accountingjournal->getNomUrl(0,1,1,'',1); } else @@ -525,15 +533,24 @@ foreach ($accounts as $key=>$type) if (! $i) $totalarray['nbfield']++; } + // Currency + if (! empty($arrayfields['b.currency_code']['checked'])) + { + print ''; + print $obj->currency_code; + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Transactions to reconcile if (! empty($arrayfields['toreconcile']['checked'])) { print ''; - if ($acc->rappro) + if ($obj->rappro) { - $result=$acc->load_board($user,$acc->id); + $result=$obj->load_board($user,$obj->id); if ($result<0) { - setEventMessages($acc->error, $acc->errors, 'errors'); + setEventMessages($obj->error, $obj->errors, 'errors'); } else { print $result->nbtodo; if ($result->nbtodolate) print '   ('.$result->nbtodolate.img_warning($langs->trans("Late")).')'; @@ -570,7 +587,7 @@ foreach ($accounts as $key=>$type) if (! empty($arrayfields['b.datec']['checked'])) { print ''; - print dol_print_date($acc->date_creation, 'dayhour'); + print dol_print_date($obj->date_creation, 'dayhour'); print ''; if (! $i) $totalarray['nbfield']++; } @@ -578,7 +595,7 @@ foreach ($accounts as $key=>$type) if (! empty($arrayfields['b.tms']['checked'])) { print ''; - print dol_print_date($acc->date_update, 'dayhour'); + print dol_print_date($obj->date_update, 'dayhour'); print ''; if (! $i) $totalarray['nbfield']++; } @@ -586,7 +603,7 @@ foreach ($accounts as $key=>$type) // Status if (! empty($arrayfields['b.clos']['checked'])) { - print ''.$acc->getLibStatut(5).''; + print ''.$obj->getLibStatut(5).''; if (! $i) $totalarray['nbfield']++; } @@ -594,7 +611,7 @@ foreach ($accounts as $key=>$type) if (! empty($arrayfields['balance']['checked'])) { print ''; - print ''.price($solde, 0, $langs, 0, 0, -1, $acc->currency_code).''; + print ''.price($solde, 0, $langs, 0, 0, -1, $obj->currency_code).''; print ''; if (! $i) $totalarray['nbfield']++; if (! $i) $totalarray['totalbalancefield']=$totalarray['nbfield']; @@ -614,7 +631,7 @@ foreach ($accounts as $key=>$type) print ''; - $total[$acc->currency_code] += $solde; + $total[$obj->currency_code] += $solde; $i++; } diff --git a/htdocs/compta/bank/transfer.php b/htdocs/compta/bank/transfer.php index a0f5fdea27b..7696427b059 100644 --- a/htdocs/compta/bank/transfer.php +++ b/htdocs/compta/bank/transfer.php @@ -30,8 +30,7 @@ require('../../main.inc.php'); require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; -$langs->load("banks"); -$langs->load("categories"); +$langs->loadLangs(array("banks", "categories", "multicurrency")); if (! $user->rights->banque->transfer) accessforbidden(); @@ -123,7 +122,7 @@ if ($action == 'add') if (! $error) { - $mesgs = $langs->trans("TransferFromToDone","id."\">".$accountfrom->label."","id."\">".$accountto->label."",$amount,$langs->transnoentities("Currency".$conf->currency)); + $mesgs = $langs->trans("TransferFromToDone",''.$accountfrom->label."",''.$accountto->label."",$amount,$langs->transnoentities("Currency".$conf->currency)); setEventMessages($mesgs, null, 'mesgs'); $db->commit(); } @@ -229,16 +228,16 @@ print ''; print ''; print ''; print ''; -print ''; +print ''; print ''; $var=false; print '"; print "\n"; print "
'.$langs->trans("TransferFrom").''.$langs->trans("TransferTo").''.$langs->trans("Date").''.$langs->trans("Description").''.$langs->trans("Amount").'
'; -$form->select_comptes($account_from,'account_from',0,'',1); +$form->select_comptes($account_from, 'account_from', 0, '', 1, '', empty($conf->multicurrency->enabled)?0:1); print "\n"; -$form->select_comptes($account_to,'account_to',0,'',1); +$form->select_comptes($account_to, 'account_to', 0, '', 1, '', empty($conf->multicurrency->enabled)?0:1); print ""; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 009f1f0dcd3..8db18e2c748 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3306,21 +3306,22 @@ class Form /** * Return a HTML select list of bank accounts * - * @param string $selected Id account pre-selected - * @param string $htmlname Name of select zone - * @param int $statut Status of searched accounts (0=open, 1=closed, 2=both) - * @param string $filtre To filter list - * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. - * @param string $moreattrib To add more attribute on select + * @param string $selected Id account pre-selected + * @param string $htmlname Name of select zone + * @param int $statut Status of searched accounts (0=open, 1=closed, 2=both) + * @param string $filtre To filter list + * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. + * @param string $moreattrib To add more attribute on select + * @param int $showcurrency Show currency in label * @return void */ - function select_comptes($selected='',$htmlname='accountid',$statut=0,$filtre='',$useempty=0,$moreattrib='') + function select_comptes($selected='',$htmlname='accountid',$statut=0,$filtre='',$useempty=0,$moreattrib='',$showcurrency=0) { global $langs, $conf; $langs->load("admin"); - $sql = "SELECT rowid, label, bank, clos as status"; + $sql = "SELECT rowid, label, bank, clos as status, currency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."bank_account"; $sql.= " WHERE entity IN (".getEntity('bank_account').")"; if ($statut != 2) $sql.= " AND clos = '".$statut."'"; @@ -3353,6 +3354,7 @@ class Form print ''; $i++; diff --git a/htdocs/langs/en_US/multicurrency.lang b/htdocs/langs/en_US/multicurrency.lang index fcf84791a1f..bd19ab1b0e9 100644 --- a/htdocs/langs/en_US/multicurrency.lang +++ b/htdocs/langs/en_US/multicurrency.lang @@ -17,3 +17,4 @@ rate=rate MulticurrencyReceived=Received, original currency MulticurrencyRemainderToTake=Remaining amout, original currency MulticurrencyPaymentAmount=Payment amount, original currency +AmountToOthercurrency=Amount To (in currency of receiving account) \ No newline at end of file From 845a33653aac9a228f9680afd9c0acca8afdb6be Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 19:07:57 +0200 Subject: [PATCH 104/108] Fix translation --- htdocs/langs/en_US/products.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 6bc5d842a8e..b324154e9d0 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -152,7 +152,7 @@ BuyingPrices=Buying prices CustomerPrices=Customer prices SuppliersPrices=Supplier prices SuppliersPricesOfProductsOrServices=Supplier prices (of products or services) -CustomCode=Customs code +CustomCode=Customs/Commodity/HS code CountryOrigin=Origin country Nature=Nature ShortLabel=Short label From 58bc30ae9a50a2618c32d2123ff21e0c011a2768 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 19:08:17 +0200 Subject: [PATCH 105/108] Add indian vat --- htdocs/install/mysql/data/llx_c_tva.sql | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index cce279d79da..ac8513ef95c 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -138,8 +138,14 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (11 insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1173, 117, '1','0','VAT super-reduced rate',0); insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1174, 117, '0','0','VAT Rate 0', 0); -insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'CGST+SGST', 0, 9, '1', 9, '1', 0, 'CGST+SGST - Same state sales', 1); -insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1177, 117, 'IGST' , 18, 0, '0', 0, '0', 0, 'IGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1178, 117, 'C+S-5', 0, 2.5, '1', 2.5, '1', 0, 'CGST+SGST - Same state sales', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1179, 117, 'I-5' , 5, 0, '0', 0, '0', 0, 'IGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1180, 117, 'C+S-12', 0, 6, '1', 6, '1', 0, 'CGST+SGST - Same state sales', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1181, 117, 'I-12' , 12, 0, '0', 0, '0', 0, 'IGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'C+S-18', 0, 9, '1', 9, '1', 0, 'CGST+SGST - Same state sales', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1177, 117, 'I-18' , 18, 0, '0', 0, '0', 0, 'IGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1182, 117, 'C+S-28', 0, 14, '1', 14, '1', 0, 'CGST+SGST - Same state sales', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1183, 117, 'I-28' , 28, 0, '0', 0, '0', 0, 'IGST', 1); -- IRELAND (id country=8) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (81, 8, '0','0','VAT Rate 0',1); From 4c7b39f49e3b4636f0f321940e5204b82ce4c970 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 19:22:41 +0200 Subject: [PATCH 106/108] FIX #7486 Empty value for multicurrency rate must be forbidden --- htdocs/admin/multicurrency.php | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 0229f4fc150..ce6a04fab30 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -78,34 +78,54 @@ if (preg_match('/del_(.*)/',$action,$reg)) if ($action == 'add_currency') { + $error=0; + $langs->loadCacheCurrencies(''); $code = GETPOST('code', 'alpha'); - $rate = GETPOST('rate', 'alpha'); + $rate = price2num(GETPOST('rate', 'alpha')); $currency = new MultiCurrency($db); $currency->code = $code; $currency->name = !empty($langs->cache_currencies[$code]['label']) ? $langs->cache_currencies[$code]['label'].' ('.$langs->getCurrencySymbol($code).')' : $code; - if ($currency->create($user) > 0) + if (empty($rate)) { - if ($currency->addRate($rate)) setEventMessages($langs->trans('RecordSaved'), array()); - else setEventMessages($langs->trans('ErrorAddRateFail'), array(), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Rate")), null, 'errors'); + $error++; + } + if (! $error) + { + if ($currency->create($user) > 0) + { + if ($currency->addRate($rate)) setEventMessages($langs->trans('RecordSaved'), array()); + else setEventMessages($langs->trans('ErrorAddRateFail'), array(), 'errors'); + } + else setEventMessages($langs->trans('ErrorAddCurrencyFail'), $currency->errors, 'errors'); } - else setEventMessages($langs->trans('ErrorAddCurrencyFail'), $currency->errors, 'errors'); } elseif ($action == 'update_currency') { + $error = 0; + $submit = GETPOST('submit', 'alpha'); if ($submit == $langs->trans('Modify')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); - $rate = GETPOST('rate', 'float'); + $rate = price2num(GETPOST('rate', 'alpha')); $currency = new MultiCurrency($db); - if ($currency->fetch($fk_multicurrency) > 0) + if (empty($rate)) { - $currency->updateRate($rate); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Rate")), null, 'errors'); + $error++; + } + if (! $error) + { + if ($currency->fetch($fk_multicurrency) > 0) + { + $currency->updateRate($rate); + } } } elseif ($submit == $langs->trans('Delete')) From fe55feb82f39c57a77864d1f72693bbf0f53a673 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 19:45:01 +0200 Subject: [PATCH 107/108] FIX #7461 --- htdocs/core/class/commonobject.class.php | 12 ++++++------ htdocs/fourn/facture/card.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d222d1ab268..f1002d86f80 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1562,22 +1562,22 @@ abstract class CommonObject switch ($this->element) { case 'propal': - $this->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $this->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, ($line->description?$line->description:$line->desc), 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); break; case 'commande': - $this->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $this->updateline($line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); break; case 'facture': - $this->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); + $this->updateline($line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); break; case 'supplier_proposal': - $this->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->desc, 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->array_options, $line->ref_fourn, $line->multicurrency_subprice); + $this->updateline($line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, ($line->description?$line->description:$line->desc), 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->array_options, $line->ref_fourn, $line->multicurrency_subprice); break; case 'order_supplier': - $this->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, false, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $this->updateline($line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, false, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); break; case 'invoice_supplier': - $this->updateline($line->id, $line->desc, $line->subprice, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->qty, 0, 'HT', $line->info_bits, $line->product_type, $line->remise_percent, false, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $this->updateline($line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->qty, 0, 'HT', $line->info_bits, $line->product_type, $line->remise_percent, false, $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); break; default: dol_syslog(get_class($this).'::setMulticurrencyRate no updateline defined', LOG_DEBUG); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index a3d396e75a1..ca9689292b4 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -320,7 +320,7 @@ if (empty($reshook)) // Multicurrency rate else if ($action == 'setmulticurrencyrate' && $user->rights->facture->creer) { - $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx'))); + $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx', 'alpha'))); } // bank account From f1791b5bf4e91e7f5864b1094e3fd7b5ae0af25f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Sep 2017 19:58:38 +0200 Subject: [PATCH 108/108] Better translation --- htdocs/langs/en_US/supplier_proposal.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/supplier_proposal.lang b/htdocs/langs/en_US/supplier_proposal.lang index dc3eae23672..d5b51978920 100644 --- a/htdocs/langs/en_US/supplier_proposal.lang +++ b/htdocs/langs/en_US/supplier_proposal.lang @@ -1,7 +1,7 @@ # Dolibarr language file - Source file is en_US - supplier_proposal SupplierProposal=Supplier commercial proposals supplier_proposalDESC=Manage price requests to suppliers -SupplierProposalNew=New request +SupplierProposalNew=New price request CommRequest=Price request CommRequests=Price requests SearchRequest=Find a request