diff --git a/.gitignore b/.gitignore index 434764e4f06..a582d0807a3 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ dev/build/node_modules/ node_modules/ vendor/ +php-vendor tmp/ #yarn diff --git a/dev/build/generate_filelist_xml.php b/dev/build/generate_filelist_xml.php index 9f57fbfdd18..5911ed1ed01 100755 --- a/dev/build/generate_filelist_xml.php +++ b/dev/build/generate_filelist_xml.php @@ -272,6 +272,16 @@ $checksumconcat = array(); fputs($fp, ''."\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'); diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index 80b94b047d1..a9a6fdd630e 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -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 diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 8d106a7bd94..f2c11adb4db 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -525,6 +525,29 @@ if ($action == 'delete') { print $formconfirm; } +// Update fields properties in realtime +if (!empty($conf->use_javascript_ajax)) { + print "\n" . '' . "\n"; +} + if ($action == 'create') { print load_fiche_titre($title); @@ -1000,7 +1023,7 @@ if ($action == 'create') { print 'subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'">'; } // Add also input for subledger label - print '
subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">'; + print '
subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">'; print ''; print 'label_operation).'">'; print 'debit)).'">'; @@ -1027,7 +1050,7 @@ if ($action == 'create') { } else { print ''; } - print '
'; + print '
'; print ''; print ''; print ''; diff --git a/htdocs/adherents/class/adherentstats.class.php b/htdocs/adherents/class/adherentstats.class.php index 1afde9322b3..e3ac6a47b5b 100644 --- a/htdocs/adherents/class/adherentstats.class.php +++ b/htdocs/adherents/class/adherentstats.class.php @@ -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,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,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,array{0:int<1,12>,1:int|float}> Array of values by month + * @return array,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, diff --git a/htdocs/adherents/class/api_members.class.php b/htdocs/adherents/class/api_members.class.php index 40a3b69a472..4f7224cc5ee 100644 --- a/htdocs/adherents/class/api_members.class.php +++ b/htdocs/adherents/class/api_members.class.php @@ -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,array{0:int<1,12>,1:int}> Array of nb each month + * @phpstan-return array,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 of nb each year + * @phpstan-return array 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,array{0:int<1,12>,1:int|float}> Array of values by month + * @phpstan-return array,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 + * @phpstan-return array + * + * @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 * diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index cfbf8d0f98c..ebc2deca917 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -134,7 +134,7 @@ $enableremotecheck = true; print '
'; print ''; -print $langs->trans("MakeIntegrityAnalysisFrom").':
'; +print img_picto('', 'search', 'class="pictofixedwidth"').$langs->trans("MakeIntegrityAnalysisFrom").'...

