Automated merge from 23.0 to develop

This commit is contained in:
Laurent Destailleur 2026-05-20 17:53:51 +02:00
commit eae494af73
13 changed files with 110 additions and 18 deletions

View file

@ -2361,6 +2361,17 @@ The following changes may create regressions for some external modules, but were
* The load of hook context productdao has been removed before calling loadvirtualstock. Modules must use the context of main parent page or 'all' for all cases.
* booking.class.php was removed, please have a look at calendar.class.php
***** ChangeLog for 18.0.10 compared to 18.0.9 *****
FIX: autofill price with multicurrency on supplier doc (backport commit 391aca5) (#38028)
FIX: calculate the files count on ECM when add multiple files in one time (#31866)
FIX: #GHSA-hq5j-39f9-qxcv (#37812)
FIX: SQL Injection via Operator Injection in Contract Service List
FIX: #GHSA-crgg-h74r-2m8r (#37636)
FIX: do not print Extrafields in PDF if printable is 0
FIX: a param must not come from end user entry.
***** ChangeLog for 18.0.9 compared to 18.0.8 *****
100 files changed, 2283 insertions(+), 591 deletions(-)

View file

@ -237,7 +237,11 @@ if (empty($reshook)) {
$form = new Form($db);
$title = $langs->trans("Categories");
$title .= ' ('.$langs->trans(empty(Categorie::$MAP_TYPE_TITLE_AREA[$type]) ? ucfirst($type) : Categorie::$MAP_TYPE_TITLE_AREA[$type]).')';
if ($type == 'product' || $type == 'service') {
$title .= ' ('.$langs->trans("ProductsOrServices").')';
} else {
$title .= ' ('.$langs->trans(empty(Categorie::$MAP_TYPE_TITLE_AREA[$type]) ? ucfirst($type) : Categorie::$MAP_TYPE_TITLE_AREA[$type]).')';
}
//$help_url = "EN:Module_Categorie|FR:Module_Categorie_FR|ES:Módulo_Categorie";
$help_url = '';
$morejs = array();

View file

@ -95,11 +95,22 @@ if ($resql) {
// Get list of category type
$arrayofcateg = array();
foreach ($categstatic->MAP_ID as $key => $idtype) {
$arrayofcateg[$key] = array();
$arrayofcateg[$key]['key'] = $key;
$arrayofcateg[$key]['nb'] = $countobjects[$idtype] ?? 0;
$arrayofcateg[$key]['label'] = $langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]);
$arrayofcateg[$key]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]));
if ($key == 'product' && !isModEnabled("product")) {
continue;
}
if ($key == 'service' && !isModEnabled("service")) {
continue;
}
$arrayofcateg[$idtype] = array();
$arrayofcateg[$idtype]['key'] = $key;
$arrayofcateg[$idtype]['nb'] = $countobjects[$idtype] ?? 0;
$arrayofcateg[$idtype]['label'] = $langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]);
$arrayofcateg[$idtype]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]));
if ($key == 'product' || $key == 'service') {
$arrayofcateg[$idtype]['label'] = $langs->transnoentitiesnoconv("ProductsAndServices");
$arrayofcateg[$idtype]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv("ProductsAndServices"));
}
}
$arrayofcateg = dol_sort_array($arrayofcateg, 'labelwithoutaccent', 'asc', 1, 0, 1);

View file

@ -7000,6 +7000,8 @@ abstract class CommonObject
switch ($attributeType) {
case 'int':
case 'duration':
case 'stars':
if (!is_numeric($value) && $value != '') {
$this->errors[] = $langs->trans("ExtraFieldHasWrongValue", $attributeLabel);
return -1;
@ -7007,6 +7009,11 @@ abstract class CommonObject
$new_array_options[$key] = null;
}
break;
case 'boolean':
if ($value === '' || $value === false || $value === null) {
$new_array_options[$key] = null;
}
break;
case 'price':
case 'double':
$value = price2num($value);

View file

@ -402,7 +402,7 @@ class modSociete extends DolibarrModules
's.code_compta' => "Text", 's.code_compta_fournisseur' => "Text",
's.client' => "Numeric", 's.fournisseur' => "Numeric",
's.address' => "Text", 's.zip' => "Text", 's.town' => "Text", 's.phone' => "Text", 's.email' => "Text",
't.code' => "List:c_stcomm:libelle:code",
't.code' => "List:c_typent:libelle:code",
'c.entity' => 'List:entity:label:rowid',
's.entity' => 'List:entity:label:rowid',
);

View file

