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

This commit is contained in:
Laurent Destailleur
2025-10-22 02:05:18 +02:00
34 changed files with 400 additions and 122 deletions

1
.gitignore vendored
View File

@@ -52,6 +52,7 @@ dev/build/node_modules/
node_modules/
vendor/
php-vendor
tmp/
#yarn

View File

@@ -272,6 +272,16 @@ $checksumconcat = array();
fputs($fp, '<dolibarr_unalterable_files version="'.$release.'">'."\n");
// TODO Use this array to make the scan
$arrayofunalterablefiles = array(
array('dir' => dirname(__FILE__).'/../../htdocs/blockedlog', 'files' => 'all', 'regextoinclude' => '(\.php|\.sql)$', 'regextoexclude' => ''),
array('dir' => dirname(__FILE__).'/../../htdocs/install/mysql/tables', 'files' => 'all', 'regextoinclude' => 'llx_blockedlog.*(\.php|\.sql)$'),
array('dir' => dirname(__FILE__).'/../../htdocs/core/triggers', 'files' => 'interface_50_modBlockedlog_ActionsBlockedLog.class.php'),
array('dir' => dirname(__FILE__).'/../../htdocs/core/class', 'files' => 'interfaces.class.php'),
array('dir' => dirname(__FILE__).'/../../htdocs/core/class', 'files' => 'commontrigger.class.php'),
array('dir' => dirname(__FILE__).'/../../htdocs/takepos', 'files' => 'receipt.php')
);
$regextoinclude = '(\.php|\.sql)$';
$regextoexclude = ''; // Exclude dirs
$files = dol_dir_list(dirname(__FILE__).'/../../htdocs/blockedlog', 'files', 1, $regextoinclude, $regextoexclude, 'fullname');

View File

@@ -16062,24 +16062,12 @@ parameters:
count: 1
path: ../../../htdocs/takepos/send.php
-
message: '#^Variable \$user might not be defined\.$#'
identifier: variable.undefined
count: 1
path: ../../../htdocs/takepos/smpcb.php
-
message: '#^Right side of && is always true\.$#'
identifier: booleanAnd.rightAlwaysTrue
count: 1
path: ../../../htdocs/takepos/split.php
-
message: '#^Variable \$fontlist might not be defined\.$#'
identifier: variable.undefined
count: 3
path: ../../../htdocs/theme/eldy/btn.inc.php
-
message: '#^If condition is always true\.$#'
identifier: if.alwaysTrue

View File