'; print '
'; print ''."\n"; @@ -245,14 +245,52 @@ if (empty($error) && !empty($xml)) { $out .= ''; $out .= ''."\n"; $out .= ''.$langs->trans("Country").''."\n"; - $out .= ''."\n"; + $out .= ''.$langs->trans("YourCountryCode").''."\n"; $out .= ''.$mysoc->country_code.''."\n"; $out .= "\n"; $out .= ''; $out .= ''."\n"; - $out .= ''.$langs->trans("ModuleMustBeEnabled", $langs->transnoentitiesnoconv("BlockedLog")).''."\n"; - $out .= ''.yn(1).''."\n"; - $out .= ''.yn(isModEnabled('blockedlog')).''."\n"; + $out .= ''.$langs->trans("StatusOfModule", $langs->transnoentitiesnoconv("BlockedLog")).''."\n"; + $out .= ''.$langs->trans("Enabled").''."\n"; + $out .= ''; + $out .= isModEnabled('blockedlog') ? ''.$langs->trans("Enabled").'' : ''.$langs->trans("Disabled").''; + + 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 = ''.$langs->trans("LastActivationDate").': '; + 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 .= '
'.$langs->trans("LastActivationAuthor").': '; + $htmltooltip .= $tmpuser->getNomUrl(0, 'nolink', -1, 1); + } + $ip = (empty($tmp['ip']) ? '' : $tmp['ip']); + if ($ip) { + $htmltooltip .= '
'.$langs->trans("LastActivationIP").': '; + $htmltooltip .= $ip; + } + $lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']); + if ($lastactivationversion && $lastactivationversion != 'dolibarr') { + $htmltooltip .= '
'.$langs->trans("LastActivationVersion").': '; + $htmltooltip .= $lastactivationversion; + } + + $out .= $form->textwithpicto('', $htmltooltip); + + $out .= "\n"; $out .= "\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,updated:array} $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 .= '

'.img_picto('', 'tick').' '.$langs->trans($resultcomment).''; + $outcurrentchecksumtext .= img_picto('', 'tick').' '.$langs->trans($resultcomment).''; } else { $resultcode = 'ok'; $resultcomment = 'Success'; $outcurrentchecksum = ''.$checksumget.''; - $outcurrentchecksum.= '

'.img_picto('', 'tick').' '.$langs->trans($resultcomment).''; + $outcurrentchecksumtext.= img_picto('', 'tick').' '.$langs->trans($resultcomment).''; } } else { $resultcode = 'error'; $resultcomment = 'FileIntegrityIsKO'; $outcurrentchecksum = ''.$checksumget.''; - $outcurrentchecksum .= '

'.img_picto('', 'error').' '.$langs->trans($resultcomment).''; + $outcurrentchecksumtext .= img_picto('', 'error').' '.$langs->trans($resultcomment).''; } // Show warning @@ -554,13 +588,27 @@ if (empty($error) && !empty($xml)) { } else { print load_fiche_titre($langs->trans("GlobalChecksum")); } - print $langs->trans("ExpectedChecksum").' = '; + + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + print ''; + print ''; + print '
'.$langs->trans("ExpectedChecksum").''.$langs->trans("CurrentChecksum").'
'; print ''; print $outexpectedchecksum; - print '
'; - print $langs->trans("CurrentChecksum").' = '.$outcurrentchecksum; + print ''; + print '
'; + print $outcurrentchecksum; + print '
'; + print $outcurrentchecksumtext.'
'; - print '

'; + print '
'; print $outforlistoffiles; print '
'; diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php index 154e0148f54..1d4c831c91e 100644 --- a/htdocs/blockedlog/admin/blockedlog_list.php +++ b/htdocs/blockedlog/admin/blockedlog_list.php @@ -431,7 +431,6 @@ $s = $langs->trans("FilesIntegrityDesc", '{s}'); $s = str_replace('{s}', DOL_URL_ROOT.'/admin/system/filecheck.php', $s); print $s; print "
\n"; - print "
\n"; print '
'; @@ -548,7 +547,7 @@ print ''; // Actions code print ''; -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 ''; // Ref diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index 1ce62ce4c9e..7d7c58d756d 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -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"; diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index 18faedc92fa..444cf66ee75 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -714,7 +714,6 @@ if ($id > 0) { $num = $db->num_rows($resql); $i = 0; - $total = 0; print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; @@ -855,7 +854,7 @@ if ($id > 0) { $action = 'presend'; } - if ($action != 'presend') { + if ($action != 'edit' && $action != 'presend') { print '
'; print ''; // ancre diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9b34e0ca967..5a169c17fd5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -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 .= '' . "\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); diff --git a/htdocs/core/class/html.formaccounting.class.php b/htdocs/core/class/html.formaccounting.class.php index 93900c30ae0..3bfe4918ea3 100644 --- a/htdocs/core/class/html.formaccounting.class.php +++ b/htdocs/core/class/html.formaccounting.class.php @@ -1,9 +1,9 @@ - * Copyright (C) 2013-2014 Olivier Geffroy - * Copyright (C) 2015 Ari Elbaz (elarifr) - * Copyright (C) 2016 Marcos García - * Copyright (C) 2016-2024 Alexandre Spangaro +/* Copyright (C) 2013-2016 Florian Henry + * Copyright (C) 2013-2014 Olivier Geffroy + * Copyright (C) 2015 Ari Elbaz (elarifr) + * Copyright (C) 2016 Marcos García + * Copyright (C) 2016-2025 Alexandre Spangaro * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * @@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; class FormAccounting extends Form { /** - * @var array> + * @var array|array>> */ 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 + ); } } diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 5e5ff698d6c..8aa1965e5ad 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -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'; diff --git a/htdocs/core/triggers/dolibarrtriggers.class.php b/htdocs/core/triggers/dolibarrtriggers.class.php index ad8bd1fa159..32b3605a6b3 100644 --- a/htdocs/core/triggers/dolibarrtriggers.class.php +++ b/htdocs/core/triggers/dolibarrtriggers.class.php @@ -1,7 +1,8 @@ * Copyright (C) 2023-2024 William Mead - * Copyright (C) 2024 MDW + * Copyright (C) 2024 MDW + * Copyright (C) 2025 Frédéric France * * 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)); diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index ba135a28511..85cf4c237dd 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -1,6 +1,7 @@ - * Copyright (C) 2017-2018 Laurent Destailleur +/* Copyright (C) 2017 ATM Consulting + * Copyright (C) 2017-2018 Laurent Destailleur + * Copyright (C) 2025 Frédéric France * * 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; diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 51726d5433a..072abb35ae9 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -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. diff --git a/htdocs/install/mysql/migration/22.0.0-23.0.0.sql b/htdocs/install/mysql/migration/22.0.0-23.0.0.sql index 4670d7f0d7a..8bf49e03c25 100644 --- a/htdocs/install/mysql/migration/22.0.0-23.0.0.sql +++ b/htdocs/install/mysql/migration/22.0.0-23.0.0.sql @@ -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 diff --git a/htdocs/install/mysql/tables/llx_oauth_token.sql b/htdocs/install/mysql/tables/llx_oauth_token.sql index a0c769768ff..b7483b1bb7a 100644 --- a/htdocs/install/mysql/tables/llx_oauth_token.sql +++ b/htdocs/install/mysql/tables/llx_oauth_token.sql @@ -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 diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 1e4b61412ce..b98b54e5a86 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -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); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index c4c9c8eccd2..1d39ec42589 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -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 this tool. +FilesIntegrityDesc=If you want to check the integrity of files instead of database, you can do it by using this tool. AttributeCodeHelp=A code of your choice (without special chars and spaces) to identify the property.
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 diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index 76e18c06185..c05b2623c52 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -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 diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index fa1d4d0dada..e9f5c6c670e 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -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 \ No newline at end of file diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 4f0a22138b4..d46bde90c31 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -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); diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 9b10c60149e..2fb73011f70 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -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 */ diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index aa0d59ce6df..c5f27da8e80 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -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 diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 2352365218b..9ae3c7e28da 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -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]; } diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php index 1cd4f21f0bd..5b58f7e9fe4 100644 --- a/htdocs/product/stock/class/api_warehouses.class.php +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -1,6 +1,7 @@ * Copyright (C) 2025 MDW + * Copyright (C) 2025 William Mead * * 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; } diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index 43e849bfbfe..954082decd6 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -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 '
'; diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index b94726695f7..f869305d9e7 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -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')); diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index 543ec1b292f..5eed04f6306 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -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 '
'.$langs->trans("AffectedTo").''; 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 ''.$langs->trans("NoUserAssignedToTheProject").''; } 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 '
'."\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 = ''; diff --git a/htdocs/recruitment/recruitmentjobposition_document.php b/htdocs/recruitment/recruitmentjobposition_document.php index 4abbbc678c0..d77180e6d14 100644 --- a/htdocs/recruitment/recruitmentjobposition_document.php +++ b/htdocs/recruitment/recruitmentjobposition_document.php @@ -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 diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 6edb5adef26..faf1efec99b 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -3,7 +3,7 @@ * Copyright (C) 2019 Josep Lluís Amador * Copyright (C) 2020 Thibault FOUCART * Copyright (C) 2024-2025 MDW - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024-2025 Frédéric France * * 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)) { diff --git a/htdocs/takepos/smpcb.php b/htdocs/takepos/smpcb.php index 2bd67b2487d..308fbc5e4f9 100644 --- a/htdocs/takepos/smpcb.php +++ b/htdocs/takepos/smpcb.php @@ -1,5 +1,6 @@ + * Copyright (C) 2025 Frédéric France * * 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(); diff --git a/htdocs/theme/eldy/btn.inc.php b/htdocs/theme/eldy/btn.inc.php index 40a3a6ae5db..6681248dc28 100644 --- a/htdocs/theme/eldy/btn.inc.php +++ b/htdocs/theme/eldy/btn.inc.php @@ -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