@ -293,11 +293,36 @@ class EcmDirectory extends CommonObject
/**
* Update cache of nb of documents into database
*
* @param string $value '+' or '-' or new number
* @param string $value '+' (one more) or '-' (one less) or new number (like '5') or 'database' (recompute from database)
* @return int Return integer <0 if KO, >0 if OK
*/
public function changeNbOfFiles($value)
{
global $conf;
if ($value == 'database') {
$relativepath = $conf->ecm->dir_output . '/' . $this->getRelativePath(); // Ex: dir1/dir2/dir3/
$relativepath = preg_replace('/^' . preg_quote(DOL_DATA_ROOT, '/') . '/', '', $relativepath);
$relativepath = trim($relativepath, '/');
// Get nb file in relative path
$sql = "SELECT COUNT(*) AS nb";
$sql .= " FROM " . $this->db->prefix() . "ecm_files";
$sql .= " WHERE filepath = '" . $this->db->escape($relativepath) . "'";
dol_syslog(get_class($this) . "::changeNbOfFiles - Get nb file in relative path", LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->error = "Error " . $this->db->lasterror();
return -1;
} else {
$value = 0;
if ($obj = $this->db->fetch_object($resql)) {
$value = (int) $obj->nb;
}
}
}
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX."ecm_directories SET";
if (preg_match('/[0-9]+/', $value)) {

View file

@ -33,6 +33,7 @@
*/
require_once 'version.inc.php'; // Define the DOL_VERSION

View file

@ -6,6 +6,7 @@
* Copyright (C) 2023 Christian Foellmann <christian@foellmann.de>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2026 Serhii Bondarenko <serhiilabs@gmail.com>
*
* 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
@ -29,7 +30,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
/**
* @var Conf $conf
* @var DoliDB $db
@ -37,7 +37,6 @@ require '../../main.inc.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
@ -190,8 +189,14 @@ if ($id > 0 || !empty($ref)) {
print dol_get_fiche_end();
// Contacts lines
include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php';
// Contacts lines (modules that overwrite templates must declare this into descriptor)
$dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl'));
foreach ($dirtpls as $reldir) {
$res = @include dol_buildpath($reldir.'/contacts.tpl.php');
if ($res) {
break;
}
}
} else {
// Contact not found
recordNotFound('', 0);

View file

@ -6,6 +6,7 @@
* Copyright (C) 2021-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2023 Christian Foellmann <christian@foellmann.de>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2026 Serhii Bondarenko <serhiilabs@gmail.com>
*
* 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
@ -273,8 +274,14 @@ if ($id > 0 || !empty($ref)) {
//print '<div class="clearboth"></div>';
//print '<br>';
// Contacts lines
include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php';
// Contacts lines (modules that overwrite templates must declare this into descriptor)
$dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl'));
foreach ($dirtpls as $reldir) {
$res = @include dol_buildpath($reldir.'/contacts.tpl.php');
if ($res) {
break;
}
}
} else {
recordNotFound('', 0);
}

View file

@ -37,5 +37,11 @@ if (empty($context) || !is_object($context)) {
<?php print '<a class="home-links-card__link" href="' . $context->getControllerUrl('invoicelist') . '" title="' . $langs->trans('WebPortalInvoiceListDesc') . '">' . $langs->trans('WebPortalInvoiceListTitle') . '</a>'; ?>
</article>
<?php endif; ?>
<?php if (isModEnabled('member') && in_array(getDolGlobalString('WEBPORTAL_MEMBER_CARD_ACCESS'), ['visible', 'edit']) && $context->logged_member && $context->logged_member->id > 0) : ?>
<article class="home-links-card --membercard">
<div class="home-links-card__icon" ></div>
<?php print '<a class="home-links-card__link" href="' . $context->getControllerUrl('membercard') . '" title="' . $langs->trans('WebPortalMemberCardMenu') . '">' . $langs->trans('WebPortalMemberCardMenu') . '</a>'; ?>
</article>
<?php endif; ?>
</div>
</main>

View file

@ -1498,6 +1498,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
$selectedcustomer = ((GETPOSTISSET('customer') && $action == 'create') ? GETPOSTINT('customer') : $selectedcustomer);
$selectedsupplier = ((GETPOSTISSET('supplier') && $action == 'create') ? GETPOSTINT('supplier') : $object->fournisseur);
if ($selectedprospect && $selectedcustomer && getDolGlobalString("SOCIETE_DISABLE_PROSPECTSCUSTOMERS")) {
// If both are not allowed, we reset $selectedcustomer
$selectedcustomer = 0;
}
print '<tr class="marginbottomlarge height50">';
if ($conf->browser->layout != 'phone') {
print '<td class="titlefieldcreate">'.$form->editfieldkey('', 'customerprospect', '', $object, 0, 'string', '', 0).'</td>';

View file

@ -1678,7 +1678,6 @@ if ($action == 'create') {
}
print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects($projSocFilter, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.((int) $soc->id).'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
print '</td>';
print '</tr>';
}
@ -1953,7 +1952,11 @@ if ($action == 'create') {
if ($action != 'classify') {
$morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
}
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
$canLinkAll = getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS');
$canLinkAll = ($canLinkAll === '' || $canLinkAll === false) ? 0 : $canLinkAll;
$currentSocId = ($object->id > 0) ? $object->socid : $socid;
$projectSocId = ((int) $canLinkAll == 1) ? -1 : $currentSocId;
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $projectSocId, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
} else {
if (!empty($object->fk_project)) {
$proj = new Project($db);

View file

@ -7,6 +7,7 @@
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2026 Serhii Bondarenko <serhiilabs@gmail.com>
*
* 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
@ -190,8 +191,14 @@ if ($id > 0 || !empty($ref)) {
print dol_get_fiche_end();
// Contacts lines
include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php';
// Contacts lines (modules that overwrite templates must declare this into descriptor)
$dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl'));
foreach ($dirtpls as $reldir) {
$res = @include dol_buildpath($reldir.'/contacts.tpl.php');
if ($res) {
break;
}
}
} else {
// Contact not found
print "ErrorRecordNotFound";