From db9cc4683a90ffa3f34625c6c1fc4084e3d0e817 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Aug 2017 15:29:40 +0200 Subject: [PATCH 01/31] Fix php warning --- htdocs/core/class/commonobject.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1c516078dd4..0693b3dd336 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4207,7 +4207,7 @@ abstract class CommonObject if (! is_array($optionsArray)) { - // $extrafields is not a known object, we initialize it. Best practice is to have $extrafields defined into card.php or list.php page. + // If $extrafields is not a known object, we initialize it. Best practice is to have $extrafields defined into card.php or list.php page. // TODO Use of existing extrafield is not yet ready (must mutualize code that use extrafields in form first) // global $extrafields; //if (! is_object($extrafields)) @@ -4228,7 +4228,7 @@ abstract class CommonObject if ($table_element == 'categorie') $table_element = 'categories'; // For compatibility // Request to get complementary values - if (count($optionsArray) > 0) + if (is_array($optionsArray) && count($optionsArray) > 0) { $sql = "SELECT rowid"; foreach ($optionsArray as $name => $label) From 109e0f71790a4037c0897edd15340461017e7c25 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Aug 2017 15:31:37 +0200 Subject: [PATCH 02/31] Fix typo --- htdocs/admin/dolistore/class/dolistore.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index cd307f36aa9..acf86766e25 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -200,7 +200,9 @@ class DolistoreModel $html = ''; } - for ($i = 0; $i < count($this->categories); $i++) { + $nbofcateg = count($this->categories); + for ($i = 0; $i < $nbofcateg; $i++) + { $cat = $this->categories[$i]; if ($cat->is_root_category == 1 && $parent == 0) { $html .= '
  • Date: Tue, 22 Aug 2017 15:32:45 +0200 Subject: [PATCH 03/31] Fix invalid link after renaming a website key. --- htdocs/admin/websites.php | 37 +++++++++++++++++++++++++++++---- htdocs/core/lib/website.lib.php | 3 +++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/websites.php b/htdocs/admin/websites.php index bab1cc0f80f..4f829db31df 100644 --- a/htdocs/admin/websites.php +++ b/htdocs/admin/websites.php @@ -247,6 +247,8 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) if ($tabrowid[$id]) { $rowidcol=$tabrowid[$id]; } else { $rowidcol="rowid"; } + $db->begin(); + $website=new Website($db); $rowid=GETPOST('rowid','int'); $website->fetch($rowid); @@ -281,14 +283,41 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) $newname = dol_sanitizeFileName(GETPOST('ref','aZ09')); if ($newname != $website->ref) { - $srcfile=DOL_DATA_ROOT.'/websites/'.$website->ref; - $destfile=DOL_DATA_ROOT.'/websites/'.$newname; - @rename($srcfile, $destfile); + $srcfile=DOL_DATA_ROOT.'/websites/'.$website->ref; + $destfile=DOL_DATA_ROOT.'/websites/'.$newname; + + if (dol_is_dir($destfile)) + { + $error++; + setEventMessages($langs->trans('ErrorDirAlreadyExists', $destfile), null, 'errors'); + } + else + { + @rename($srcfile, $destfile); + + // We must now rename $website->ref into $newname inside files + $arrayreplacement = array($website->ref.'/htmlheader.html' => $newname.'/htmlheader.html'); + $listofilestochange = dol_dir_list($destfile, 'files', 0, '\.php$'); + foreach ($listofilestochange as $key => $value) + { + dolReplaceInFile($value['fullname'], $arrayreplacement); + } + } } } else { - setEventMessages($db->error(), null, 'errors'); + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + } + + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); } } //$_GET["id"]=GETPOST('id', 'int'); // Force affichage dictionnaire en cours d'edition diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 2de1bfb4ecd..ca690f492c5 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -166,7 +166,10 @@ function dolIncludeHtmlContent($contentfile) } // TODO Remove body and html if included //$content = file_get_contents($fullpathfile); + //print preg_replace(array('/^.*]*>/ims','/<\/body>.*$/ims'), array('', ''), $content);*/ + + print "\n".''."\n"; $res = include $fullpathfile; // Include because we want to execute code content if (! $res) { From a2b41a30fc53d8f81f916300aed32031cf6b591a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Aug 2017 15:44:28 +0200 Subject: [PATCH 04/31] Fix duplicate header in website module --- htdocs/core/lib/website.lib.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index ca690f492c5..4396b5a862c 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -164,13 +164,18 @@ function dolIncludeHtmlContent($contentfile) print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.$MAXLEVEL.".\n"; return; } - // TODO Remove body and html if included + // file_get_contents is not possible. We must execute code with include //$content = file_get_contents($fullpathfile); - //print preg_replace(array('/^.*]*>/ims','/<\/body>.*$/ims'), array('', ''), $content);*/ - print "\n".''."\n"; + ob_start(); $res = include $fullpathfile; // Include because we want to execute code content + $tmpoutput = ob_get_contents(); + ob_end_clean(); + + print "\n".''."\n"; + print preg_replace(array('/^.*]*>/ims','/<\/body>.*$/ims'), array('', ''), $tmpoutput); + if (! $res) { print 'ERROR: FAILED TO INCLUDE PAGE '.$contentfile.".\n"; From 687ccbfa1021bbf280ed8a05930e962aa8f95667 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Aug 2017 15:58:57 +0200 Subject: [PATCH 05/31] Fix output keywords --- htdocs/websites/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/websites/index.php b/htdocs/websites/index.php index 5b2ac181e03..1d0bda1ec04 100644 --- a/htdocs/websites/index.php +++ b/htdocs/websites/index.php @@ -1560,7 +1560,7 @@ function dolSavePageContent($filetpl, $object, $objectpage) $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; From 64c4f899f3aa988a6cff99ff7136b685f1218938 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 22 Aug 2017 18:00:54 +0200 Subject: [PATCH 06/31] Fix charset management with ace --- htdocs/core/class/doleditor.class.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/doleditor.class.php b/htdocs/core/class/doleditor.class.php index eaf72ffff71..38c03a7330d 100644 --- a/htdocs/core/class/doleditor.class.php +++ b/htdocs/core/class/doleditor.class.php @@ -63,7 +63,7 @@ class DolEditor * @param string $cols Size of cols for textarea tool (textarea number of cols '70' or percent 'x%') * @param int $readonly 0=Read/Edit, 1=Read only */ - function __construct($htmlname,$content,$width='',$height=200,$toolbarname='Basic',$toolbarlocation='In',$toolbarstartexpanded=false,$uselocalbrowser=true,$okforextendededitor=true,$rows=0,$cols=0,$readonly=0) + function __construct($htmlname, $content, $width='', $height=200, $toolbarname='Basic', $toolbarlocation='In', $toolbarstartexpanded=false, $uselocalbrowser=true, $okforextendededitor=true, $rows=0, $cols=0, $readonly=0) { global $conf,$langs; @@ -121,7 +121,7 @@ class DolEditor $this->editor->Config['SkinPath'] = DOL_URL_ROOT.'/theme/'.$conf->theme.'/fckeditor/'; } } - +var_dump($content);exit; // Define some properties if (in_array($this->tool,array('textarea','ckeditor','ace'))) { @@ -282,11 +282,10 @@ class DolEditor $out.= ($this->height?' height: '.$this->height.'px; ':''); //$out.=" min-height: 100px;"; $out.= '">'; - /*$out.= preg_replace(array('/^<\?php/','/\?>$/'), array('<?php','?>'), $this->content); */ - $out.= htmlentities($this->content); + $out.= htmlspecialchars($this->content); $out.= ''; $out.= ''; $out.= ''; - } print $this->select_produits_fournisseurs_list($socid,$selected,$htmlname,$filtertype,$filtre,'',-1,0,0,$alsoproductwithnosupplierprice); } } diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index e7d8a7cf538..f793bb2601d 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -40,6 +40,7 @@ * Ex: array('disabled'=> * Ex: array('show'=> * Ex: array('update_textarea'=> + * Ex: array('option_disabled'=> id to disable and warning to show if we select a disabled value (this is possible when using autocomplete ajax) * @return string Script */ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array()) @@ -140,6 +141,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Select new value // Disable an element if (options.option_disabled) { + console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled) if (ui.item.disabled) { $("#" + options.option_disabled).prop("disabled", true); if (options.error) { @@ -148,28 +150,32 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt if (options.warning) { $.jnotify(options.warning, "warning", false); // Output with jnotify the warning message } - } else { + } else { $("#" + options.option_disabled).removeAttr("disabled"); } } if (options.disabled) { + console.log("Make action disabled on each "+options.option_disabled) $.each(options.disabled, function(key, value) { $("#" + value).prop("disabled", true); }); } if (options.show) { + console.log("Make action show on each "+options.show) $.each(options.show, function(key, value) { $("#" + value).show().trigger("show"); }); } // Update an input if (ui.item.update) { + console.log("Make action update on each ui.item.update") // loop on each "update" fields $.each(ui.item.update, function(key, value) { $("#" + key).val(value).trigger("change"); }); } if (ui.item.textarea) { + console.log("Make action textarea on each ui.item.textarea") $.each(ui.item.textarea, function(key, value) { if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") { CKEDITOR.instances[key].setData(value); @@ -181,12 +187,12 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt }); } console.log("ajax_autocompleter new value selected, we trigger change on original component so field #search_'.$htmlname.'"); - + $("#search_'.$htmlname.'").trigger("change"); // We have changed value of the combo select, we must be sure to trigger all js hook binded on this event. This is required to trigger other javascript change method binded on original field by other code. } ,delay: 500 }).data("ui-autocomplete")._renderItem = function( ul, item ) { - + return $("
  • ") .data( "ui-autocomplete-item", item ) // jQuery UI > 1.10.0 .append( \'\' + item.label + "" ) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 5e9786f2ba4..f14af2b838f 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -26,7 +26,7 @@ * $langs * $dateSelector * $forceall (0 by default, 1 for supplier invoices/orders) - * $senderissupplier (0 by default, 1 for supplier invoices/orders) + * $senderissupplier (0 by default, 1 or 2 for supplier invoices/orders) * $inputalsopricewithtax (0 by default, 1 to also show column with unit price including tax) */ @@ -52,7 +52,7 @@ if (in_array($object->element,array('propal', 'supplier_proposal','facture','fac ?> -lines) == 0 || $forcetoshowtitlelines); if ($nolinesbefore) { ?> @@ -94,7 +94,7 @@ if ($nolinesbefore) { global->MARGIN_TYPE == "1") echo $langs->trans('BuyingPrice'); else @@ -108,7 +108,7 @@ if ($nolinesbefore) { ?>   - @@ -200,20 +200,22 @@ else { } else { + // $senderissupplier=2 is same than 1 but disable test on minimum qty and disable autofill qty with minimum if ($senderissupplier != 2) { $ajaxoptions=array( 'update' => array('qty'=>'qty','remise_percent' => 'discount','idprod' => 'idprod'), // html id tags that will be edited with which ajax json response key - 'option_disabled' => 'addPredefinedProductButton', // html id to disable once select is done - 'warning' => $langs->trans("NoPriceDefinedForThisSupplier") // translation of an error saved into var 'error' + 'option_disabled' => 'idthatdoesnotexists', // html id to disable once select is done + 'warning' => $langs->trans("NoPriceDefinedForThisSupplier") // translation of an error saved into var 'warning' (for exemple shown we select a disabled option into combo) ); $alsoproductwithnosupplierprice=0; } - else + else { $ajaxoptions = array(); $alsoproductwithnosupplierprice=1; } + $form->select_produits_fournisseurs($object->socid, GETPOST('idprodfournprice'), 'idprodfournprice', '', '', $ajaxoptions, 1, $alsoproductwithnosupplierprice); } echo ''; @@ -263,13 +265,13 @@ else { "> - + multicurrency->enabled)) { $colspan++;?> "> - + "> @@ -306,7 +308,7 @@ else { rights->margins->creer) { if (! empty($conf->global->DISPLAY_MARGIN_RATES)) @@ -561,9 +563,9 @@ jQuery(document).ready(function() { $("#idprod, #idprodfournprice").change(function() { console.log("#idprod, #idprodfournprice change triggered"); - + setforpredef(); // TODO Keep vat combo visible and set it to first entry into list that match result of get_default_tva - + jQuery('#trlinefordates').show(); global->MARGIN_TYPE)) { if ($conf->global->MARGIN_TYPE == '1') print 'bestsupplierprice'; @@ -598,7 +600,7 @@ jQuery(document).ready(function() { if ($conf->global->MARGIN_TYPE == 'costprice') print 'costprice'; } ?>'; console.log("we will set the field for margin. defaultbuyprice="+defaultbuyprice); - + var i = 0; $(data).each(function() { if (this.id != 'pmpprice' && this.id != 'costprice') @@ -615,7 +617,7 @@ jQuery(document).ready(function() { //console.log("id="+this.id+"-price="+this.price); if ('pmp' == defaultbuyprice || 'costprice' == defaultbuyprice) { - if (this.price > 0) { + if (this.price > 0) { defaultkey = this.id; defaultprice = this.price; pmppriceid = this.id; pmppricevalue = this.price; //console.log("pmppricevalue="+pmppricevalue); } @@ -634,22 +636,22 @@ jQuery(document).ready(function() { options += ''; }); options += ''; - + console.log("finally selected defaultkey="+defaultkey+" defaultprice="+defaultprice); - + $("#fournprice_predef").html(options).show(); if (defaultkey != '') { $("#fournprice_predef").val(defaultkey); } - + /* At loading, no product are yet selected, so we hide field of buying_price */ $("#buying_price").hide(); - + /* Define default price at loading */ var defaultprice = $("#fournprice_predef").find('option:selected').attr("price"); $("#buying_price").val(defaultprice); - + $("#fournprice_predef").change(function() { console.log("change on fournprice_predef"); /* Hide field buying_price according to choice into list (if 'inputprice' or not) */ diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index e9da56d2093..1d099ee9265 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1157,7 +1157,7 @@ class CommandeFournisseur extends CommonOrder // insert products details into database for ($i=0;$i<$num;$i++) { - $result = $this->addline( // This include test on qty if option SUPPLIERORDER_WITH_NOPRICEDEFINED is not set + $result = $this->addline( // This include test on qty if option SUPPLIER_ORDER_WITH_NOPRICEDEFINED is not set $this->lines[$i]->desc, $this->lines[$i]->subprice, $this->lines[$i]->qty, @@ -1393,7 +1393,7 @@ class CommandeFournisseur extends CommonOrder if ($fk_product > 0) { - if (empty($conf->global->SUPPLIERORDER_WITH_NOPRICEDEFINED)) + if (empty($conf->global->SUPPLIER_ORDER_WITH_NOPRICEDEFINED)) { // Check quantity is enough dol_syslog(get_class($this)."::addline we check supplier prices fk_product=".$fk_product." fk_prod_fourn_price=".$fk_prod_fourn_price." qty=".$qty." fourn_ref=".$fourn_ref); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index bbc91bc3871..74d96158f65 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -346,21 +346,29 @@ if (empty($reshook)) { $productsupplier = new ProductFournisseur($db); - if (empty($conf->global->SUPPLIER_ORDER_WITH_NOPRICEDEFINED)) + if (empty($conf->global->SUPPLIER_ORDER_WITH_NOPRICEDEFINED)) // TODO this test seems useless { $idprod=0; if (GETPOST('idprodfournprice') == -1 || GETPOST('idprodfournprice') == '') $idprod=-99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...) } - - if (GETPOST('idprodfournprice') > 0) + if (preg_match('/^idprod_([0-9]+)$/',GETPOST('idprodfournprice'), $reg)) + { + $idprod=$reg[1]; + $res=$productsupplier->fetch($idprod); + // Call to init properties of $productsupplier + // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price + $productsupplier->get_buyprice(0, -1, $idprod, 'none'); // We force qty to -1 to be sure to find if a supplier price exist + } + elseif (GETPOST('idprodfournprice') > 0) { - $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qty); // Just to see if a price exists for the quantity. Not used to found vat. + $qtytosearch=$qty; // Just to see if a price exists for the quantity. Not used to found vat. + //$qtytosearch=-1; // We force qty to -1 to be sure to find if a supplier price exist + $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qtytosearch); + $res=$productsupplier->fetch($idprod); } if ($idprod > 0) { - $res=$productsupplier->fetch($idprod); - $label = $productsupplier->label; $desc = $productsupplier->description; @@ -381,8 +389,8 @@ if (empty($reshook)) $tva_tx, $localtax1_tx, $localtax2_tx, + $idprod, $productsupplier->id, - GETPOST('idprodfournprice'), $productsupplier->fourn_ref, $remise_percent, 'HT', @@ -2074,6 +2082,7 @@ elseif (! empty($object->id)) // Add free products/services form global $forceall, $senderissupplier, $dateSelector; $forceall=1; $senderissupplier=1; $dateSelector=0; + if (! empty($conf->global->SUPPLIER_ORDER_WITH_NOPRICEDEFINED)) $senderissupplier=2; // $senderissupplier=2 is same than 1 but disable test on minimum qty and disable autofill qty with minimum. // Show object lines $inputalsopricewithtax=0; diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index e90af97cfd9..8402b298f93 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -201,7 +201,7 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $result=$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); if ($result < 0) dol_print_error($db,$result); } @@ -945,21 +945,30 @@ if (empty($reshook)) if (GETPOST('prod_entry_mode') != 'free' && empty($error)) // With combolist mode idprodfournprice is > 0 or -1. With autocomplete, idprodfournprice is > 0 or '' { - $idprod=0; $productsupplier=new ProductFournisseur($db); - if (GETPOST('idprodfournprice') == -1 || GETPOST('idprodfournprice') == '') $idprod=-2; // Same behaviour than with combolist. When not select idprodfournprice is now -2 (to avoid conflict with next action that may return -1) + $idprod=0; + if (GETPOST('idprodfournprice') == -1 || GETPOST('idprodfournprice') == '') $idprod=-99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...) - if (GETPOST('idprodfournprice') > 0) + if (preg_match('/^idprod_([0-9]+)$/',GETPOST('idprodfournprice'), $reg)) + { + $idprod=$reg[1]; + $res=$productsupplier->fetch($idprod); + // Call to init properties of $productsupplier + // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price + $productsupplier->get_buyprice(0, -1, $idprod, 'none'); // We force qty to -1 to be sure to find if a supplier price exist + } + elseif (GETPOST('idprodfournprice') > 0) { - $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qty); // Just to see if a price exists for the quantity. Not used to found vat. + $qtytosearch=$qty; // Just to see if a price exists for the quantity. Not used to found vat. + //$qtytosearch=-1; // We force qty to -1 to be sure to find if a supplier price exist + $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qtytosearch); + $res=$productsupplier->fetch($idprod); } //Replaces $fk_unit with the product's if ($idprod > 0) { - $result=$productsupplier->fetch($idprod); - $label = $productsupplier->label; $desc = $productsupplier->description; @@ -974,10 +983,29 @@ if (empty($reshook)) $type = $productsupplier->type; $price_base_type = 'HT'; - // TODO Save the product supplier ref into database into field ref_supplier (must rename field ref into ref_supplier first) - $result=$object->addline($desc, $productsupplier->fourn_pu, $tva_tx, $localtax1_tx, $localtax2_tx, $qty, $idprod, $remise_percent, $date_start, $date_end, 0, $tva_npr, $price_base_type, $type, -1, 0, $array_options, $productsupplier->fk_unit); + // TODO Save the product supplier ref into database (like done for supplier propal and order) into field ref_supplier (must rename field ref into ref_supplier first) + $result=$object->addline( + $desc, + $productsupplier->fourn_pu, + $tva_tx, + $localtax1_tx, + $localtax2_tx, + $qty, + $idprod, + $remise_percent, + $date_start, + $date_end, + 0, + $tva_npr, + $price_base_type, + $type, + -1, + 0, + $array_options, + $productsupplier->fk_unit + ); } - if ($idprod == -2 || $idprod == 0) + if ($idprod == -99 || $idprod == 0) { // Product not selected $error++; @@ -1019,7 +1047,7 @@ if (empty($reshook)) } $price_base_type = 'HT'; $pu_ht_devise = price2num($price_ht_devise, 'MU'); - + $result=$object->addline($product_desc, $pu_ht, $tva_tx, $localtax1_tx, $localtax2_tx, $qty, 0, $remise_percent, $date_start, $date_end, 0, $tva_npr, $price_base_type, $type, -1, 0, $array_options, $fk_unit, 0, $pu_ht_devise); } @@ -1518,7 +1546,7 @@ if ($action == 'create') if ((empty($origin)) || ((($origin == 'propal') || ($origin == 'commande')) && (! empty($originid)))) { // Deposit - if (empty($conf->global->INVOICE_DISABLE_DEPOSIT)) + if (empty($conf->global->INVOICE_DISABLE_DEPOSIT)) { print '
    '; $tmp=' '; @@ -1548,12 +1576,12 @@ if ($action == 'create') } } */ - + /* Not yet supporter for supplier if ($societe->id > 0) { // Replacement - if (empty($conf->global->INVOICE_DISABLE_REPLACEMENT)) + if (empty($conf->global->INVOICE_DISABLE_REPLACEMENT)) { print ''; print '
    '; @@ -1603,7 +1631,7 @@ if ($action == 'create') if ($societe->id > 0) { // Credit note - if (empty($conf->global->INVOICE_DISABLE_CREDIT_NOTE)) + if (empty($conf->global->INVOICE_DISABLE_CREDIT_NOTE)) { print '
    '; $tmp='textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3); print $desc; - + print '
    '; print '    0 ? 'checked':'').' /> "; print '
        0 ? 'checked':'').' /> "; print '
    '; - + print '
    '; } } @@ -2029,7 +2057,7 @@ else $object->totalpaye = $alreadypaid; // To give a chance to dol_banner_tab to use already paid amount to show correct status - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); print '
    '; print '
    '; @@ -2229,9 +2257,9 @@ else // Other attributes $cols = 2; include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; - + print ''; - + print '
    '; print '
    '; print '
    '; @@ -2245,12 +2273,12 @@ else print '' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . ''; print '' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . ''; print ''; - + // Multicurrency Amount VAT print '' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . ''; print '' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . ''; print ''; - + // Multicurrency Amount TTC print '' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . ''; print '' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . ''; @@ -2288,13 +2316,13 @@ else print ''.$langs->trans('AmountTTC').''.price($object->total_ttc,1,$langs,0,-1,-1,$conf->currency).''; print ''; - + /* * List of payments */ - + $totalpaye = 0; - + $sign = 1; if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE) $sign = - 1; @@ -2387,9 +2415,9 @@ else { print ''.$langs->trans('AlreadyPaid').' :'.price($totalpaye).''; print ''.$langs->trans("Billed").' :'.price($object->total_ttc).''; - + $resteapayer = $object->total_ttc - $totalpaye; - + print ''.$langs->trans('RemainderToPay').' :'; print ''.price($resteapayer).''; } @@ -2402,7 +2430,7 @@ else dol_print_error($db); } - if ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE) + if ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE) { // Total already paid print ''; @@ -2453,7 +2481,7 @@ else dol_print_error($db); } */ - + // Paye partiellement 'escompte' if (($object->statut == FactureFournisseur::STATUS_CLOSED || $object->statut == FactureFournisseur::STATUS_ABANDONED) && $object->close_code == 'discount_vat') { print ''; @@ -2502,7 +2530,7 @@ else print ' :'; print '' . price($resteapayeraffiche) . ''; print ' '; - } + } else // Credit note { // Total already paid back @@ -2534,9 +2562,9 @@ else print '
    '; print '
    '; print '
    '; - + print '

    '; - + if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $blocname = 'contacts'; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index fee2d3b4a1c..26729ecf866 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -579,7 +579,7 @@ if (empty($reshook)) { $productsupplier = new ProductFournisseur($db); - if (empty($conf->global->SUPPLIER_PROPOSAL_WITH_NOPRICEDEFINED)) + if (empty($conf->global->SUPPLIER_PROPOSAL_WITH_NOPRICEDEFINED)) // TODO this test seems useless { $idprod=0; if (GETPOST('idprodfournprice') == -1 || GETPOST('idprodfournprice') == '') $idprod=-99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...) @@ -594,8 +594,9 @@ if (empty($reshook)) } elseif (GETPOST('idprodfournprice') > 0) { - //$idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qty); // Just to see if a price exists for the quantity. Not used to found vat. - $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), -1); // We force qty to -1 to be sure to find if a supplier price exist + //$qtytosearch=$qty; // Just to see if a price exists for the quantity. Not used to found vat. + $qtytosearch=-1; // We force qty to -1 to be sure to find if a supplier price exist + $idprod=$productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qtytosearch); $res=$productsupplier->fetch($idprod); } @@ -605,7 +606,7 @@ if (empty($reshook)) $price_base_type = $productsupplier->fourn_price_base_type; $type = $productsupplier->type; $label = $productsupplier->label; - $desc = $productsupplier->description; + $desc = $productsupplier->description; if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc); $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice')); From 4c243d3b9e16062866079144d9674ccc49310797 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 15:18:54 +0200 Subject: [PATCH 16/31] Fix index declaration must be moved into the .key.sql files. --- .../install/mysql/migration/6.0.0-7.0.0.sql | 6 ++++++ .../mysql/tables/llx_holiday_config.key.sql | 20 +++++++++++++++++++ .../mysql/tables/llx_holiday_config.sql | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 htdocs/install/mysql/tables/llx_holiday_config.key.sql diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index b027f560aa0..5759423abbb 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -190,3 +190,9 @@ ALTER TABLE llx_extrafields ADD COLUMN fk_user_author integer; ALTER TABLE llx_extrafields ADD COLUMN fk_user_modif integer; ALTER TABLE llx_extrafields ADD COLUMN datec datetime; ALTER TABLE llx_extrafields ADD COLUMN tms timestamp; + +ALTER TABLE llx_holiday_config MODIFY COLUMN name varchar(128); +ALTER TABLE llx_holiday_config ADD UNIQUE INDEX idx_holiday_config (name); + + + diff --git a/htdocs/install/mysql/tables/llx_holiday_config.key.sql b/htdocs/install/mysql/tables/llx_holiday_config.key.sql new file mode 100644 index 00000000000..cda95c87f39 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_holiday_config.key.sql @@ -0,0 +1,20 @@ +-- =================================================================== +-- Copyright (C) 2012 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 +-- 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 . +-- +-- =================================================================== + +ALTER TABLE llx_holiday_config ADD UNIQUE INDEX idx_holiday_config (name); + diff --git a/htdocs/install/mysql/tables/llx_holiday_config.sql b/htdocs/install/mysql/tables/llx_holiday_config.sql index 2f08bf5aa41..4ef6f15c7df 100644 --- a/htdocs/install/mysql/tables/llx_holiday_config.sql +++ b/htdocs/install/mysql/tables/llx_holiday_config.sql @@ -19,7 +19,7 @@ CREATE TABLE llx_holiday_config ( rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, -name VARCHAR( 255 ) NOT NULL UNIQUE, +name VARCHAR(128) NOT NULL, value TEXT NULL ) ENGINE=innodb; \ No newline at end of file From 52a8692a8508fcef88fe4b36067af3bfdc84030a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 16:07:11 +0200 Subject: [PATCH 17/31] FIX #7226 --- .../class/fournisseur.commande.class.php | 22 ++- htdocs/fourn/commande/dispatch.php | 144 +++++++++++++----- 2 files changed, 123 insertions(+), 43 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 1d099ee9265..d7d1e542b3a 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2832,8 +2832,9 @@ class CommandeFournisseur extends CommonOrder $supplierorderdispatch = new CommandeFournisseurDispatch($this->db); $filter=array('t.fk_commande'=>$this->id); if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) { - $filter['t.status']=1; + $filter['t.status']=1; // Restrict to lines with status validated } + $ret=$supplierorderdispatch->fetchAll('','',0,0,$filter); if ($ret<0) { @@ -2844,20 +2845,27 @@ class CommandeFournisseur extends CommonOrder { if (is_array($supplierorderdispatch->lines) && count($supplierorderdispatch->lines)>0) { - //Build array with quantity deliverd by product + $date_liv = dol_now(); + + // Build array with quantity deliverd by product foreach($supplierorderdispatch->lines as $line) { $qtydelivered[$line->fk_product]+=$line->qty; } foreach($this->lines as $line) { $qtywished[$line->fk_product]+=$line->qty; } - - $date_liv = dol_now(); - //Compare array - $diff_array=array_diff_assoc($qtydelivered,$qtywished); + $diff_array=array_diff_assoc($qtydelivered,$qtywished); // Warning: $diff_array is done only on common keys. + $keysinwishednotindelivered=array_diff(array_keys($qtywished),array_keys($qtydelivered)); // To check we also have same number of keys + $keysindeliverednotinwished=array_diff(array_keys($qtydelivered),array_keys($qtywished)); // To check we also have same number of keys + /*var_dump(array_keys($qtydelivered)); + var_dump(array_keys($qtywished)); + var_dump($diff_array); + var_dump($keysinwishednotindelivered); + var_dump($keysindeliverednotinwished); + exit;*/ - if (count($diff_array)==0) //No diff => mean everythings is received + if (count($diff_array)==0 && count($keysinwishednotindelivered)==0 && count($keysindeliverednotinwished)==0) //No diff => mean everythings is received { if ($closeopenorder) { diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index c87b3a62bed..c6a6034c684 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -28,6 +28,7 @@ * \ingroup commande * \brief Page to dispatch receiving */ + require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT . '/core/modules/supplier_order/modules_commandefournisseur.php'; require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php'; @@ -84,17 +85,33 @@ if ($id > 0 || ! empty($ref)) { * Actions */ -if ($action == 'checkdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { +if ($action == 'checkdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) +{ + $error=0; $supplierorderdispatch = new CommandeFournisseurDispatch($db); + + $db->begin(); + $result = $supplierorderdispatch->fetch($lineid); if (! $result) - dol_print_error($db); - $result = $supplierorderdispatch->setStatut(1); - if ($result < 0) { + { + $error++; setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); - $error ++; $action = ''; - } else { + } + + if (! $error) + { + $result = $supplierorderdispatch->setStatut(1); + if ($result < 0) { + setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); + $error++; + $action = ''; + } + } + + if (! $error) + { $result = $object->calcAndSetStatusDispatch($user); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -102,19 +119,42 @@ if ($action == 'checkdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED $action = ''; } } + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); + } } -if ($action == 'uncheckdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { +if ($action == 'uncheckdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) +{ + $error=0; $supplierorderdispatch = new CommandeFournisseurDispatch($db); + + $db->begin(); + $result = $supplierorderdispatch->fetch($lineid); if (! $result) - dol_print_error($db); - $result = $supplierorderdispatch->setStatut(0); - if ($result < 0) { + { + $error++; setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); - $error ++; $action = ''; - } else { + } + + if (! $error) + { + $result = $supplierorderdispatch->setStatut(0); + if ($result < 0) { + setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); + $error ++; + $action = ''; + } + } + if (! $error) + { $result = $object->calcAndSetStatusDispatch($user); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -122,19 +162,42 @@ if ($action == 'uncheckdispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANC $action = ''; } } + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); + } } -if ($action == 'denydispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { +if ($action == 'denydispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) +{ + $error=0; $supplierorderdispatch = new CommandeFournisseurDispatch($db); + + $db->begin(); + $result = $supplierorderdispatch->fetch($lineid); if (! $result) - dol_print_error($db); - $result = $supplierorderdispatch->setStatut(2); - if ($result < 0) { + { + $error++; setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); - $error ++; $action = ''; - } else { + } + + if (! $error) + { + $result = $supplierorderdispatch->setStatut(2); + if ($result < 0) { + setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); + $error ++; + $action = ''; + } + } + if (! $error) + { $result = $object->calcAndSetStatusDispatch($user); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -142,6 +205,14 @@ if ($action == 'denydispatchline' && ! ((empty($conf->global->MAIN_USE_ADVANCED_ $action = ''; } } + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); + } } if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) { @@ -150,10 +221,10 @@ if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) $db->begin(); $pos = 0; - foreach ($_POST as $key => $value) + foreach ($_POST as $key => $value) { // without batch module enabled - if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) + if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) { $pos ++; @@ -184,7 +255,7 @@ if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) } } // with batch module enabled - if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) + if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { $pos ++; @@ -286,11 +357,11 @@ if ($id > 0 || ! empty($ref)) { $title = $langs->trans("SupplierOrder"); dol_fiche_head($head, 'dispatch', $title, 0, 'order'); - + // Supplier order card $linkback = ''.$langs->trans("BackToList").''; - + $morehtmlref='
    '; // Ref supplier $morehtmlref.=$form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', 0, 1); @@ -331,14 +402,14 @@ if ($id > 0 || ! empty($ref)) { } } $morehtmlref.='
    '; - - - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); - + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + print '
    '; print '
    '; - + print ''; // Date @@ -362,7 +433,7 @@ if ($id > 0 || ! empty($ref)) { print "
    "; print '
    '; - + // if ($mesg) print $mesg; print '
    '; @@ -382,7 +453,7 @@ if ($id > 0 || ! empty($ref)) { print '
    '; print ''; print ''; - + print '
    '; print ''; @@ -585,10 +656,10 @@ if ($id > 0 || ! empty($ref)) { print ''; print "
    \n"; - if ($nbproduct) + if ($nbproduct) { $checkboxlabel=$langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv($object->statuts[5])); - + print '
    '; print $langs->trans("Comment") . ' : '; print '
    '; print ' '.$checkboxlabel; - + print '
    0 || ! empty($ref)) { if (! $nbproduct) { if (empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) print '
    '.$langs->trans("NoPredefinedProductToDispatch").'
    '; // No predefined line at all - else + else print '
    '.$langs->trans("NoMorePredefinedProductToDispatch").'
    '; // No predefined line that remain to be dispatched. } @@ -618,7 +689,7 @@ if ($id > 0 || ! empty($ref)) { dol_fiche_end(); - + // List of lines already dispatched $sql = "SELECT p.ref, p.label,"; $sql .= " e.rowid as warehouse_id, e.label as entrepot,"; @@ -699,7 +770,8 @@ if ($id > 0 || ! empty($ref)) { // Add button to check/uncheck disaptching print '
    '; - if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check))) { + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check))) + { if (empty($objp->status)) { print '' . $langs->trans("Approve") . ''; print '' . $langs->trans("Deny") . ''; From 6b5b10fc949fd04451a595a59cb14c33beca904c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 16:28:34 +0200 Subject: [PATCH 18/31] FIX #7224 --- htdocs/product/class/productcustomerprice.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/product/class/productcustomerprice.class.php b/htdocs/product/class/productcustomerprice.class.php index 5b9050077c9..b3066df8188 100644 --- a/htdocs/product/class/productcustomerprice.class.php +++ b/htdocs/product/class/productcustomerprice.class.php @@ -169,12 +169,12 @@ class Productcustomerprice extends CommonObject $sql .= " " . (empty($this->price_min_ttc) ? '0' : "'" . $this->price_min_ttc . "'") . ","; $sql .= " " . (! isset($this->price_base_type) ? 'NULL' : "'" . $this->db->escape($this->price_base_type) . "'") . ","; $sql .= " ".($this->default_vat_code ? "'".$this->db->escape($this->default_vat_code)."'" : "null").","; - $sql .= " " . (! isset($this->tva_tx) ? 'NULL' : "'" . $this->tva_tx . "'") . ","; + $sql .= " " . (! isset($this->tva_tx) ? 'NULL' : (empty($this->tva_tx)?0:$this->tva_tx)) . ","; $sql .= " " . (! isset($this->recuperableonly) ? 'NULL' : "'" . $this->recuperableonly . "'") . ","; $sql .= " " . (empty($this->localtax1_type) ? "'0'" : "'" . $this->localtax1_type . "'") . ","; - $sql .= " " . (! isset($this->localtax1_tx) ? 'NULL' : "'" . $this->localtax1_tx . "'") . ","; + $sql .= " " . (! isset($this->localtax1_tx) ? 'NULL' : (empty($this->localtax1_tx)?0:$this->localtax1_tx)) . ","; $sql .= " " . (empty($this->localtax2_type) ? "'0'" : "'" . $this->localtax2_type . "'") . ","; - $sql .= " " . (! isset($this->localtax2_tx) ? 'NULL' : "'" . $this->localtax2_tx . "'") . ","; + $sql .= " " . (! isset($this->localtax2_tx) ? 'NULL' : (empty($this->localtax2_tx)?0:$this->localtax2_tx)) . ","; $sql .= " " . $user->id . ","; $sql .= " " . (! isset($this->import_key) ? 'NULL' : "'" . $this->db->escape($this->import_key) . "'") . ""; $sql .= ")"; @@ -656,10 +656,10 @@ class Productcustomerprice extends CommonObject $sql .= " price_min_ttc=" . (isset($this->price_min_ttc) ? $this->price_min_ttc : "null") . ","; $sql .= " price_base_type=" . (isset($this->price_base_type) ? "'" . $this->db->escape($this->price_base_type) . "'" : "null") . ","; $sql .= " default_vat_code = ".($this->default_vat_code ? "'".$this->db->escape($this->default_vat_code)."'" : "null").","; - $sql .= " tva_tx=" . (isset($this->tva_tx) ? $this->tva_tx : "null") . ","; + $sql .= " tva_tx=" . (isset($this->tva_tx) ? (empty($this->tva_tx)?0:$this->tva_tx) : "null") . ","; $sql .= " recuperableonly=" . (isset($this->recuperableonly) ? $this->recuperableonly : "null") . ","; - $sql .= " localtax1_tx=" . (isset($this->localtax1_tx) ? $this->localtax1_tx : "null") . ","; - $sql .= " localtax2_tx=" . (isset($this->localtax2_tx) ? $this->localtax2_tx : "null") . ","; + $sql .= " localtax1_tx=" . (isset($this->localtax1_tx) ? (empty($this->localtax1_tx)?0:$this->localtax1_tx) : "null") . ","; + $sql .= " localtax2_tx=" . (isset($this->localtax2_tx) ? (empty($this->localtax2_tx)?0:$this->localtax2_tx) : "null") . ","; $sql .= " localtax1_type=" . (! empty($this->localtax1_type) ? "'".$this->localtax1_type."'": "'0'") . ","; $sql .= " localtax2_type=" . (! empty($this->localtax2_type) ? "'".$this->localtax2_type."'": "'0'") . ","; $sql .= " fk_user=" . $user->id . ","; From 947acfffe204575feeee6eb5bb38cd88bd09424a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 16:53:29 +0200 Subject: [PATCH 19/31] FIX #7173 --- htdocs/adherents/subscription.php | 52 +++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 0c9c8467f1f..c7904667846 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -113,7 +113,6 @@ if ($action == 'confirm_create_thirdparty' && $confirm == 'yes' && $user->rights if ($result < 0) { $langs->load("errors"); - $errmsg=$langs->trans($company->error); setEventMessages($company->error, $company->errors, 'errors'); } else @@ -123,7 +122,7 @@ if ($action == 'confirm_create_thirdparty' && $confirm == 'yes' && $user->rights } else { - $errmsg=$object->error; + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -211,7 +210,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $paymentdate=dol_mktime(0, 0, 0, $_POST["paymentmonth"], $_POST["paymentday"], $_POST["paymentyear"]); } - $subscription=$_POST["subscription"]; // Amount of subscription + $subscription=price2num(GETPOST("subscription",'alpha')); // Amount of subscription $label=$_POST["label"]; // Payment informations @@ -229,6 +228,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $error++; $langs->load("errors"); $errmsg=$langs->trans("ErrorBadDateFormat",$langs->transnoentitiesnoconv("DateSubscription")); + setEventMessages($errmsg, null, 'errors'); $action='addsubscription'; } if (GETPOST('end') && ! $datesubend) @@ -236,6 +236,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $error++; $langs->load("errors"); $errmsg=$langs->trans("ErrorBadDateFormat",$langs->transnoentitiesnoconv("DateEndSubscription")); + setEventMessages($errmsg, null, 'errors'); $action='addsubscription'; } if (! $datesubend) @@ -246,16 +247,20 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $error++; $errmsg=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePayment")); + setEventMessages($errmsg, null, 'errors'); $action='addsubscription'; } + $amount = price2num(GETPOST("subscription",'alpha')); + // Check if a payment is mandatory or not if (! $error && $adht->subscription) // Member type need subscriptions { - if (! is_numeric($_POST["subscription"])) + if (! is_numeric($amount)) { // If field is '' or not a numeric value $errmsg=$langs->trans("ErrorFieldRequired",$langs->transnoentities("Amount")); + setEventMessages($errmsg, null, 'errors'); $error++; $action='addsubscription'; } @@ -273,7 +278,11 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { if ($_POST["accountid"]) $errmsg=$langs->trans("ErrorDoNotProvideAccountsIfNullAmount"); } - if ($errmsg) $action='addsubscription'; + if ($errmsg) + { + setEventMessages($errmsg, null, 'errors'); + $action='addsubscription'; + } } } } @@ -319,6 +328,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $error++; $errmsg=$db->lasterror(); + setEventMessages($errmsg, null, 'errors'); } } else @@ -326,14 +336,16 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $error++; $errmsg=$acct->error; $errmsgs=$acct->errors; - } + setEventMessages($errmsg, $errmsgs, 'errors'); + } } else { $error++; $errmsg=$acct->error; $errmsgs=$acct->errors; - } + setEventMessages($errmsg, $errmsgs, 'errors'); + } } // If option choosed, we create invoice @@ -351,6 +363,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $langs->load("errors"); $errmsg=$langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst"); + setEventMessages($errmsg, null, 'errors'); $error++; } } @@ -361,6 +374,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $errmsg=$customer->error; $errmsgs=$acct->errors; + setEventMessages($errmsg, $errmsgs, 'errors'); $error++; } } @@ -378,6 +392,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $error++; $errmsg='ErrorNoPaymentTermRECEPFound'; + setEventMessages($errmsg, null, 'errors'); } } $invoice->socid=$object->fk_soc; @@ -389,12 +404,13 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $invoice->linked_objects = array_merge($invoice->linked_objects, $_POST['other_linked_objects']); } - + $result=$invoice->create($user); if ($result <= 0) { $errmsg=$invoice->error; $errmsgs=$invoice->errors; + setEventMessages($errmsg, $errmsgs, 'errors'); $error++; } } @@ -415,6 +431,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! if ($result <= 0) { $errmsg=$invoice->error; + setEventMessages($errmsg, null, 'errors'); $error++; } } @@ -427,6 +444,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $errmsg=$invoice->error; $errmsgs=$invoice->errors; + setEventMessages($errmsg, $errmsgs, 'errors'); $error++; } } @@ -454,6 +472,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! { $errmsg=$paiement->error; $errmsgs=$paiement->errors; + setEventMessages($errmsg, $errmsgs, 'errors'); $error++; } } @@ -535,6 +554,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! if ($result < 0) { $errmsg=$object->error; + setEventMessages($errmsg, null, 'errors'); } } @@ -581,12 +601,12 @@ if ($rowid > 0) dol_fiche_head($head, 'subscription', $langs->trans("Member"), 0, 'user'); $linkback = ''.$langs->trans("BackToList").''; - + dol_banner_tab($object, 'rowid', $linkback); - + print '
    '; print '
    '; - + print '
    '; print ''; @@ -624,13 +644,13 @@ if ($rowid > 0) } print '
    '; - + print '
    '; print '
    '; - + print '
    '; print ''; - + // Birthday print ''; @@ -677,7 +697,7 @@ if ($rowid > 0) } } print ''; - + // Third party Dolibarr if (! empty($conf->societe->enabled)) { @@ -752,7 +772,7 @@ if ($rowid > 0) print "\n"; print '
    '; - + dol_fiche_end(); print ''; From 1b1d1a8d0b093f0bc34d717acce479048afea69e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 16:57:07 +0200 Subject: [PATCH 20/31] FIX #7156 --- htdocs/societe/soc.php | 55 ++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/htdocs/societe/soc.php b/htdocs/societe/soc.php index b9c962a5168..06846d34203 100644 --- a/htdocs/societe/soc.php +++ b/htdocs/societe/soc.php @@ -140,7 +140,7 @@ if (empty($reshook)) if (!$errors) { // TODO Move the merge function into class of object. - + $db->begin(); // Recopy some data @@ -157,26 +157,29 @@ if (empty($reshook)) { if (empty($object->$property)) $object->$property = $soc_origin->$property; } - + // Concat some data $listofproperties=array( - 'note_public', 'note_private' + 'note_public', 'note_private' ); foreach ($listofproperties as $property) { $object->$property = dol_concatdesc($object->$property, $soc_origin->$property); } - + // Merge extrafields - foreach ($soc_origin->array_options as $key => $val) + if (is_array($soc_origin->array_options)) { - if (empty($object->array_options[$key])) $object->array_options[$key] = $val; + foreach ($soc_origin->array_options as $key => $val) + { + if (empty($object->array_options[$key])) $object->array_options[$key] = $val; + } } // TODO Merge categories $object->update($object->id, $user); - - // Move links + + // Move links $objects = array( 'Adherent' => '/adherents/class/adherent.class.php', 'Societe' => '/societe/class/societe.class.php', @@ -487,7 +490,7 @@ if (empty($reshook)) if (empty($object->fournisseur)) $object->code_fournisseur=''; $result = $object->create($user); - + if ($result >= 0) { if ($object->particulier) @@ -557,7 +560,7 @@ if (empty($reshook)) $object->code_fournisseur = null; $object->code_client = null; } - + $error=$object->error; $errors=$object->errors; } @@ -852,7 +855,7 @@ else $object->particulier = $private; $object->prefix_comm = GETPOST('prefix_comm'); $object->client = GETPOST('client')?GETPOST('client'):$object->client; - + if(empty($duplicate_code_error)) { $object->code_client = GETPOST('code_client', 'alpha'); $object->fournisseur = GETPOST('fournisseur')?GETPOST('fournisseur'):$object->fournisseur; @@ -860,7 +863,7 @@ else else { setEventMessages($langs->trans('NewCustomerSupplierCodeProposed'),'', 'warnings'); } - + $object->code_fournisseur = GETPOST('code_fournisseur', 'alpha'); $object->address = GETPOST('address', 'alpha'); $object->zip = GETPOST('zipcode', 'alpha'); @@ -1136,7 +1139,7 @@ else print ''; print ''; print ''; - + // Skype if (! empty($conf->skype->enabled)) { @@ -1216,7 +1219,7 @@ else print ''; - + } elseif($mysoc->localtax1_assuj=="1") { @@ -1230,7 +1233,7 @@ else print $form->selectyesno('localtax2assuj_value',(isset($conf->global->THIRDPARTY_DEFAULT_USELOCALTAX2)?$conf->global->THIRDPARTY_DEFAULT_USELOCALTAX2:0),1); print ''; } - + // Type - Size print ''; - + } elseif($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj!="1") { @@ -1774,7 +1777,7 @@ else print ''; } print ''; - + } elseif($mysoc->localtax2_assuj=="1" && $mysoc->localtax1_assuj!="1") { @@ -1788,7 +1791,7 @@ else } print ''; } - + // VAT Code print ''; print ''; - + if($object->localtax1_assuj=="1" && (! isOnlyOneLocalTax(1))) { print ''; @@ -2144,7 +2147,7 @@ else print ''; } print ''; - + } } elseif($mysoc->localtax2_assuj=="1" && $mysoc->localtax1_assuj!="1") @@ -2154,7 +2157,7 @@ else print ''; if($object->localtax2_assuj=="1" && (! isOnlyOneLocalTax(2))) { - + print ''; print ''; print ''; @@ -2167,7 +2170,7 @@ else print ''; } print ''; - + } } /* @@ -2178,7 +2181,7 @@ else print ''; } */ - + // VAT Code print ''; print '
    '.$langs->trans("Birthday").''.dol_print_date($object->birth,'day').'
    '.fieldLabel('Web','url').'
    '.$langs->transcountry("LocalTax2IsUsed",$mysoc->country_code).''; print $form->selectyesno('localtax2assuj_value',(isset($conf->global->THIRDPARTY_DEFAULT_USELOCALTAX2)?$conf->global->THIRDPARTY_DEFAULT_USELOCALTAX2:0),1); print '
    '.fieldLabel('ThirdPartyType','typent_id').''."\n"; $sortparam=(empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?'ASC':$conf->global->SOCIETE_SORT_ON_TYPEENT); // NONE means we keep sort of original array, so we sort on position. ASC, means next function will sort on label. @@ -1751,7 +1754,7 @@ else $formcompany->select_localtax(1,$object->localtax1_value, "lt1"); print ''; } - + print ''.fieldLabel($langs->transcountry("LocalTax2IsUsed",$mysoc->country_code),'localtax2assuj_value').''; print $form->selectyesno('localtax2assuj_value',$object->localtax2_assuj,1); if (! isOnlyOneLocalTax(2)) @@ -1761,7 +1764,7 @@ else print ''; } print '
    '.fieldLabel('VATIntra','intra_vat').''; @@ -2090,7 +2093,7 @@ else print '
    '.$langs->transcountry("LocalTax2IsUsed",$mysoc->country_code).''; print yn($object->localtax2_assuj); print '
    '.$object->localtax1_value.'
    '.$object->localtax2_value.'
    '.$langs->trans('VATIntra').''; @@ -2573,10 +2576,10 @@ else // Subsidiaries list if (empty($conf->global->SOCIETE_DISABLE_SUBSIDIARIES)) - { + { $result=show_subsidiaries($conf,$langs,$db,$object); } - + // Contacts list if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { From d90a23efb69efc9f6aeec5c93a10ae2f042de8f3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 17:00:50 +0200 Subject: [PATCH 21/31] Fix for old php --- htdocs/admin/dolistore/class/dolistore.class.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index acf86766e25..482bd124a40 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -56,13 +56,11 @@ class Dolistore extends DolistoreModel $this->end = $this->per_page; } - $lang = explode('_', $langs->defaultlang); - $lang = $lang[0]; - $lang_array = ['fr', 'en', 'es', 'it', 'de']; - if (!in_array($lang, $lang_array)) { - $lang = 'en'; - } - $this->lang = array_search($lang, $lang_array) + 1; // 1=fr 2=en ... + $langtmp = explode('_', $langs->defaultlang); + $lang = $langtmp[0]; + $lang_array = array('fr'=>1, 'en'=>2, 'es'=>3, 'it'=>4, 'de'=>5); + if (! in_array($lang, array_keys($lang_array))) $lang = 'en'; + $this->lang = $lang_array[$lang]; // 1=fr 2=en ... try { $this->api = new PrestaShopWebservice($conf->global->MAIN_MODULE_DOLISTORE_API_SRV, From 9079d2890c429ac8012a70a3546f238d1330e1b8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 18:13:42 +0200 Subject: [PATCH 22/31] Fix ajout du code devise Franc Pacifique --- htdocs/install/mysql/data/llx_c_currencies.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/data/llx_c_currencies.sql b/htdocs/install/mysql/data/llx_c_currencies.sql index d9b1390bb32..cb34f60291f 100644 --- a/htdocs/install/mysql/data/llx_c_currencies.sql +++ b/htdocs/install/mysql/data/llx_c_currencies.sql @@ -154,7 +154,7 @@ INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'VEF' INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'VND', '[8363]', 1, 'Viet Nam Dong'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XAF', NULL, 1, 'Communaute Financiere Africaine (BEAC) CFA Franc'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XOF', NULL, 1, 'Communaute Financiere Africaine (BCEAO) Franc'); -INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XPF', NULL, 1, 'Franc pacifique (XPF)'); +INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XPF', '[70]', 1, 'Franc pacifique (XPF)'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'YER', '[65020]', 1, 'Yemen Rial'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'ZWD', '[90,36]', 1, 'Zimbabwe Dollar'); From ccb5344d32b803dd8abb02d27e2888f856f24612 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 18:52:03 +0200 Subject: [PATCH 23/31] Fix links --- htdocs/core/boxes/box_activity.php | 494 +++++++++--------- .../install/mysql/data/llx_c_currencies.sql | 2 +- 2 files changed, 248 insertions(+), 248 deletions(-) diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php index ae3e270101e..02b1d1880c8 100644 --- a/htdocs/core/boxes/box_activity.php +++ b/htdocs/core/boxes/box_activity.php @@ -97,181 +97,95 @@ class box_activity extends ModeleBoxes $cumuldata = array(); - // list the summary of the bills - if (! empty($conf->facture->enabled) && $user->rights->facture->lire) + + // list the summary of the propals + if (! empty($conf->propal->enabled) && $user->rights->propale->lire) { - include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; - $facturestatic=new Facture($db); + include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; + $propalstatic=new Propal($db); - // part 1 - $cachedir = DOL_DATA_ROOT.'/facture/temp'; - $filename = '/boxactivity-invoice'.$fileid; + $cachedir = DOL_DATA_ROOT.'/propale/temp'; + $filename = '/boxactivity-propal'.$fileid; + $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); + $data = array(); + if ($refresh) + { + $sql = "SELECT p.fk_statut, SUM(p.total) as Mnttot, COUNT(*) as nb"; + $sql.= " FROM (".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."propal as p"; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= ")"; + $sql.= " WHERE p.entity = ".$conf->entity; + $sql.= " AND p.fk_soc = s.rowid"; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; + $sql.= " AND p.datep >= '".$db->idate($tmpdate)."'"; + $sql.= " AND p.date_cloture IS NULL"; // just unclosed + $sql.= " GROUP BY p.fk_statut"; + $sql.= " ORDER BY p.fk_statut DESC"; - $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); - $data = array(); - if ($refresh) - { - $sql = "SELECT f.fk_statut, SUM(f.total_ttc) as Mnttot, COUNT(*) as nb"; - $sql.= " FROM (".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; - if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= ")"; - $sql.= " WHERE f.entity = ".$conf->entity; - if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; - if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; - $sql.= " AND f.fk_soc = s.rowid"; - $sql.= " AND f.datef >= '".$db->idate($tmpdate)."' AND paye=1"; - $sql.= " GROUP BY f.fk_statut"; - $sql.= " ORDER BY f.fk_statut DESC"; + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); - $j=0; - while ($j < $num) { - $data[$j]=$db->fetch_object($result); - $j++; - } - if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { - dol_filecache($cachedir, $filename, $data); - } - $db->free($result); - } else { - dol_print_error($db); - } - } else { - $data = dol_readcachefile($cachedir, $filename); - } + $j=0; + while ($j < $num) { + $data[$j]=$db->fetch_object($result); + $j++; + } + if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { + dol_filecache($cachedir, $filename, $data); + } + $db->free($result); + } else { + dol_print_error($db); + } + } + else + { + $data = dol_readcachefile($cachedir, $filename); + } - $cumuldata=array_merge($cumuldata, $data); - if (! empty($data)) { - $j=0; - while ($line < count($cumuldata)) { - $billurl="viewstatut=2&paye=1&year=".$data[$j]->annee; - $this->info_box_contents[$line][0] = array( - 'td' => 'align="left" width="16"', - 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1,$data[$j]->fk_statut,0), - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", - 'logo' => 'bill', - ); + $cumuldata=array_merge($cumuldata, $data); + if (! empty($data)) + { + $j=0; + while ($line < count($cumuldata)) + { + $this->info_box_contents[$line][0] = array( + 'td' => 'align="left" width="16"', + 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&viewstatut=".$data[$j]->fk_statut, + 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), + 'logo' => 'object_propal' + ); - $this->info_box_contents[$line][1] = array( - 'td' => '', - 'text' => $langs->trans("Bills")." ".$facturestatic->LibStatut(1,$data[$j]->fk_statut,0)." ".$data[$j]->annee, - ); + $this->info_box_contents[$line][1] = array( + 'td' => '', + 'text' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), + ); - $this->info_box_contents[$line][2] = array( - 'td' => 'class="right"', - 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1,$data[$j]->fk_statut,0), - 'text' => $data[$j]->nb, - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", - ); + $this->info_box_contents[$line][2] = array( + 'td' => 'class="right"', + 'text' => $data[$j]->nb, + 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), + 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&viewstatut=".$data[$j]->fk_statut, + ); + $totalnb += $data[$j]->nb; - $this->info_box_contents[$line][3] = array( - 'td' => 'class="right"', - 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency) - ); + $this->info_box_contents[$line][3] = array( + 'td' => 'class="right"', + 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency), + ); + $totalMnt += $data[$j]->Mnttot; + $this->info_box_contents[$line][4] = array( + 'td' => 'align="right" width="18"', + 'text' => $propalstatic->LibStatut($data[$j]->fk_statut,3), + ); - // We add only for the current year - if ($data[$j]->annee == date("Y")) { - $totalnb += $data[$j]->nb; - $totalMnt += $data[$j]->Mnttot; - } - $this->info_box_contents[$line][4] = array( - 'td' => 'align="right" width="18"', - 'text' => $facturestatic->LibStatut(1,$data[$j]->fk_statut,3), - ); - $line++; - $j++; - } - if (count($data)==0) - $this->info_box_contents[$line][0] = array( - 'td' => 'align="center"', - 'text'=>$langs->trans("NoRecordedInvoices"), - ); - } - - // part 2 - $cachedir = DOL_DATA_ROOT.'/facture/temp'; - $filename = '/boxactivity-invoice2'.$fileid; - - $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); - - if ($refresh) { - $sql = "SELECT f.fk_statut, SUM(f.total_ttc) as Mnttot, COUNT(*) as nb"; - $sql.= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; - $sql.= " WHERE f.entity = ".$conf->entity; - $sql.= " AND f.fk_soc = s.rowid"; - $sql.= " AND paye=0"; - $sql.= " GROUP BY f.fk_statut"; - $sql.= " ORDER BY f.fk_statut DESC"; - - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); - $j=0; - while ($j < $num) { - $data[$j]=$db->fetch_object($result); - $j++; - } - if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { - dol_filecache($cachedir, $filename, $data); - } - $db->free($result); - } else { - dol_print_error($db); - } - } else { - $data = dol_readcachefile($cachedir, $filename); - } - - $cumuldata=array_merge($cumuldata, $data); - if (! empty($data)) { - $j=0; - - while ($line < count($cumuldata)) { - $billurl="viewstatut=".$data[$j]->fk_statut."&paye=0"; - $this->info_box_contents[$line][0] = array( - 'td' => 'align="left" width="16"', - 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", - 'logo' => 'bill', - ); - - $this->info_box_contents[$line][1] = array( - 'td' => '', - 'text' => $langs->trans("Bills")." ".$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), - ); - - $this->info_box_contents[$line][2] = array( - 'td' => 'class="right"', - 'text' => $data[$j]->nb, - 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", - ); - $totalnb += $data[$j]->nb; - $this->info_box_contents[$line][3] = array( - 'td' => 'class="right"', - 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency), - ); - $totalMnt += $objp->Mnttot; - $this->info_box_contents[$line][4] = array( - 'td' => 'align="right" width="18"', - 'text' => $facturestatic->LibStatut(0,$data[$j]->fk_statut,3), - ); - $line++; - $j++; - } - if ($num==0) - $this->info_box_contents[$line][0] = array( - 'td' => 'align="center"', - 'text'=>$langs->trans("NoRecordedInvoices"), - ); - } else { - $this->info_box_contents[0][0] = array( - 'td' => '', - 'maxlength'=>500, 'text' => ($db->error().' sql='.$sql), - ); - } + $line++; + $j++; + } + } } // list the summary of the orders @@ -295,12 +209,10 @@ class box_activity extends ModeleBoxes if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; $sql.= " AND c.date_commande >= '".$db->idate($tmpdate)."'"; - $sql.= " AND c.facture=0"; $sql.= " GROUP BY c.fk_statut"; $sql.= " ORDER BY c.fk_statut DESC"; $result = $db->query($sql); - if ($result) { $num = $db->num_rows($result); $j=0; @@ -359,94 +271,182 @@ class box_activity extends ModeleBoxes } } - // list the summary of the propals - if (! empty($conf->propal->enabled) && $user->rights->propale->lire) + + // list the summary of the bills + if (! empty($conf->facture->enabled) && $user->rights->facture->lire) { - include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; - $propalstatic=new Propal($db); + include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $facturestatic=new Facture($db); - $cachedir = DOL_DATA_ROOT.'/propale/temp'; - $filename = '/boxactivity-propal'.$fileid; - $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); - $data = array(); - if ($refresh) - { - $sql = "SELECT p.fk_statut, SUM(p.total) as Mnttot, COUNT(*) as nb"; - $sql.= " FROM (".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."propal as p"; - if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= ")"; - $sql.= " WHERE p.entity = ".$conf->entity; - $sql.= " AND p.fk_soc = s.rowid"; - if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; - if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; - $sql.= " AND p.datep >= '".$db->idate($tmpdate)."'"; - $sql.= " AND p.date_cloture IS NULL"; // just unclosed - $sql.= " GROUP BY p.fk_statut"; - $sql.= " ORDER BY p.fk_statut DESC"; + // part 1 + $cachedir = DOL_DATA_ROOT.'/facture/temp'; + $filename = '/boxactivity-invoice'.$fileid; - $result = $db->query($sql); - if ($result) - { - $num = $db->num_rows($result); + $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); + $data = array(); + if ($refresh) + { + $sql = "SELECT f.fk_statut, SUM(f.total_ttc) as Mnttot, COUNT(*) as nb"; + $sql.= " FROM (".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= ")"; + $sql.= " WHERE f.entity = ".$conf->entity; + if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if($user->societe_id) $sql.= " AND s.rowid = ".$user->societe_id; + $sql.= " AND f.fk_soc = s.rowid"; + $sql.= " AND f.datef >= '".$db->idate($tmpdate)."' AND paye=1"; + $sql.= " GROUP BY f.fk_statut"; + $sql.= " ORDER BY f.fk_statut DESC"; - $j=0; - while ($j < $num) { - $data[$j]=$db->fetch_object($result); - $j++; - } - if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { - dol_filecache($cachedir, $filename, $data); - } - $db->free($result); - } else { - dol_print_error($db); - } - } - else - { - $data = dol_readcachefile($cachedir, $filename); - } + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + $j=0; + while ($j < $num) { + $data[$j]=$db->fetch_object($result); + $j++; + } + if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { + dol_filecache($cachedir, $filename, $data); + } + $db->free($result); + } else { + dol_print_error($db); + } + } else { + $data = dol_readcachefile($cachedir, $filename); + } - $cumuldata=array_merge($cumuldata, $data); - if (! empty($data)) - { - $j=0; - while ($line < count($cumuldata)) - { - $this->info_box_contents[$line][0] = array( - 'td' => 'align="left" width="16"', - 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&viewstatut=".$data[$j]->fk_statut, - 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), - 'logo' => 'object_propal' - ); + $cumuldata=array_merge($cumuldata, $data); + if (! empty($data)) { + $j=0; + while ($line < count($cumuldata)) { + $billurl="search_status=2&paye=1&year=".$data[$j]->annee; + $this->info_box_contents[$line][0] = array( + 'td' => 'align="left" width="16"', + 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1,$data[$j]->fk_statut,0), + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + 'logo' => 'bill', + ); - $this->info_box_contents[$line][1] = array( - 'td' => '', - 'text' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), - ); + $this->info_box_contents[$line][1] = array( + 'td' => '', + 'text' => $langs->trans("Bills")." ".$facturestatic->LibStatut(1,$data[$j]->fk_statut,0)." ".$data[$j]->annee, + ); - $this->info_box_contents[$line][2] = array( - 'td' => 'class="right"', - 'text' => $data[$j]->nb, - 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut,0), - 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&viewstatut=".$data[$j]->fk_statut, - ); - $totalnb += $data[$j]->nb; + $this->info_box_contents[$line][2] = array( + 'td' => 'class="right"', + 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1,$data[$j]->fk_statut,0), + 'text' => $data[$j]->nb, + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + ); - $this->info_box_contents[$line][3] = array( - 'td' => 'class="right"', - 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency), - ); - $totalMnt += $data[$j]->Mnttot; - $this->info_box_contents[$line][4] = array( - 'td' => 'align="right" width="18"', - 'text' => $propalstatic->LibStatut($data[$j]->fk_statut,3), - ); + $this->info_box_contents[$line][3] = array( + 'td' => 'class="right"', + 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency) + ); - $line++; - $j++; - } - } + // We add only for the current year + if ($data[$j]->annee == date("Y")) { + $totalnb += $data[$j]->nb; + $totalMnt += $data[$j]->Mnttot; + } + $this->info_box_contents[$line][4] = array( + 'td' => 'align="right" width="18"', + 'text' => $facturestatic->LibStatut(1,$data[$j]->fk_statut,3), + ); + $line++; + $j++; + } + if (count($data)==0) + $this->info_box_contents[$line][0] = array( + 'td' => 'align="center"', + 'text'=>$langs->trans("NoRecordedInvoices"), + ); + } + + // part 2 + $cachedir = DOL_DATA_ROOT.'/facture/temp'; + $filename = '/boxactivity-invoice2'.$fileid; + + $refresh = dol_cache_refresh($cachedir, $filename, $cachetime); + + if ($refresh) { + $sql = "SELECT f.fk_statut, SUM(f.total_ttc) as Mnttot, COUNT(*) as nb"; + $sql.= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; + $sql.= " WHERE f.entity = ".$conf->entity; + $sql.= " AND f.fk_soc = s.rowid"; + $sql.= " AND paye=0"; + $sql.= " GROUP BY f.fk_statut"; + $sql.= " ORDER BY f.fk_statut DESC"; + + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + $j=0; + while ($j < $num) { + $data[$j]=$db->fetch_object($result); + $j++; + } + if (! empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { + dol_filecache($cachedir, $filename, $data); + } + $db->free($result); + } else { + dol_print_error($db); + } + } else { + $data = dol_readcachefile($cachedir, $filename); + } + + $cumuldata=array_merge($cumuldata, $data); + if (! empty($data)) { + $j=0; + + while ($line < count($cumuldata)) { + $billurl="search_status=".$data[$j]->fk_statut."&paye=0"; + $this->info_box_contents[$line][0] = array( + 'td' => 'align="left" width="16"', + 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + 'logo' => 'bill', + ); + + $this->info_box_contents[$line][1] = array( + 'td' => '', + 'text' => $langs->trans("Bills")." ".$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), + ); + + $this->info_box_contents[$line][2] = array( + 'td' => 'class="right"', + 'text' => $data[$j]->nb, + 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(0,$data[$j]->fk_statut,0), + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + ); + $totalnb += $data[$j]->nb; + $this->info_box_contents[$line][3] = array( + 'td' => 'class="right"', + 'text' => price($data[$j]->Mnttot,1,$langs,0,0,-1,$conf->currency), + ); + $totalMnt += $objp->Mnttot; + $this->info_box_contents[$line][4] = array( + 'td' => 'align="right" width="18"', + 'text' => $facturestatic->LibStatut(0,$data[$j]->fk_statut,3), + ); + $line++; + $j++; + } + if ($num==0) + $this->info_box_contents[$line][0] = array( + 'td' => 'align="center"', + 'text'=>$langs->trans("NoRecordedInvoices"), + ); + } else { + $this->info_box_contents[0][0] = array( + 'td' => '', + 'maxlength'=>500, 'text' => ($db->error().' sql='.$sql), + ); + } } // Add the sum in the bottom of the boxes diff --git a/htdocs/install/mysql/data/llx_c_currencies.sql b/htdocs/install/mysql/data/llx_c_currencies.sql index cb34f60291f..db1ba19aa6e 100644 --- a/htdocs/install/mysql/data/llx_c_currencies.sql +++ b/htdocs/install/mysql/data/llx_c_currencies.sql @@ -154,7 +154,7 @@ INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'VEF' INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'VND', '[8363]', 1, 'Viet Nam Dong'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XAF', NULL, 1, 'Communaute Financiere Africaine (BEAC) CFA Franc'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XOF', NULL, 1, 'Communaute Financiere Africaine (BCEAO) Franc'); -INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XPF', '[70]', 1, 'Franc pacifique (XPF)'); +INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'XPF', '[70]', 1, 'Franc CFP'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'YER', '[65020]', 1, 'Yemen Rial'); INSERT INTO llx_c_currencies ( code_iso, unicode, active, label ) VALUES ( 'ZWD', '[90,36]', 1, 'Zimbabwe Dollar'); From ab37794f616a4f8df4a5a5ba5d6b308b55015b1c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 19:34:26 +0200 Subject: [PATCH 24/31] Fix text --- htdocs/core/class/html.formmail.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index f2e861ea932..4ec9c91aa80 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -473,7 +473,7 @@ class FormMail extends Form $out.= ' <'.$this->tomail.'>'; if ($this->withtofree) { - $out.= '
    '.$langs->trans("or").' withto) :"").'" />'; + $out.= '
    '.$langs->trans("and").' withto) :"").'" />'; } } else @@ -489,7 +489,7 @@ class FormMail extends Form } if (! empty($this->withto) && is_array($this->withto)) { - if (! empty($this->withtofree)) $out.= " ".$langs->trans("or")." "; + if (! empty($this->withtofree)) $out.= " ".$langs->trans("and")."/".$langs->trans("or")." "; // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time $tmparray = $this->withto; foreach($tmparray as $key => $val) @@ -522,7 +522,7 @@ class FormMail extends Form $out.= 'withtocc) : (isset($_POST["sendtocc"])?$_POST["sendtocc"]:"") ).'" />'; if (! empty($this->withtocc) && is_array($this->withtocc)) { - $out.= " ".$langs->trans("or")." "; + $out.= " ".$langs->trans("and")."/".$langs->trans("or")." "; // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time $tmparray = $this->withtocc; foreach($tmparray as $key => $val) @@ -551,7 +551,7 @@ class FormMail extends Form $out.= 'withtoccc) : (isset($_POST["sendtoccc"])?$_POST["sendtoccc"]:"") ).'" />'; if (! empty($this->withtoccc) && is_array($this->withtoccc)) { - $out.= " ".$langs->trans("or")." "; + $out.= " ".$langs->trans("and")."/".$langs->trans("or")." "; // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time $tmparray = $this->withtoccc; foreach($tmparray as $key => $val) From 9f5718f00a5842008b923298d82cdef24ac54f6b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 23 Aug 2017 19:38:06 +0200 Subject: [PATCH 25/31] Fix php unit --- htdocs/admin/dolistore/class/dolistore.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index 482bd124a40..5e0aa546cc0 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -306,11 +306,11 @@ class DolistoreModel function get_previous_link($text = '<<') { - return "$text"; + return ''.$text.''; } function get_next_link($text = '>>') { - return "$text"; + return ''.$text.''; } } From 17f44ad980c0fa62c65fb9adac4fee40317add50 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 24 Aug 2017 02:02:00 +0200 Subject: [PATCH 26/31] NEW Can make a specific setup for SMTP sending for emailing module --- htdocs/admin/mails.php | 14 +- htdocs/admin/mails_emailing.php | 643 ++++++++++++++++++++++++++ htdocs/admin/mails_templates.php | 8 + htdocs/core/actions_sendmails.inc.php | 3 +- htdocs/core/class/CMailFile.class.php | 129 ++++-- htdocs/core/class/smtps.class.php | 29 +- htdocs/langs/en_US/mails.lang | 3 + 7 files changed, 767 insertions(+), 62 deletions(-) create mode 100644 htdocs/admin/mails_emailing.php diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index dadf7b476ee..5ff8078e826 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -114,7 +114,7 @@ $server=! empty($conf->global->MAIN_MAIL_SMTP_SERVER)?$conf->global->MAIN_MAIL_S if (! $server) $server='127.0.0.1'; -$wikihelp='EN:Setup EMails|FR:Paramétrage EMails|ES:Configuración EMails'; +$wikihelp='EN:Setup_EMails|FR:Paramétrage_EMails|ES:Configuración_EMails'; llxHeader('',$langs->trans("Setup"),$wikihelp); print load_fiche_titre($langs->trans("EMailsSetup"),'','title_setup'); @@ -127,6 +127,14 @@ $head[$h][1] = $langs->trans("OutGoingEmailSetup"); $head[$h][2] = 'common'; $h++; +if ($conf->mailing->enabled) +{ + $head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php"; + $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing"); + $head[$h][2] = 'common_emailing'; + $h++; +} + $head[$h][0] = DOL_URL_ROOT."/admin/mails_templates.php"; $head[$h][1] = $langs->trans("DictionaryEMailTemplates"); $head[$h][2] = 'templates'; @@ -238,7 +246,7 @@ if ($action == 'edit') $var=true; print ''; - print ''; + print ''; // Disable @@ -462,7 +470,7 @@ else $var=true; print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '; - print ''; + print ''; // Disable diff --git a/htdocs/admin/mails_emailing.php b/htdocs/admin/mails_emailing.php new file mode 100644 index 00000000000..b98661edab5 --- /dev/null +++ b/htdocs/admin/mails_emailing.php @@ -0,0 +1,643 @@ + + * Copyright (C) 2009-2012 Regis Houssin + * Copyright (C) 2013 Juanjo Menent + * Copyright (C) 2016 Jonathan TISSEAU + * + * 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/mails.php + * \brief Page to setup emails sending + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + +$langs->load("companies"); +$langs->load("products"); +$langs->load("admin"); +$langs->load("mails"); +$langs->load("other"); +$langs->load("errors"); + +$action=GETPOST('action','alpha'); + +if (! $user->admin) accessforbidden(); + +$usersignature=$user->signature; +// For action = test or send, we ensure that content is not html, even for signature, because this we want a test with NO html. +if ($action == 'test' || $action == 'send') +{ + $usersignature=dol_string_nohtmltag($usersignature); +} + +$substitutionarrayfortest=array( +'__LOGIN__' => $user->login, +'__ID__' => 'TESTIdRecord', +'__EMAIL__' => 'TESTEMail', +'__LASTNAME__' => 'TESTLastname', +'__FIRSTNAME__' => 'TESTFirstname', +'__SIGNATURE__' => (($user->signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN))?$usersignature:''), +//'__PERSONALIZED__' => 'TESTPersonalized' // Hiden because not used yet +); +complete_substitutions_array($substitutionarrayfortest, $langs); + + + +/* + * Actions + */ + +if ($action == 'update' && empty($_POST["cancel"])) +{ + // Send mode parameters + dolibarr_set_const($db, "MAIN_MAIL_SENDMODE_EMAILING", GETPOST("MAIN_MAIL_SENDMODE_EMAILING"),'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_SMTP_PORT_EMAILING", GETPOST("MAIN_MAIL_SMTP_PORT_EMAILING"),'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_SMTP_SERVER_EMAILING", GETPOST("MAIN_MAIL_SMTP_SERVER_EMAILING"),'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_SMTPS_ID_EMAILING", GETPOST("MAIN_MAIL_SMTPS_ID_EMAILING"), 'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_SMTPS_PW_EMAILING", GETPOST("MAIN_MAIL_SMTPS_PW_EMAILING"), 'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_EMAIL_TLS_EMAILING", GETPOST("MAIN_MAIL_EMAIL_TLS_EMAILING"),'chaine',0,'',$conf->entity); + dolibarr_set_const($db, "MAIN_MAIL_EMAIL_STARTTLS_EMAILING", GETPOST("MAIN_MAIL_EMAIL_STARTTLS_EMAILING"),'chaine',0,'',$conf->entity); + + header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); + exit; +} + + +// Actions to send emails +$id=0; +$actiontypecode=''; // Not an event for agenda +$trigger_name=''; // Disable triggers +$paramname='id'; +$mode='emailfortest'; +$trackid=(($action == 'testhtml')?"testhtml":"test"); +$sendcontext='emailing'; // Force to use dedicated context of setup for emailing +include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; + +if ($action == 'presend' && GETPOST('trackid') == 'test') $action='test'; +if ($action == 'presend' && GETPOST('trackid') == 'testhtml') $action='testhtml'; + + + + +/* + * View + */ + +$linuxlike=1; +if (preg_match('/^win/i',PHP_OS)) $linuxlike=0; +if (preg_match('/^mac/i',PHP_OS)) $linuxlike=0; + +if (empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING)) $conf->global->MAIN_MAIL_SENDMODE_EMAILING='default'; +$port=! empty($conf->global->MAIN_MAIL_SMTP_PORT_EMAILING)?$conf->global->MAIN_MAIL_SMTP_PORT_EMAILING:ini_get('smtp_port'); +if (! $port) $port=25; +$server=! empty($conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING)?$conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING:ini_get('SMTP'); +if (! $server) $server='127.0.0.1'; + + +$wikihelp='EN:Setup_EMails|FR:Paramétrage_EMails|ES:Configuración_EMails'; +llxHeader('',$langs->trans("Setup"),$wikihelp); + +print load_fiche_titre($langs->trans("EMailsSetup"),'','title_setup'); + + +$h = 0; + +$head[$h][0] = DOL_URL_ROOT."/admin/mails.php"; +$head[$h][1] = $langs->trans("OutGoingEmailSetup"); +$head[$h][2] = 'common'; +$h++; + +if ($conf->mailing->enabled) +{ + $head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php"; + $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing"); + $head[$h][2] = 'common_emailing'; + $h++; +} + +$head[$h][0] = DOL_URL_ROOT."/admin/mails_templates.php"; +$head[$h][1] = $langs->trans("DictionaryEMailTemplates"); +$head[$h][2] = 'templates'; +$h++; + + +// List of sending methods +$listofmethods=array(); +$listofmethods['default']=$langs->trans('DefaultOutgoingEmailSetup'); +$listofmethods['mail']='PHP mail function'; +//$listofmethods['simplemail']='Simplemail class'; +$listofmethods['smtps']='SMTP/SMTPS socket library'; +$listofmethods['swiftmailer']='Swift Mailer socket library'; + + +if ($action == 'edit') +{ + $form=new Form($db); + + if ($conf->use_javascript_ajax) + { + print "\n".''."\n"; + } + + print '
    '; + print ''; + print ''; + + dol_fiche_head($head, 'common_emailing', '', -1); + + print $langs->trans("EMailsDesc")."
    \n"; + print "
    \n"; + + + clearstatcache(); + $var=true; + + print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '; + print ''; + + // Method + + print ''; + + // Host server + + print ''; + + // Port + + print ''; + + // ID + if (! empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) + { + + $mainstmpid=(! empty($conf->global->MAIN_MAIL_SMTPS_ID_EMAILING)?$conf->global->MAIN_MAIL_SMTPS_ID_EMAILING:''); + print ''; + } + + // PW + if (! empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) + { + + $mainsmtppw=(! empty($conf->global->MAIN_MAIL_SMTPS_PW_EMAILING)?$conf->global->MAIN_MAIL_SMTPS_PW_EMAILING:''); + print ''; + } + + // TLS + + print ''; + + // STARTTLS + + print ''; + + print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("MAIN_MAIL_SENDMODE").''; + + // SuperAdministrator access only + if ((empty($conf->global->MAIN_MODULE_MULTICOMPANY)) || ($user->admin && !$user->entity)) + { + print $form->selectarray('MAIN_MAIL_SENDMODE_EMAILING',$listofmethods,$conf->global->MAIN_MAIL_SENDMODE_EMAILING); + } + else + { + $text = $listofmethods[$conf->global->MAIN_MAIL_SENDMODE_EMAILING]; + if (empty($text)) $text = $langs->trans("Undefined"); + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($text,$htmltext,1,'superadmin'); + print ''; + } + print '
    '; + if (! $conf->use_javascript_ajax && $linuxlike && $conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail') + { + print $langs->trans("MAIN_MAIL_SMTP_SERVER_NotAvailableOnLinuxLike"); + print ''; + print $langs->trans("SeeLocalSendMailSetup"); + } + else + { + $mainserver = (! empty($conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING)?$conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING:''); + $smtpserver = ini_get('SMTP')?ini_get('SMTP'):$langs->transnoentities("Undefined"); + if ($linuxlike) print $langs->trans("MAIN_MAIL_SMTP_SERVER_NotAvailableOnLinuxLike"); + else print $langs->trans("MAIN_MAIL_SMTP_SERVER",$smtpserver); + print ''; + // SuperAdministrator access only + if (empty($conf->multicompany->enabled) || ($user->admin && ! $user->entity)) + { + print ''; + print ''; + print ''.$langs->trans("SeeLocalSendMailSetup").''; + } + else + { + $text = ! empty($mainserver) ? $mainserver : $smtpserver; + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($text,$htmltext,1,'superadmin'); + print ''; + } + } + print '
    '; + if (! $conf->use_javascript_ajax && $linuxlike && $conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail') + { + print $langs->trans("MAIN_MAIL_SMTP_PORT_NotAvailableOnLinuxLike"); + print ''; + print $langs->trans("SeeLocalSendMailSetup"); + } + else + { + $mainport = (! empty($conf->global->MAIN_MAIL_SMTP_PORT_EMAILING) ? $conf->global->MAIN_MAIL_SMTP_PORT_EMAILING : ''); + $smtpport = ini_get('smtp_port')?ini_get('smtp_port'):$langs->transnoentities("Undefined"); + if ($linuxlike) print $langs->trans("MAIN_MAIL_SMTP_PORT_NotAvailableOnLinuxLike"); + else print $langs->trans("MAIN_MAIL_SMTP_PORT",$smtpport); + print ''; + // SuperAdministrator access only + if (empty($conf->multicompany->enabled) || ($user->admin && ! $user->entity)) + { + print ''; + print ''; + print ''.$langs->trans("SeeLocalSendMailSetup").''; + } + else + { + $text = (! empty($mainport) ? $mainport : $smtpport); + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($text,$htmltext,1,'superadmin'); + print ''; + } + } + print '
    '.$langs->trans("MAIN_MAIL_SMTPS_ID").''; + // SuperAdministrator access only + if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) + { + print ''; + } + else + { + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($conf->global->MAIN_MAIL_SMTPS_ID_EMAILING,$htmltext,1,'superadmin'); + print ''; + } + print '
    '.$langs->trans("MAIN_MAIL_SMTPS_PW").''; + // SuperAdministrator access only + if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) + { + print ''; + } + else + { + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($conf->global->MAIN_MAIL_SMTPS_PW_EMAILING,$htmltext,1,'superadmin'); + print ''; + } + print '
    '.$langs->trans("MAIN_MAIL_EMAIL_TLS").''; + if (! empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) + { + if (function_exists('openssl_open')) + { + print $form->selectyesno('MAIN_MAIL_EMAIL_TLS_EMAILING',(! empty($conf->global->MAIN_MAIL_EMAIL_TLS_EMAILING)?$conf->global->MAIN_MAIL_EMAIL_TLS_EMAILING:0),1); + } + else print yn(0).' ('.$langs->trans("YourPHPDoesNotHaveSSLSupport").')'; + } + else print yn(0).' ('.$langs->trans("NotSupported").')'; + print '
    '.$langs->trans("MAIN_MAIL_EMAIL_STARTTLS").''; + if (! empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) + { + if (function_exists('openssl_open')) + { + print $form->selectyesno('MAIN_MAIL_EMAIL_STARTTLS_EMAILING',(! empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS_EMAILING)?$conf->global->MAIN_MAIL_EMAIL_STARTTLS_EMAILING:0),1); + } + else print yn(0).' ('.$langs->trans("YourPHPDoesNotHaveSSLSupport").')'; + } + else print yn(0).' ('.$langs->trans("NotSupported").')'; + print '
    '; + + dol_fiche_end(); + + print '
    '; + print ''; + print '     '; + print ''; + print '
    '; + + print ''; +} +else +{ + dol_fiche_head($head, 'common_emailing', '', -1); + + print $langs->trans("EMailsDesc")."
    \n"; + print "
    \n"; + + + $var=true; + + print ''; + print ''; + + // Method + + print ''; + + if (! empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') + { + // Host server + + if ($linuxlike && (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail')) + { + print ''; + } + else + { + print ''; + } + + // Port + + if ($linuxlike && (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail')) + { + print ''; + } + else + { + print ''; + } + + // SMTPS ID + + if (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer'))) + { + print ''; + } + + // SMTPS PW + + if (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer'))) + { + print ''; + } + + // TLS + + print ''; + + // STARTTLS + + print ''; + } + + print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("MAIN_MAIL_SENDMODE").''; + $text=$listofmethods[$conf->global->MAIN_MAIL_SENDMODE_EMAILING]; + if (empty($text)) $text=$langs->trans("Undefined").img_warning(); + print $text; + print '
    '.$langs->trans("MAIN_MAIL_SMTP_SERVER_NotAvailableOnLinuxLike").''.$langs->trans("SeeLocalSendMailSetup").'
    '.$langs->trans("MAIN_MAIL_SMTP_SERVER",ini_get('SMTP')?ini_get('SMTP'):$langs->transnoentities("Undefined")).''.(! empty($conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING)?$conf->global->MAIN_MAIL_SMTP_SERVER_EMAILING:'').'
    '.$langs->trans("MAIN_MAIL_SMTP_PORT_NotAvailableOnLinuxLike").''.$langs->trans("SeeLocalSendMailSetup").'
    '.$langs->trans("MAIN_MAIL_SMTP_PORT",ini_get('smtp_port')?ini_get('smtp_port'):$langs->transnoentities("Undefined")).''.(! empty($conf->global->MAIN_MAIL_SMTP_PORT_EMAILING)?$conf->global->MAIN_MAIL_SMTP_PORT_EMAILING:'').'
    '.$langs->trans("MAIN_MAIL_SMTPS_ID").''.$conf->global->MAIN_MAIL_SMTPS_ID_EMAILING.'
    '.$langs->trans("MAIN_MAIL_SMTPS_PW").''.preg_replace('/./','*',$conf->global->MAIN_MAIL_SMTPS_PW_EMAILING).'
    '.$langs->trans("MAIN_MAIL_EMAIL_TLS").''; + if (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer'))) + { + if (function_exists('openssl_open')) + { + print yn($conf->global->MAIN_MAIL_EMAIL_TLS_EMAILING); + } + else print yn(0).' ('.$langs->trans("YourPHPDoesNotHaveSSLSupport").')'; + } + else print yn(0).' ('.$langs->trans("NotSupported").')'; + print '
    '.$langs->trans("MAIN_MAIL_EMAIL_STARTTLS").''; + if (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer'))) + { + if (function_exists('openssl_open')) + { + print yn($conf->global->MAIN_MAIL_EMAIL_STARTTLS_EMAILING); + } + else print yn(0).' ('.$langs->trans("YourPHPDoesNotHaveSSLSupport").')'; + } + else print yn(0).' ('.$langs->trans("NotSupported").')'; + print '
    '; + + dol_fiche_end(); + + + if ($conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail' && empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA)) + { + print '
    '; + /* + // Warning 1 + if ($linuxlike) + { + $sendmailoption=ini_get('mail.force_extra_parameters'); + if (empty($sendmailoption) || ! preg_match('/ba/',$sendmailoption)) + { + print info_admin($langs->trans("SendmailOptionNotComplete")); + } + }*/ + // Warning 2 + print info_admin($langs->trans("SendmailOptionMayHurtBuggedMTA")); + } + + + // Boutons actions + print '
    '; + + print ''.$langs->trans("Modify").''; + + if (! empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') + { + if ($conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'mail' || ! $linuxlike) + { + if (function_exists('fsockopen') && $port && $server) + { + print ''.$langs->trans("DoTestServerAvailability").''; + } + } + else + { + print ''.$langs->trans("DoTestServerAvailability").''; + } + + print ''.$langs->trans("DoTestSend").''; + + if (! empty($conf->fckeditor->enabled)) + { + print ''.$langs->trans("DoTestSendHTML").''; + } + } + + print '
    '; + + + if ($conf->global->MAIN_MAIL_SENDMODE_EMAILING == 'mail' && ! in_array($action, array('testconnect', 'test', 'testhtml'))) + { + $text = $langs->trans("WarningPHPMail"); + print info_admin($text); + } + + // Run the test to connect + if ($action == 'testconnect') + { + print load_fiche_titre($langs->trans("DoTestServerAvailability")); + + include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + $mail = new CMailFile('','','',''); + $result=$mail->check_server_port($server,$port); + if ($result) print '
    '.$langs->trans("ServerAvailableOnIPOrPort",$server,$port).'
    '; + else + { + $errormsg = $langs->trans("ServerNotAvailableOnIPOrPort",$server,$port); + + if ($mail->error) { + $errormsg .= ' - '.$mail->error; + } + + setEventMessages($errormsg, null, 'errors'); + } + print '
    '; + } + + // Show email send test form + if ($action == 'test' || $action == 'testhtml') + { + print '
    '; + print load_fiche_titre($action == 'testhtml'?$langs->trans("DoTestSendHTML"):$langs->trans("DoTestSend")); + + dol_fiche_head(''); + + // Cree l'objet formulaire mail + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + $formmail->fromname = (isset($_POST['fromname'])?$_POST['fromname']:$conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->frommail = (isset($_POST['frommail'])?$_POST['frommail']:$conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->trackid=(($action == 'testhtml')?"testhtml":"test"); + $formmail->withfromreadonly=0; + $formmail->withsubstit=0; + $formmail->withfrom=1; + $formmail->witherrorsto=1; + $formmail->withto=(! empty($_POST['sendto'])?$_POST['sendto']:($user->email?$user->email:1)); + $formmail->withtocc=(! empty($_POST['sendtocc'])?$_POST['sendtocc']:1); // ! empty to keep field if empty + $formmail->withtoccc=(! empty($_POST['sendtoccc'])?$_POST['sendtoccc']:1); // ! empty to keep field if empty + $formmail->withtopic=(isset($_POST['subject'])?$_POST['subject']:$langs->trans("Test")); + $formmail->withtopicreadonly=0; + $formmail->withfile=2; + $formmail->withbody=(isset($_POST['message'])?$_POST['message']:($action == 'testhtml'?$langs->transnoentities("PredefinedMailTestHtml"):$langs->transnoentities("PredefinedMailTest"))); + $formmail->withbodyreadonly=0; + $formmail->withcancel=1; + $formmail->withdeliveryreceipt=1; + $formmail->withfckeditor=($action == 'testhtml'?1:0); + $formmail->ckeditortoolbar='dolibarr_mailings'; + // Tableau des substitutions + $formmail->substit=$substitutionarrayfortest; + // Tableau des parametres complementaires du post + $formmail->param["action"]="send"; + $formmail->param["models"]="body"; + $formmail->param["mailid"]=0; + $formmail->param["returnurl"]=$_SERVER["PHP_SELF"]; + + // Init list of files + if (GETPOST("mode")=='init') + { + $formmail->clear_attached_files(); + } + + print $formmail->get_form('addfile','removefile'); + + dol_fiche_end(); + } +} + + +llxFooter(); + +$db->close(); diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index dabc0f5f730..f0cbb91c6c3 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -410,6 +410,14 @@ $head[$h][1] = $langs->trans("OutGoingEmailSetup"); $head[$h][2] = 'common'; $h++; +if ($conf->mailing->enabled) +{ + $head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php"; + $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing"); + $head[$h][2] = 'common_emailing'; + $h++; +} + $head[$h][0] = DOL_URL_ROOT."/admin/mails_templates.php"; $head[$h][1] = $langs->trans("DictionaryEMailTemplates"); $head[$h][2] = 'templates'; diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 1998808bf11..58bc00e3f0f 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -345,7 +345,8 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO } // Send mail - $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1,'','',$trackid); + if (empty($sendcontext)) $sendcontext = 'standard'; + $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,$sendtobcc,$deliveryreceipt,-1,'','',$trackid,'',$sendcontext); if ($mailfile->error) { setEventMessage($mailfile->error, 'errors'); diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 3b3efe96fb0..b05b8a162a1 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -38,8 +38,7 @@ class CMailFile { public $sendcontext; public $sendmode; - public $sendsetup; - + var $subject; // Topic: Subject of email var $addr_from; // From: Label and EMail of sender (must include '<>'). For example '' or 'John Doe ' or ''). Note that with gmail smtps, value here is forced by google to account (but not the reply-to). // Sender: Who send the email ("Sender" has sent emails on behalf of "From"). @@ -115,14 +114,15 @@ class CMailFile global $conf, $dolibarr_main_data_root; $this->sendcontext = $sendcontext; - + + // Define this->sendmode $this->sendmode = ''; - if ($this->sendcontext == 'emailing') $this->sendmode = $conf->global->EMAILING_MAIL_SENDMODE; + if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') + { + $this->sendmode = $conf->global->MAIN_MAIL_SENDMODE_EMAILING; + } if (empty($this->sendmode)) $this->sendmode=$conf->global->MAIN_MAIL_SENDMODE; if (empty($this->sendmode)) $this->sendmode='mail'; - - $this->sendsetup = array(); - // We define end of line (RFC 821). $this->eol="\r\n"; @@ -145,7 +145,7 @@ class CMailFile $this->alternative_boundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3); // Force md5 hash (does not contains special chars) dol_syslog("CMailFile::CMailfile: sendmode=".$this->sendmode." charset=".$conf->file->character_set_client." from=$from, to=$to, addr_cc=$addr_cc, addr_bcc=$addr_bcc, errors_to=$errors_to, trackid=$trackid sendcontext=$sendcontext", LOG_DEBUG); - dol_syslog("CMailFile::CMailfile: subject=$subject, deliveryreceipt=$deliveryreceipt, msgishtml=$msgishtml", LOG_DEBUG); + dol_syslog("CMailFile::CMailfile: subject=".$subject.", deliveryreceipt=".$deliveryreceipt.", msgishtml=".$msgishtml, LOG_DEBUG); if (empty($subject)) { @@ -157,7 +157,7 @@ class CMailFile { dol_syslog("CMailFile::CMailfile: Try to send an email with empty body"); $msg='.'; // Avoid empty message (with empty message conten show a multipart structure) - } + } // Detect if message is HTML (use fast method) if ($msgishtml == -1) @@ -230,7 +230,7 @@ class CMailFile $this->addr_bcc = $addr_bcc; $this->deliveryreceipt = $deliveryreceipt; $this->trackid = $trackid; - + $smtp_headers = $this->write_smtpheaders(); if (! empty($moreinheader)) $smtp_headers.=$moreinheader; // $moreinheader contains the \r\n @@ -339,7 +339,7 @@ class CMailFile $this->phpmailer->SetReplyTo($this->getValidAddress($from,0,1)); // Set property with this->phpmailer->setReplyTo after constructor if you want to use another value than the From // TODO Add trackid into smtp header // TODO if (! empty($moreinheader)) ... - + if (! empty($this->html)) { if (!empty($css)) @@ -487,9 +487,7 @@ class CMailFile { require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; $hookmanager = new HookManager($db); - $hookmanager->initHooks(array( - 'maildao' - )); + $hookmanager->initHooks(array('maildao')); $reshook = $hookmanager->executeHooks('doactions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if (! empty($reshook)) { @@ -532,6 +530,22 @@ class CMailFile return false; } + $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER'; + $keyforsmtpport ='MAIN_MAIL_SMTP_PORT'; + $keyforsmtpid ='MAIN_MAIL_SMTPS_ID'; + $keyforsmtppw ='MAIN_MAIL_SMTPS_PW'; + $keyfortls ='MAIN_MAIL_EMAIL_TLS'; + $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS'; + if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') + { + $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER_EMAILING'; + $keyforsmtpport ='MAIN_MAIL_SMTP_PORT_EMAILING'; + $keyforsmtpid ='MAIN_MAIL_SMTPS_ID_EMAILING'; + $keyforsmtppw ='MAIN_MAIL_SMTPS_PW_EMAILING'; + $keyfortls ='MAIN_MAIL_EMAIL_TLS_EMAILING'; + $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS_EMAILING'; + } + // Action according to choosed sending method if ($this->sendmode == 'mail') { @@ -548,9 +562,9 @@ class CMailFile @ini_set('sendmail_from',$this->getValidAddress($this->addr_from,2)); } - // Forcage parametres - if (! empty($conf->global->MAIN_MAIL_SMTP_SERVER)) ini_set('SMTP',$conf->global->MAIN_MAIL_SMTP_SERVER); - if (! empty($conf->global->MAIN_MAIL_SMTP_PORT)) ini_set('smtp_port',$conf->global->MAIN_MAIL_SMTP_PORT); + // Force parameters + if (! empty($conf->global->$keyforsmtpserver)) ini_set('SMTP',$conf->global->$keyforsmtpserver); + if (! empty($conf->global->$keyforsmtpport)) ini_set('smtp_port',$conf->global->$keyforsmtpport); $dest=$this->getValidAddress($this->addr_to,2); if (! $dest) @@ -610,9 +624,9 @@ class CMailFile @ini_restore('sendmail_from'); } - // Forcage parametres - if (! empty($conf->global->MAIN_MAIL_SMTP_SERVER)) ini_restore('SMTP'); - if (! empty($conf->global->MAIN_MAIL_SMTP_PORT)) ini_restore('smtp_port'); + // Restore parameters + if (! empty($conf->global->$keyforsmtpserver)) ini_restore('SMTP'); + if (! empty($conf->global->$keyforsmtpport)) ini_restore('smtp_port'); } else if ($this->sendmode == 'smtps') { @@ -622,28 +636,30 @@ class CMailFile $this->smtps->setTransportType(0); // Only this method is coded in SMTPs library // Clean parameters - if (empty($conf->global->MAIN_MAIL_SMTP_SERVER)) $conf->global->MAIN_MAIL_SMTP_SERVER=ini_get('SMTP'); - if (empty($conf->global->MAIN_MAIL_SMTP_PORT)) $conf->global->MAIN_MAIL_SMTP_PORT=ini_get('smtp_port'); - - // TODO Manage alternative parameters + if (empty($conf->global->$keyforsmtpserver)) $conf->global->$keyforsmtpserver=ini_get('SMTP'); + if (empty($conf->global->$keyforsmtpport)) $conf->global->$keyforsmtpport=ini_get('smtp_port'); // If we use SSL/TLS - $server=$conf->global->MAIN_MAIL_SMTP_SERVER; - if (! empty($conf->global->MAIN_MAIL_EMAIL_TLS) && function_exists('openssl_open')) $server='ssl://'.$server; - $port=$conf->global->MAIN_MAIL_SMTP_PORT; + $server=$conf->global->$keyforsmtpserver; + $secure=''; + if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $secure='ssl'; + if (! empty($conf->global->$keyforstarttls) && function_exists('openssl_open')) $secure='tls'; + $server=($secure?$secure.'://':'').$server; + + $port=$conf->global->$keyforsmtpport; $this->smtps->setHost($server); $this->smtps->setPort($port); // 25, 465...; $loginid=''; $loginpass=''; - if (! empty($conf->global->MAIN_MAIL_SMTPS_ID)) + if (! empty($conf->global->$keyforsmtpid)) { - $loginid = $conf->global->MAIN_MAIL_SMTPS_ID; + $loginid = $conf->global->$keyforsmtpid; $this->smtps->setID($loginid); } - if (! empty($conf->global->MAIN_MAIL_SMTPS_PW)) + if (! empty($conf->global->$keyforsmtppw)) { - $loginpass = $conf->global->MAIN_MAIL_SMTPS_PW; + $loginpass = $conf->global->$keyforsmtppw; $this->smtps->setPW($loginpass); } @@ -651,14 +667,14 @@ class CMailFile $from=$this->smtps->getFrom('org'); if (! $from) { - $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->MAIN_MAIL_SMTP_PORT."
    Sender address '$from' invalid"; + $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
    Sender address '$from' invalid"; dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); $res=false; } $dest=$this->smtps->getTo(); if (! $dest) { - $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->MAIN_MAIL_SMTP_PORT."
    Recipient address '$dest' invalid"; + $this->error="Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
    Recipient address '$dest' invalid"; dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); $res=false; } @@ -666,7 +682,7 @@ class CMailFile if ($res) { if (! empty($conf->global->MAIN_MAIL_DEBUG)) $this->smtps->setDebug(true); - + $result=$this->smtps->sendMsg(); //print $result; @@ -684,26 +700,24 @@ class CMailFile } else if ($this->sendmode == 'swiftmailer') { - // Use Swift Mailer library // ------------------------------------------ require_once DOL_DOCUMENT_ROOT.'/includes/swiftmailer/lib/swift_required.php'; - // Forcage parametres - if (empty($conf->global->MAIN_MAIL_SMTP_SERVER)) $conf->global->MAIN_MAIL_SMTP_SERVER=ini_get('SMTP'); - if (empty($conf->global->MAIN_MAIL_SMTP_PORT)) $conf->global->MAIN_MAIL_SMTP_PORT=ini_get('smtp_port'); + // Clean parameters + if (empty($conf->global->$keyforsmtpserver)) $conf->global->$keyforsmtpserver=ini_get('SMTP'); + if (empty($conf->global->$keyforsmtpport)) $conf->global->$keyforsmtpport=ini_get('smtp_port'); // If we use SSL/TLS - $server=$conf->global->MAIN_MAIL_SMTP_SERVER; + $server=$conf->global->$keyforsmtpserver; $secure=''; - //var_dump(stream_get_transports()); - if (! empty($conf->global->MAIN_MAIL_EMAIL_TLS) && function_exists('openssl_open')) $secure='ssl'; - if (! empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS) && function_exists('openssl_open')) $secure='tls'; + if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $secure='ssl'; + if (! empty($conf->global->$keyforstarttls) && function_exists('openssl_open')) $secure='tls'; - $this->transport = Swift_SmtpTransport::newInstance($server, $conf->global->MAIN_MAIL_SMTP_PORT, $secure); + $this->transport = Swift_SmtpTransport::newInstance($server, $conf->global->$keyforsmtpport, $secure); - if (! empty($conf->global->MAIN_MAIL_SMTPS_ID)) $this->transport->setUsername($conf->global->MAIN_MAIL_SMTPS_ID); - if (! empty($conf->global->MAIN_MAIL_SMTPS_PW)) $this->transport->setPassword($conf->global->MAIN_MAIL_SMTPS_PW); + if (! empty($conf->global->$keyforsmtpid)) $this->transport->setUsername($conf->global->$keyforsmtpid); + if (! empty($conf->global->$keyforsmtppw)) $this->transport->setPassword($conf->global->$keyforsmtppw); //$smtps->_msgReplyTo = 'reply@web.com'; // Create the Mailer using your created Transport @@ -1026,7 +1040,7 @@ class CMailFile $out.= $this->eol; $out.= "--" . $this->related_boundary . $this->eol; } - + if (! $this->atleastoneimage && $strContentAltText && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part { $out.= "Content-Type: multipart/alternative; boundary=\"".$this->alternative_boundary."\"".$this->eol; @@ -1036,7 +1050,7 @@ class CMailFile $out.= $this->eol.$strContentAltText.$this->eol; $out.= "--" . $this->alternative_boundary . $this->eol; } - + $out.= "Content-Type: text/html; charset=".$conf->file->character_set_client.$this->eol; $out.= $this->eol.$strContent.$this->eol; @@ -1154,13 +1168,30 @@ class CMailFile function check_server_port($host,$port) { global $conf; + $_retVal=0; $timeout=5; // Timeout in seconds if (function_exists('fsockopen')) { + $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER'; + $keyforsmtpport ='MAIN_MAIL_SMTP_PORT'; + $keyforsmtpid ='MAIN_MAIL_SMTPS_ID'; + $keyforsmtppw ='MAIN_MAIL_SMTPS_PW'; + $keyfortls ='MAIN_MAIL_EMAIL_TLS'; + $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS'; + if ($this->sendcontext == 'emailing' && !empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') + { + $keyforsmtpserver='MAIN_MAIL_SMTP_SERVER_EMAILING'; + $keyforsmtpport ='MAIN_MAIL_SMTP_PORT_EMAILING'; + $keyforsmtpid ='MAIN_MAIL_SMTPS_ID_EMAILING'; + $keyforsmtppw ='MAIN_MAIL_SMTPS_PW_EMAILING'; + $keyfortls ='MAIN_MAIL_EMAIL_TLS_EMAILING'; + $keyforstarttls ='MAIN_MAIL_EMAIL_STARTTLS_EMAILING'; + } + // If we use SSL/TLS - if (! empty($conf->global->MAIN_MAIL_EMAIL_TLS) && function_exists('openssl_open')) $host='ssl://'.$host; + if (! empty($conf->global->$keyfortls) && function_exists('openssl_open')) $host='ssl://'.$host; // tls smtp start with no encryption //if (! empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS) && function_exists('openssl_open')) $host='tls://'.$host; @@ -1355,7 +1386,7 @@ class CMailFile if ($email) { $i++; - + $newemail=''; if ($format == 4) { diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index c92558bf1d3..cfaa88363a4 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -358,8 +358,11 @@ class SMTPs // This is done here because '@fsockopen' will not give me this // information if it failes to connect because it can't find the HOST $host=$this->getHost(); + $usetls = preg_match('@tls://@i',$host); + $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix + $host=preg_replace('@tls://@i','',$host); // Remove prefix // @CHANGE LDR include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; @@ -373,7 +376,7 @@ class SMTPs { //See if we can connect to the SMTP server if ($this->socket = @fsockopen( - $this->getHost(), // Host to 'hit', IP or domain + preg_replace('@tls://@i','',$this->getHost()), // Host to 'hit', IP or domain $this->getPort(), // which Port number to use $this->errno, // actual system level error $this->errstr, // and any text that goes with the error @@ -416,16 +419,17 @@ class SMTPs // This improvment as provided by 'SirSir' to // accomodate both SMTP AND ESMTP capable servers $host=$this->getHost(); + $usetls = preg_match('@tls://@i',$host); + $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix - if (!empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS)) - { - $host=preg_replace('@tls://@i','',$host); // Remove prefix - $host='tls://'.$host; - } + $host=preg_replace('@tls://@i','',$host); // Remove prefix + + if ($usetls) $host='tls://'.$host; + if ( $_retVal = $this->socket_send_str('EHLO ' . $host, '250') ) { - if (!empty($conf->global->MAIN_MAIL_EMAIL_STARTTLS)) + if ($usetls) { /* The following dialog illustrates how a client and server can start a TLS STARTTLS session @@ -443,7 +447,7 @@ class SMTPs // Second pass EHLO C: EHLO client-domain.com S: 250-server-domain.com - S: 250 AUTH LOGIN + S: 250 AUTH LOGIN C: socket_send_str('STARTTLS', 220)) @@ -456,7 +460,7 @@ class SMTPs $this->_setErr(132, 'STARTTLS connection failed.'); return $_retVal; } - // Most server servers expect a 2nd pass of EHLO after TLS is established to get another time + // Most server servers expect a 2nd pass of EHLO after TLS is established to get another time // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS. if (!$_retVal = $this->socket_send_str('EHLO '.$host, '250')) { @@ -514,8 +518,12 @@ class SMTPs { // Send the RFC821 specified HELO. $host=$this->getHost(); + $usetls = preg_match('@tls://@i',$host); + $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix + $host=preg_replace('@tls://@i','',$host); // Remove prefix + $_retVal = $this->socket_send_str('HELO ' . $host, '250'); } @@ -1237,8 +1245,11 @@ class SMTPs */ $host=$this->getHost(); + $usetls = preg_match('@tls://@i',$host); + $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix + $host=preg_replace('@tls://@i','',$host); // Remove prefix $host=dol_getprefix('email'); diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 1e4f1446fa7..a78b7bbc6c8 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -156,4 +156,7 @@ NoContactWithCategoryFound=No contact/address with a category found NoContactLinkedToThirdpartieWithCategoryFound=No contact/address with a category found OutGoingEmailSetup=Outgoing email setup InGoingEmailSetup=Incoming email setup +OutGoingEmailSetupForEmailing=Outgoing email setup (for mass emailing) +DefaultOutgoingEmailSetup=Default outgoing email setup + From 7da6f93d7e5d972fc693c6c6431d9aef63f3d45e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 24 Aug 2017 13:23:15 +0200 Subject: [PATCH 27/31] FIX select of category FIX pb with extrafield list and key '0' --- htdocs/core/class/commonobject.class.php | 12 +++++ htdocs/core/class/extrafields.class.php | 18 ++++---- htdocs/core/class/html.form.class.php | 2 +- htdocs/core/lib/functions.lib.php | 2 +- htdocs/install/mysql/migration/repair.sql | 3 +- htdocs/langs/en_US/admin.lang | 10 ++--- .../modulebuilder/template/myobject_list.php | 2 +- htdocs/societe/list.php | 45 +++++++++++-------- 8 files changed, 57 insertions(+), 37 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0693b3dd336..50ccf362de6 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4352,6 +4352,12 @@ abstract class CommonObject $this->array_options[$key] = null; } break; + /*case 'select': // Not required, we chosed value='0' for undefined values + if ($value=='-1') + { + $this->array_options[$key] = null; + } + break;*/ case 'price': $this->array_options[$key] = price2num($this->array_options[$key]); break; @@ -4485,6 +4491,12 @@ abstract class CommonObject $this->array_options["options_".$key] = null; } break; + /*case 'select': // Not required, we chosed value='0' for undefined values + if ($value=='-1') + { + $this->array_options[$key] = null; + } + break;*/ case 'price': $this->array_options["options_".$key] = price2num($this->array_options["options_".$key]); break; diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 3fcb909fc51..a66648df2c2 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -348,7 +348,7 @@ class ExtraFields $sql .= " " . $user->id . ","; $sql .= "'" . $this->db->idate(dol_now()) . "'"; $sql.=')'; - + dol_syslog(get_class($this)."::create_label", LOG_DEBUG); if ($this->db->query($sql)) { @@ -721,8 +721,8 @@ class ExtraFields { $array_name_label[$tab->name]=$tab->label; } - - + + // Old usage $this->attribute_type[$tab->name]=$tab->type; @@ -740,8 +740,8 @@ class ExtraFields $this->attribute_list[$tab->name]=$tab->list; $this->attribute_hidden[$tab->name]=$tab->ishidden; $this->attribute_entityid[$tab->name]=$tab->entity; - - + + // New usage $this->attributes[$tab->elementtype]['type'][$tab->name]=$tab->type; @@ -759,8 +759,8 @@ class ExtraFields $this->attributes[$tab->elementtype]['list'][$tab->name]=$tab->list; $this->attributes[$tab->elementtype]['ishidden'][$tab->name]=$tab->ishidden; $this->attributes[$tab->elementtype]['entityid'][$tab->name]=$tab->entity; - - + + if (!empty($conf->multicompany->enabled)) { $sql_entity_name='SELECT label FROM '.MAIN_DB_PREFIX.'entity WHERE rowid='.$tab->entity; $resql_entity_name=$this->db->query($sql_entity_name); @@ -944,10 +944,10 @@ class ExtraFields $out.=''; foreach ($param['options'] as $key => $val) { - if ($key == '') continue; + if ((string) $key == '') continue; list($val, $parent) = explode('|', $val); $out.='