diff --git a/ChangeLog b/ChangeLog
index ae767c91649..76709bd8f85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,9 +4,20 @@ English Dolibarr ChangeLog
***** ChangeLog for 17.0.0 compared to 16.0.0 *****
+For users:
+---------------
+
+...
+
+
For developers or integrators:
------------------------------
+...
+
+
+WARNING:
+
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product
@@ -192,6 +203,8 @@ NEW: Add hooks select product list and select thirdparty list function
NEW: Add hook to getSellPrice function
+WARNING:
+
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* There is a new specific permission to be allowed to enter timesheets. If you use timesheet, don't forget to give the new permission (disable and
enable the module project if it is not visible).
@@ -489,6 +502,8 @@ NEW: we need to be able to put more filters on deleteByParentField() function
NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object
NEW: Experimental feature to manage user sessions in database
+
+WARNING:
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field
diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php
index 3075225abb9..1995485eb4e 100644
--- a/htdocs/adherents/list.php
+++ b/htdocs/adherents/list.php
@@ -63,6 +63,7 @@ $search_email = GETPOST("search_email", 'alpha');
$search_categ = GETPOST("search_categ", 'int');
$search_filter = GETPOST("search_filter", 'alpha');
$search_status = GETPOST("search_status", 'intcomma');
+$search_morphy = GETPOST("search_morphy", 'alpha');
$search_import_key = trim(GETPOST("search_import_key", "alpha"));
$catid = GETPOST("catid", 'int');
$optioncss = GETPOST('optioncss', 'alpha');
@@ -382,6 +383,9 @@ if ($search_status != '') {
// Peut valoir un nombre ou liste de nombre separes par virgules
$sql .= " AND d.statut in (".$db->sanitize($db->escape($search_status)).")";
}
+if ($search_morphy != '') {
+ $sql .= natural_search("d.morphy", $search_morphy);
+}
if ($search_ref) {
$sql .= natural_search("d.ref", $search_ref);
}
@@ -731,6 +735,11 @@ if (!empty($arrayfields['d.login']['checked'])) {
}
if (!empty($arrayfields['d.morphy']['checked'])) {
print '
';
+
+global $dolibarr_main_url_root;
+
+// Define $urlwithroot
+$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
+$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
+//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
+
+// Url for CIDLookup
+//print '
';
if (!empty($conf->global->MAIN_MAIL_SENDMODE_TICKET) && $conf->global->MAIN_MAIL_SENDMODE_TICKET != 'default') {
diff --git a/htdocs/admin/system/constall.php b/htdocs/admin/system/constall.php
index 96cb98809ef..9a27feb3d7a 100644
--- a/htdocs/admin/system/constall.php
+++ b/htdocs/admin/system/constall.php
@@ -89,6 +89,7 @@ $configfileparameters = array(
'separator',
'?dolibarr_mailing_limit_sendbyweb',
'?dolibarr_mailing_limit_sendbycli',
+ '?dolibarr_mailing_limit_sendbyday',
'?dolibarr_strict_mode'
);
$configfilelib = array(
diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php
index e58cf45dd7e..8a982f6e0bd 100644
--- a/htdocs/admin/system/dolibarr.php
+++ b/htdocs/admin/system/dolibarr.php
@@ -360,6 +360,7 @@ $configfileparameters = array(
'dolibarr_main_restrict_ip' => 'Restrict access to some IPs only',
'?dolibarr_mailing_limit_sendbyweb' => 'Limit nb of email sent by page',
'?dolibarr_mailing_limit_sendbycli' => 'Limit nb of email sent by cli',
+ '?dolibarr_mailing_limit_sendbyday' => 'Limit nb of email sent per day',
'?dolibarr_strict_mode' => 'Strict mode is on/off',
'?dolibarr_nocsrfcheck' => 'Disable CSRF security checks'
);
diff --git a/htdocs/api/index.php b/htdocs/api/index.php
index afb0289aa32..8543e284533 100644
--- a/htdocs/api/index.php
+++ b/htdocs/api/index.php
@@ -257,6 +257,8 @@ if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $
continue;
}
+ //dol_syslog("We scan to search api file with into ".$dir_part.$file_searched);
+
$regapi = array();
if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $regapi)) {
$classname = ucwords($regapi[1]);
diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php
index d46a02132a1..748c5fabf10 100644
--- a/htdocs/comm/mailing/card.php
+++ b/htdocs/comm/mailing/card.php
@@ -801,13 +801,20 @@ if ($action == 'create') {
// MAILING_NO_USING_PHPMAIL may be defined or not.
// MAILING_LIMIT_SENDBYWEB is always defined to something != 0 (-1=forbidden).
// MAILING_LIMIT_SENDBYCLI may be defined ot not (-1=forbidden, 0 or undefined=no limit).
+ // MAILING_LIMIT_SENDBYDAY may be defined ot not (0 or undefined=no limit).
if (!empty($conf->global->MAILING_NO_USING_PHPMAIL) && $sendingmode == 'mail') {
// EMailing feature may be a spam problem, so when you host several users/instance, having this option may force each user to use their own SMTP agent.
// You ensure that every user is using its own SMTP server when using the mass emailing module.
$linktoadminemailbefore = '';
$linktoadminemailend = '';
setEventMessages($langs->trans("MailSendSetupIs", $listofmethods[$sendingmode]), null, 'warnings');
- setEventMessages($langs->trans("MailSendSetupIs2", $linktoadminemailbefore, $linktoadminemailend, $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $listofmethods['smtps']), null, 'warnings');
+ $messagetoshow = $langs->trans("MailSendSetupIs2", '{s1}', '{s2}', '{s3}', '{s4}');
+ $messagetoshow = str_replace('{s1}', $linktoadminemailbefore, $messagetoshow);
+ $messagetoshow = str_replace('{s2}', $linktoadminemailend, $messagetoshow);
+ $messagetoshow = str_replace('{s3}', $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $messagetoshow);
+ $messagetoshow = str_replace('{s4}', $listofmethods['smtps'], $messagetoshow);
+ setEventMessages($messagetoshow, null, 'warnings');
+
if (!empty($conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS)) {
setEventMessages($langs->trans("MailSendSetupIs3", $conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS), null, 'warnings');
}
@@ -836,14 +843,21 @@ if ($action == 'create') {
}
$text = '';
- if (!isset($conf->global->MAILING_LIMIT_SENDBYCLI) || $conf->global->MAILING_LIMIT_SENDBYCLI >= 0) {
- $text .= $langs->trans("MailingNeedCommand");
- $text .= ' ';
+
+ if (isset($conf->global->MAILING_LIMIT_SENDBYDAY) && $conf->global->MAILING_LIMIT_SENDBYDAY >= 0) {
+ $text .= $langs->trans('WarningLimitSendByDay', $conf->global->MAILING_LIMIT_SENDBYDAY);
$text .= '
';
+ $text .= $langs->trans("MailingNeedCommand");
+ $text .= ' ';
+ }
+
+ print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('SendMailing'), $text, 'sendallconfirmed', '', '', 1, 330, 600, 0, $langs->trans("Confirm"), $langs->trans("Cancel"));
}
}
diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php
index 5cdc0d0c6e4..06149063806 100644
--- a/htdocs/contact/card.php
+++ b/htdocs/contact/card.php
@@ -1301,11 +1301,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$action = 'presend';
}
+ // View mode
if (!empty($id) && $action != 'edit' && $action != 'create') {
$objsoc = new Societe($db);
- // View mode
-
// Show errors
dol_htmloutput_errors(is_numeric($error) ? '' : $error, $errors);
@@ -1530,9 +1529,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
if ($object->user_id) {
$dolibarr_user = new User($db);
$result = $dolibarr_user->fetch($object->user_id);
- print $dolibarr_user->getLoginUrl(1);
+ print $dolibarr_user->getLoginUrl(-1);
} else {
- print $langs->trans("NoDolibarrAccess");
+ //print ''.$langs->trans("NoDolibarrAccess").'';
+ if (!$object->user_id && $user->rights->user->user->creer) {
+ print ''.img_picto($langs->trans("CreateDolibarrLogin"), 'add').' '.$langs->trans("CreateDolibarrLogin").'';
+ }
}
print '';
@@ -1565,10 +1567,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print ''.$langs->trans('Modify').'';
}
- if (!$object->user_id && $user->rights->user->user->creer) {
- print ''.$langs->trans("CreateDolibarrLogin").'';
- }
-
// Activer
if ($object->statut == 0 && $user->rights->societe->contact->creer) {
print ''.$langs->trans("Reactivate").'';
diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php
index 322f3f4652e..1e8da8a9a81 100644
--- a/htdocs/contrat/class/contrat.class.php
+++ b/htdocs/contrat/class/contrat.class.php
@@ -668,7 +668,7 @@ class Contrat extends CommonObject
if (!$id) {
$sql .= " WHERE entity IN (".getEntity('contract').")";
} else {
- $sql .= " WHERE rowid=".(int) $id;
+ $sql .= " WHERE rowid = ".(int) $id;
}
if ($ref_customer) {
$sql .= " AND ref_customer = '".$this->db->escape($ref_customer)."'";
@@ -677,7 +677,7 @@ class Contrat extends CommonObject
$sql .= " AND ref_supplier = '".$this->db->escape($ref_supplier)."'";
}
if ($ref) {
- $sql .= " AND ref='".$this->db->escape($ref)."'";
+ $sql .= " AND ref = '".$this->db->escape($ref)."'";
}
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
@@ -724,10 +724,13 @@ class Contrat extends CommonObject
// Retrieve all extrafields
// fetch optionals attributes and labels
- $this->fetch_optionals();
+ $result = $this->fetch_optionals();
// Lines
- $result = $this->fetch_lines();
+ if ($result >= 0 && !empty($this->table_element_line)) {
+ $result = $this->fetch_lines();
+ }
+
if ($result < 0) {
$this->error = $this->db->lasterror();
return -3;
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 4d83acfe44c..b0ea04adb3e 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -7633,16 +7633,24 @@ abstract class CommonObject
}
if ($result > 0) {
if ($object->element === 'product') {
- $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]);
- $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]);
- $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]);
- $getnomurlparam6 = (!isset($InfoFieldList[8]) ? '' : $InfoFieldList[8]);
- $getnomurlparam7 = (!isset($InfoFieldList[9]) ? 0 : $InfoFieldList[9]);
+ $get_name_url_param_arr = array($getnomurlparam, $getnomurlparam2, 0, -1, 0, '', 0);
+ if (isset($val['get_name_url_params'])) {
+ $get_name_url_params = explode(':', $val['get_name_url_params']);
+ if (!empty($get_name_url_params)) {
+ $param_num_max = count($get_name_url_param_arr) - 1;
+ foreach ($get_name_url_params as $param_num => $param_value) {
+ if ($param_num > $param_num_max) {
+ break;
+ }
+ $get_name_url_param_arr[$param_num] = $param_value;
+ }
+ }
+ }
/**
* @var Product $object
*/
- $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6, $getnomurlparam7);
+ $value = $object->getNomUrl($get_name_url_param_arr[0], $get_name_url_param_arr[1], $get_name_url_param_arr[2], $get_name_url_param_arr[3], $get_name_url_param_arr[4], $get_name_url_param_arr[5], $get_name_url_param_arr[6]);
} else {
$value = $object->getNomUrl($getnomurlparam, $getnomurlparam2);
}
diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php
index 22a6f8da7a4..2e544a9953a 100644
--- a/htdocs/core/class/conf.class.php
+++ b/htdocs/core/class/conf.class.php
@@ -1038,12 +1038,15 @@ class Conf
if (!empty($this->file->mailing_limit_sendbyweb)) {
$this->global->MAILING_LIMIT_SENDBYWEB = $this->file->mailing_limit_sendbyweb;
}
- if (empty($this->global->MAILING_LIMIT_SENDBYWEB)) {
+ if (empty($this->global->MAILING_LIMIT_SENDBYWEB)) { // Limit by web can't be 0
$this->global->MAILING_LIMIT_SENDBYWEB = 25;
}
if (!empty($this->file->mailing_limit_sendbycli)) {
$this->global->MAILING_LIMIT_SENDBYCLI = $this->file->mailing_limit_sendbycli;
}
+ if (!empty($this->file->mailing_limit_sendbyday)) {
+ $this->global->MAILING_LIMIT_SENDBYDAY = $this->file->mailing_limit_sendbyday;
+ }
return 0;
}
diff --git a/htdocs/core/class/dolgraph.class.php b/htdocs/core/class/dolgraph.class.php
index 2fe60cc323c..e24afd73879 100644
--- a/htdocs/core/class/dolgraph.class.php
+++ b/htdocs/core/class/dolgraph.class.php
@@ -1316,7 +1316,7 @@ class DolGraph
if (empty($showlegend)) {
$this->stringtoshow .= 'legend: { display: false }, '."\n";
} else {
- $this->stringtoshow .= 'legend: { maxWidth: '.round($this->width / 2).', labels: { boxWidth: 15 }, position: \'' . ($showlegend == 2 ? 'right' : 'top') . '\' },'."\n";
+ $this->stringtoshow .= 'legend: { maxWidth: '.round(intVal($this->width) / 2).', labels: { boxWidth: 15 }, position: \'' . (($showlegend && $showlegend == 2) ? 'right' : 'top') . '\' },'."\n";
}
$this->stringtoshow .= "}, \n";
diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php
index f2463804e32..c12cfc480fc 100644
--- a/htdocs/core/class/extrafields.class.php
+++ b/htdocs/core/class/extrafields.class.php
@@ -908,7 +908,7 @@ class ExtraFields
$this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
$this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
$this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
- $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms);
+ $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms);
$this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs;
$this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list;
$this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable;
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 68bca2606b7..625791ea0d0 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -3342,7 +3342,6 @@ class Form
}
$outref = $objp->ref;
- $outval = '';
$outbarcode = $objp->barcode;
$outqty = 1;
$outdiscount = 0;
@@ -3523,48 +3522,52 @@ class Form
}
}
- $opt = '\n";
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax
// "label" value of json key array is used by jQuery automatically as text for combo box
- $out .= $opt;
- array_push(
- $outarray,
- array('key'=>$outkey,
- 'value'=>$outref,
- 'label'=>$outval,
- 'qty'=>$outqty,
- 'price_qty_ht'=>price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
- 'price_unit_ht'=>price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
- 'price_ht'=>price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
- 'tva_tx'=>$objp->tva_tx,
- 'default_vat_code'=>$objp->default_vat_code,
- 'discount'=>$outdiscount,
- 'type'=>$outtype,
- 'duration_value'=>$outdurationvalue,
- 'duration_unit'=>$outdurationunit,
- 'disabled'=>(empty($objp->idprodfournprice) ? true : false),
- 'description'=>$objp->description
- )
- );
+ $out .= $optstart . ' data-html="'.dol_escape_htmltag($optlabel).'">' . $optlabel . "\n";;
+ array_push($outarray, $outarrayentry);
+
// Exemple of var_dump $outarray
// array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
// ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php
index 32f2a9b1007..2a900ea53a4 100644
--- a/htdocs/core/class/html.formcompany.class.php
+++ b/htdocs/core/class/html.formcompany.class.php
@@ -825,13 +825,14 @@ class FormCompany extends Form
/**
* showContactRoles on view and edit mode
*
- * @param string $htmlname Html component name and id
- * @param Contact $contact Contact Obejct
- * @param string $rendermode view, edit
- * @param array $selected $key=>$val $val is selected Roles for input mode
- * @return string String with contacts roles
+ * @param string $htmlname Html component name and id
+ * @param Contact $contact Contact Obejct
+ * @param string $rendermode view, edit
+ * @param array $selected $key=>$val $val is selected Roles for input mode
+ * @param string $morecss More css
+ * @return string String with contacts roles
*/
- public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array())
+ public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array(), $morecss = 'minwidth500')
{
if ($rendermode === 'view') {
$toprint = array();
@@ -856,7 +857,7 @@ class FormCompany extends Form
$selected = $newselected;
}
}
- return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, 'minwidth500');
+ return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, $morecss);
}
return 'ErrorBadValueForParameterRenderMode'; // Should not happened
diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php
index df7408200a9..4c77566eeed 100644
--- a/htdocs/core/class/html.formmail.class.php
+++ b/htdocs/core/class/html.formmail.class.php
@@ -954,7 +954,7 @@ class FormMail extends Form
$out .= '';
} else {
if (!isset($this->ckeditortoolbar)) {
- $this->ckeditortoolbar = 'dolibarr_notes';
+ $this->ckeditortoolbar = 'dolibarr_mailings';
}
// Editor wysiwyg
diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php
index 5bee2f31dd4..103b370dcb0 100644
--- a/htdocs/core/class/html.formother.class.php
+++ b/htdocs/core/class/html.formother.class.php
@@ -1513,9 +1513,10 @@ class FormOther
* @param array $search_xaxis Array of preselected fields
* @param array $arrayofxaxis Array of groupby to fill
* @param string $showempty '1' or 'text'
+ * @param string $morecss More css
* @return string HTML string component
*/
- public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1')
+ public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1', $morecss = 'minwidth250 maxwidth500')
{
global $form;
@@ -1523,7 +1524,7 @@ class FormOther
foreach ($arrayofxaxis as $key => $val) {
$arrayofxaxislabel[$key] = $val['label'];
}
- $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth250 maxwidth500', 1);
+ $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1);
return $result;
}
diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php
index 46b885bd60a..c1222a6b762 100644
--- a/htdocs/core/customreports.php
+++ b/htdocs/core/customreports.php
@@ -217,7 +217,7 @@ foreach ($arrayoftype as $key => $val) {
if (dol_eval($val['enabled'], 1, 1, '1')) {
$newarrayoftype[$key] = $arrayoftype[$key];
}
- if ($val['langs']) {
+ if (!empty($val['langs'])) {
$langs->load($val['langs']);
}
}
@@ -450,7 +450,7 @@ $simplearrayofmesures = array();
foreach ($arrayofmesures as $key => $val) {
$simplearrayofmesures[$key] = $arrayofmesures[$key]['label'];
}
-print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth400', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields
+print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth300', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields
print '';
// XAxis
@@ -458,7 +458,7 @@ $count = 0;
print '
';
print '
';
//var_dump($arrayofxaxis);
-print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis")); // Fill the array $arrayofxaxis with possible fields
+print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis"), 'minwidth300 maxwidth400'); // Fill the array $arrayofxaxis with possible fields
print '