@@ -525,6 +525,29 @@ if ($action == 'delete') {
print $formconfirm;
}
// Update fields properties in realtime
if (!empty($conf->use_javascript_ajax)) {
print "\n" . '<script type="text/javascript">';
print '$(document).ready(function () {
function toggleSubledger() {
var isCentral = $("#accountingaccount_number option:selected").data("centralized");
console.log("the selected general ledger account is centralised?", isCentral);
if (isCentral) {
$("#subledger_account, #subledger_label").prop("disabled", false);
} else {
$("#subledger_account, #subledger_label").prop("disabled", true);
}
}
toggleSubledger();
$("#accountingaccount_number").on("change", toggleSubledger);
$("#accountingaccount_number").on("select2:select", toggleSubledger);
';
print ' });' . "\n";
print ' </script>' . "\n";
}
if ($action == 'create') {
print load_fiche_titre($title);
@@ -1000,7 +1023,7 @@ if ($action == 'create') {
print '<input type="text" class="maxwidth150" name="subledger_account" value="'.(GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'">';
}
// Add also input for subledger label
print '<br><input type="text" class="maxwidth150" name="subledger_label" value="'.(GETPOSTISSET("subledger_label") ? GETPOST("subledger_label", "alpha") : $line->subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">';
print '<br><input type="text" class="maxwidth150" name="subledger_label" id="subledger_label" value="'.(GETPOSTISSET("subledger_label") ? GETPOST("subledger_label", "alpha") : $line->subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">';
print '</td>';
print '<td><input type="text" class="minwidth200" name="label_operation" value="'.(GETPOSTISSET("label_operation") ? GETPOST("label_operation", "alpha") : $line->label_operation).'"></td>';
print '<td class="right"><input type="text" class="right width50" name="debit" value="'.(GETPOSTISSET("debit") ? GETPOST("debit", "alpha") : price($line->debit)).'"></td>';
@@ -1027,7 +1050,7 @@ if ($action == 'create') {
} else {
print '<input type="text" class="maxwidth150" name="subledger_account" value="" placeholder="' . dol_escape_htmltag($langs->trans("SubledgerAccount")) . '">';
}
print '<br><input type="text" class="maxwidth150" name="subledger_label" value="" placeholder="' . dol_escape_htmltag($langs->trans("SubledgerAccountLabel")) . '">';
print '<br><input type="text" class="maxwidth150" name="subledger_label" id="subledger_label" value="" placeholder="' . dol_escape_htmltag($langs->trans("SubledgerAccountLabel")) . '">';
print '</td>';
print '<td><input type="text" class="minwidth200" name="label_operation" value="' . dol_escape_htmltag($label_operation) . '"/></td>';
print '<td class="right"><input type="text" class="right width50" name="debit" value=""/></td>';

View File

@@ -68,11 +68,11 @@ class AdherentStats extends Stats
/**
* Constructor
* Constructor
*
* @param DoliDB $db Database handler
* @param int $socid Id third party
* @param int $userid Id user for filter
* @param DoliDB $db Database handler
* @param int $socid Id third party
* @param int $userid Id user for filter
*/
public function __construct($db, $socid = 0, $userid = 0)
{
@@ -97,11 +97,11 @@ class AdherentStats extends Stats
/**
* Return the number of proposition by month for a given year
* Return the number of members by month for a given year
*
* @param int $year Year
* @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month
* @return array<int<0,11>,array{0:int<1,12>,1:int}> Array of nb each month
* @param int $year Year
* @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month
* @return array<int<0,11>,array{0:int<1,12>,1:int}> Array of nb each month
*/
public function getNbByMonth($year, $format = 0)
{
@@ -136,7 +136,7 @@ class AdherentStats extends Stats
*
* @param int $year Year
* @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month
* @return array<int<0,11>,array{0:int<1,12>,1:int|float}> Array of values by month
* @return array<int<0,11>,array{0:int<1,12>,1:int|float}> Array of values by month
*/
public function getAmountByMonth($year, $format = 0)
{
@@ -375,7 +375,7 @@ class AdherentStats extends Stats
'datem' => $this->db->jdate($objp->datem),
'status' => (int) $objp->status,
'date_end_subscription' => $this->db->jdate($objp->date_end_subscription),
'photo' => $objp->photo,
'photo' => isset($objp->photo) ? (string) $objp->photo : null,
'email' => $objp->email,
'gender' => $objp->gender,
'morphy' => $objp->morphy,

View File

@@ -26,6 +26,7 @@ require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherentstats.class.php';
/**
@@ -44,6 +45,11 @@ class Members extends DolibarrApi
'typeid'
);
/**
* @var AdherentStats
*/
public $memberstats;
/**
* Constructor
*/
@@ -51,6 +57,7 @@ class Members extends DolibarrApi
{
global $db;
$this->db = $db;
$this->memberstats = new AdherentStats($this->db, DolibarrApiAccess::$user->socid, DolibarrApiAccess::$user->id);
}
/**
@@ -982,6 +989,91 @@ class Members extends DolibarrApi
);
}
/**
* Return an array with the number of members by month for a given year
*
* @param int $year Year
* @param int $format 0=Label of abscissa is a translated text
* 1=Label of abscissa is month number
* 2=Label of abscissa is first letter of month
* @return array Array of statistics for last modified members
* @phan-return array<int<0,11>,array{0:int<1,12>,1:int}> Array of nb each month
* @phpstan-return array<int<0,11>,array{0:int<1,12>,1:int}> Array of nb each month
*
* @url GET stats/nbbymonth
* @throws RestException 403 Access denied
*/
public function getNbByMonth($year, $format = 0)
{
if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
throw new RestException(403);
}
return $this->memberstats->getNbByMonth($year, $format);
}
/**
* Return an array with the number of subscriptions by year
*
* @return array Array of statistics for last modified members
* @phan-return array<array{0:int,1:int}> Array of nb each year
* @phpstan-return array<array{0:int,1:int}> Array of nb each year
*
* @url GET stats/nbbyyear
* @throws RestException 403 Access denied
*/
public function getNbByYear()
{
if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
throw new RestException(403);
}
return $this->memberstats->getNbByYear();
}
/**
* Return the number of subscriptions by month for a given year
*
* @param int $year Year
* @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month
* @return array Array of statistics for last modified members
* @phan-return array<int<0,11>,array{0:int<1,12>,1:int|float}> Array of values by month
* @phpstan-return array<int<0,11>,array{0:int<1,12>,1:int|float}> Array of values by month
*
* @url GET stats/amountbymonth
* @throws RestException 403 Access denied
*/
public function getAmountByMonth($year, $format = 0)
{
if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
throw new RestException(403);
}
return $this->memberstats->getAmountByMonth($year, $format);
}
/**
* Last Modified Members
*
* Get an array of statistics for last modified members
*
* @param int $max Max numbers of members
* @return array Array of statistics for last modified members
* @phan-return array<int,array{id:int,ref:string,firstname:string,lastname:string,company:string,fk_soc:?int,datec:int|'',datem:int|'',status:int,date_end_subscription:int|'',photo:null|string,email:string,gender:string,morphy:string,typeid:int,need_subscription:0|1|null,subscription:'0'|'1'|null,label:string}>
* @phpstan-return array<int,array{id:int,ref:string,firstname:string,lastname:string,company:string,fk_soc:?int,datec:int|'',datem:int|'',status:int,date_end_subscription:int|'',photo:null|string,email:string,gender:string,morphy:string,typeid:int,need_subscription:0|1|null,subscription:'0'|'1'|null,label:string}>
*
* @url GET stats/lastmodifiedmembers
* @throws RestException 403 Access denied
*/
public function getLastModifiedMembers($max)
{
if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
throw new RestException(403);
}
return $this->memberstats->getLastModifiedMembers($max);
}
/**
* Validate fields before creating an object
*

View File

@@ -134,7 +134,7 @@ $enableremotecheck = true;
print '<form name="check" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print $langs->trans("MakeIntegrityAnalysisFrom").':<br>';
print img_picto('', 'search', 'class="pictofixedwidth"').$langs->trans("MakeIntegrityAnalysisFrom").'...<br><br>';
print '<div class="divsection">';
print '<!-- for a local check target=local&xmlshortfile=... -->'."\n";
@@ -245,14 +245,52 @@ if (empty($error) && !empty($xml)) {
$out .= '<tr class="oddeven">';
$out .= '<td></td>'."\n";
$out .= '<td>'.$langs->trans("Country").'</td>'."\n";
$out .= '<td class="center"></td>'."\n";
$out .= '<td class="center"><span class="opacitymedium">'.$langs->trans("YourCountryCode").'</span></td>'."\n";
$out .= '<td class="center">'.$mysoc->country_code.'</td>'."\n";
$out .= "</tr>\n";
$out .= '<tr class="oddeven">';
$out .= '<td></td>'."\n";
$out .= '<td>'.$langs->trans("ModuleMustBeEnabled", $langs->transnoentitiesnoconv("BlockedLog")).'</td>'."\n";
$out .= '<td class="center">'.yn(1).'</td>'."\n";
$out .= '<td class="center">'.yn(isModEnabled('blockedlog')).'</td>'."\n";
$out .= '<td>'.$langs->trans("StatusOfModule", $langs->transnoentitiesnoconv("BlockedLog")).'</td>'."\n";
$out .= '<td class="center">'.$langs->trans("Enabled").'</td>'."\n";
$out .= '<td class="center">';
$out .= isModEnabled('blockedlog') ? '<span class="ok">'.$langs->trans("Enabled").'</span>' : '<span class="warning">'.$langs->trans("Disabled").'</span>';
include_once DOL_DOCUMENT_ROOT.'/core/modules/modBlockedLog.class.php';
$objMod = new modBlockedLog($db);
$modulename = $objMod->getName();
$moduledesc = $objMod->getDesc();
$moduleauthor = $objMod->getPublisher();
$moduledir = strtolower(preg_replace('/^mod/i', '', get_class($objMod)));
$const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod)));
$htmltooltip = '<span class="opacitymedium">'.$langs->trans("LastActivationDate").':</span> ';
if (getDolGlobalString($const_name)) {
$htmltooltip .= dol_print_date($objMod->getLastActivationDate(), 'dayhour');
} else {
$htmltooltip .= $langs->trans("Disabled");
}
$tmp = $objMod->getLastActivationInfo();
$authorid = (empty($tmp['authorid']) ? '' : $tmp['authorid']);
if ($authorid > 0) {
$tmpuser = new User($db);
$tmpuser->fetch($authorid);
$htmltooltip .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationAuthor").':</span> ';
$htmltooltip .= $tmpuser->getNomUrl(0, 'nolink', -1, 1);
}
$ip = (empty($tmp['ip']) ? '' : $tmp['ip']);
if ($ip) {
$htmltooltip .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationIP").':</span> ';
$htmltooltip .= $ip;
}
$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']);
if ($lastactivationversion && $lastactivationversion != 'dolibarr') {
$htmltooltip .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationVersion").':</span> ';
$htmltooltip .= $lastactivationversion;
}
$out .= $form->textwithpicto('', $htmltooltip);
$out .= "</td>\n";
$out .= "</tr>\n";
}
@@ -472,8 +510,7 @@ if (empty($error) && !empty($xml)) {
// Scan scripts
/*
if (is_object($xml->dolibarr_script_dir[0]))
{
if (is_object($xml->dolibarr_script_dir[0])) {
$file_list = array();
$ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', ???, $checksumconcat); // Fill array $file_list
'@phan-var-force array{insignature:string[],missing?:array<array{filename:string,expectedmd5:string,expectedsize:string}>,updated:array<array{filename:string,expectedmd5:string,expectedsize:string,md5:string}>} $file_list';
@@ -492,31 +529,28 @@ if (empty($error) && !empty($xml)) {
$nameofsection = 'dolibarr_htdocs_dir_checksum';
$checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum);
}
//var_dump(count($file_list['added']));
//var_dump($checksumget);
//var_dump($checksumtoget);
//var_dump($checksumget == $checksumtoget);
$resultcomment = '';
$outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown"));
$outcurrentchecksumtext = '';
if ($checksumget == $checksumtoget) {
if (empty($onlymodifiedorremoved) && !empty($file_list['added'])) {
$resultcode = 'warning';
$resultcomment = 'FileIntegrityIsOkButFilesWereAdded';
$outcurrentchecksum = $checksumget;
$outcurrentchecksum .= '<br><br>'.img_picto('', 'tick').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
$outcurrentchecksumtext .= img_picto('', 'tick').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
} else {
$resultcode = 'ok';
$resultcomment = 'Success';
$outcurrentchecksum = '<span class="'.$resultcode.'" title="Checksum of all current checksums concatenated separated by a comma">'.$checksumget.'</span>';
$outcurrentchecksum.= '<br><br>'.img_picto('', 'tick').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
$outcurrentchecksumtext.= img_picto('', 'tick').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
}
} else {
$resultcode = 'error';
$resultcomment = 'FileIntegrityIsKO';
$outcurrentchecksum = '<span class="'.$resultcode.'" title="Checksum of all current checksums concatenated separated by a comma">'.$checksumget.'</span>';
$outcurrentchecksum .= '<br><br>'.img_picto('', 'error').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
$outcurrentchecksumtext .= img_picto('', 'error').' <span class="'.$resultcode.'">'.$langs->trans($resultcomment).'</span>';
}
// Show warning
@@ -554,13 +588,27 @@ if (empty($error) && !empty($xml)) {
} else {
print load_fiche_titre($langs->trans("GlobalChecksum"));
}
print $langs->trans("ExpectedChecksum").' = ';
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("ExpectedChecksum").'</td>';
print '<td>'.$langs->trans("CurrentChecksum").'</td>';
print '</tr>'."\n";
print '<tr><td>';
print '<span title="Checksum of all checksums in file separated by a comma and saved into '.$nameofsection.'">';
print $outexpectedchecksum;
print '</span><br>';
print $langs->trans("CurrentChecksum").' = '.$outcurrentchecksum;
print '</span>';
print '</td><td>';
print $outcurrentchecksum;
print '</td>';
print '</tr>';
print '</table>';
print $outcurrentchecksumtext.'<br>';
print '<br><br>';
print '<br>';
print $outforlistoffiles;
print '<br>';

View File

@@ -431,7 +431,6 @@ $s = $langs->trans("FilesIntegrityDesc", '{s}');
$s = str_replace('{s}', DOL_URL_ROOT.'/admin/system/filecheck.php', $s);
print $s;
print "<br>\n";
print "</div>\n";
print '<br>';
@@ -548,7 +547,7 @@ print '</td>';
// Actions code
print '<td class="liste_titre">';
print $form->multiselectarray('search_code', $block_static->trackedevents, $search_code, 0, 0, 'maxwidth200', 1);
print $form->multiselectarray('search_code', $block_static->trackedevents, $search_code, 0, 0, 'maxwidth150', 1);
print '</td>';
// Ref

View File

@@ -431,6 +431,19 @@ if ($action == 'create') {
$(\'#fieldchqemetteur\').val(\'\');
}
}
function toggleSubledger() {
var isCentral = $("#accountancy_code option:selected").data("centralized");
console.log("the selected general ledger account is centralised?", isCentral);
if (isCentral) {
$("#subledger_account").prop("disabled", false);
} else {
$("#subledger_account").prop("disabled", true);
}
}
toggleSubledger();
$("#accountancy_code").on("change", toggleSubledger);
$("#accountancy_code").on("select2:select", toggleSubledger);
';
print ' });'."\n";

View File

@@ -714,7 +714,6 @@ if ($id > 0) {
$num = $db->num_rows($resql);
$i = 0;
$total = 0;
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="noborder paymenttable">';
@@ -855,7 +854,7 @@ if ($id > 0) {
$action = 'presend';
}
if ($action != 'presend') {
if ($action != 'edit' && $action != 'presend') {
print '<div class="fichecenter"><div class="fichehalfleft">';
print '<a name="builddoc"></a>'; // ancre

View File

@@ -2211,7 +2211,7 @@ class Form
global $action;
// If no preselected user defined, we take current user
if ((is_numeric($selected) && ($selected < -3 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
if ((is_numeric($selected) && ($selected < -4 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
$selected = $user->id;
}
@@ -2388,6 +2388,18 @@ class Form
'picto' => ''
);
}
if ($showalso == 4) {
$out .= '<option value="-4"' . ((in_array(-4, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("AllProjectContacts") . ' --</option>' . "\n";
$outarray[-4] = '-- ' . $langs->trans("AllProjectContacts") . ' --';
$outarray2[-4] = array(
'id' => -4,
'label' => '-- ' . $langs->trans("AllProjectContacts") . ' --',
'labelhtml' => '-- ' . $langs->trans("AllProjectContacts") . ' --',
'color' => '',
'picto' => ''
);
}
$userstatic = new User($this->db);

View File

@@ -1,9 +1,9 @@
<?php
/* Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2016-2024 Alexandre Spangaro <aspangaro@easya.solutions>
/* Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2016-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
@@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
class FormAccounting extends Form
{
/**
* @var array<string,array<string,string>>
* @var array<string, array<string, string>|array<string, array<string, mixed>>>
*/
private $options_cache = array();
@@ -457,7 +457,10 @@ class FormAccounting extends Form
$selected = $select_value_out;
}
$options[$select_value_out] = $label;
$options[$select_value_out] = array(
'label' => $label,
'data-centralized' => $obj->centralized ? 1 : 0
);
}
}

