From ab99c178e1a587f301ecad0e34b8bdb57e552469 Mon Sep 17 00:00:00 2001 From: Inovea Conseil Date: Thu, 1 Jun 2017 09:04:20 +0200 Subject: [PATCH 01/12] Print the value of fields Add a loop for printing the value of fields --- dev/skeletons/skeleton_list.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/dev/skeletons/skeleton_list.php b/dev/skeletons/skeleton_list.php index 4453f2d8302..7053486234f 100644 --- a/dev/skeletons/skeleton_list.php +++ b/dev/skeletons/skeleton_list.php @@ -2,6 +2,7 @@ /* Copyright (C) 2007-2016 Laurent Destailleur * Copyright (C) 2014-2016 Juanjo Menent * Copyright (C) 2016 Jean-François Ferry + * 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 @@ -440,17 +441,14 @@ while ($i < min($num, $limit)) // Show here line of result print ''; // LIST_OF_TD_FIELDS_LIST - /* - if (! empty($arrayfields['t.field1']['checked'])) - { - print ''.$obj->field1.''; - if (! $i) $totalarray['nbfield']++; + foreach ($arrayfields as $key => $value) { + if (!empty($arrayfields[$key]['checked'])) { + $key2 = str_replace('t.', '', $key); + print '' . $obj->$key2 . ''; + if (!$i) + $totalarray['nbfield'] ++; + } } - if (! empty($arrayfields['t.field2']['checked'])) - { - print ''.$obj->field2.''; - if (! $i) $totalarray['nbfield']++; - }*/ // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { From ca5fd6ac4cd986ccdde6e5634f1e3d5105f5ab6f Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Tue, 6 Jun 2017 09:15:11 +0200 Subject: [PATCH 02/12] FIX #6926 --- htdocs/contrat/class/contrat.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 9878e08d447..a1696c749f8 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -46,7 +46,7 @@ class Contrat extends CommonObject public $fk_element='fk_contrat'; protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe public $picto='contract'; - + /** * {@inheritdoc} */ @@ -609,7 +609,7 @@ class Contrat extends CommonObject $this->lines=array(); $pos = 0; - + // Selectionne les lignes contrats liees a un produit $sql = "SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref,"; $sql.= " d.rowid, d.fk_contrat, d.statut, d.description, d.price_ht, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.remise_percent, d.subprice, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht,"; @@ -1849,7 +1849,7 @@ class Contrat extends CommonObject $url = DOL_URL_ROOT.'/contrat/card.php?id='.$this->id; $picto = 'contract'; $label = ''; - + if ($user->rights->contrat->lire) { $label = ''.$langs->trans("ShowContract").''; $label .= '
'.$langs->trans('Ref').': '.$this->ref; @@ -1865,7 +1865,7 @@ class Contrat extends CommonObject $label .= '
'.$langs->trans('AmountTTC').': '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency); } } - + $linkclose=''; if (empty($notooltip) && $user->rights->contrat->lire) { @@ -1881,7 +1881,7 @@ class Contrat extends CommonObject $linkstart = ''; $linkend=''; - + if ($withpicto) $result.=($linkstart.img_object(($notooltip?'':$label), $picto, ($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).$linkend); if ($withpicto && $withpicto != 2) $result.=' '; $result.=$linkstart.$this->ref.$linkend; @@ -2911,7 +2911,7 @@ class ContratLigne extends CommonObjectLine // Insertion dans la base $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet"; - $sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx,"; + $sql.= " (fk_contrat, label, description, fk_product, qty, vat_src_code, tva_tx,"; $sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,"; $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,"; $sql.= " info_bits,"; From a63050bf46ca78c6563c16dff2f849c6033030c5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 00:27:19 +0200 Subject: [PATCH 03/12] FIX Warnings Conflicts: htdocs/core/lib/files.lib.php htdocs/core/lib/images.lib.php --- htdocs/core/lib/files.lib.php | 57 ++++++++++++++++++++-------------- htdocs/core/lib/images.lib.php | 3 +- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 708aee9e498..7d8f29f7681 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -67,9 +67,14 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil $path=preg_replace('/([\\/]+)$/i','',$path); $newpath=dol_osencode($path); - if (! $nohook) + $reshook = 0; + $file_list = array(); + + if (is_object($hookmanager) && ! $nohook) { - $hookmanager->initHooks(array('fileslib')); + $hookmanager->resArray=array(); + + $hookmanager->initHooks(array('fileslib')); $parameters=array( 'path' => $newpath, @@ -202,6 +207,10 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil return array(); } } + + if (is_object($hookmanager) && is_array($hookmanager->resArray)) $file_list = array_merge($file_list, $hookmanager->resArray); + + return $file_list; } @@ -442,7 +451,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists) $destexists=dol_is_dir($destfile); if (! $overwriteifexists && $destexists) return 0; - + if (! $destexists) { // We must set mask just before creating dir, becaause it can be set differently by dol_copy @@ -452,7 +461,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists) $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files dol_mkdir($destfile."/".$file, '', decoct($dirmaskdec)); } - + $srcfile=dol_osencode($srcfile); $destfile=dol_osencode($destfile); @@ -726,7 +735,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n dol_syslog("Refused to delete file ".$file, LOG_WARNING); return False; } - + if (empty($nohook)) { $hookmanager->initHooks(array('fileslib')); @@ -777,7 +786,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n if ($nophperrors) $ok=@unlink($file_osencoded); else $ok=unlink($file_osencoded); if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG); - else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING); + else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING); } return $ok; @@ -802,7 +811,7 @@ function dol_delete_dir($dir,$nophperrors=0) dol_syslog("Refused to delete dir ".$dir, LOG_WARNING); return False; } - + $dir_osencoded=dol_osencode($dir); return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded)); } @@ -1050,17 +1059,17 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $val = array($val); } } - + $nbfile = count($TFile['name']); - + for ($i = 0; $i < $nbfile; $i++) { // Define $destpath (path to file including filename) and $destfile (only filename) $destpath=$upload_dir . "/" . $TFile['name'][$i]; $destfile=$TFile['name'][$i]; - + $savingdocmask = dol_sanitizeFileName($savingdocmask); - + if ($savingdocmask) { $destpath=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask); @@ -1072,12 +1081,12 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio $destpath = $info['dirname'].'/'.$info['filename'].'.'.strtolower($info['extension']); $info = pathinfo($destfile); $destfile = $info['filename'].'.'.strtolower($info['extension']); - + $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destpath, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles); if (is_numeric($resupload) && $resupload > 0) { global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini; - + include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; if (empty($donotupdatesession)) { @@ -1090,14 +1099,14 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio { // Create thumbs // We can't use $object->addThumbs here because there is no $object known - + // Used on logon for example $imgThumbSmall = vignette($destpath, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); // Create mini thumbs for image (Ratio is near 16/9) // Used on menu or for setup page for example $imgThumbMini = vignette($destpath, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); } - + setEventMessages($langs->trans("FileTransferComplete"), null, 'mesgs'); } else @@ -1117,7 +1126,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio } } } - + } } elseif ($link) { require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; @@ -1374,7 +1383,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu { global $user, $conf, $db; global $dolibarr_main_data_root; - + if (! is_object($fuser)) $fuser=$user; if (empty($modulepart)) return 'ErrorBadParameter'; @@ -1389,7 +1398,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu if (empty($refname)) $refname=basename(dirname($original_file)."/"); $relative_original_file = $original_file; - + // Wrapping for some images if ($modulepart == 'companylogo' && !empty($conf->mycompany->dir_output)) { @@ -1564,7 +1573,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } $original_file=$conf->user->dir_output.'/'.$original_file; } - + // Wrapping for third parties else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output)) { @@ -1620,7 +1629,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } $original_file=$conf->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file; } - + // Wrapping for interventions else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output)) { @@ -1686,7 +1695,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu } // Wrapping pour les commandes fournisseurs - else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) + else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) { if ($fuser->rights->fournisseur->commande->lire || preg_match('/^specimen/i',$original_file)) { @@ -1841,14 +1850,14 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu $accessallowed=1; $original_file=$conf->fckeditor->dir_output.'/'.$original_file; } - + // Wrapping for miscellaneous medias files elseif ($modulepart == 'medias' && !empty($dolibarr_main_data_root)) { $accessallowed=1; $original_file=$dolibarr_main_data_root.'/medias/'.$original_file; } - + // Wrapping for backups else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output)) { @@ -1896,7 +1905,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu // If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart else { - if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path. + if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path. if ($fuser->admin) $accessallowed=1; // If user is admin // Define $accessallowed diff --git a/htdocs/core/lib/images.lib.php b/htdocs/core/lib/images.lib.php index 8a95a91db40..d4bc996fdfb 100644 --- a/htdocs/core/lib/images.lib.php +++ b/htdocs/core/lib/images.lib.php @@ -86,7 +86,7 @@ function dol_getImageSize($file, $url = false) $ret['width']=$infoImg[0]; // Largeur de l'image $ret['height']=$infoImg[1]; // Hauteur de l'image } - + return $ret; } @@ -434,6 +434,7 @@ function vignette($file, $maxWidth = 160, $maxHeight = 120, $extName='_small', $ dol_mkdir($dirthumb); // Initialisation des variables selon l'extension de l'image + $img=null; switch($infoImg[2]) { case IMAGETYPE_GIF: // 1 From d326f161ef96cd149000ed102648be2a89b4e964 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 01:06:52 +0200 Subject: [PATCH 04/12] Fix permission on page to print barcode --- htdocs/barcode/printsheet.php | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index a60ac19d0af..daf366d0739 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -1,7 +1,7 @@ * Copyright (C) 2003 Jean-Louis Bergamo - * Copyright (C) 2006-2016 Laurent Destailleur + * Copyright (C) 2006-2017 Laurent Destailleur * * 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 @@ -145,7 +145,7 @@ if ($action == 'builddoc') // Load barcode class for generating barcode image $classname = "mod".ucfirst($generator); $module = new $classname($db); - if ($generator != 'tcpdfbarcode') + if ($generator != 'tcpdfbarcode') { // May be phpbarcode $template = 'standardlabel'; @@ -374,19 +374,25 @@ jQuery(document).ready(function() { print ' '.$langs->trans("FillBarCodeTypeAndValueManually").'   '; print '
'; -print ' '.$langs->trans("FillBarCodeTypeAndValueFromProduct").'   '; -print '
'; -print '
'; -$form->select_produits(GETPOST('productid'), 'productid', ''); -print '   '; -print '
'; +if (! empty($user->rights->produit->lire) || ! empty($user->rights->service->lire)) +{ + print ' '.$langs->trans("FillBarCodeTypeAndValueFromProduct").'   '; + print '
'; + print '
'; + $form->select_produits(GETPOST('productid'), 'productid', ''); + print '   '; + print '
'; +} -print ' '.$langs->trans("FillBarCodeTypeAndValueFromThirdParty").'   '; -print '
'; -print '
'; -print $form->select_company(GETPOST('socid'), 'socid', '', 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300'); -print '   '; -print '
'; +if (! empty($user->rights->societe->lire)) +{ + print ' '.$langs->trans("FillBarCodeTypeAndValueFromThirdParty").'   '; + print '
'; + print '
'; + print $form->select_company(GETPOST('socid'), 'socid', '', 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300'); + print '   '; + print '
'; +} print '
'; From d6ba16d3570a98406cb554ce83af4be724b4cf97 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 09:45:22 +0200 Subject: [PATCH 05/12] Fix missing printFieldListWhere hook --- htdocs/product/index.php | 17 ++++++++++++++--- htdocs/product/list.php | 40 ++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/htdocs/product/index.php b/htdocs/product/index.php index 74a974804ff..56508616edd 100644 --- a/htdocs/product/index.php +++ b/htdocs/product/index.php @@ -42,6 +42,9 @@ else $result=restrictedArea($user,'produit|service'); $langs->load("products"); $langs->load("stocks"); +// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks +$hookmanager->initHooks(array('productindex')); + $product_static = new Product($db); @@ -80,7 +83,7 @@ print '
'; /* * Search Area of product/service */ - + // Search contract if ((! empty($conf->product->enabled) || ! empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { @@ -102,7 +105,7 @@ if (count($listofsearchfields)) print ''; $i++; } - print ''; + print ''; print ''; print '
'; } @@ -117,6 +120,10 @@ $sql = "SELECT COUNT(p.rowid) as total, p.fk_product_type, p.tosell, p.tobuy"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ' WHERE p.entity IN ('.getEntity($product_static->element, 1).')'; $sql.= " GROUP BY p.fk_product_type, p.tosell, p.tobuy"; +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; $result = $db->query($sql); while ($objp = $db->fetch_object($result)) { @@ -246,6 +253,10 @@ $sql.= " p.tms as datem"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= " WHERE p.entity IN (".getEntity($product_static->element, 1).")"; if ($type != '') $sql.= " AND p.fk_product_type = ".$type; +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; $sql.= $db->order("p.tms","DESC"); $sql.= $db->plimit($max,0); @@ -419,7 +430,7 @@ function activitytrim($product_type) $i = 0; $var=true; - + while ($i < $num) { $objp = $db->fetch_object($result); diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 1aec109474e..043327920db 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -78,7 +78,7 @@ $contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'productser if ((string) $type == '1') { $contextpage='servicelist'; if ($search_type=='') $search_type='1'; } if ((string) $type == '0') { $contextpage='productlist'; if ($search_type=='') $search_type='0'; } -// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array +// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks $hookmanager->initHooks(array($contextpage)); $extrafields = new ExtraFields($db); $form=new Form($db); @@ -163,7 +163,7 @@ $arrayfields=array( // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { - foreach($extrafields->attribute_label as $key => $val) + foreach($extrafields->attribute_label as $key => $val) { $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key]); } @@ -284,7 +284,7 @@ else $typ=$extrafields->attribute_type[$tmpkey]; $mode=0; if (in_array($typ, array('int','double'))) $mode=1; // Search on a numeric - if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) + if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) { $sql .= natural_search('ef.'.$tmpkey, $crit, $mode); } @@ -369,8 +369,8 @@ else $crit=$val; $tmpkey=preg_replace('/search_options_/','',$key); if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); - } - + } + print '
'; if ($optioncss != '') print ''; print ''; @@ -416,7 +416,7 @@ else foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); print $langs->trans("FilterOnInto", $sall) . join(', ',$fieldstosearchall); } - + // Filter on categories $moreforfilter=''; if (! empty($conf->categorie->enabled)) @@ -458,9 +458,9 @@ else if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) print_liste_field_titre($arrayfields['p.accountancy_code_buy']['label'], $_SERVER["PHP_SELF"],"p.accountancy_code_buy","",$param,'',$sortfield,$sortorder); if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { - foreach($extrafields->attribute_label as $key => $val) + foreach($extrafields->attribute_label as $key => $val) { - if (! empty($arrayfields["ef.".$key]['checked'])) + if (! empty($arrayfields["ef.".$key]['checked'])) { $align=$extrafields->getAlignFlag($key); print_liste_field_titre($extralabels[$key],$_SERVER["PHP_SELF"],"ef.".$key,"",$param,($align?'align="'.$align.'"':''),$sortfield,$sortorder); @@ -552,7 +552,7 @@ else // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { - foreach($extrafields->attribute_label as $key => $val) + foreach($extrafields->attribute_label as $key => $val) { if (! empty($arrayfields["ef.".$key]['checked'])) print ''; } @@ -627,7 +627,7 @@ else $product_static->status_buy = $objp->tobuy; $product_static->status = $objp->tosell; $product_static->entity = $objp->entity; - + if (! empty($conf->stock->enabled) && $user->rights->stock->lire && $type != 1) // To optimize call of load_stock { if ($objp->fk_product_type != 1) // Not a service @@ -635,8 +635,8 @@ else $product_static->load_stock('nobatch'); // Load stock_reel + stock_warehouse. This also call load_virtual_stock() } } - - + + $var=!$var; print ''; @@ -659,7 +659,7 @@ else { print ''.dol_trunc($objp->label,40).''; } - + // Barcode if (! empty($arrayfields['p.barcode']['checked'])) { @@ -765,7 +765,7 @@ else print ''; print yn($objp->tobatch); print ''; - } + } // Accountancy code sell if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) print ''.$objp->accountancy_code_sell.''; // Accountancy code sell @@ -773,9 +773,9 @@ else // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { - foreach($extrafields->attribute_label as $key => $val) + foreach($extrafields->attribute_label as $key => $val) { - if (! empty($arrayfields["ef.".$key]['checked'])) + if (! empty($arrayfields["ef.".$key]['checked'])) { print 'getAlignFlag($key); @@ -804,8 +804,8 @@ else print ''; print dol_print_date($objp->date_update, 'dayhour'); print ''; - } - + } + // Status (to sell) if (! empty($arrayfields['p.tosell']['checked'])) { @@ -828,13 +828,13 @@ else } print ''; } - // Action + // Action print ' '; print "\n"; $i++; } - + $db->free($resql); print ""; From 929946ad470dd950a401eba7a14a40ca4d081fac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 10:12:01 +0200 Subject: [PATCH 06/12] Fix several problem with hook printFieldListWhere --- htdocs/core/class/commonobject.class.php | 58 +++++++++++++----------- htdocs/core/class/hookmanager.class.php | 10 ++-- htdocs/core/class/html.form.class.php | 12 ++++- htdocs/core/lib/functions.lib.php | 3 +- 4 files changed, 48 insertions(+), 35 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 529bb20a89b..835ad698a1b 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -398,7 +398,7 @@ abstract class CommonObject $lastname=$this->lastname; $firstname=$this->firstname; if (empty($lastname)) $lastname=(isset($this->lastname)?$this->lastname:(isset($this->name)?$this->name:(isset($this->nom)?$this->nom:(isset($this->societe)?$this->societe:(isset($this->company)?$this->company:''))))); - + $ret=''; if ($option && $this->civility_id) { @@ -597,11 +597,11 @@ abstract class CommonObject dol_syslog("CODE_NOT_VALID_FOR_THIS_ELEMENT"); return -3; } - + $datecreate = dol_now(); $this->db->begin(); - + // Insertion dans la base $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_contact"; $sql.= " (element_id, fk_socpeople, datecreate, statut, fk_c_type_contact) "; @@ -1230,19 +1230,19 @@ abstract class CommonObject function setValueFrom($field, $value, $table='', $id=null, $format='', $id_field='', $fuser=null, $trigkey='') { global $user,$langs,$conf; - + if (empty($table)) $table=$this->table_element; if (empty($id)) $id=$this->id; if (empty($format)) $format='text'; if (empty($id_field)) $id_field='rowid'; $error=0; - + $this->db->begin(); // Special case if ($table == 'product' && $field == 'note_private') $field='note'; - + $sql = "UPDATE ".MAIN_DB_PREFIX.$table." SET "; if ($format == 'text') $sql.= $field." = '".$this->db->escape($value)."'"; else if ($format == 'int') $sql.= $field." = ".$this->db->escape($value); @@ -1284,7 +1284,7 @@ abstract class CommonObject /** * Load properties id_previous and id_next * - * @param string $filter Optional filter + * @param string $filter Optional filter. Example: " AND (t.field1 = 'aa' OR t.field2 = 'bb')" * @param int $fieldid Name of field to use for the select MAX and MIN * @param int $nodbprefix Do not include DB prefix to forge table name * @return int <0 if KO, >0 if OK @@ -1310,11 +1310,15 @@ abstract class CommonObject if (empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc"; $sql.= " WHERE te.".$fieldid." < '".$this->db->escape($this->ref)."'"; // ->ref must always be defined (set to id if field does not exists) if (empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir) $sql.= " AND sc.fk_user = " .$user->id; - if (! empty($filter)) $sql.=" AND ".$filter; + if (! empty($filter)) + { + if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND "; // For backward compatibility + $sql.=$filter; + } if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 || ($this->element != 'societe' && empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir)) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to entity if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element, 1).')'; - //print $sql."
"; + //print $filter.' '.$sql."
"; $result = $this->db->query($sql); if (! $result) { @@ -1518,7 +1522,7 @@ abstract class CommonObject if($mode == 1) { $line->subprice = 0; } - + 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); @@ -2154,7 +2158,7 @@ abstract class CommonObject // Special cas //var_dump($this->table_element);exit; if ($this->table_element == 'product') $suffix=''; - + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET note".$suffix." = ".(!empty($note)?("'".$this->db->escape($note)."'"):"NULL"); $sql.= " WHERE rowid =". $this->id; @@ -2164,7 +2168,7 @@ abstract class CommonObject { if ($suffix == '_public') $this->note_public = $note; else if ($suffix == '_private') $this->note_private = $note; - else + else { $this->note = $note; // deprecated $this->note_private = $note; @@ -2413,7 +2417,7 @@ abstract class CommonObject // Special case if ($origin == 'order') $origin='commande'; if ($origin == 'invoice') $origin='facture'; - + $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_element ("; @@ -2446,10 +2450,10 @@ abstract class CommonObject * Fetch array of objects linked to current object. Links are loaded into this->linkedObjects array and this->linkedObjectsIds * Possible usage for parameters: * - all parameters empty -> we look all link to current object (current object can be source or target) - * - source id+type -> will get target list linked to source - * - target id+type -> will get source list linked to target - * - source id+type + target type -> will get target list of the type - * - target id+type + target source -> will get source list of the type + * - source id+type -> will get target list linked to source + * - target id+type -> will get source list linked to target + * - source id+type + target type -> will get target list of the type + * - target id+type + target source -> will get source list of the type * * @param int $sourceid Object source id (if not defined, id of object) * @param string $sourcetype Object source type (if not defined, element name of object) @@ -2902,7 +2906,7 @@ abstract class CommonObject function isObjectUsed($id=0) { if (empty($id)) $id=$this->id; - + // Check parameters if (! isset($this->childtables) || ! is_array($this->childtables) || count($this->childtables) == 0) { @@ -3019,12 +3023,12 @@ abstract class CommonObject foreach ($this->lines as $line) { - if (isset($line->qty_asked)) + if (isset($line->qty_asked)) { if (empty($totalOrdered)) $totalOrdered=0; // Avoid warning because $totalOrdered is '' $totalOrdered+=$line->qty_asked; // defined for shipment only } - if (isset($line->qty_shipped)) + if (isset($line->qty_shipped)) { if (empty($totalToShip)) $totalToShip=0; // Avoid warning because $totalToShip is '' $totalToShip+=$line->qty_shipped; // defined for shipment only @@ -3052,7 +3056,7 @@ abstract class CommonObject if (empty($totalWeight)) $totalWeight=0; // Avoid warning because $totalWeight is '' if (empty($totalVolume)) $totalVolume=0; // Avoid warning because $totalVolume is '' - + //var_dump($line->volume_units); if ($weight_units < 50) // >50 means a standard unit (power of 10 of official unit), > 50 means an exotic unit (like inch) { @@ -3369,9 +3373,9 @@ abstract class CommonObject if ($conf->global->MARGIN_TYPE == "1") print ''.$langs->trans('BuyingPrice').''; else - print ''.$langs->trans('CostPrice').''; + print ''.$langs->trans('CostPrice').''; } - + if (! empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) print ''.$langs->trans('MarginRate').''; if (! empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) @@ -3906,7 +3910,7 @@ abstract class CommonObject if ($filefound) { global $db; // Required to solve a conception default in commonstickergenerator.class.php making an include of code using $db - + require_once $file; $obj = new $classname($this->db); @@ -3965,7 +3969,7 @@ abstract class CommonObject // output format that does not support UTF8. $sav_charset_output=$outputlangs->charset_output; - if (in_array(get_class($this), array('Adherent'))) + if (in_array(get_class($this), array('Adherent'))) { $arrayofrecords = array(); // The write_file of templates of adherent class need this $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, $moreparams); @@ -4226,7 +4230,7 @@ abstract class CommonObject require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $extrafields = new ExtraFields($this->db); $target_extrafields=$extrafields->fetch_name_optionals_label($this->table_element); - + //Eliminate copied source object extra_fields that do not exist in target object $new_array_options=array(); foreach ($this->array_options as $key => $value) { @@ -4275,7 +4279,7 @@ abstract class CommonObject { if (is_numeric($value)) $res=$object->fetch($value); else $res=$object->fetch('',$value); - + if ($res > 0) $this->array_options[$key]=$object->id; else { diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 0c78e89fa9e..ea1048fd4d1 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -121,7 +121,7 @@ class HookManager * All types can also return some values into an array ->results that will be finaly merged into this->resArray for caller. * $this->error or this->errors are also defined by class called by this function if error. */ - function executeHooks($method, $parameters=false, &$object='', &$action='') + function executeHooks($method, $parameters=array(), &$object='', &$action='') { if (! is_array($this->hooks) || empty($this->hooks)) return ''; @@ -200,9 +200,9 @@ class HookManager // test to avoid running twice a hook, when a module implements several active contexts if (in_array($module,$modulealreadyexecuted)) continue; - + dol_syslog(get_class($this).'::executeHooks a qualified hook was found for method='.$method.' module='.$module." action=".$action." context=".$context); - + $modulealreadyexecuted[$module]=$module; // Use the $currentcontext in method to avoid running twice // Clean class (an error may have been set from a previous call of another method for same module/hook) @@ -229,7 +229,7 @@ class HookManager // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) else { - // TODO. this should be done into the method of hook by returning nothing + // TODO. this test should be done into the method of hook by returning nothing if (is_array($parameters) && ! empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) continue; //dol_syslog("Call method ".$method." of class ".get_class($actionclassinstance).", module=".$module.", hooktype=".$hooktype, LOG_DEBUG); @@ -237,7 +237,7 @@ class HookManager if (! empty($actionclassinstance->results) && is_array($actionclassinstance->results)) $this->resArray =array_merge($this->resArray, $actionclassinstance->results); if (! empty($actionclassinstance->resprints)) $this->resPrint.=$actionclassinstance->resprints; - // TODO dead code to remove (do not enable this, but fix hook instead): result must not be a string. we must use $actionclassinstance->resprints to return a string + // TODO dead code to remove (do not enable this, but fix hook instead): result must not be a string but an int. you must use $actionclassinstance->resprints to return a string if (! is_array($resaction) && ! is_numeric($resaction)) { dol_syslog('Error: Bug into hook '.$method.' of module class '.get_class($actionclassinstance).'. Method must not return a string but an int (0=OK, 1=Replace, -1=KO) and set string into ->resprints', LOG_ERR); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index dedac785362..b440c012f04 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5683,7 +5683,7 @@ class Form /** * Return a HTML area with the reference of object and a navigation bar for a business object - * To add a particular filter on select, you must set $object->next_prev_filter to SQL criteria. + * Note: To add a particular filter on select, you can have $object->next_prev_filter set to add SQL criterias. * * @param object $object Object to show. * @param string $paramid Name of parameter to use to name the id into the URL next/previous link. @@ -5701,12 +5701,20 @@ class Form */ function showrefnav($object,$paramid,$morehtml='',$shownav=1,$fieldid='rowid',$fieldref='ref',$morehtmlref='',$moreparam='',$nodbprefix=0,$morehtmlleft='',$morehtmlstatus='',$morehtmlright='') { - global $langs,$conf; + global $langs,$conf,$hookmanager; $ret=''; if (empty($fieldid)) $fieldid='rowid'; if (empty($fieldref)) $fieldref='ref'; + // Add where from hooks + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters, $object); // Note that $action and $object may have been modified by hook + $object->next_prev_filter.=$hookmanager->resPrint; + } + //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam"; $object->load_previous_next_ref((isset($object->next_prev_filter)?$object->next_prev_filter:''),$fieldid,$nodbprefix); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 0943bc1a7af..44670d7a5c1 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -972,7 +972,8 @@ function dol_get_fiche_end($notab=0) } /** - * Show tab footer of a card + * Show tab footer of a card. + * Note: $object->next_prev_filter can be set to restrict select to find next or previous record by $form->showrefnav. * * @param object $object Object to show * @param string $paramid Name of parameter to use to name the id into the URL next/previous link From bec6ad9fb30f1c7037014fdab1d107a2173b8bc0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 10:22:07 +0200 Subject: [PATCH 07/12] Fix bad position of hook --- htdocs/product/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/index.php b/htdocs/product/index.php index 56508616edd..c882390a56a 100644 --- a/htdocs/product/index.php +++ b/htdocs/product/index.php @@ -119,11 +119,11 @@ $prodser[0][0]=$prodser[0][1]=$prodser[1][0]=$prodser[1][1]=0; $sql = "SELECT COUNT(p.rowid) as total, p.fk_product_type, p.tosell, p.tobuy"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ' WHERE p.entity IN ('.getEntity($product_static->element, 1).')'; -$sql.= " GROUP BY p.fk_product_type, p.tosell, p.tobuy"; // Add where from hooks $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook $sql.=$hookmanager->resPrint; +$sql.= " GROUP BY p.fk_product_type, p.tosell, p.tobuy"; $result = $db->query($sql); while ($objp = $db->fetch_object($result)) { From 02781b41ca3ac52a1df93a4badc32bdaacf71d50 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 11:02:34 +0200 Subject: [PATCH 08/12] Fix several problem with hook printFieldListWhere --- htdocs/core/boxes/box_produits.php | 9 +- .../core/boxes/box_produits_alerte_stock.php | 11 +- htdocs/product/class/product.class.php | 125 +++++++++--------- htdocs/product/class/service.class.php | 9 +- 4 files changed, 91 insertions(+), 63 deletions(-) diff --git a/htdocs/core/boxes/box_produits.php b/htdocs/core/boxes/box_produits.php index 51ee156fbeb..c495c83f867 100644 --- a/htdocs/core/boxes/box_produits.php +++ b/htdocs/core/boxes/box_produits.php @@ -53,7 +53,7 @@ class box_produits extends ModeleBoxes */ function loadBox($max=5) { - global $user, $langs, $db, $conf; + global $user, $langs, $db, $conf, $hookmanager; $this->max=$max; @@ -69,6 +69,13 @@ class box_produits extends ModeleBoxes $sql.= ' WHERE p.entity IN ('.getEntity($productstatic->element, 1).')'; if (empty($user->rights->produit->lire)) $sql.=' AND p.fk_product_type != 0'; if (empty($user->rights->service->lire)) $sql.=' AND p.fk_product_type != 1'; + // Add where from hooks + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + } $sql.= $db->order('p.datec', 'DESC'); $sql.= $db->plimit($max, 0); diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php index 884cf92b52a..c8c856684af 100644 --- a/htdocs/core/boxes/box_produits_alerte_stock.php +++ b/htdocs/core/boxes/box_produits_alerte_stock.php @@ -55,7 +55,7 @@ class box_produits_alerte_stock extends ModeleBoxes */ function loadBox($max=5) { - global $user, $langs, $db, $conf; + global $user, $langs, $db, $conf, $hookmanager; $this->max=$max; @@ -74,7 +74,14 @@ class box_produits_alerte_stock extends ModeleBoxes $sql.= " AND p.tosell = 1 AND p.seuil_stock_alerte > 0"; if (empty($user->rights->produit->lire)) $sql.=' AND p.fk_product_type != 0'; if (empty($user->rights->service->lire)) $sql.=' AND p.fk_product_type != 1'; - $sql.= " GROUP BY p.rowid, p.ref, p.label, p.price, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte, p.entity"; + // Add where from hooks + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + } + $sql.= " GROUP BY p.rowid, p.ref, p.label, p.price, p.price_base_type, p.price_ttc, p.fk_product_type, p.tms, p.tosell, p.tobuy, p.seuil_stock_alerte, p.entity"; $sql.= " HAVING SUM(".$db->ifsql("s.reel IS NULL","0","s.reel").") < p.seuil_stock_alerte"; $sql.= $db->order('p.seuil_stock_alerte', 'DESC'); $sql.= $db->plimit($max, 0); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 48badb5623e..0f28ffdea30 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -108,7 +108,7 @@ class Product extends CommonObject var $localtax2_tx; var $localtax1_type; var $localtax2_type; - + //! Stock real var $stock_reel; //! Stock virtual @@ -196,7 +196,7 @@ class Product extends CommonObject public $fourn_pu; public $fourn_price_base_type; - + /** * @deprecated * @see ref_supplier @@ -306,7 +306,7 @@ class Product extends CommonObject if (empty($this->localtax2_tx)) $this->localtax2_tx = 0; if (empty($this->localtax1_type)) $this->localtax1_type = '0'; if (empty($this->localtax2_type)) $this->localtax2_type = '0'; - + if (empty($this->price)) $this->price = 0; if (empty($this->price_min)) $this->price_min = 0; @@ -675,7 +675,7 @@ class Product extends CommonObject $org->fetch($this->id); $this->oldcopy=$org; } - + // Test if batch management is activated on existing product // If yes, we create missing entries into product_batch if ($this->hasbatch() && !$this->oldcopy->hasbatch()) @@ -691,7 +691,7 @@ class Product extends CommonObject $qty_batch = 0; foreach ($ObjW->detail_batch as $detail) // Each lines of detail in product_batch of the current $ObjW = product_stock { - if ($detail->batch == $valueforundefinedlot || $detail->batch == 'Undefined') + if ($detail->batch == $valueforundefinedlot || $detail->batch == 'Undefined') { // We discard this line, we will create it later $sqlclean="DELETE FROM ".MAIN_DB_PREFIX."product_batch WHERE batch in('Undefined', '".$valueforundefinedlot."') AND fk_product_stock = ".$ObjW->id; @@ -703,7 +703,7 @@ class Product extends CommonObject } continue; } - + $qty_batch += $detail->qty; } // Quantities in batch details are not same as stock quantity, @@ -711,7 +711,7 @@ class Product extends CommonObject if ($ObjW->real <> $qty_batch) { $ObjBatch = new Productbatch($this->db); - $ObjBatch->batch = $valueforundefinedlot; + $ObjBatch->batch = $valueforundefinedlot; $ObjBatch->qty = ($ObjW->real - $qty_batch); $ObjBatch->fk_product_stock = $ObjW->id; @@ -738,7 +738,7 @@ class Product extends CommonObject $sql.= ", localtax2_tx = " . $this->localtax2_tx; $sql.= ", localtax1_type = " . ($this->localtax1_type!=''?"'".$this->localtax1_type."'":"'0'"); $sql.= ", localtax2_type = " . ($this->localtax2_type!=''?"'".$this->localtax2_type."'":"'0'"); - + $sql.= ", barcode = ". (empty($this->barcode)?"null":"'".$this->db->escape($this->barcode)."'"); $sql.= ", fk_barcode_type = ". (empty($this->barcode_type)?"null":$this->db->escape($this->barcode_type)); @@ -924,8 +924,8 @@ class Product extends CommonObject if ($result < 0) { $error++; } // End call triggers } - - // Delete from product_batch on product delete + + // Delete from product_batch on product delete if (! $error) { $sql = "DELETE FROM ".MAIN_DB_PREFIX.'product_batch'; @@ -940,7 +940,7 @@ class Product extends CommonObject $this->errors[] = $this->db->lasterror(); } } - + // Delete all child tables if (! $error) { @@ -1038,7 +1038,7 @@ class Product extends CommonObject function setMultiLangs($user) { global $conf, $langs; - + $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 0, 2); $current_lang = $langs->getDefaultLang(); @@ -1357,7 +1357,7 @@ class Product extends CommonObject $sql.= " WHERE pfp.rowid = ".$prodfournprice; if ($qty > 0) $sql.= " AND pfp.quantity <= ".$qty; $sql.= " ORDER BY pfp.quantity DESC"; - + dol_syslog(get_class($this)."::get_buyprice first search by prodfournprice/qty", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) @@ -1487,7 +1487,7 @@ class Product extends CommonObject // If multiprices are enabled, then we check if the current product is subject to price autogeneration // Price will be modified ONLY when the first one is the one that is being modified - if (!empty($conf->global->PRODUIT_MULTIPRICES) && !$ignore_autogen && $this->price_autogen && ($level == 1)) + if (!empty($conf->global->PRODUIT_MULTIPRICES) && !$ignore_autogen && $this->price_autogen && ($level == 1)) { return $this->generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpsq); } @@ -1555,7 +1555,7 @@ class Product extends CommonObject } if (empty($localtax1)) $localtax1=0; // If = '' then = 0 if (empty($localtax2)) $localtax2=0; // If = '' then = 0 - + $this->db->begin(); // Ne pas mettre de quote sur les numeriques decimaux. @@ -1601,7 +1601,7 @@ class Product extends CommonObject $this->localtax2_tx = $localtax2; $this->localtax1_type = $localtaxtype1; $this->localtax2_type = $localtaxtype2; - + // Price by quantity $this->price_by_qty = $newpsq; @@ -1702,7 +1702,7 @@ class Product extends CommonObject $this->url = $obj->url; $this->note_private = $obj->note_private; $this->note = $obj->note_private; // deprecated - + $this->type = $obj->fk_product_type; $this->status = $obj->tosell; $this->status_buy = $obj->tobuy; @@ -1726,7 +1726,7 @@ class Product extends CommonObject $this->localtax2_tx = $obj->localtax2_tx; $this->localtax1_type = $obj->localtax1_type; $this->localtax2_type = $obj->localtax2_type; - + $this->finished = $obj->finished; $this->duration = $obj->duration; $this->duration_value = substr($obj->duration,0,dol_strlen($obj->duration)-1); @@ -1773,7 +1773,7 @@ class Product extends CommonObject // multilangs if (! empty($conf->global->MAIN_MULTILANGS)) $this->getMultiLangs(); - + // Load multiprices array if (! empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -2006,29 +2006,29 @@ class Product extends CommonObject $this->stats_commande['rows']=$obj->nb_rows; $this->stats_commande['qty']=$obj->qty?$obj->qty:0; - // if it's a virtual product, maybe it is in order by extension + // if it's a virtual product, maybe it is in order by extension if (! empty($conf->global->ORDER_ADD_ORDERS_WITH_PARENT_PROD_IF_INCDEC)) - { + { $TFather = $this->getFather(); if (is_array($TFather) && !empty($TFather)) { foreach($TFather as &$fatherData) { $pFather = new Product($this->db); - $pFather->id = $fatherData['id']; + $pFather->id = $fatherData['id']; $qtyCoef = $fatherData['qty']; - + if ($fatherData['incdec']) { $pFather->load_stats_commande($socid, $filtrestatut); - + $this->stats_commande['customers']+=$pFather->stats_commande['customers']; $this->stats_commande['nb']+=$pFather->stats_commande['nb']; $this->stats_commande['rows']+=$pFather->stats_commande['rows']; $this->stats_commande['qty']+=$pFather->stats_commande['qty'] * $qtyCoef; - + } } } } - + return 1; } else @@ -2432,7 +2432,7 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(p.datep, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT p.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."propaldet as d, ".MAIN_DB_PREFIX."propal as p, ".MAIN_DB_PREFIX."societe as s"; - if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as prod"; + if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as prod"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE p.rowid = d.fk_propal"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; @@ -2464,7 +2464,7 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(p.date_valid, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT p.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."supplier_proposaldet as d, ".MAIN_DB_PREFIX."supplier_proposal as p, ".MAIN_DB_PREFIX."societe as s"; - if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as prod"; + if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as prod"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE p.rowid = d.fk_supplier_proposal"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; @@ -2479,7 +2479,7 @@ class Product extends CommonObject return $this->_get_stats($sql,$mode); } - + /** * Return nb of units or orders in which product is included * @@ -2526,7 +2526,7 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(c.date_commande, '%Y%m')"; if ($mode == 'bynumber') $sql.= ", count(DISTINCT c.rowid)"; $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as d, ".MAIN_DB_PREFIX."commande_fournisseur as c, ".MAIN_DB_PREFIX."societe as s"; - if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as p"; + if ($filteronproducttype >= 0) $sql.=", ".MAIN_DB_PREFIX."product as p"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE c.rowid = d.fk_commande"; if ($this->id > 0) $sql.= " AND d.fk_product =".$this->id; @@ -2715,7 +2715,7 @@ class Product extends CommonObject $now=dol_now(); dol_syslog(get_class($this)."::add_fournisseur id_fourn = ".$id_fourn." ref_fourn=".$ref_fourn." quantity=".$quantity, LOG_DEBUG); - + if ($ref_fourn) { $sql = "SELECT rowid, fk_product"; @@ -3104,7 +3104,7 @@ class Product extends CommonObject function getChildsArbo($id, $firstlevelonly=0, $level=1) { global $alreadyfound; - + $sql = "SELECT p.rowid, p.label as label, pa.qty as qty, pa.fk_product_fils as id, p.fk_product_type, pa.incdec"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ", ".MAIN_DB_PREFIX."product_association as pa"; @@ -3113,18 +3113,18 @@ class Product extends CommonObject $sql.= " AND pa.fk_product_fils != ".$id; // This should not happens, it is to avoid infinite loop if it happens dol_syslog(get_class($this).'::getChildsArbo id='.$id.' level='.$level, LOG_DEBUG); - + if ($level == 1) $alreadyfound=array($id=>1); // We init array of found object to start of tree, so if we found it later (should not happened), we stop immediatly // Protection against infinite loop if ($level > 30) return array(); - + $res = $this->db->query($sql); if ($res) { $prods = array(); while ($rec = $this->db->fetch_array($res)) { - if (! empty($alreadyfound[$rec['rowid']])) + if (! empty($alreadyfound[$rec['rowid']])) { dol_syslog(get_class($this).'::getChildsArbo the product id='.$rec['rowid'].' was already found at a higher level in tree. We discard to avoid infinite loop', LOG_WARNING); continue; @@ -3194,7 +3194,7 @@ class Product extends CommonObject $result=''; $newref=$this->ref; if ($maxlength) $newref=dol_trunc($newref,$maxlength,'middle'); - + if ($this->type == Product::TYPE_PRODUCT) $label = '' . $langs->trans("ShowProduct") . ''; if ($this->type == Product::TYPE_SERVICE) $label = '' . $langs->trans("ShowService") . ''; if (! empty($this->ref)) @@ -3217,13 +3217,13 @@ class Product extends CommonObject { // } - if (! empty($this->entity)) + if (! empty($this->entity)) { $tmpphoto = $this->show_photos($conf->product->multidir_output[$this->entity],1,1,0,0,0,80); - if ($this->nbphoto > 0) $label .= '
' . $tmpphoto; + if ($this->nbphoto > 0) $label .= '
' . $tmpphoto; } - + $linkclose=''; if (empty($notooltip)) { @@ -3235,7 +3235,7 @@ class Product extends CommonObject $linkclose.= ' title="'.dol_escape_htmltag($label, 1, 1).'"'; $linkclose.=' class="classfortooltip"'; - + if (! is_object($hookmanager)) { include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; @@ -3260,7 +3260,7 @@ class Product extends CommonObject $linkstart = ''; $linkend=''; - + if ($withpicto) { if ($this->type == Product::TYPE_PRODUCT) $result.=($linkstart.img_object(($notooltip?'':$label), 'product', ($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).$linkend.' '); if ($this->type == Product::TYPE_SERVICE) $result.=($linkstart.img_object(($notooltip?'':$label), 'service', ($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).$linkend.' '); @@ -3303,7 +3303,7 @@ class Product extends CommonObject function LibStatut($status,$mode=0,$type=0) { global $conf, $langs; - + $langs->load('products'); if (! empty($conf->productbatch->enabled)) $langs->load("productbatch"); @@ -3473,14 +3473,14 @@ class Product extends CommonObject /** * Load information about stock of a product into stock_reel, stock_warehouse[] (including stock_warehouse[idwarehouse]->detail_batch for batch products) - * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. + * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. * If ENTREPOT_EXTRA_STATUS set, filtering on warehouse status possible. * - * @param string $option '' = Load all stock info, also from closed and internal warehouses, - * 'nobatch' = Do not load batch information, + * @param string $option '' = Load all stock info, also from closed and internal warehouses, + * 'nobatch' = Do not load batch information, * 'novirtual' = Do not load virtual stock, * 'warehouseopen' = Load stock from open warehouses, - * 'warehouseclosed' = Load stock from closed warehouses, + * 'warehouseclosed' = Load stock from closed warehouses, * 'warehouseinternal' = Load stock from warehouses for internal correct/transfer only * @return int < 0 if KO, > 0 if OK * @see load_virtual_stock, getBatchInfo @@ -3488,26 +3488,26 @@ class Product extends CommonObject function load_stock($option='') { global $conf; - + $this->stock_reel = 0; $this->stock_warehouse = array(); $this->stock_theorique = 0; $warehouseStatus = array(); - if (preg_match('/warehouseclosed/', $option)) + if (preg_match('/warehouseclosed/', $option)) { $warehouseStatus[] = Entrepot::STATUS_CLOSED; } - if (preg_match('/warehouseopen/', $option)) + if (preg_match('/warehouseopen/', $option)) { $warehouseStatus[] = Entrepot::STATUS_OPEN_ALL; } - if (preg_match('/warehouseinternal/', $option)) + if (preg_match('/warehouseinternal/', $option)) { $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL; } - + $sql = "SELECT ps.rowid, ps.reel, ps.fk_entrepot"; $sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps"; $sql.= ", ".MAIN_DB_PREFIX."entrepot as w"; @@ -3537,7 +3537,7 @@ class Product extends CommonObject } $this->db->free($result); - if (! preg_match('/novirtual/', $option)) + if (! preg_match('/novirtual/', $option)) { $this->load_virtual_stock(); // This also load stats_commande_fournisseur, ... } @@ -3553,7 +3553,7 @@ class Product extends CommonObject /** * Load value ->stock_theorique of a product. Property this->id must be defined. - * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. + * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. * * @return int < 0 if KO, > 0 if OK * @see load_stock, getBatchInfo @@ -3790,7 +3790,7 @@ class Product extends CommonObject // Find name of thumb file $photo_vignette=basename(getImageFileNameForSize($dir.$file, '_small')); if (! dol_is_file($dirthumb.$photo_vignette)) $photo_vignette=''; - + // Get filesize of original file $imgarray=dol_getImageSize($dir.$photo); @@ -3804,9 +3804,9 @@ class Product extends CommonObject else if ($nbbyrow < 0) $return .= '
'; $return.= "\n"; - + $relativefile=preg_replace('/^\//', '', $pdir.$photo); - if (empty($nolink)) + if (empty($nolink)) { $urladvanced=getAdvancedPreviewUrl('product', $relativefile); if ($urladvanced) $return.=''; @@ -3817,7 +3817,7 @@ class Product extends CommonObject // Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine $alt=$langs->transnoentitiesnoconv('File').': '.$relativefile; $alt.=' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height']; - + if (empty($maxHeight) || $photo_vignette && $imgarray['height'] > $maxHeight) { $return.= ''; @@ -4017,7 +4017,7 @@ class Product extends CommonObject */ function load_state_board() { - global $conf, $user; + global $conf, $user, $hookmanager; $this->nb=array(); @@ -4025,6 +4025,13 @@ class Product extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ' WHERE p.entity IN ('.getEntity($this->element, 1).')'; $sql.= " AND p.fk_product_type <> 1"; + // Add where from hooks + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + } $resql=$this->db->query($sql); if ($resql) @@ -4350,7 +4357,7 @@ class Product extends CommonObject return $user->rights->service; } } - + /** * Load information for tab info * diff --git a/htdocs/product/class/service.class.php b/htdocs/product/class/service.class.php index 2cd785527a5..ed78adb5ee5 100644 --- a/htdocs/product/class/service.class.php +++ b/htdocs/product/class/service.class.php @@ -56,7 +56,7 @@ class Service extends CommonObject */ function load_state_board() { - global $conf, $user; + global $conf, $user, $hookmanager; $this->nb=array(); @@ -64,6 +64,13 @@ class Service extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; $sql.= " AND p.fk_product_type = 1"; + // Add where from hooks + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook + $sql.=$hookmanager->resPrint; + } $resql=$this->db->query($sql); if ($resql) From 62933e9a267dccc6da52e6f534af58eade3fff53 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 11:22:42 +0200 Subject: [PATCH 09/12] Fix sql syntax error in some cases --- htdocs/core/class/commonobject.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 835ad698a1b..d98625db1cc 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1335,7 +1335,11 @@ abstract class CommonObject if (empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc"; $sql.= " WHERE te.".$fieldid." > '".$this->db->escape($this->ref)."'"; // ->ref must always be defined (set to id if field does not exists) if (empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir) $sql.= " AND sc.fk_user = " .$user->id; - if (! empty($filter)) $sql.=" AND ".$filter; + if (! empty($filter)) + { + if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND "; // For backward compatibility + $sql.=$filter; + } if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 || ($this->element != 'societe' && empty($this->isnolinkedbythird) && !$user->rights->societe->client->voir)) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to entity if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element, 1).')'; // Rem: Bug in some mysql version: SELECT MIN(rowid) FROM llx_socpeople WHERE rowid > 1 when one row in database with rowid=1, returns 1 instead of null From 41586b76c045f44afe6c30710f5db280d8e6f693 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 11:31:08 +0200 Subject: [PATCH 10/12] Fix missing css --- htdocs/admin/perms.php | 2 +- htdocs/theme/eldy/style.css.php | 9 ++++++--- htdocs/theme/md/style.css.php | 13 ++++++++----- htdocs/user/perms.php | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/perms.php b/htdocs/admin/perms.php index 4302222630c..10d72f88bf0 100644 --- a/htdocs/admin/perms.php +++ b/htdocs/admin/perms.php @@ -189,7 +189,7 @@ if ($result) $var=!$var; print ''; - print ''.img_object('',$picto).' '.$objMod->getName(); + print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); print ' '; $perm_libelle=($conf->global->MAIN_USE_ADVANCED_PERMS && ($langs->trans("PermissionAdvanced".$obj->id)!=("PermissionAdvanced".$obj->id))?$langs->trans("PermissionAdvanced".$obj->id):(($langs->trans("Permission".$obj->id)!=("Permission".$obj->id))?$langs->trans("Permission".$obj->id):$obj->libelle)); diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index dd91fc17d28..8d803160325 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -986,6 +986,9 @@ div.nopadding { margin-: 8px; margin-bottom: 4px; } +.pictoobjectwidth { + width: 14px; +} .pictosubstatus { padding-left: 2px; padding-right: 2px; @@ -2972,16 +2975,16 @@ div.tabBar .noborder { border: 1px solid #CCC; text-align: center; border-radius: 2px; - + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - width: 115px; + width: 115px; } @media only screen and (max-width: 767px) { .boxstats { - width: 100px; + width: 100px; } } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 05b127250cb..a047eabef13 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -756,10 +756,10 @@ div.fiche>form>div.div-table-responsive { width: 20px; object-fit: contain; } - + div.statusref { padding-right: 10px; - } + } } .linkobject { cursor: pointer; } @@ -1010,6 +1010,9 @@ table.noborder tr.liste_titre td { margin-: 8px; margin-bottom: 4px; } +.pictoobjectwidth { + width: 14px; +} .pictosubstatus { padding-left: 2px; padding-right: 2px; @@ -2854,16 +2857,16 @@ div .tdtop { text-align: center; border-radius: 2px; min-height: 38px; - + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - width: 115px; + width: 115px; } @media only screen and (max-width: 767px) { .boxstats { - width: 100px; + width: 100px; } } .boxstats:hover { diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 082d6286b8a..694ed013318 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -333,7 +333,7 @@ if ($result) { // On affiche ligne pour modifier droits print ''; - print ''.img_object('',$picto).' '.$objMod->getName(); + print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); print ''; print ''; print ''.$langs->trans("All").""; @@ -348,7 +348,7 @@ if ($result) print ''; // Picto and label of permission - print ''.img_object('',$picto).' '.$objMod->getName().''; + print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName().''; // Permission and tick if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission own because admin From 1935de03c719a4128a748cde234730192b2ffc57 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 12:01:55 +0200 Subject: [PATCH 11/12] Fix bad consistency of labels --- htdocs/product/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 043327920db..40dcd116ab4 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -158,7 +158,7 @@ $arrayfields=array( 'p.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), 'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), 'p.tosell'=>array('label'=>$langs->trans("Status").' ('.$langs->trans("Sell").')', 'checked'=>1, 'position'=>1000), - 'p.tobuy'=>array('label'=>$langs->trans("Status").' ('.$langs->trans("Purchases").')', 'checked'=>1, 'position'=>1000) + 'p.tobuy'=>array('label'=>$langs->trans("Status").' ('.$langs->trans("Buy").')', 'checked'=>1, 'position'=>1000) ); // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) @@ -473,8 +473,8 @@ else print $hookmanager->resPrint; if (! empty($arrayfields['p.datec']['checked'])) print_liste_field_titre($arrayfields['p.datec']['label'],$_SERVER["PHP_SELF"],"p.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['p.tms']['checked'])) print_liste_field_titre($arrayfields['p.tms']['label'],$_SERVER["PHP_SELF"],"p.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); - if (! empty($arrayfields['p.tosell']['checked'])) print_liste_field_titre($langs->trans("Status").' ('.$langs->trans("Sell").')',$_SERVER["PHP_SELF"],"p.tosell","",$param,'align="right"',$sortfield,$sortorder); - if (! empty($arrayfields['p.tobuy']['checked'])) print_liste_field_titre($langs->trans("Status").' ('.$langs->trans("Buy").')',$_SERVER["PHP_SELF"],"p.tobuy","",$param,'align="right"',$sortfield,$sortorder); + if (! empty($arrayfields['p.tosell']['checked'])) print_liste_field_titre($arrayfields['p.tosell']['label'],$_SERVER["PHP_SELF"],"p.tosell","",$param,'align="right"',$sortfield,$sortorder); + if (! empty($arrayfields['p.tobuy']['checked'])) print_liste_field_titre($arrayfields['p.tobuy']['label'],$_SERVER["PHP_SELF"],"p.tobuy","",$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch '); print "\n"; From 985a9ed8d32f56c17c6611c2918c8e6d4ba73b14 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 9 Jun 2017 12:12:12 +0200 Subject: [PATCH 12/12] FIX Redirect to payment page from member subscription page failed if a unique security key was defined. --- htdocs/public/members/new.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index b101e656f67..03f24c3ec80 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -300,20 +300,27 @@ if ($action == 'add') { if ($conf->global->MEMBER_NEWFORM_PAYONLINE == 'paybox') { - $urlback=DOL_MAIN_URL_ROOT.'/public/paybox/newpayment.php?from=membernewform&source=membersubscription&ref='.$adh->ref; + $urlback=DOL_MAIN_URL_ROOT.'/public/paybox/newpayment.php?from=membernewform&source=membersubscription&ref='.urlencode($adh->ref); if (price2num(GETPOST('amount'))) $urlback.='&amount='.price2num(GETPOST('amount')); if (GETPOST('email')) $urlback.='&email='.urlencode(GETPOST('email')); } else if ($conf->global->MEMBER_NEWFORM_PAYONLINE == 'paypal') { - $urlback=DOL_MAIN_URL_ROOT.'/public/paypal/newpayment.php?from=membernewform&source=membersubscription&ref='.$adh->ref; + $urlback=DOL_MAIN_URL_ROOT.'/public/paypal/newpayment.php?from=membernewform&source=membersubscription&ref='.urlencode($adh->ref); if (price2num(GETPOST('amount'))) $urlback.='&amount='.price2num(GETPOST('amount')); if (GETPOST('email')) $urlback.='&email='.urlencode(GETPOST('email')); - if (! empty($conf->global->PAYPAL_SECURITY_TOKEN) && ! empty($conf->global->PAYPAL_SECURITY_TOKEN_UNIQUE)) + if (! empty($conf->global->PAYPAL_SECURITY_TOKEN)) { - $urlback.='&securekey='.dol_hash($conf->global->PAYPAL_SECURITY_TOKEN . 'membersubscription' . $adh->ref, 2); + if (! empty($conf->global->PAYPAL_SECURITY_TOKEN_UNIQUE)) + { + $urlback.='&securekey='.urlencode(dol_hash($conf->global->PAYPAL_SECURITY_TOKEN . 'membersubscription' . $adh->ref, 2)); + } + else + { + $urlback.='&securekey='.urlencode($conf->global->PAYPAL_SECURITY_TOKEN); + } } - + } else {