Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur
2025-10-17 13:44:54 +02:00
10 changed files with 85 additions and 33 deletions

View File

@@ -3539,7 +3539,7 @@ class BookKeeping extends CommonObject
*/
public function newCloneMass($toselect, $code_journal, $docdate)
{
global $langs;
global $langs, $user;
$error = 0;
$this->db->begin();
@@ -3593,22 +3593,55 @@ class BookKeeping extends CommonObject
if ($bookKeeping->fetch($toselectid)) {
$code_journal = getDolGlobalString('ACCOUNTING_CLONING_ENABLE_INPUT_JOURNAL') ? $code_journal : $bookKeeping->code_journal;
$journal_label = getDolGlobalString('ACCOUNTING_CLONING_ENABLE_INPUT_JOURNAL') ? $accountingJournal->label : $bookKeeping->journal_label;
$sql = "SELECT piece_num, label_operation, numero_compte, label_compte, doc_type, code_journal, fk_user_author, doc_ref, fk_doc, fk_docdet, debit, credit, journal_label, sens, montant ";
$sql .= "FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE rowid = " . ((int) $toselectid);
$sql = "SELECT piece_num, label_operation, numero_compte, label_compte, subledger_account, subledger_label, doc_type, code_journal, fk_user_author, doc_ref, fk_doc, fk_docdet, debit, credit, journal_label, sens, montant";
$sql .= " FROM ".$this->db->prefix()."accounting_bookkeeping WHERE rowid = " . ((int) $toselectid);
$resql = $this->db->query($sql);
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
$docRef = $langs->trans("CloneOf", $obj->doc_ref);
$sql_insert = "INSERT INTO ".$this->db->prefix()."accounting_bookkeeping";
$sql_insert .= " (piece_num, label_operation, numero_compte, label_compte, doc_type, code_journal, doc_date,";
$sql_insert .= " fk_user_author, doc_ref, fk_doc, fk_docdet, debit, credit, journal_label, sens, montant";
$sql_insert = "INSERT INTO ".$this->db->prefix()."accounting_bookkeeping (";
$sql_insert .= " piece_num";
$sql_insert .= ", label_operation";
$sql_insert .= ", numero_compte";
$sql_insert .= ", label_compte";
$sql_insert .= ", subledger_account";
$sql_insert .= ", subledger_label";
$sql_insert .= ", doc_type";
$sql_insert .= ", code_journal";
$sql_insert .= ", doc_date";
$sql_insert .= ", date_creation";
$sql_insert .= ", fk_user_author";
$sql_insert .= ", doc_ref";
$sql_insert .= ", fk_doc";
$sql_insert .= ", fk_docdet";
$sql_insert .= ", debit";
$sql_insert .= ", credit";
$sql_insert .= ", journal_label";
$sql_insert .= ", sens";
$sql_insert .= ", montant";
$sql_insert .= ")";
$sql_insert .= " VALUES (" . ((int) $pieceNumNext) . ", '" . $this->db->escape($obj->label_operation) . "', '" . $this->db->escape($obj->numero_compte) . "',";
$sql_insert .= " '" . $this->db->escape($obj->label_compte) . "', '" . $this->db->escape($obj->doc_type) . "', '" . $this->db->escape($code_journal) . "', '" . $this->db->idate($docdate)."',";
$sql_insert .= " '" . $this->db->escape($obj->fk_user_author) . "', '" . $this->db->escape($docRef) . "', " . ((int) $obj->fk_doc) . ", " . ((int) $obj->fk_docdet) . ",";
$sql_insert .= " " . (float) $obj->debit . ", " . (float) $obj->credit . ", '" . $this->db->escape($journal_label) . "', '" . $this->db->escape($obj->sens) . "', " . (float) $obj->montant;
$sql_insert .= " VALUES (";
$sql_insert .= $pieceNumNext;
$sql_insert .= ", '" . $this->db->escape($obj->label_operation) . "'";
$sql_insert .= ", '" . $this->db->escape($obj->numero_compte) . "'";
$sql_insert .= ", '" . $this->db->escape($obj->label_compte) . "'";
$sql_insert .= ", '" . $this->db->escape($obj->subledger_account) . "'";
$sql_insert .= ", '" . $this->db->escape($obj->subledger_label) . "'";
$sql_insert .= ", ''";
$sql_insert .= ", '" . $this->db->escape($code_journal) . "'";
$sql_insert .= ", '" . $this->db->idate($docdate)."'";
$sql_insert .= ", '" . $this->db->idate($now)."'";
$sql_insert .= ", ".($user->id > 0 ? ((int) $user->id) : "NULL");
$sql_insert .= ", '" . $this->db->escape($docRef) . "'";
$sql_insert .= ", 0";
$sql_insert .= ", 0";
$sql_insert .= ", " . (float) $obj->debit;
$sql_insert .= ", " . (float) $obj->credit;
$sql_insert .= ", '" . $this->db->escape($journal_label) . "'";
$sql_insert .= ", '" . $this->db->escape($obj->sens) . "'";
$sql_insert .= ", " . (float) $obj->montant;
$sql_insert .= ")";
$resqlInsert = $this->db->query($sql_insert);

View File

@@ -997,7 +997,7 @@ class ExternalModules
// Check if there is a known ID
$reg = array();
$id = 0;
if (!empty($package['dolistore-download']) && preg_match('/www\.dolistore\.com\/product\.php\?id=(\d+)/', $package['dolistore-download'], $reg)) {
if (!empty($package['dolistore-download']) && preg_match('/www\.dolistore\.com\/product\.php\?id=(\d+)/', (string) $package['dolistore-download'], $reg)) {
$id = $reg[1];
}

View File

@@ -47,7 +47,9 @@ if ($action == 'setnote_public' && !empty($permissionnote) && !GETPOST('cancel',
$object->fetch($id); // Fetch may not be already done
}
$result_update = $object->update_note(dol_html_entity_decode(GETPOST('note_public', 'restricthtml'), ENT_QUOTES | ENT_HTML5, 'UTF-8', 1), '_public');
$notePublic = GETPOST('note_public', 'restricthtml');
$result_update = $object->update_note(dol_html_entity_decode($notePublic, ENT_QUOTES | ENT_HTML5, 'UTF-8', 1), '_public');
if ($result_update < 0) {
setEventMessages($object->error, $object->errors, 'errors');
@@ -82,10 +84,6 @@ if ($action == 'setnote_public' && !empty($permissionnote) && !GETPOST('cancel',
if ($resultGenDoc < 0) {
setEventMessages($object->error, $object->errors, 'warnings');
}
if ($result < 0) {
dol_print_error($db, $object->error, $object->errors);
}
}
}
} elseif ($action == 'setnote_private' && !empty($permissionnote) && !GETPOST('cancel', 'alpha')) { // Set public note
@@ -97,7 +95,10 @@ if ($action == 'setnote_public' && !empty($permissionnote) && !GETPOST('cancel',
if (empty($object->id)) {
$object->fetch($id); // Fetch may not be already done
}
$result = $object->update_note(dol_html_entity_decode(GETPOST('note_private', 'restricthtml'), ENT_QUOTES | ENT_HTML5, 'UTF-8', 1), '_private');
$notePrivate = GETPOST('note_private', 'restricthtml');
$result = $object->update_note(dol_html_entity_decode($notePrivate, ENT_QUOTES | ENT_HTML5, 'UTF-8', 1), '_private');
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}

View File

@@ -93,7 +93,7 @@ class box_last_knowledgerecord extends ModeleBoxes
if ($user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
$sql = 'SELECT k.rowid as id, k.date_creation, k.ref, k.lang, k.question, k.status as status';
$sql .= " FROM ".MAIN_DB_PREFIX."knowledgemanagement_knowledgerecord as k";
$sql .= " WHERE k.entity IN (".getEntity('knowledgemanagement').")";
$sql .= " WHERE k.entity IN (".getEntity('knowledgerecord').")";
if ($user->socid) {
$sql .= " AND k.fk_soc= ".((int) $user->socid);

View File

@@ -94,7 +94,7 @@ class box_last_modified_knowledgerecord extends ModeleBoxes
$sql = 'SELECT k.rowid as id, k.date_creation, GREATEST(k.tms, kef.tms) as date_modification, k.ref, k.lang, k.question, k.status as status';
$sql .= " FROM ".MAIN_DB_PREFIX."knowledgemanagement_knowledgerecord as k";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."knowledgemanagement_knowledgerecord_extrafields as kef ON kef.fk_object = k.rowid";
$sql .= " WHERE k.entity IN (".getEntity('knowledgemanagement').")";
$sql .= " WHERE k.entity IN (".getEntity('knowledgerecord').")";
if ($user->socid) {
$sql .= " AND k.fk_soc= ".((int) $user->socid);

View File

@@ -83,9 +83,9 @@ class box_last_ticket extends ModeleBoxes
$sql .= " type.label as type_label, category.label as category_label, severity.label as severity_label,";
$sql .= " s.nom as company_name, s.email as socemail, s.client, s.fournisseur";
$sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code = t.type_code AND type.entity = t.entity";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code = t.category_code AND category.entity = t.entity";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code = t.severity_code AND severity.entity = t.entity";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=t.fk_soc";
$sql .= " WHERE t.entity IN (".getEntity('ticket').")";
// $sql.= " AND e.rowid = er.fk_event";

View File

@@ -207,8 +207,12 @@ class DolEditor
$fullpage = false;
// syntax is [] for attributes and {} for value inside style
$extraAllowedContent = 'a[target];';
$extraAllowedContent .= 'section[contenteditable,id];';
$extraAllowedContent .= 'table{border-spacing};';
$extraAllowedContent .= 'td{padding};';
$extraAllowedContent .= 'p{margin-left,margin-right,margin-top,margin-bottom,padding,line-height};';
$extraAllowedContent .= 'div{background-color,color,display,float,height,margin,margin-top,margin-bottom,padding,padding-left,padding-right,padding-top,padding-bottom,width,border-top-left-radius,border-top-right-radius,border-bottom-left-radius,border-bottom-right-radius,box-shadow}';
if (is_string($restrictContent)) {

View File

@@ -9201,6 +9201,12 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
do {
$oldstringtoclean = $out;
$outishtml = 0;
if (dol_textishtml($out)) {
$outishtml = 1;
}
// HTML sanitizer by DOMDocument
if (!empty($out) && getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML') && $check != 'restricthtmlallowunvalid') {
try {
libxml_use_internal_errors(false); // Avoid to fill memory with xml errors
@@ -9217,7 +9223,7 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
// like 'abc' that wrongly ends up, without the trick, with '<p>abc</p>'
// Add also a trick <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"> to solve utf8 lost.
// I don't know what the xml encoding is the trick for
if (dol_textishtml($out)) {
if ($outishtml) {
//$out = '<?xml encoding="UTF-8"><html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body><div class="tricktoremove">'.$out.'</div></body></html>';
$out = '<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body><div class="tricktoremove">' . $out . '</div></body></html>';
//$out = '<html><head><meta charset="utf-8"></head><body><div class="tricktoremove">'.$out.'</div></body></html>';
@@ -9240,6 +9246,10 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
// $out = preg_replace('/^<\?xml encoding="UTF-8"><div class="tricktoremove">/', '', $out);
// $out = preg_replace('/<\/div>$/', '', $out);
// var_dump('rrrrrrrrrrrrrrrrrrrrrrrrrrrrr'.$out);
if (!$outishtml) { // If $out was not HTML content we made before a dol_nl2br so we must do the opposite operation now
$out = str_replace('<br>', '', $out);
}
} catch (Exception $e) {
// If error, invalid HTML string with no way to clean it
//print $e->getMessage();
@@ -9247,8 +9257,10 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
}
}
if (!empty($out) && getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY') && !in_array($check, array('restricthtmlallowunvalid', 'restricthtmlallowlinkscript'))) {
// HTML sanitizer by Tidy
// Tidy can't be used for restricthtmlallowunvalid and restricthtmlallowlinkscript
// Tidy can't be used for non html text content as it is corrupting the new lines fields.
if (!empty($out) && getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY') && !in_array($check, array('restricthtmlallowunvalid', 'restricthtmlallowlinkscript')) && $outishtml) {
// TODO Try to implement a hack for restricthtmlallowlinkscript by renaming tag <link> and <script> ?
try {
//var_dump($out);
@@ -9662,6 +9674,8 @@ function dol_textishtml($msg, $option = 0)
return true; // Html entities names (http://www.w3schools.com/tags/ref_entities.asp)
} elseif (preg_match('/&#[0-9]{2,3};/i', $msg)) {
return true; // Html entities numbers (http://www.w3schools.com/tags/ref_entities.asp)
} elseif (preg_match('/&#x[a-f0-9][a-f0-9];/i', $msg)) {
return true; // Html entities numbers in hexa
}
return false;

View File

@@ -299,9 +299,9 @@ class modKnowledgeManagement extends DolibarrModules
'langs' => 'knowledgemanagement',
'position' => 101,
// Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
'enabled' => '$conf->knowledgemanagement->enabled',
'enabled' => 'isModEnabled("knowledgemanagement")',
// Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules
'perms' => '$user->rights->knowledgemanagement->knowledgerecord->read',
'perms' => '$user->hasRight("knowledgemanagement", "knowledgerecord", "read")',
'target' => '',
// 0=Menu for internal users, 1=external users, 2=both
'user' => 2,
@@ -319,9 +319,9 @@ class modKnowledgeManagement extends DolibarrModules
'langs' => 'knowledgemanagement',
'position' => 111,
// Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
'enabled' => '$conf->knowledgemanagement->enabled',
'enabled' => 'isModEnabled("knowledgemanagement")',
// Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules
'perms' => '$user->rights->knowledgemanagement->knowledgerecord->read',
'perms' => '$user->hasRight("knowledgemanagement", "knowledgerecord", "read")',
'target' => '',
// 0=Menu for internal users, 1=external users, 2=both
'user' => 2,
@@ -339,7 +339,7 @@ class modKnowledgeManagement extends DolibarrModules
'langs' => 'knowledgemanagement',
'position' => 110,
// Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
'enabled' => '$conf->knowledgemanagement->enabled',
'enabled' => 'isModEnabled("knowledgemanagement")',
// Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules
'perms' => '$user->hasRight("knowledgemanagement", "knowledgerecord", "write")',
'target' => '',
@@ -354,8 +354,8 @@ class modKnowledgeManagement extends DolibarrModules
'url' => '/categories/categorie_list.php?type=13',
'langs' => 'knowledgemanagement',
'position' => 112,
'enabled' => '$conf->knowledgemanagement->enabled',
'perms' => '$user->rights->knowledgemanagement->knowledgerecord->read',
'enabled' => 'isModEnabled("knowledgemanagement") && isModenabled("category")',
'perms' => '$user->hasRight("knowledgemanagement", "knowledgerecord", "read")',
'target' => '',
'user' => 0
);

View File

@@ -3709,7 +3709,7 @@ class Product extends CommonObject
$sql .= " WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).") AND f.fk_statut > ".Facture::STATUS_DRAFT." AND fd.fk_product = ".((int) $this->id);
$sql .= " AND EXISTS (SELECT cd.fk_product FROM ".$this->db->prefix()."commandedet as cd WHERE cd.fk_product = fd.fk_product AND cd.fk_commande = c.rowid)"; // We check that the product is in order lines
$sql .= " UNION ";
$sql .= " UNION ALL ";
$sql .= "SELECT sum(".$this->db->ifsql('f.type=2', '-1', '1')." * fd.qty) as count FROM ".$this->db->prefix()."facturedet as fd ";
$sql .= " JOIN ".$this->db->prefix()."facture as f ON fd.fk_facture = f.rowid";