View File

@@ -2653,7 +2653,7 @@ function getModuleDirForApiClass($moduleobject)
$moduledirforclass = 'contrat';
} elseif (in_array($moduleobject, array('admin', 'login', 'setup', 'access', 'status', 'tools', 'documents', 'objectlinks'))) {
$moduledirforclass = 'api';
} elseif ($moduleobject == 'contact' || $moduleobject == 'contacts' || $moduleobject == 'customer' || $moduleobject == 'thirdparty' || $moduleobject == 'thirdparties') {
} elseif (in_array($moduleobject, ['contact', 'contacts', 'customer', 'thirdparty', 'thirdparties'])) {
$moduledirforclass = 'societe';
} elseif ($moduleobject == 'propale' || $moduleobject == 'proposals') {
$moduledirforclass = 'comm/propal';
@@ -2661,7 +2661,7 @@ function getModuleDirForApiClass($moduleobject)
$moduledirforclass = 'comm/action';
} elseif ($moduleobject == 'mailing') {
$moduledirforclass = 'comm/mailing';
} elseif ($moduleobject == 'adherent' || $moduleobject == 'members' || $moduleobject == 'memberstypes' || $moduleobject == 'subscriptions') {
} elseif (in_array($moduleobject, ['adherent', 'members', 'memberstypes', 'subscriptions'])) {
$moduledirforclass = 'adherents';
} elseif ($moduleobject == 'don' || $moduleobject == 'donations') {
$moduledirforclass = 'don';

View File

@@ -1,7 +1,8 @@
<?php
/* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2023-2024 William Mead <william.mead@manchenumerique.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* 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
@@ -163,10 +164,10 @@ abstract class DolibarrTriggers
/**
* setErrorsFromObject
*
* @param CommonObject $object Object
* @param CommonObject|BlockedLog $object Object
* @return void
*/
public function setErrorsFromObject(CommonObject $object)
public function setErrorsFromObject($object)
{
if (!empty($object->error)) {
$this->errors = array_merge($this->errors, array($object->error));

View File

@@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
* Copyright (C) 2017-2018 Laurent Destailleur <eldy@users.sourceforge.net>
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
* Copyright (C) 2017-2018 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* 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
@@ -75,7 +76,7 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers
if (!is_object($object) || !property_exists($object, 'element') || !in_array($object->element, $listofqualifiedelement)) {
return 1;
}
/** @var Facture|Don|Paiement|PaymentDonation|Subscription|PaymentVarious|CashControl $object */
dol_syslog("Trigger '".$this->name."' for action '".$action."' launched by ".__FILE__.". id=".$object->id);
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
@@ -104,8 +105,10 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers
if (in_array($action, array(
'MEMBER_SUBSCRIPTION_CREATE', 'MEMBER_SUBSCRIPTION_MODIFY', 'MEMBER_SUBSCRIPTION_DELETE',
'DON_VALIDATE', 'DON_MODIFY', 'DON_DELETE'))) {
/** @var Don|Subscription $object */
$amounts = (float) $object->amount;
} elseif ($action == 'CASHCONTROL_VALIDATE') {
/** @var CashControl $object */
$amounts = (float) $object->cash + (float) $object->cheque + (float) $object->card;
} elseif (property_exists($object, 'total_ttc')) {
$amounts = (float) $object->total_ttc;
@@ -144,16 +147,14 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers
//var_dump($b); exit;
if ($result < 0) {
$this->error = $b->error;
$this->errors = $b->errors;
$this->setErrorsFromObject($b);
return -1;
}
$res = $b->create($user);
$res = $b->create($user); // Insert event in unalterable log. We are in a trigger so inside a global db transaction.
if ($res < 0) {
$this->error = $b->error;
$this->errors = $b->errors;
$this->setErrorsFromObject($b);
return -1;
} else {
return 1;

View File

@@ -29,18 +29,24 @@
/**
* \file htdocs/filefunc.inc.php
* \ingroup core
* \brief File that include conf.php file and commons lib like functions.lib.php
* \brief File that include the conf.php file and commons lib like functions.lib.php
*/
// TODO Move this 2 information into a file that will be included into the LNE
if (!defined('DOL_APPLICATION_TITLE')) {
define('DOL_APPLICATION_TITLE', 'Dolibarr');
}
if (!defined('DOL_VERSION')) {
define('DOL_VERSION', '23.0.0-alpha'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
define('DOL_VERSION', '23.0.0-alpha'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
}
if (!defined('EURO')) {
define('EURO', chr(128));
// End of common declaration part
if (defined('DOL_INC_FOR_VERSION_ERROR')) {
return;
}
if (!defined('CERTIF_LNE')) {
define('CERTIF_LNE', '0'); // Set to 1 if version was certified
}
// Define syslog constants
@@ -58,11 +64,6 @@ if (!defined('LOG_DEBUG')) {
}
}
// End of common declaration part
if (defined('DOL_INC_FOR_VERSION_ERROR')) {
return;
}
/**
* Replace session_start()
@@ -196,23 +197,9 @@ $result = @include_once $conffile; // Keep @ because with some error reporting m
@phan-var-force ?string $dolibarr_lib_TCPDI_PATH
';
// Disable some not used PHP stream
$listofwrappers = stream_get_wrappers();
// We need '.phar' for geoip2. TODO Replace phar in geoip with exploded files so we can disable phar by default.
// phar stream does not auto unserialize content (possible code execution) since PHP 8.1
// zip stream is necessary by excel import module
$arrayofstreamtodisable = array('compress.zlib', 'compress.bzip2', 'ftp', 'ftps', 'glob', 'data', 'expect', 'ogg', 'rar', 'zlib');
if (!empty($dolibarr_main_stream_to_disable) && is_array($dolibarr_main_stream_to_disable)) {
$arrayofstreamtodisable = $dolibarr_main_stream_to_disable;
}
foreach ($arrayofstreamtodisable as $streamtodisable) {
if (!empty($listofwrappers) && in_array($streamtodisable, $listofwrappers)) {
/*if (!empty($dolibarr_main_stream_do_not_disable) && is_array($dolibarr_main_stream_do_not_disable) && in_array($streamtodisable, $dolibarr_main_stream_do_not_disable)) {
continue; // We do not disable this stream
}*/
stream_wrapper_unregister($streamtodisable);
}
}
/*
* Redirect if install not done
*/
if (!$result && !empty($_SERVER["GATEWAY_INTERFACE"])) { // If install not done and we are in a web session
if (!empty($_SERVER["CONTEXT_PREFIX"])) { // CONTEXT_PREFIX and CONTEXT_DOCUMENT_ROOT are not defined on all apache versions
@@ -494,7 +481,7 @@ if (!defined('DOL_DEFAULT_TTF_BOLD')) {
/*
* Include functions
* Decode values read in conf file
*/
// If password is encoded, we decode it. Note: When page is called for install, $dolibarr_main_db_pass may not be defined yet.

View File

@@ -258,6 +258,7 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (5, '5
INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (5, '519', 'gGmbH - gemeinnützige Gesellschaft mit beschränkter Haftung', 1);
INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (5, '520', 'gUG - gemeinnützige Unternehmergesellschaft (haftungsbeschränkt)', 1);
ALTER TABLE llx_oauth_token ADD COLUMN tokenstring_refresh text NULL AFTER tokenstring;
ALTER TABLE llx_oauth_token ADD COLUMN expire_at datetime NULL AFTER lastaccess;
ALTER TABLE llx_blockedlog ADD COLUMN linktoref varchar(255);
@@ -265,4 +266,8 @@ ALTER TABLE llx_blockedlog ADD COLUMN linktype varchar(16);
ALTER TABLE llx_blockedlog ADD COLUMN vat double(24,8) DEFAULT NULL;
-- Fix a wrong migration script
UPDATE llx_oauth_token SET tokenstring = token, token = NULL WHERE service = 'dolibarr_rest_api' AND tokenstring IS NULL AND token IS NOT NULL;
-- end of migration

View File

@@ -20,6 +20,8 @@ CREATE TABLE llx_oauth_token (
service varchar(36), -- What king of key or token: 'Google', 'Stripe', 'auth-public-key', 'api', ...
token text, -- token in serialize format, of an object StdOAuth2Token of library phpoauth2. Deprecated, use tokenstring instead.
tokenstring text, -- token in json or text format. Value depends on 'service'. For example for an OAUTH service: '{"access_token": "sk_test_cccc", "refresh_token": "rt_aaa", "token_type": "bearer", ..., "scope": "read_write"}
tokenstring_refresh text NULL, -- token refresh in text format. Value depends on 'service'.
expire_at datetime NULL,
state text, -- the state (list of permission) the token was obtained if relevant
fk_soc integer, -- Id of thirdparty in llx_societe
fk_user integer, -- Id of user in llx_user
@@ -29,7 +31,6 @@ CREATE TABLE llx_oauth_token (
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
entity integer DEFAULT 1,
lastaccess datetime NULL, -- updated at each api access
expire_at datetime NULL,
apicount_previous_month BIGINT UNSIGNED DEFAULT 0,
apicount_month BIGINT UNSIGNED DEFAULT 0, -- increased by 1 at each page access, saved into pageviews_previous_month when on different month than lastaccess
apicount_total BIGINT UNSIGNED DEFAULT 0 -- increased by 1 at each page access, no reset

View File

@@ -5423,7 +5423,7 @@ function migrate_apiresttokens()
unset($tmpuser->conf); $tmpuser->conf = new stdClass();
$tmpuser->fetch((int) $obj->fk_user, '', '', 1, ($obj->entity ? $obj->entity : $conf->entity));
$sqlforinsert = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, token, fk_user, datec, entity, apicount_total)";
$sqlforinsert = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, tokenstring, fk_user, datec, entity, apicount_total)";
$sqlforinsert .= " VALUES ('".$db->escape($obj->service)."', '".$db->escape(dolEncrypt(dolDecrypt($obj->token)))."', ";
$sqlforinsert .= ((int) $obj->fk_user).", '".$db->idate(dol_now())."', ".((int) $obj->entity).", ";
$sqlforinsert .= getDolUserInt('API_COUNT_CALL', 0, $tmpuser);

View File

@@ -2575,7 +2575,7 @@ TextTranslation=Text translation
ImageGeneration=Image generation
VideoGeneration=Video generation
AudioGeneration=Audio generation
AIPromptForFeatures=AI custom prompts per features (AI service %s)
AIPromptForFeatures=AI custom prompts (AI service %s)
AIModelForFeature=AI model per features (AI service %s)
NewCustomPrompt=New custom prompt
AudioTranscription=Audio transcription
@@ -2662,7 +2662,7 @@ AlgorithmFor=Algorithm for: %s
SensitiveData=Sensitive data
ToolToDecryptAString=Tool to decrypt a string
Decrypt=Decrypt
FilesIntegrityDesc=If you want to check the integrity of files instead of database, you can do it by using <a href="%s">this tool</a>.
FilesIntegrityDesc=If you want to check the integrity of files instead of database, you can do it by using <a href="%s"><span class="fas fa-external-link-alt pictofixedwidth"></span>this tool</a>.
AttributeCodeHelp=A code of your choice (without special chars and spaces) to identify the property.<br>Note that if an object B is created from an existing object A that has a different type (for example creation of an invoice from an order), the value of the complementary attributes of A are also copied into the complementary attributes of B when the code of the attribute is the same.
ThereIsMoreThanXAnswers=There is more than %s answers with your filter. Please add more filters...
PdfAddTermOfSaleHelp=You can upload the file at the bottom of this setup page
@@ -2736,3 +2736,4 @@ ModuleProviderSites=Module providers
StillInDevelopment=Still in development
SeeValueIntoConfPhp=Some sensitive data in database are encrypted using this key. Without it, system backup and restoration is still possible but sensitive data (Tokens, BAN) would remain obfuscated and you will need to regenerate them.
SeeValueIntoConfPhp2=For security purpose, this value can be read from a system user, that have file system access to the conf/conf.php file. If you need a non system backup, without encrypted data, you can use the "export" menu to export your data in clear CSV files.
StatusOfModule=Status of module %s

View File

@@ -1,7 +1,8 @@
BlockedLog=Unalterable Logs
BlockedLogDesc=This module tracks some events into an unalterable log (that you can't modify once recorded) into a block chain, in real time. This module provides compatibility with requirements of laws of some countries (like France with the law Finance 2016 - Norme NF525).
Fingerprints=Archived events and fingerprints
FingerprintsDesc=This is the tool to browse or extract the unalterable logs. Unalterable logs are generated and archived locally into a dedicated table, in real time when you record a business event. You can use this tool to export this archive and save it into an external support (some countries, like France, ask that you do it every year). Note that, there is no feature to purge this log and every change tried to be done directly into this log (by a hacker for example) will be reported with a non-valid fingerprint. If you really need to purge this table because you used your application for a demo/test purpose and want to clean your data to start your production, you can ask your reseller or integrator to reset your database (all your data will be removed).
FingerprintsDesc=This is the tool to browse or extract the unalterable logs. Unalterable logs are generated and archived locally into a dedicated table, in real time when a business event appears. You can use this tool to export this archive and save it into an external support (some countries, like France, ask that you do it at least every year). Note that, there is no feature to purge this log and every change tried to be done directly into this log (by a hacker for example) will be reported with a non-valid fingerprint.
FingerprintsDesc2=If you really need to purge this table because you used your application for a demo/test purpose and want to clean your data to start your production, you can ask your reseller or integrator to reset your database (all your data will be removed).
CompanyInitialKey=Company initial key (hash of genesis block)
BrowseBlockedLog=Unalterable logs
ShowAllFingerPrintsMightBeTooLong=Show all archived unlaterable logs (might be long)
@@ -34,6 +35,7 @@ BlockedLogDisabledBis=System to track events into unalterable logs has been disa
LinkHasBeenDisabledForPerformancePurpose=For performance purpose, direct link to the document is not shown after the 100th line.
SavedOnLine=Saved on line
UnlaterableDataOfEvent=Unalterable data of event
YourCountryCode=Your country code
## logTypes
logBILL_DELETE=Customer invoice logically deleted

View File

@@ -1395,3 +1395,4 @@ NeedHelpCenter=Need support?
Efficiency=Efficiency
AccordingToYourSetupTheFileWillBeConcatenated=According to your setup, the file %s (uploaded in module setup) will be concatenated to any generated PDF
TransactionID=Transaction ID
AllProjectContacts=All project contacts

View File

@@ -42,7 +42,7 @@
//@ini_set('memory_limit', '128M'); // This may be useless if memory is hard limited by your PHP
// For optional tuning. Enabled if environment variable MAIN_SHOW_TUNING_INFO is defined.
$micro_start_time = 0;
$micro_start_time = 0; // Used as global var into printCommonFooter()
if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) {
list($usec, $sec) = explode(" ", microtime());
$micro_start_time = ((float) $usec + (float) $sec);

View File

@@ -62,6 +62,7 @@ require_once 'filefunc.inc.php';
* @var string $dolibarr_main_url_root
* @var string $dolibarr_main_url_root_alt
* @var string $dolibarr_main_document_root_alt
* @var string $dolibarr_main_stream_to_disable
*/
'
@phan-var-force ?string $dolibarr_main_db_prefix
@@ -73,6 +74,7 @@ require_once 'filefunc.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/conf.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
if (!function_exists('is_countable')) {
/**
* function is_countable (to remove when php version supported will be >= 7.3)
@@ -87,6 +89,50 @@ if (!function_exists('is_countable')) {
}
/*
* Define some constants
*/
if (!defined('EURO')) {
define('EURO', chr(128));
}
// Define syslog constants
if (!defined('LOG_DEBUG')) {
if (!function_exists("syslog")) {
// For PHP versions without syslog (like running on Windows OS)
define('LOG_EMERG', 0);
define('LOG_ALERT', 1);
define('LOG_CRIT', 2);
define('LOG_ERR', 3);
define('LOG_WARNING', 4);
define('LOG_NOTICE', 5);
define('LOG_INFO', 6);
define('LOG_DEBUG', 7);
}
}
/*
* Disable some not used PHP stream
*/
$listofwrappers = stream_get_wrappers();
// We need '.phar' for geoip2. TODO Replace phar in geoip with exploded files so we can disable phar by default.
// phar stream does not auto unserialize content (possible code execution) since PHP 8.1
// zip stream is necessary by excel import module
$arrayofstreamtodisable = array('compress.zlib', 'compress.bzip2', 'ftp', 'ftps', 'glob', 'data', 'expect', 'ogg', 'rar', 'zlib');
if (!empty($dolibarr_main_stream_to_disable) && is_array($dolibarr_main_stream_to_disable)) {
$arrayofstreamtodisable = $dolibarr_main_stream_to_disable;
}
foreach ($arrayofstreamtodisable as $streamtodisable) {
if (!empty($listofwrappers) && in_array($streamtodisable, $listofwrappers)) {
/*if (!empty($dolibarr_main_stream_do_not_disable) && is_array($dolibarr_main_stream_do_not_disable) && in_array($streamtodisable, $dolibarr_main_stream_do_not_disable)) {
continue; // We do not disable this stream
}*/
stream_wrapper_unregister($streamtodisable);
}
}
/*
* Create $conf object
*/

View File

@@ -156,7 +156,7 @@ class modMyModule extends DolibarrModules
$this->langfiles = array("mymodule@mymodule");
// Prerequisites
$this->phpmin = array(7, 1); // Minimum version of PHP required by module
$this->phpmin = array(7, 2); // Minimum version of PHP required by module
// $this->phpmax = array(8, 0); // Maximum version of PHP required by module
$this->need_dolibarr_version = array(19, -3); // Minimum version of Dolibarr required by module
// $this->max_dolibarr_version = array(19, -3); // Maximum version of Dolibarr required by module

View File

@@ -2435,7 +2435,8 @@ class Product extends CommonObject
$price_min = $this->multiprices_min[$thirdparty_buyer->price_level];
$price_min_ttc = $this->multiprices_min_ttc[$thirdparty_buyer->price_level];
$price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level];
if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) {
// using this option is a bug. kept for backward compatibility
if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) {
$tva_tx = $this->multiprices_tva_tx[$thirdparty_buyer->price_level];
}

View File

@@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 William Mead <william@m34d.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
@@ -84,20 +85,24 @@ class Warehouses extends DolibarrApi
*
* Get a list of warehouses
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param int $category Use this param to filter list by category
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'WH-%') and (t.date_creation:<:'20160101')"
* @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
* @return array Array of warehouse objects
* @since 4.0.0 Initial implementation
* @since 23.0.0 Data pagination
*
* @param string $sortfield Sort field
* @param string $sortorder Sort order
* @param int $limit Limit for list
* @param int $page Page number
* @param int $category Use this param to filter list by category
* @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'WH-%') and (t.date_creation:<:'20160101')"
* @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
* @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*
* @return array Array of warehouse objects
* @phan-return Entrepot[]
* @phpstan-return Entrepot[]
*
* @throws RestException
*/
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $category = 0, $sqlfilters = '', $properties = '')
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $category = 0, $sqlfilters = '', $properties = '', $pagination_data = false)
{
$obj_ret = array();
@@ -125,6 +130,9 @@ class Warehouses extends DolibarrApi
}
}
//this query will return total warehouses with the filters given
$sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
$sql .= $this->db->order($sortfield, $sortorder);
if ($limit) {
if ($page < 0) {
@@ -152,6 +160,23 @@ class Warehouses extends DolibarrApi
throw new RestException(503, 'Error when retrieve warehouse list : '.$this->db->lasterror());
}
//if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
if ($pagination_data) {
$totalsResult = $this->db->query($sqlTotals);
$total = $this->db->fetch_object($totalsResult)->total;
$tmp = $obj_ret;
$obj_ret = [];
$obj_ret['data'] = $tmp;
$obj_ret['pagination'] = [
'total' => (int) $total,
'page' => $page, //count starts from 0
'page_count' => ceil((int) $total / $limit),
'limit' => $limit
];
}
return $obj_ret;
}

View File

@@ -391,7 +391,21 @@ if ($action == 'createtask' && $user->hasRight('projet', 'creer')) {
$taskid = $task->create($user);
if ($taskid > 0) {
$result = $task->add_contact(GETPOSTINT("userid"), 'TASKEXECUTIVE', 'internal');
$userid = GETPOSTINT("userid");
if ($userid == -4) {
if (empty($object->id)) {
$object->fetch($projectid);
}
$contactlist = array();
foreach (array('internal', 'external') as $source) {
$contactlist = array_merge($contactlist, $object->liste_contact(-1, $source));
}
foreach ($contactlist as $key => $contact) {
$result = $task->add_contact(((int) $contact["id"]), ($contact["code"] == "PROJECTLEADER" ? 'TASKEXECUTIVE' : "TASKCONTRIBUTOR"), $contact["source"]);
}
} else {
$result = $task->add_contact(GETPOSTINT("userid"), 'TASKEXECUTIVE', 'internal');
}
} else {
if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
$langs->load("projects");
@@ -819,12 +833,12 @@ if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object-
print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
print img_picto('', 'user', 'class="pictofixedwidth"');
if (is_array($contactsofproject) && count($contactsofproject)) {
print $form->select_dolusers($user->id, 'userid', 0, null, 0, '', $contactsofproject, '0', 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
print $form->select_dolusers('-4', 'userid', 0, null, 0, '', $contactsofproject, '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
} else {
if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
} else {
print $form->select_dolusers($user->id, 'userid', 0, null, 0, '', '', '0', 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
print $form->select_dolusers('-4', 'userid', 0, null, 0, '', '', '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
}
}
print '</td></tr>';

View File

@@ -809,7 +809,7 @@ if ($id > 0 || !empty($ref)) {
* Generated documents
*/
$subdir = dol_sanitizeFileName($projectstatic->ref)."/".dol_sanitizeFileName($object->ref);
$filedir = $conf->project->multidir_output[$object->entity]."/".$subdir;
$filedir = $conf->project->multidir_output[$object->entity ?? $conf->entity]."/".$subdir;
$urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
$genallowed = ($user->hasRight('projet', 'lire'));
$delallowed = ($user->hasRight('projet', 'creer'));

View File

@@ -111,14 +111,14 @@ if ($reshook < 0) {
if (empty($reshook)) {
$error = 0;
$backurlforlist = dol_buildpath('/recruitment/recruitmentjobposition_list.php', 1);
$backurlforlist = dolBuildUrl(DOL_URL_ROOT.'/recruitment/recruitmentjobposition_list.php');
if (empty($backtopage) || ($cancel && empty($id))) {
if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
$backtopage = $backurlforlist;
} else {
$backtopage = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
$backtopage = dolBuildUrl(DOL_URL_ROOT.'/recruitment/recruitmentjobposition_card.php', ['id' => ((!empty($id) && $id > 0) ? $id : '__ID__')]);
}
}
}
@@ -210,7 +210,7 @@ if ($action == 'create') {
$_POST['fk_user_recruiter'] = $user->id;
}
print dol_get_fiche_head(array(), '');
print dol_get_fiche_head([], '');
print '<table class="border centpercent tableforfieldcreate">'."\n";
@@ -268,7 +268,7 @@ if (($id || $ref) && $action == 'edit') {
// Part to show record
if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
$head = recruitmentjobpositionPrepareHead($object);
print dol_get_fiche_head($head, 'card', $langs->trans("RecruitmentJobPosition"), -1, $object->picto);
print dol_get_fiche_head($head, 'card', $langs->trans("RecruitmentJobPosition"), -1, $object->picto, 0, '', '', 0, '', 1);
$formconfirm = '';

View File

@@ -118,7 +118,7 @@ if ($object->id && $upload_dir !== null) {
*/
$head = recruitmentjobpositionPrepareHead($object);
print dol_get_fiche_head($head, 'document', $langs->trans("RecruitmentJobPosition"), -1, $object->picto);
print dol_get_fiche_head($head, 'document', $langs->trans("RecruitmentJobPosition"), -1, $object->picto, 0, '', '', 0, '', 1);
// Build file list

View File

@@ -3,7 +3,7 @@
* Copyright (C) 2019 Josep Lluís Amador <joseplluis@lliuretic.cat>
* Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* 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
@@ -1354,7 +1354,7 @@ if (isset($_SESSION["takeposterminal"]) && $_SESSION["takeposterminal"]) {
$sql .= " AND active = 1";
$sql .= " ORDER BY libelle";
$resql = $db->query($sql);
$resql = $db->query($sql);
$paiementsModes = array();
if ($resql) {
while ($obj = $db->fetch_object($resql)) {

View File

@@ -1,5 +1,6 @@
<?php
/* Copyright (C) 2020 Andreu Bisquerra Gaya <jove@bisquerra.com>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* 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
@@ -36,6 +37,9 @@ if (!defined('NOREQUIREAJAX')) {
// Load Dolibarr environment
require '../main.inc.php';
/**
* @var User $user
*/
if (!$user->hasRight('takepos', 'run')) {
accessforbidden();

View File

@@ -25,6 +25,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) {
* @var string $butactionbg
* @var string $colortextlink
* @var int $dol_optimize_smallscreen
* @var string $fontlist
* @var string $textbutaction
* @var int<0,max> $nbtopmenuentries
* @var string $right