diff --git a/README.md b/README.md index 4285df41792..3c2b2e0ac43 100644 --- a/README.md +++ b/README.md @@ -262,10 +262,12 @@ See [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) fil Follow Dolibarr project on: -- [Mastodon](https://pouet.chapril.org/@dolibarr) -- [Facebook](https://www.facebook.com/dolibarr) -- [X](https://x.com/dolibarr) - [LinkedIn](https://www.linkedin.com/company/association-dolibarr) +- [Mastodon](https://pouet.chapril.org/@dolibarr) +- [BlueSky](https://bsky.app/profile/dolibarr.org) +- [Threads](https://www.threads.net/@dolibarr) +- [X](https://x.com/dolibarr) +- [Facebook](https://www.facebook.com/dolibarr) - [Reddit](https://www.reddit.com/r/Dolibarr_ERP_CRM/) - [YouTube](https://www.youtube.com/user/DolibarrERPCRM) - [GitHub](https://github.com/Dolibarr/dolibarr) diff --git a/dev/build/generate_filelist_xml.php b/dev/build/generate_filelist_xml.php index d85a9e0bb7c..8fbc5ff777b 100755 --- a/dev/build/generate_filelist_xml.php +++ b/dev/build/generate_filelist_xml.php @@ -151,8 +151,20 @@ if (empty($fp)) { exit(6); } +$gitcommit = 'seetag'; +$branchname = preg_replace('/^(\d+\.\d+)\..*$/', '\1', $release); // Keep only x.y into x.y.z +$fileforgit = dirname(dirname(dirname(__FILE__))).'/.git/refs/heads/'.$branchname; +print "Try to get last commit ID from file ".$fileforgit."\n"; +$fileforgitcontent = file_get_contents($fileforgit); +if (empty($fileforgitcontent)) { + print "Failed to get the last commit ID. Are you on the branch for the release (branch name '.$branchname.') ?\n"; +} +$gitcommit = trim($fileforgitcontent); + fputs($fp, ''."\n"); -fputs($fp, ''."\n"); +fputs($fp, ''."\n"); + +$needtoclose = 0; foreach ($includeconstants as $countrycode => $tmp) { fputs($fp, ''."\n"); @@ -161,7 +173,7 @@ foreach ($includeconstants as $countrycode => $tmp) { $checksumconcat[] = $valueforchecksum; fputs($fp, ' '.$valueforchecksum.''."\n"); } - fputs($fp, ''."\n"); + fputs($fp, ''."\n\n"); } fputs($fp, ''."\n"); @@ -172,7 +184,6 @@ $regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|conf|install| $files = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; -$needtoclose = 0; foreach ($files as $filetmp) { $file = $filetmp['fullname']; //$newdir = str_replace(dirname(__FILE__).'/../htdocs', '', dirname($file)); @@ -180,6 +191,7 @@ foreach ($files as $filetmp) { if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; @@ -193,6 +205,7 @@ foreach ($files as $filetmp) { } if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ''."\n"); @@ -200,7 +213,7 @@ asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); -fputs($fp, ''."\n"); +fputs($fp, ''."\n\n"); // Add the checksum for the part in scripts @@ -213,7 +226,6 @@ $regextoinclude = '\.(php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$'; $regextoexclude = '(custom|documents|conf|install)$'; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../scripts/', 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; -$needtoclose = 0; foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); @@ -221,6 +233,7 @@ foreach ($files as $filetmp) { if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; @@ -234,13 +247,14 @@ foreach ($files as $filetmp) { } if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ''."\n"); asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); -fputs($fp, ''."\n"); +fputs($fp, ''."\n\n"); // Add the checksum for the files into the scope of the unalterable system (record, read, export) @@ -253,7 +267,6 @@ $regextoinclude = '(\.php|\.sql)$'; $regextoexclude = ''; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../htdocs/blockedlog', 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir = ''; -$needtoclose = 0; foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); @@ -261,6 +274,7 @@ foreach ($files as $filetmp) { if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; @@ -274,12 +288,12 @@ foreach ($files as $filetmp) { } if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } // Add the SQL file $regextoinclude = 'llx_blockedlog.*(\.php|\.sql)$'; $regextoexclude = ''; // Exclude dirs $files = dol_dir_list(dirname(__FILE__).'/../../htdocs/install/mysql/tables', 'files', 0, $regextoinclude, $regextoexclude, 'fullname'); -$needtoclose = 0; foreach ($files as $filetmp) { $file = $filetmp['fullname']; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); @@ -287,6 +301,7 @@ foreach ($files as $filetmp) { if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; @@ -297,21 +312,19 @@ foreach ($files as $filetmp) { $checksumconcat[] = $md5; fputs($fp, ' '.$md5.''."\n"); } - if ($needtoclose) { - fputs($fp, ' '."\n"); - } } if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } // Add the trigger file $file = dirname(__FILE__).'/../../htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php'; -$needtoclose = 0; $newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file)); $newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file)); if ($newdir != $dir) { if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ' '."\n"); $dir = $newdir; @@ -324,13 +337,14 @@ if (filetype($file) == "file") { } if ($needtoclose) { fputs($fp, ' '."\n"); + $needtoclose = 0; } fputs($fp, ''."\n"); asort($checksumconcat); // Sort list of checksum fputs($fp, ''."\n"); fputs($fp, md5(join(',', $checksumconcat))."\n"); -fputs($fp, ''."\n"); +fputs($fp, ''."\n\n"); diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index df1b0fc1af4..6da7165d0fe 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1744,7 +1744,7 @@ if ($action == 'create') { print '$(document).ready(function () { $("#projectid").change(function () { var url = "'.DOL_URL_ROOT.'/projet/ajax/projects.php?mode=gettasks&socid="+$("#search_socid").val()+"&projectid="+$("#projectid").val(); - console.log("Call url to get new list of tasks: "+url); + console.log("Call url to get the new list of tasks: "+url); $.get(url, function(data) { console.log(data); if (data) $("#taskid").html(data).select2(); @@ -1765,7 +1765,15 @@ if ($action == 'create') { $tid = GETPOSTISSET("projecttaskid") ? GETPOSTINT("projecttaskid") : (GETPOSTISSET("taskid") ? GETPOSTINT("taskid") : ''); - $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $tid, 'taskid', 24, 0, '1', 1, 0, 0, 'maxwidth500 widthcentpercentminusxx', (string) $projectsListId); + if (empty($projectsListId)) { + print ''; + print ajax_combobox('taskid'); + } else { + print $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $tid, 'taskid', 32, 0, '1', 1, 0, 0, 'maxwidth500 widthcentpercentminusxx', (string) $projectsListId, 'all', null, 1); + } print ''; } @@ -2318,7 +2326,7 @@ if ($id > 0 && $action != 'create') { })'; print ''."\n"; - $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $object->fk_element, 'fk_element', 24, 0, '', 1, 0, 0, 'maxwidth500', (string) $object->fk_project); + print $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $object->fk_element, 'fk_element', 24, 0, '', 1, 0, 0, 'maxwidth500', (string) $object->fk_project, 'all', null, 1); print ''; print ''; @@ -2349,7 +2357,7 @@ if ($id > 0 && $action != 'create') { $tid = GETPOSTINT("taskid"); } - $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $tid, 'taskid', 24, 0, '1', 1, 0, 0, 'maxwidth500 widthcentpercentminusxx', (string) $projectsListId); + print $formproject->selectTasks((!empty($societe->id) ? $societe->id : -1), $tid, 'taskid', 24, 0, '1', 1, 0, 0, 'maxwidth500 widthcentpercentminusxx', (string) $projectsListId, 'all', null, 1); print ''; } else { diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 2d3b9658c5e..8a9e3b7d340 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -52,6 +52,13 @@ require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $MAXAGENDA = getDolGlobalString('AGENDA_EXT_NB', 5); $DELAYFORCACHE = 300; // 300 seconds +$action = GETPOST('action', 'aZ09'); +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$mode = GETPOST('mode', 'aZ09'); +if (empty($mode) && preg_match('/show_/', $action)) { + $mode = $action; // For backward compatibility +} + $disabledefaultvalues = GETPOSTINT('disabledefaultvalues'); $check_holiday = GETPOSTINT('check_holiday'); @@ -68,13 +75,15 @@ if (empty($filtert) && !getDolGlobalString('AGENDA_ALL_CALENDARS')) { $newparam = ''; +// Pagination parameters +$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page"); -if (empty($page) || $page == -1) { +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters $page = 0; -} // If $page is not defined, or '' or -1 -$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; +} $offset = $limit * $page; if (!$sortorder) { $sortorder = "ASC"; @@ -103,12 +112,6 @@ if (!$user->hasRight('agenda', 'allactions', 'read') || $filter == 'mine') { // $filtert = (string) $user->id; } -$action = GETPOST('action', 'aZ09'); - -$mode = GETPOST('mode', 'aZ09'); -if (empty($mode) && preg_match('/show_/', $action)) { - $mode = $action; // For backward compatibility -} $resourceid = GETPOSTINT("search_resourceid"); $year = GETPOSTINT("year") ? GETPOSTINT("year") : date("Y"); $month = GETPOSTINT("month") ? GETPOSTINT("month") : date("m"); @@ -118,7 +121,6 @@ $pid = GETPOSTISSET("search_projectid") ? GETPOSTINT("search_projectid", 3) : GE $status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); // status may be 0, 50, 100, 'todo', 'na' or -1 $type = GETPOSTISSET("search_type") ? GETPOST("search_type", 'aZ09') : GETPOST("type", 'aZ09'); $maxprint = GETPOSTISSET("maxprint") ? GETPOSTINT("maxprint") : getDolGlobalInt('AGENDA_MAX_EVENTS_DAY_VIEW', 3); -$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $dateselect = dol_mktime(0, 0, 0, GETPOSTINT('dateselectmonth'), GETPOSTINT('dateselectday'), GETPOSTINT('dateselectyear')); if ($dateselect > 0) { @@ -191,7 +193,7 @@ if (GETPOST("viewlist", 'alpha') || $mode == 'show_list') { if ($key == 'token') { continue; } - $param .= '&'.$key.'='.urlencode($val); + $param .= '&'.urlencode($key).'='.urlencode($val); } } if (!preg_match('/action=/', $param)) { @@ -209,7 +211,7 @@ if (GETPOST("viewperuser", 'alpha') || $mode == 'show_peruser') { if ($key == 'token') { continue; } - $param .= '&'.$key.'='.urlencode($val); + $param .= '&'.urlencode($key).'='.urlencode($val); } } //print $param; @@ -755,29 +757,41 @@ $sql .= ' a.fk_soc, a.fk_contact, a.fk_project, a.fk_bookcal_calendar,'; $sql .= ' a.fk_element, a.elementtype,'; $sql .= ' ca.code as type_code, ca.libelle as type_label, ca.color as type_color, ca.type as type_type, ca.picto as type_picto'; +// Add fields from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= ' FROM '.MAIN_DB_PREFIX.'c_actioncomm as ca, '.MAIN_DB_PREFIX."actioncomm as a"; +$sqlfields = $sql; // $sql fields to remove for count total + +$sql .= " FROM ".MAIN_DB_PREFIX."c_actioncomm as ca, ".MAIN_DB_PREFIX."actioncomm as a"; // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar"; - $sql .= " ON ar.fk_actioncomm = a.id AND ar.element_type='user'"; - if ($filtert > 0) { - $sql .= " AND ar.fk_element = ".((int) $filtert); +if (($filtert != '-1' && $filtert != '-2') || $usergroup > 0) { + // TODO Replace with a AND EXISTS + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar ON ar.fk_actioncomm = a.id AND ar.element_type = 'user'"; + if ($filtert != '-1' && $filtert != '-2' && $filtert != '-3') { + $sql .= " AND (ar.fk_element IN (".$db->sanitize($filtert).") OR (ar.fk_element IS NULL AND a.fk_user_action = ".((int) $filtert)."))"; // The OR is for backward compatibility + } elseif ($filtert == '-3') { + $sql .= " AND ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; } if ($usergroup > 0) { $sql .= " INNER JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element AND ugu.fk_usergroup = ".((int) $usergroup); } } + // We must filter on resource table if ($resourceid > 0) { $sql .= ", ".MAIN_DB_PREFIX."element_resources as r"; } -$sql .= ' WHERE a.fk_action = ca.id'; -$sql .= ' AND a.entity IN ('.getEntity('agenda').')'; // bookcal is a "virtual view" of agenda + +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +$sql .= " WHERE a.fk_action = ca.id"; +$sql .= " AND a.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda // Condition on actioncode if (!empty($actioncode)) { if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { @@ -794,14 +808,27 @@ if (!empty($actioncode)) { } } } else { - if ($actioncode == 'AC_NON_AUTO') { + if ($actioncode === 'AC_NON_AUTO') { $sql .= " AND ca.type != 'systemauto'"; - } elseif ($actioncode == 'AC_ALL_AUTO') { + } elseif ($actioncode === 'AC_ALL_AUTO') { $sql .= " AND ca.type = 'systemauto'"; - } elseif (/* !empty($actioncode) && */ $actioncode !== '-1') { + } else { if (is_array($actioncode)) { - $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; - } else { + // Remove all -1 values + $actioncode = array_filter( + $actioncode, + /** + * @param string $value + * @return bool + */ + function ($value) { + return ((string) $value !== '-1'); + } + ); + if (count($actioncode)) { + $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; + } + } elseif ($actioncode !== '-1') { $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")"; } } @@ -827,7 +854,7 @@ if ($search_sale && $search_sale != '-1') { } } // Search on socid -if ($socid) { +if ($socid > 0) { $sql .= " AND a.fk_soc = ".((int) $socid); } //var_dump($day.' '.$month.' '.$year); @@ -876,17 +903,6 @@ if ($status == 'done' || $status == '100') { if ($status == 'todo') { $sql .= " AND (a.percent >= 0 AND a.percent < 100)"; } -// We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= " AND ("; - if ($filtert > 0) { - $sql .= "ar.fk_element = ".((int) $filtert); - } - if ($usergroup > 0) { - $sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".((int) $usergroup); - } - $sql .= ")"; -} // Search in categories, -1 is all and -2 is no categories if ($search_categ_cus != -1) { diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 416ba6b69cf..647c1405f63 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -58,14 +58,13 @@ $cancel = GETPOST('cancel', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'actioncommlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); - - -$disabledefaultvalues = GETPOSTINT('disabledefaultvalues'); - $mode = GETPOST('mode', 'aZ09'); if (empty($mode) && preg_match('/show_/', $action)) { $mode = $action; // For backward compatibility } + +$disabledefaultvalues = GETPOSTINT('disabledefaultvalues'); + $resourceid = GETPOSTINT("search_resourceid") ? GETPOSTINT("search_resourceid") : GETPOSTINT("resourceid"); $pid = GETPOSTINT("search_projectid", 3) ? GETPOSTINT("search_projectid", 3) : GETPOSTINT("projectid", 3); $search_status = (GETPOST("search_status", 'aZ09') != '') ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); @@ -120,7 +119,7 @@ $extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // If not choice done on calendar owner, we filter on user. if (empty($filtert) && !getDolGlobalString('AGENDA_ALL_CALENDARS')) { - $filtert = $user->id; + $filtert = (string) $user->id; } // Pagination parameters @@ -163,7 +162,7 @@ if (!$user->hasRight('agenda', 'allactions', 'read')) { $canedit = 0; } if (!$user->hasRight('agenda', 'allactions', 'read') || $filter == 'mine') { // If no permission to see all, we show only affected to me - $filtert = $user->id; + $filtert = (string) $user->id; } $arrayfields = array( @@ -206,7 +205,7 @@ if (GETPOST("viewcal") || GETPOST("viewweek") || GETPOST("viewday")) { $param = ''; if (is_array($_POST)) { foreach ($_POST as $key => $val) { - $param .= '&'.$key.'='.urlencode($val); + $param .= '&'.urlencode($key).'='.urlencode($val); } } //print $param; @@ -332,10 +331,10 @@ if ($search_status != '') { $param .= "&search_status=".urlencode($search_status); } if ($filter) { - $param .= "&search_filter=".urlencode($filter); + $param .= "&search_filter=".urlencode((string) $filter); } if ($filtert) { - $param .= "&search_filtert=".urlencode($filtert); + $param .= "&search_filtert=".urlencode((string) $filtert); } if ($usergroup > 0) { $param .= "&search_usergroup=".urlencode((string) ($usergroup)); @@ -463,11 +462,17 @@ if ($resourceid > 0) { $sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_resources as r ON r.element_type = 'action' AND r.element_id = a.id"; } // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar ON ar.fk_actioncomm = a.id AND ar.element_type='user'"; -} -if ($usergroup > 0) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element"; +if (($filtert != '-1' && $filtert != '-2') || $usergroup > 0) { + // TODO Replace with a AND EXISTS + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar ON ar.fk_actioncomm = a.id AND ar.element_type = 'user'"; + if ($filtert != '' && $filtert != '-1' && $filtert != '-2' && $filtert != '-3') { + $sql .= " AND (ar.fk_element IN (".$db->sanitize($filtert).") OR (ar.fk_element IS NULL AND a.fk_user_action = ".((int) $filtert)."))"; // The OR is for backward compatibility + } elseif ($filtert == '-3') { + $sql .= " AND ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; + } + if ($usergroup > 0) { + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element AND ugu.fk_usergroup = ".((int) $usergroup); + } } // Add table from hooks @@ -475,7 +480,7 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= " WHERE a.entity IN (".getEntity('agenda').")"; +$sql .= " WHERE a.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda // Condition on actioncode if (!empty($actioncode)) { if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { @@ -546,18 +551,18 @@ if ($type) { $sql .= " AND c.id = ".((int) $type); } if ($search_status == '0') { + // To do (not started) $sql .= " AND a.percent = 0"; } if ($search_status == 'na') { + // Not applicable $sql .= " AND a.percent = -1"; -} // Not applicable -if ($search_status == '50') { - $sql .= " AND (a.percent > 0 AND a.percent < 100)"; -} // Running already started -if ($search_status == '100') { - $sql .= " AND a.percent = 100"; } -if ($search_status == 'done') { +if ($search_status == '50') { + // Running already started + $sql .= " AND (a.percent > 0 AND a.percent < 100)"; +} +if ($search_status == 'done' || $search_status == '100') { $sql .= " AND (a.percent = 100)"; } if ($search_status == 'todo') { @@ -572,17 +577,6 @@ if ($search_title) { if ($search_note) { $sql .= natural_search('a.note', $search_note); } -// We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= " AND ("; - if ($filtert > 0) { - $sql .= "(ar.fk_element = ".((int) $filtert)." OR (ar.fk_element IS NULL AND a.fk_user_action = ".((int) $filtert)."))"; // The OR is for backward compatibility - } - if ($usergroup > 0) { - $sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".((int) $usergroup); - } - $sql .= ")"; -} // The second or of next test is to take event with no end date (we suppose duration is 1 hour in such case) if ($dateselect > 0) { diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index f3f6226d43f..ad286058579 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -57,7 +57,7 @@ $action = GETPOST('action', 'aZ09'); $disabledefaultvalues = GETPOSTINT('disabledefaultvalues'); $filter = GETPOST("search_filter", 'alpha', 3) ? GETPOST("search_filter", 'alpha', 3) : GETPOST("filter", 'alpha', 3); -$filtert = GETPOSTINT("search_filtert", 3) ? GETPOSTINT("search_filtert", 3) : GETPOSTINT("filtert", 3); +$filtert = GETPOST("search_filtert", "intcomma", 3) ? GETPOST("search_filtert", "intcomma", 3) : GETPOST("filtert", "intcomma", 3); $usergroup = GETPOSTINT("search_usergroup", 3) ? GETPOSTINT("search_usergroup", 3) : GETPOSTINT("usergroup", 3); //if (! ($usergroup > 0) && ! ($filtert > 0)) $filtert = $user->id; @@ -95,8 +95,7 @@ if ($socid < 0) { $socid = ''; } -// Permissions -$canedit = 1; +$canedit = 1; // can read events of others if (!$user->hasRight('agenda', 'myactions', 'read')) { accessforbidden(); } @@ -104,7 +103,7 @@ if (!$user->hasRight('agenda', 'allactions', 'read')) { $canedit = 0; } if (!$user->hasRight('agenda', 'allactions', 'read') || $filter == 'mine') { // If no permission to see all, we show only affected to me - $filtert = $user->id; + $filtert = (string) $user->id; } $mode = 'show_pertype'; @@ -137,11 +136,11 @@ if ($dateselect > 0) { } // working hours -$tmp = !getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS') ? '9-18' : $conf->global->MAIN_DEFAULT_WORKING_HOURS; +$tmp = getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS', '9-18'); $tmp = str_replace(' ', '', $tmp); // FIX 7533 $tmparray = explode('-', $tmp); -$begin_h = GETPOSTINT('begin_h') != '' ? GETPOSTINT('begin_h') : ($tmparray[0] != '' ? $tmparray[0] : 9); -$end_h = GETPOSTINT('end_h') ? GETPOSTINT('end_h') : ($tmparray[1] != '' ? $tmparray[1] : 18); +$begin_h = GETPOSTISSET('begin_h') ? GETPOSTINT('begin_h') : ($tmparray[0] != '' ? $tmparray[0] : 9); +$end_h = GETPOSTISSET('end_h') ? GETPOSTINT('end_h') : ($tmparray[1] != '' ? $tmparray[1] : 18); if ($begin_h < 0 || $begin_h > 23) { $begin_h = 9; } @@ -196,7 +195,7 @@ $langs->loadLangs(array('users', 'agenda', 'other', 'commercial')); // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $hookmanager->initHooks(array('agenda')); -$result = restrictedArea($user, 'agenda', 0, '', 'myactions'); +$result = restrictedArea($user, 'agenda', 0, 'actioncomm&societe', 'myactions'); if ($user->socid && $socid) { $result = restrictedArea($user, 'societe', $socid); } @@ -283,10 +282,12 @@ if ($status == 'todo') { } $param = ''; -if ($actioncode || GETPOSTISSET('search_actioncode')) { +if (($actioncode && $actioncode !== '-1') || GETPOSTISSET('search_actioncode')) { if (is_array($actioncode)) { foreach ($actioncode as $str_action) { - $param .= "&search_actioncode[]=".urlencode($str_action); + if ($str_action != '-1') { + $param .= "&search_actioncode[]=".urlencode($str_action); + } } } else { $param .= "&search_actioncode=".urlencode($actioncode); @@ -299,7 +300,7 @@ if ($status || GETPOSTISSET('status') || GETPOSTISSET('search_status')) { $param .= "&search_status=".urlencode($status); } if ($filter) { - $param .= "&search_filter=".urlencode($filter); + $param .= "&search_filter=".urlencode((string) $filter); } if ($filtert) { $param .= "&search_filtert=".urlencode((string) $filtert); @@ -310,7 +311,7 @@ if ($usergroup > 0) { if ($socid > 0) { $param .= "&search_socid=".urlencode((string) ($socid)); } -if ($showbirthday) { +if ($showbirthday) { // Always false @phpstan-suppress-current-line $param .= "&search_showbirthday=1"; } if ($pid) { @@ -323,16 +324,16 @@ if ($mode != 'show_pertype') { $param .= '&mode='.urlencode((string) $mode); } if ($begin_h != '') { - $param .= '&begin_h='.urlencode($begin_h); + $param .= '&begin_h='.((int) $begin_h); } if ($end_h != '') { - $param .= '&end_h='.urlencode($end_h); + $param .= '&end_h='.((int) $end_h); } if ($begin_d != '') { - $param .= '&begin_d='.urlencode((string) ($begin_d)); + $param .= '&begin_d='.((int) $begin_d); } if ($end_d != '') { - $param .= '&end_d='.urlencode((string) ($end_d)); + $param .= '&end_d='.((int) $end_d); } $param .= "&maxprint=".urlencode((string) ($maxprint)); @@ -489,7 +490,7 @@ $newcardbutton = ''; if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) { $tmpforcreatebutton = dol_getdate(dol_now('tzuserrel'), true); - $newparam .= '&month='.str_pad($month, 2, "0", STR_PAD_LEFT).'&year='.$tmpforcreatebutton['year']; + $newparam .= '&month='.str_pad((string) $month, 2, "0", STR_PAD_LEFT).'&year='.((int) $tmpforcreatebutton['year']); $urltocreateaction = DOL_URL_ROOT.'/comm/action/card.php?action=create'; $urltocreateaction .= '&apyear='.$tmpforcreatebutton['year'].'&apmonth='.$tmpforcreatebutton['mon'].'&apday='.$tmpforcreatebutton['mday'].'&aphour='.$tmpforcreatebutton['hours'].'&apmin='.$tmpforcreatebutton['minutes']; @@ -524,7 +525,7 @@ $eventarray = array(); // DEFAULT CALENDAR + AUTOEVENT CALENDAR + CONFERENCEBOOTH CALENDAR -$sql = 'SELECT'; +$sql = "SELECT"; if ($usergroup > 0) { $sql .= " DISTINCT"; } @@ -536,20 +537,34 @@ $sql .= ' a.fk_user_author,a.fk_user_action,'; $sql .= ' a.transparency, a.priority, a.fulldayevent, a.location,'; $sql .= ' a.fk_soc, a.fk_contact, a.fk_element, a.elementtype, a.fk_project,'; $sql .= ' ca.code, ca.libelle as type_label, ca.color, ca.type as type_type, ca.picto as type_picto'; + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + $sql .= ' FROM '.MAIN_DB_PREFIX.'c_actioncomm as ca, '.MAIN_DB_PREFIX."actioncomm as a"; // We must filter on resource table if ($resourceid > 0) { $sql .= ", ".MAIN_DB_PREFIX."element_resources as r"; } // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= ", ".MAIN_DB_PREFIX."actioncomm_resources as ar"; +if (($filtert != '-1' && $filtert != '-2') || $usergroup > 0) { + // TODO Replace with a AND EXISTS + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar"; + $sql .= " ON ar.fk_actioncomm = a.id AND ar.element_type = 'user'"; + if ($filtert != '-1' && $filtert != '-2' && $filtert != '-3') { + $sql .= " AND ar.fk_element IN (".$db->sanitize($filtert).")"; + } elseif ($filtert == -3) { + $sql .= " AND ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; + } + if ($usergroup > 0) { + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element AND ugu.fk_usergroup = ".((int) $usergroup); + } } -if ($usergroup > 0) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element"; -} -$sql .= ' WHERE a.fk_action = ca.id'; -$sql .= ' AND a.entity IN ('.getEntity('agenda').')'; + +$sql .= " WHERE a.fk_action = ca.id"; +$sql .= " AND a.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda + // Condition on actioncode if (!empty($actioncode)) { if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { @@ -570,9 +585,16 @@ if (!empty($actioncode)) { $sql .= " AND ca.type != 'systemauto'"; } elseif ($actioncode == 'AC_ALL_AUTO') { $sql .= " AND ca.type = 'systemauto'"; - } else { + } elseif ($actioncode !== '-1' && $actioncode !== '-3') { if (is_array($actioncode)) { - $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; + foreach ($actioncode as $key => $val) { + if ($val == '-1' || $val == '-2') { + unset($actioncode[$key]); + } + } + if (!empty($actioncode)) { + $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; + } } else { $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")"; } @@ -587,7 +609,7 @@ if ($pid) { } // If the internal user must only see his customers, force searching by him $search_sale = 0; -if (!$user->hasRight('societe', 'client', 'voir')) { +if (isModEnabled("societe") && !$user->hasRight('societe', 'client', 'voir')) { $search_sale = $user->id; } // Search on sale representative @@ -602,10 +624,7 @@ if ($search_sale && $search_sale != '-1') { if ($socid) { $sql .= " AND a.fk_soc = ".((int) $socid); } -// We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { - $sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'"; -} + if ($mode == 'show_day') { $sql .= " AND ("; $sql .= " (a.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; @@ -616,7 +635,7 @@ if ($mode == 'show_day') { $sql .= " OR "; $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; $sql .= " AND a.datep2 > '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; - $sql .= ')'; + $sql .= ")"; } else { // To limit array $sql .= " AND ("; @@ -634,6 +653,7 @@ if ($type) { $sql .= " AND ca.id = ".((int) $type); } if ($status == '0') { + // To do (not started) $sql .= " AND a.percent = 0"; } if ($status === 'na') { @@ -651,26 +671,33 @@ if ($status == 'todo') { $sql .= " AND (a.percent >= 0 AND a.percent < 100)"; } // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { +if (($filtert > 0 || $filtert == -3) || $usergroup > 0) { + // TODO Replace with a AND EXISTS $sql .= " AND ("; if ($filtert > 0) { - $sql .= "ar.fk_element = ".$filtert; + $sql .= "ar.fk_element = ".((int) $filtert); + } elseif ($filtert == -3) { + $sql .= "ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; } if ($usergroup > 0) { $sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".((int) $usergroup); } $sql .= ")"; } + // Sort on date -$sql .= ' ORDER BY fk_user_action, datep'; //fk_user_action +$sql .= $db->order("fk_user_action, datep"); + //print $sql; dol_syslog("comm/action/pertype.php", LOG_DEBUG); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); + + $MAXONSAMEPAGE = 10000; // Useless to have more. Protection to avoid memory overload when high number of event (for example after a mass import) $i = 0; - while ($i < $num) { + while ($i < $num && $i < $MAXONSAMEPAGE) { $obj = $db->fetch_object($resql); // Discard auto action if option is on diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index 6b6e3a6134f..4b364d8735f 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -54,19 +54,14 @@ $DELAYFORCACHE = 300; // 300 seconds $disabledefaultvalues = GETPOSTINT('disabledefaultvalues'); +$action = GETPOST('action', 'aZ09'); + $check_holiday = GETPOSTINT('check_holiday'); $filter = GETPOST("search_filter", 'alpha', 3) ? GETPOST("search_filter", 'alpha', 3) : GETPOST("filter", 'alpha', 3); -$filtert = GETPOSTINT("search_filtert", 3) ? GETPOSTINT("search_filtert", 3) : GETPOSTINT("filtert", 3); +$filtert = GETPOST("search_filtert", "intcomma", 3) ? GETPOST("search_filtert", "intcomma", 3) : GETPOST("filtert", "intcomma", 3); $usergroup = GETPOSTINT("search_usergroup", 3) ? GETPOSTINT("search_usergroup", 3) : GETPOSTINT("usergroup", 3); -//if (! ($usergroup > 0) && ! ($filtert > 0)) $filtert = $user->id; -//$showbirthday = empty($conf->use_javascript_ajax)?GETPOST("showbirthday","int"):1; $showbirthday = getDolGlobalInt('AGENDA_ENABLE_SHOW_BIRTHDAY_PER_USER'); // disabled by default -// If no choice done on calendar owner (like on left menu link "Agenda"), we filter on current user by default. -/*if (empty($filtert) && !getDolGlobalString('AGENDA_ALL_CALENDARS')) { - $filtert = (string) $user->id; -}*/ - $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page"); @@ -91,7 +86,7 @@ if ($socid < 0) { $socid = ''; } -$canedit = 1; +$canedit = 1; // can read events of others if (!$user->hasRight('agenda', 'myactions', 'read')) { accessforbidden(); } @@ -102,8 +97,6 @@ if (!$user->hasRight('agenda', 'allactions', 'read') || $filter == 'mine') { // $filtert = (string) $user->id; } -$action = GETPOST('action', 'aZ09'); - $mode = 'show_peruser'; $resourceid = GETPOSTINT("search_resourceid") ? GETPOSTINT("search_resourceid") : GETPOSTINT("resourceid"); $year = GETPOSTINT("year") ? GETPOSTINT("year") : date("Y"); @@ -133,6 +126,7 @@ if ($dateselect > 0) { $year = GETPOSTINT('dateselectyear'); } +// working hours $tmp = getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS', '9-18'); $tmp = str_replace(' ', '', $tmp); // FIX 7533 $tmparray = explode('-', $tmp); @@ -148,6 +142,7 @@ if ($end_h <= $begin_h) { $end_h = $begin_h + 1; } +// working days $tmp = getDolGlobalString('MAIN_DEFAULT_WORKING_DAYS', '1-5'); $tmp = str_replace(' ', '', $tmp); // FIX 7533 $tmparray = explode('-', $tmp); @@ -171,19 +166,22 @@ if (empty($mode) && !GETPOSTISSET('mode')) { $mode = getDolGlobalString('AGENDA_DEFAULT_VIEW', 'show_peruser'); } +// View by month if (GETPOST('viewcal', 'alpha') && $mode != 'show_day' && $mode != 'show_week' && $mode != 'show_peruser') { $mode = 'show_month'; $day = ''; -} // View by month +} +// View by week if (GETPOST('viewweek', 'alpha') || $mode == 'show_week') { $mode = 'show_week'; $week = ($week ? $week : date("W")); $day = ($day ? $day : date("d")); -} // View by week +} +// View by day if (GETPOST('viewday', 'alpha') || $mode == 'show_day') { $mode = 'show_day'; $day = ($day ? $day : date("d")); -} // View by day +} $object = new ActionComm($db); @@ -335,10 +333,12 @@ if ($status == 'todo') { } $param = ''; -if ($actioncode || GETPOSTISSET('search_actioncode')) { +if (($actioncode && $actioncode !== '-1') || GETPOSTISSET('search_actioncode')) { if (is_array($actioncode)) { foreach ($actioncode as $str_action) { - $param .= "&search_actioncode[]=".urlencode($str_action); + if ($str_action != '-1') { + $param .= "&search_actioncode[]=".urlencode($str_action); + } } } else { $param .= "&search_actioncode=".urlencode($actioncode); @@ -531,16 +531,16 @@ if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda' $urltocreateaction = DOL_URL_ROOT.'/comm/action/card.php?action=create'; $urltocreateaction .= '&apyear='.$tmpforcreatebutton['year'].'&apmonth='.$tmpforcreatebutton['mon'].'&apday='.$tmpforcreatebutton['mday'].'&aphour='.$tmpforcreatebutton['hours'].'&apmin='.$tmpforcreatebutton['minutes']; - $urltocreateaction .= '&backtopage='.urlencode($_SERVER["PHP_SELF"] . $newparam); + $urltocreateaction .= '&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam ? '?'.$newparam : '')); $newcardbutton .= dolGetButtonTitle($langs->trans("AddAction"), '', 'fa fa-plus-circle', $urltocreateaction); } -// Define the legend/list of calendard to show -$s = ''; $link = ''; +// Define the legend/list of calendard to show +$s = ''; $showextcals = $listofextcals; $bookcalcalendars = array(); @@ -554,7 +554,7 @@ if (isModEnabled("bookcal")) { $sql .= " WHERE bc.status = 1"; $sql .= " AND ba.status = 1"; $sql .= " AND bc.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda - if (!empty($filtert) && $filtert != '-1') { + if (!empty($filtert) && $filtert != '-1' && $filtert != '-2') { $sql .= " AND bc.visibility IN (".$db->sanitize($filtert, 0, 0, 0, 0).")"; } $resql = $db->query($sql); @@ -677,7 +677,7 @@ $sql .= " a.id, a.label,"; $sql .= " a.datep,"; $sql .= " a.datep2,"; $sql .= " a.percent,"; -$sql .= " a.fk_user_author,a.fk_user_action,"; +$sql .= " a.fk_user_author, a.fk_user_action,"; $sql .= " a.transparency, a.priority, a.fulldayevent, a.location,"; $sql .= " a.fk_soc, a.fk_contact, a.fk_project, a.fk_bookcal_calendar,"; $sql .= " a.fk_element, a.elementtype,"; @@ -692,12 +692,16 @@ $sql .= " FROM ".MAIN_DB_PREFIX."c_actioncomm as ca, ".MAIN_DB_PREFIX."actioncom if ($resourceid > 0) { $sql .= ", ".MAIN_DB_PREFIX."element_resources as r"; } + // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { +if (($filtert != '-1' && $filtert != '-2') || $usergroup > 0) { + // TODO Replace with a AND EXISTS $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar"; - $sql .= " ON ar.fk_actioncomm = a.id AND ar.element_type='user'"; - if ($filtert > 0) { - $sql .= " AND ar.fk_element = ".((int) $filtert); + $sql .= " ON ar.fk_actioncomm = a.id AND ar.element_type = 'user'"; + if ($filtert != '' && $filtert != '-1' && $filtert != '-2' && $filtert != '-3') { + $sql .= " AND ar.fk_element IN (".$db->sanitize($filtert).")"; + } elseif ($filtert == '-3') { + $sql .= " AND ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; } if ($usergroup > 0) { $sql .= " INNER JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element AND ugu.fk_usergroup = ".((int) $usergroup); @@ -706,6 +710,7 @@ if ($filtert > 0 || $usergroup > 0) { $sql .= " WHERE a.fk_action = ca.id"; $sql .= " AND a.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda + // Condition on actioncode if (!empty($actioncode)) { if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { @@ -726,9 +731,16 @@ if (!empty($actioncode)) { $sql .= " AND ca.type != 'systemauto'"; } elseif ($actioncode == 'AC_ALL_AUTO') { $sql .= " AND ca.type = 'systemauto'"; - } elseif (/* !empty($actioncode) && */ $actioncode !== '-1') { + } elseif ($actioncode !== '-1' && $actioncode !== '-3') { if (is_array($actioncode)) { - $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; + foreach ($actioncode as $key => $val) { + if ($val == '-1' || $val == '-2') { + unset($actioncode[$key]); + } + } + if (!empty($actioncode)) { + $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")"; + } } else { $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")"; } @@ -805,10 +817,13 @@ if ($status == 'todo') { $sql .= " AND (a.percent >= 0 AND a.percent < 100)"; } // We must filter on assignment table -if ($filtert > 0 || $usergroup > 0) { +if (($filtert > 0 || $filtert == -3) || $usergroup > 0) { + // TODO Replace with a AND EXISTS $sql .= " AND ("; if ($filtert > 0) { $sql .= "ar.fk_element = ".((int) $filtert); + } elseif ($filtert == -3) { + $sql .= "ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds('hierarchyme'))).")"; } if ($usergroup > 0) { $sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".((int) $usergroup); @@ -1056,8 +1071,8 @@ if ($showbirthday) { // always false @phpstan-ignore-line } } +// LEAVE-HOLIDAY CALENDAR if ($user->hasRight("holiday", "read")) { - // LEAVE-HOLIDAY CALENDAR $sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.statut, x.rowid, x.date_debut as date_start, x.date_fin as date_end, x.halfday, x.statut as status"; $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u"; $sql .= " WHERE u.rowid = x.fk_user"; @@ -1499,6 +1514,7 @@ $link = ''; // Show div with list of calendars print $s; +// Top filters print '
'; print_actions_filter($form, $canedit, $search_status, $year, $month, $day, $showbirthday, '', (string) $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid, $search_categ_cus); print '
'; @@ -1543,13 +1559,13 @@ while ($currentdaytoshow < $lastdaytoshow) { print $langs->trans("DaysOfWeek").''; print "\n"; print '
'; - print ''; + print ''; if (empty($conf->dol_use_jmobile)) { print ' - '; } else { print '
'; } - print ''; + print ''; print '
'; } @@ -1582,13 +1598,13 @@ while ($currentdaytoshow < $lastdaytoshow) { print $langs->trans("Hours").''; print "\n"; print '
'; - print ''; + print ''; if (empty($conf->dol_use_jmobile)) { print ' - '; } else { print '
'; } - print ''; + print ''; if (empty($conf->dol_use_jmobile)) { print ' '.$langs->trans("HourShort"); } @@ -1630,7 +1646,7 @@ while ($currentdaytoshow < $lastdaytoshow) { } } } else { - /* Use this list to have lines for all users */ + /* Use this list to have lines of all users to show */ $sql = "SELECT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity"; $sql .= " FROM ".$db->prefix()."user as u"; if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) { @@ -1661,6 +1677,13 @@ while ($currentdaytoshow < $lastdaytoshow) { // External users should see only contacts of their company $sql .= " AND u.fk_soc = ".((int) $user->socid); } + // Filter on users in hierarchy + if (!$canedit || $filtert == '-3') { // If we can't read event of others + if (!$user->hasRight('user', 'user', 'lire') || $filtert == '-3') { + $usersInHierarchy = $user->getAllChildIds(1); + $sql .= " AND u.rowid IN (".$db->sanitize(implode(',', $usersInHierarchy)).")"; + } + } //print $sql; $resql = $db->query($sql); diff --git a/htdocs/commande/class/orderline.class.php b/htdocs/commande/class/orderline.class.php index 28c5e9851f5..212809062e0 100644 --- a/htdocs/commande/class/orderline.class.php +++ b/htdocs/commande/class/orderline.class.php @@ -37,6 +37,7 @@ */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonorder.class.php'; // Because the CommonOrderLine is still in commonorder.class.php file require_once DOL_DOCUMENT_ROOT.'/margin/lib/margins.lib.php'; @@ -150,6 +151,42 @@ class OrderLine extends CommonOrderLine */ public $packaging; + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array|string,position:int,notnull?:int,visible:int<-6,6>|string,alwayseditable?:int<0,1>,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,csslist?:string,help?:string,showoncombobox?:int<0,4>,disabled?:int<0,1>,arrayofkeyval?:array,autofocusoncreate?:int<0,1>,comment?:string,copytoclipboard?:int<1,2>,validate?:int<0,1>,showonheader?:int<0,1>}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array( + 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10), + 'ref' => array('type' => 'varchar(50)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'showoncombobox' => 1, 'position' => 15, 'searchall' => 1), + 'ref_ext' => array('type' => 'varchar(255)', 'label' => 'RefExt', 'enabled' => 1, 'visible' => 0, 'position' => 20), + 'ref_customer' => array('type' => 'varchar(50)', 'label' => 'RefCustomer', 'enabled' => 1, 'visible' => -1, 'position' => 25, 'searchall' => 1), + 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 30, 'index' => 1), + 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 35), + 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 40), + 'fk_commande' => array('type' => 'integer:Commande:commande/class/commande.class.php', 'label' => 'Order', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 70), + 'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)', 'label' => 'Project', 'enabled' => "isModEnabled('project')", 'visible' => -1, 'position' => 75), + 'fk_product' => array('type' => 'integer:Product:product/class/product.class.php:1', 'label' => 'ProductOrService', 'enabled' => "isModEnabled('product') || isModEnabled('service')", 'visible' => -1, 'position' => 76), + //'fk_commercial_signature' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'SaleRepresentative Signature', 'enabled' => 1, 'visible' => -1, 'position' => 80), + //'fk_commercial_suivi' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'SaleRepresentative follower', 'enabled' => 1, 'visible' => -1, 'position' => 85), + 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 90), + 'total_ht' => array('type' => 'double(24,8)', 'label' => 'TotalHT', 'enabled' => 1, 'visible' => -1, 'position' => 125, 'isameasure' => 1), + 'total_tva' => array('type' => 'double(24,8)', 'label' => 'VAT', 'enabled' => 1, 'visible' => -1, 'position' => 130, 'isameasure' => 1), + 'localtax1' => array('type' => 'double(24,8)', 'label' => 'LocalTax1', 'enabled' => 1, 'visible' => -1, 'position' => 135, 'isameasure' => 1), + 'localtax2' => array('type' => 'double(24,8)', 'label' => 'LocalTax2', 'enabled' => 1, 'visible' => -1, 'position' => 140, 'isameasure' => 1), + 'total_ttc' => array('type' => 'double(24,8)', 'label' => 'TotalTTC', 'enabled' => 1, 'visible' => -1, 'position' => 145, 'isameasure' => 1), + 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 105, 'searchall' => 1), + 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110, 'searchall' => 1), + 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 115), + 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 120), + 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 125), + 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 135), + 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'Last main doc', 'enabled' => 1, 'visible' => -1, 'position' => 140), + 'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'position' => 500, 'notnull' => 1, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', 2 => 'Closed')) + ); + // END MODULEBUILDER PROPERTIES + + /** * Constructor * diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index af7e5fcd76d..00b43fbfe59 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -191,11 +191,11 @@ if (empty($user->socid)) { $checkedtypetiers = 0; $arrayfields = array( // Détail commande - 'rowid' => array('label' => 'TechnicalID', 'checked' => '-1', 'position' => 1, 'enabled' => '1'), - 'pr.ref' => array('label' => 'ProductRef', 'checked' => '1', 'position' => 2), - 'pr.desc' => array('label' => 'ProductDescription', 'checked' => '-1', 'position' => 3), - 'cdet.qty' => array('label' => 'QtyOrdered', 'checked' => '1', 'position' => 4), + 'rowid' => array('label' => 'LineID', 'checked' => '-1', 'position' => 1, 'enabled' => '1'), 'c.ref' => array('label' => "RefOrder", 'checked' => '1', 'position' => 5), + 'pr.ref' => array('label' => 'ProductRef', 'checked' => '1', 'position' => 6), + 'pr.desc' => array('label' => 'ProductDescription', 'checked' => '-1', 'position' => 7), + 'cdet.qty' => array('label' => 'QtyOrdered', 'checked' => '1', 'position' => 8), 'c.ref_client' => array('label' => "RefCustomerOrder", 'checked' => '-1', 'position' => 10), 'p.ref' => array('label' => "ProjectRef", 'checked' => '-1', 'enabled' => (string) (int) isModEnabled('project'), 'position' => 20), 'p.title' => array('label' => "ProjectLabel", 'checked' => '0', 'enabled' => (string) (int) isModEnabled('project'), 'position' => 25), @@ -1032,7 +1032,13 @@ if ($resql) { print ''; print ''; } - // Détail commande + // Ref order + if (!empty($arrayfields['c.ref']['checked'])) { + print ''; + print ''; + print ''; + } + // Product ref if (!empty($arrayfields['pr.ref']['checked'])) { print ''; print ''; @@ -1049,12 +1055,6 @@ if ($resql) { print ''; } - // Ref - if (!empty($arrayfields['c.ref']['checked'])) { - print ''; - print ''; - print ''; - } // Ref customer if (!empty($arrayfields['c.ref_client']['checked'])) { print ''; @@ -1321,11 +1321,14 @@ if ($resql) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); } - // Détail commande + // Detail order if (!empty($arrayfields['rowid']['checked'])) { // @phan-suppress-next-line PhanTypeInvalidDimOffset print_liste_field_titre($arrayfields['rowid']['label'], $_SERVER["PHP_SELF"], 'rowid', '', $param, '', $sortfield, $sortorder); } + if (!empty($arrayfields['c.ref']['checked'])) { + print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); + } if (!empty($arrayfields['pr.ref']['checked'])) { print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); } @@ -1336,9 +1339,6 @@ if ($resql) { print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); } - if (!empty($arrayfields['c.ref']['checked'])) { - print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); - } if (!empty($arrayfields['c.ref_client']['checked'])) { print_liste_field_titre($arrayfields['c.ref_client']['label'], $_SERVER["PHP_SELF"], 'c.ref_client', '', $param, '', $sortfield, $sortorder); } @@ -1611,6 +1611,22 @@ if ($resql) { } } + // Ref order + if (!empty($arrayfields['c.ref']['checked'])) { + print ''; + print $generic_commande->getNomUrl(1, ($search_status != 2 ? 0 : $obj->fk_statut), 0, 0, 0, 1, 1); + + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->commande->multidir_output[$conf->entity].'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; + print $formfile->getDocumentsLink($generic_commande->element, $filename, $filedir); + + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Product Ref if (!empty($arrayfields['pr.ref']['checked'])) { if (!empty($obj->product_rowid)) { @@ -1660,22 +1676,6 @@ if ($resql) { } } - // Ref - if (!empty($arrayfields['c.ref']['checked'])) { - print ''; - print $generic_commande->getNomUrl(1, ($search_status != 2 ? 0 : $obj->fk_statut), 0, 0, 0, 1, 1); - - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->commande->multidir_output[$conf->entity].'/'.dol_sanitizeFileName($obj->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; - print $formfile->getDocumentsLink($generic_commande->element, $filename, $filedir); - - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Ref customer if (!empty($arrayfields['c.ref_client']['checked'])) { print ''.$obj->ref_client.''; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a9187f9f7b7..5b69dd41310 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2140,13 +2140,13 @@ class Form * @param int<0,1>|string $show_empty 0=list with no empty value, 1=add also an empty value into list * @param int[]|null $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled - * @param int[]|''|'hierarchy'|'hierarchyme' $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me + * @param int[]|''|'hierarchy'|'hierarchyme' $include Array list of users id to include. Use '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me * @param int[]|'' $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled * @param string $force_entity '0' or list of Ids of environment to force, separated by a comma, or 'default' = do no extend to all entities allowed to superadmin. * @param int $maxlength Maximum length of string into list (0=no limit) * @param int<-1,1> $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request (Example: '(employee:=:1)'). This value must not come from user input. - * @param int<0,1> $show_every 0=default list, 1=add also a value "Everybody" at beginning of list + * @param int<0,3> $showalso 0=default list, 1=add also a value "Everybody" at beginning of list, 2=add also a value "My team" at beginning of list (if user has at least 1 people), 3=add also "Everybody" + "My Team" * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty. * @param string $morecss More css * @param int<0,1> $notdisabled Show only active users (note: this will also happen, whatever is this option, if USER_HIDE_INACTIVE_IN_COMBOBOX is on). @@ -2156,14 +2156,14 @@ class Form * @return string|array HTML select string * @see select_dolgroups() */ - public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0) + public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $showalso = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0) { // phpcs:enable global $conf, $user, $langs, $hookmanager; global $action; // If no preselected user defined, we take current user - if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) { + if ((is_numeric($selected) && ($selected < -3 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) { $selected = $user->id; } @@ -2173,23 +2173,38 @@ class Form $selected = array($selected); } + // Exclude some users in $excludeUsers string $excludeUsers = null; - $includeUsers = null; - - // Exclude some users if (is_array($exclude)) { $excludeUsers = implode(",", $exclude); } - // Include some uses + + // Include some users in $includeUsers string + $includeUsers = null; + $includeUsersArray = array(); if (is_array($include)) { - $includeUsers = implode(",", $include); + $includeUsersArray = $include; } elseif ($include == 'hierarchy') { - // Build list includeUsers to have only hierarchy - $includeUsers = implode(",", $user->getAllChildIds(0)); + // Build list includeUsersArray to have only hierarchy + $includeUsersArray = $user->getAllChildIds(0); } elseif ($include == 'hierarchyme') { - // Build list includeUsers to have only hierarchy and current user - $includeUsers = implode(",", $user->getAllChildIds(1)); + // Build list includeUsersArray to have only hierarchy and current user + $includeUsersArray = $user->getAllChildIds(1); } + // Get list of allowed users + /* We do not limit list of users. Because we should limit this only for combo list into HR features where we may be allowed to + * see all other users and element in other. For example in agenda, we can have permission to read all event of otherusers. + * So we disable this. + if (!$user->hasRight('user', 'user', 'lire')) { + if (empty($includeUsersArray)) { + $includeUsers = implode(",", $user->getAllChildIds(1)); + } else { + $includeUsers = implode(",", array_intersect($includeUsersArray, $user->getAllChildIds(1))); + } + } else { + $includeUsers = implode(",", $includeUsersArray); + } */ + $includeUsers = implode(",", $includeUsersArray); $num = 0; @@ -2297,7 +2312,23 @@ class Form 'picto' => '' ); } - if ($show_every) { + if ($showalso == 2 || $showalso == 3) { + $out .= '' . "\n"; + + $hasAtLeastOneSubordinate = (count($user->getAllChildIds(1)) > 1); + if ($hasAtLeastOneSubordinate) { + //$sql = "SELECT rowid FROM".MAIN_DB_PREFIX."user " + $outarray[-3] = '-- ' . $langs->trans("MyTeam") . ' --'; + $outarray2[-3] = array( + 'id' => -3, + 'label' => '-- ' . $langs->trans("MyTeam") . ' --', + 'labelhtml' => '-- ' . $langs->trans("MyTeam") . ' --', + 'color' => '', + 'picto' => '' + ); + } + } + if ($showalso == 1 || $showalso == 3) { $out .= '' . "\n"; $outarray[-2] = '-- ' . $langs->trans("Everybody") . ' --'; diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index dea64295d9e..5030ba106b7 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -400,7 +400,7 @@ class FormProjets extends Form } if (empty($option_only)) { - $out .= ''."\n"; } if (!empty($show_empty)) { $out .= ''; + $out .= ''."\n"; } $num = $this->db->num_rows($resql); @@ -486,7 +486,7 @@ class FormProjets extends Form $out .= ''."\n"; } else { if ($hideunselectables && $disabled && ($selected != $obj->rowid)) { $resultat = ''; @@ -500,7 +500,7 @@ class FormProjets extends Form $resultat .= ' data-html="' . dol_escape_htmltag($labeltoshowhtml) . '"'; $resultat .= '>'; $resultat .= $labeltoshow; - $resultat .= ''; + $resultat .= ''."\n"; } $out .= $resultat; } @@ -509,7 +509,7 @@ class FormProjets extends Form } } if (empty($option_only)) { - $out .= ''; + $out .= ''."\n"; } $this->nboftasks = $num; diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index f6a3b9bdd6a..2ce92a511de 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -162,11 +162,12 @@ $arrayoftype = array( 'thirdparty' => array('langs' => 'companies', 'label' => 'ThirdParties', 'picto' => 'company', 'ObjectClassName' => 'Societe', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/societe/class/societe.class.php"), 'contact' => array('label' => 'Contacts', 'picto' => 'contact', 'ObjectClassName' => 'Contact', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/contact/class/contact.class.php"), 'proposal' => array('label' => 'Proposals', 'picto' => 'proposal', 'ObjectClassName' => 'Propal', 'enabled' => isModEnabled('propal'), 'ClassPath' => "/comm/propal/class/propal.class.php"), - 'order' => array('label' => 'Orders', 'picto' => 'order', 'ObjectClassName' => 'Commande', 'enabled' => isModEnabled('order'), 'ClassPath' => "/commande/class/commande.class.php"), + 'order' => array('langs' => 'orders', 'label' => 'Orders', 'picto' => 'order', 'ObjectClassName' => 'Commande', 'enabled' => isModEnabled('order'), 'ClassPath' => "/commande/class/commande.class.php"), + 'orderdet' => array('langs' => 'orders', 'label' => 'SaleOrderLines', 'picto' => 'order', 'ObjectClassName' => 'OrderLine', 'enabled' => isModEnabled('order'), 'ClassPath' => "/commande/class/orderline.class.php"), 'invoice' => array('langs' => 'facture', 'label' => 'Invoices', 'picto' => 'bill', 'ObjectClassName' => 'Facture', 'enabled' => isModEnabled('invoice'), 'ClassPath' => "/compta/facture/class/facture.class.php"), 'invoice_template' => array('label' => 'PredefinedInvoices', 'picto' => 'bill', 'ObjectClassName' => 'FactureRec', 'enabled' => isModEnabled('invoice'), 'ClassPath' => "/compta/class/facturerec.class.php", 'langs' => 'bills'), - 'contract' => array('label' => 'Contracts', 'picto' => 'contract', 'ObjectClassName' => 'Contrat', 'enabled' => isModEnabled('contract'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs' => 'contracts'), - 'contractdet' => array('label' => 'ContractLines', 'picto' => 'contract', 'ObjectClassName' => 'ContratLigne', 'enabled' => isModEnabled('contract'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs' => 'contracts'), + 'contract' => array('langs' => 'contracts', 'label' => 'Contracts', 'picto' => 'contract', 'ObjectClassName' => 'Contrat', 'enabled' => isModEnabled('contract'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs' => 'contracts'), + 'contractdet' => array('langs' => 'contracts', 'label' => 'ContractLines', 'picto' => 'contract', 'ObjectClassName' => 'ContratLigne', 'enabled' => isModEnabled('contract'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs' => 'contracts'), 'bom' => array('label' => 'BOM', 'picto' => 'bom', 'ObjectClassName' => 'Bom', 'enabled' => isModEnabled('bom')), 'mrp' => array('label' => 'MO', 'picto' => 'mrp', 'ObjectClassName' => 'Mo', 'enabled' => isModEnabled('mrp'), 'ClassPath' => "/mrp/class/mo.class.php"), 'ticket' => array('label' => 'Ticket', 'picto' => 'ticket', 'ObjectClassName' => 'Ticket', 'enabled' => isModEnabled('ticket')), @@ -210,6 +211,7 @@ if ($objecttype) { if ($fileforclass !== null) { dol_include_once($fileforclass); + $ObjectClassName = $arrayoftype[$objecttype]['ObjectClassName']; } if (!empty($ObjectClassName)) { @@ -636,7 +638,7 @@ if (!defined('MAIN_CUSTOM_REPORT_KEEP_GRAPH_ONLY')) { print '
'; print '
'.$langs->trans("StatisticsOn").'
'; - print $form->selectarray('objecttype', $newarrayoftype, $objecttype, 0, 0, 0, '', 1, 0, 0, '', 'minwidth200', 1, '', 0, 1); + print $form->selectarray('objecttype', $newarrayoftype, $objecttype, 0, 0, 0, '', 1, 0, 0, '', 'minwidth250', 1, '', 0, 1); if (empty($conf->use_javascript_ajax)) { print ''; } else { diff --git a/htdocs/core/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index f6ceda1516b..3d3ea0f90d1 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -104,7 +104,7 @@ function print_actions_filter( // Assigned to user print '
'; print img_picto($langs->trans("ActionsToDoBy"), 'user', 'class="pictofixedwidth inline-block"'); - print $form->select_dolusers($filtert, 'search_filtert', 1, null, (int) !$canedit, '', '', '0', 0, 0, '', 0, '', 'minwidth100 maxwidth250 widthcentpercentminusx'); + print $form->select_dolusers($filtert, 'search_filtert', 1, null, (int) !$canedit, '', '', '0', 0, 0, '', 2, '', 'minwidth100 maxwidth250 widthcentpercentminusx'); print '
'; // Assigned to user group diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 74078dc325d..d4ceb2c5586 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1528,7 +1528,6 @@ function dol_include_once($relpath, $classname = '') dol_syslog('functions::dol_include_once Tried to load unexisting file: '.$relpath, LOG_WARNING); return false; } - if (!empty($classname) && !class_exists($classname)) { return include $fullpath; } else { diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index bf2edf45f95..29b5334d860 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -205,7 +205,7 @@ $enabledtypetiers = 0; $arrayfields = array( 'u.login' => array('label' => "AuthorRequest", 'enabled' => '1', 'position' => 41), 's.name_alias' => array('label' => "AliasNameShort", 'position' => 51, 'checked' => '0'), - 's.town' => array('label' => "Town", 'enabled' => '1', 'position' => 55, 'checked' => '1'), + 's.town' => array('label' => "Town", 'enabled' => '1', 'position' => 55, 'checked' => '0'), 's.zip' => array('label' => "Zip", 'enabled' => '1', 'position' => 56, 'checked' => '1'), 'state.nom' => array('label' => "StateShort", 'enabled' => '1', 'position' => 57), 'country.code_iso' => array('label' => "Country", 'enabled' => '1', 'position' => 58), diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php index c08dcdff5f7..82731acd31d 100644 --- a/htdocs/hrm/index.php +++ b/htdocs/hrm/index.php @@ -274,7 +274,7 @@ if (isModEnabled('holiday') && $user->hasRight('holiday', 'read')) { print ''.$userstatic->getNomUrl(-1, 'leave').''; $leavecode = empty($typeleaves[$obj->fk_type]) ? 'Undefined' : $typeleaves[$obj->fk_type]['code']; - print ''.dol_escape_htmltag($langs->trans($leavecode)).''; + print ''.dol_escape_htmltag($langs->trans($leavecode)).''; $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning'; $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon'; diff --git a/htdocs/install/mysql/data/llx_00_c_country.sql b/htdocs/install/mysql/data/llx_00_c_country.sql index e0f0f2e4caf..7a7dabb8d0f 100644 --- a/htdocs/install/mysql/data/llx_00_c_country.sql +++ b/htdocs/install/mysql/data/llx_00_c_country.sql @@ -49,7 +49,7 @@ INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUE INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (18, 'HU', 'HUN', 'Hungary', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (19, 'RU', 'RUS', 'Russia', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (20, 'SE', 'SWE', 'Sweden', 1, 0); -INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (21, 'CI', 'CIV', 'Côte d''Ivoire', 1, 0); +INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (21, 'CI', 'CIV', 'Ivory Cost', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (22, 'SN', 'SEN', 'Senegal', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (23, 'AR', 'ARG', 'Argentina', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (24, 'CM', 'CMR', 'Cameroun', 1, 0); @@ -91,12 +91,12 @@ INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUE INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (61, 'BI', 'BDI', 'Burundi', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (62, 'KH', 'KHM', 'Cambodge / Cambodia', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (63, 'CV', 'CPV', 'Cap-Vert', 1, 0); -INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (64, 'KY', 'CYM', 'Iles Cayman', 1, 0); +INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (64, 'KY', 'CYM', 'Cayman Island', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (65, 'CF', 'CAF', 'Central African Republic (CAR/RCA)', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (66, 'TD', 'TCD', 'Tchad', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (67, 'CL', 'CHL', 'Chile', 1, 0); -INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (68, 'CX', 'CXR', 'Ile Christmas', 1, 0); -INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (69, 'CC', 'CCK', 'Iles des Cocos (Keeling)', 1, 0); +INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (68, 'CX', 'CXR', 'Christmas Island', 1, 0); +INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (69, 'CC', 'CCK', 'Cocos Islands (Keeling)', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (70, 'CO', 'COL', 'Colombie', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (71, 'KM', 'COM', 'Comores', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (72, 'CG', 'COG', 'Congo', 1, 0); @@ -137,7 +137,7 @@ INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUE INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (108, 'GN', 'GIN', 'Guinea', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (109, 'GW', 'GNB', 'Guinea-Bissao', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (111, 'HT', 'HTI', 'Haiti', 1, 0); -INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (112, 'HM', 'HMD', 'Iles Heard et McDonald', 1, 0); +INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (112, 'HM', 'HMD', 'Heard Island and McDonald Islands', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (113, 'VA', 'VAT', 'Vatican City (Saint-Siège)', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (114, 'HN', 'HND', 'Honduras', 1, 0); INSERT INTO llx_c_country (rowid, code, code_iso, label, active, favorite) VALUES (115, 'HK', 'HKG', 'Hong Kong', 1, 0); @@ -536,4 +536,3 @@ UPDATE llx_c_country SET eec = 1 WHERE code IN ('AT','BE','BG','CY','CZ','DE','D -- Set field sepa UPDATE llx_c_country SET sepa = 1 WHERE code IN ('AD','AT','BE','BG','CH','CY','CZ','DE','DK','EE','ES','FI','FR','GR','HR','HU','IE','IT','LT','LU','LV','MC','MT','NL','PL','PT','RO','SE','SI','SK','SM','VA'); - diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 0830888bb94..5883c494205 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -589,6 +589,8 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ $afterversionarray = explode('.', '21.0.9'); $beforeversionarray = explode('.', '22.0.9'); if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + dol_syslog("Run migrate_... versionto is between ".json_encode($afterversionarray)." and ".json_encode($beforeversionarray)); + migrate_accountingbookkeeping($entity); } } diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 2ba130ee389..645d43bd91c 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -441,7 +441,7 @@ AccountRemovedFromGroup=Account removed from group SaleLocal=Local sale SaleExport=Export sale SaleEEC=Sale in EEC -SaleEECWithVAT=Sale is in EEC with a VAT not null, so we suppose this is NOT an intracommunautary sale and the suggested account is the standard product account. +SaleEECWithVAT=Sale is in EEC with a VAT not null, so we suppose this is NOT an intra-community sale and the suggested account is the standard product account. SaleEECWithoutVATNumber=Sale is in EEC with no VAT but the VAT ID of third party is not defined. We fall back on the account for standard sales. You can fix the VAT ID of the third party, or change the product account suggested for binding if needed. AnySale=Any sale ForbiddenTransactionAlreadyExported=Forbidden: The transaction has been validated and/or exported. @@ -486,7 +486,7 @@ AccountancyClosureConfirmClose=Are you sure you want to close the current fiscal AccountancyClosureConfirmAccountingReversal=Are you sure you want to record entries for the "Retained earnings" ? ## Warning -WarningBookkeepingRecordAlreadyExists=Transaction for (doc_type=%s, doc_id=%s, doc_det=%s) were already recorded +WarningBookkeepingRecordAlreadyExists=Transaction for (doc_type=%s, doc_id=%s, doc_det=%s) has already been recorded ## Error SomeMandatoryStepsOfSetupWereNotDone=Some mandatory steps of setup was not done, please complete them @@ -509,7 +509,7 @@ ErrorNoFiscalPeriodActiveFound=No active fiscal period (with a start and end dat ErrorBookkeepingDocDateNotOnActiveFiscalPeriod=The bookkeeping doc date is not inside the active fiscal period ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod=The bookkeeping doc date is inside a closed fiscal period Error_BOOKKEEPING_ADDON_NotDefined=Error, the rule for bookkeeping numbering ref is not defined into general setup of Accountancy module -ErrorBookkeepingTryInsertNotBalancedTransactionAndCanceled=Try to insert a non balanced transaction in book for %s (Payment ID: %s). Canceled. Surely a bug. +ErrorBookkeepingTryInsertNotBalancedTransactionAndCanceled=You tried to insert a non balanced transaction in the book for %s (Payment ID: %s). Action is canceled ProductUsage=Product or service usage ## Import ImportAccountingEntries=Accounting entries @@ -538,15 +538,15 @@ ExpenseReportJournal=Expense Report Journal DocsAlreadyExportedAreIncluded=Docs already exported are included ClickToShowAlreadyExportedLines=Click to show already exported lines NAccounts=%s accounts -ACCOUNTING_USE_TREASURY_Desc=This is the mode for treasury accountancy. We are using the payments only and their date for doing the accountancy. -ACCOUNTING_USE_NON_TREASURY_Desc=This is the mode for real accountancy. We are using both the invoices and payments for doing the accountancy. +ACCOUNTING_USE_NON_TREASURY_Desc=This is the method for accrual accounting (known as "real" or "complete"). We use all the information (sales and purchase invoices, expense reports, bank, etc.) to generate the accounting. +ACCOUNTING_USE_TREASURY_Desc=This is the cash accounting method. We only use payments and their dates to generate the accounting. Check with your accounting firm to see if you are eligible for this accounting method. PieceDesc=The reference of the source document that generates this bank transaction (Invoice Ref, Expense report ref, ...) BankTransactionRef=A reference for the bank transaction (Optional, an automatic ID is already generated) ## Mass Actions ConfirmMassCloneBookkeepingWritingQuestion=This will clone the bookkeeping entry (all lines linked to this bookkeeping entry will be cloned). Are you sure you want to clone the selected %s records? ConfirmMassCloneBookkeepingWriting=Confirm mass cloning -ConfirmMassReturnAccountBookkeepingWriting=Confirm mass extinction -ConfirmMassReturnAccountBookkeepingWritingQuestion=This will extinguish the bookkeeping entry (all lines linked to this bookkeeping entry will be extinguished). Are you sure you want to bypass the %s selected records? +ConfirmMassReturnAccountBookkeepingWriting=Confirm mass reversal +ConfirmMassReturnAccountBookkeepingWritingQuestion=This will create reversal entries for the selected bookkeeping records (all lines linked to these records will be reversed: debit and credit will be swapped, and a reversal operation will be recorded). Are you sure you want to perform this reversal for the %s selected records? ConfirmMassAssignAccountBookkeepingWritingQuestion=This will change the account of all selected lines. confirmMassAssignAccountBookkeepingWritingConfirm=Confirm mass account change CloningSuccess=Successful transaction cloning : %s @@ -561,6 +561,6 @@ NoAccountsChangedWithAccountNumber=Transactions not updated with account numbers HasAlreadyBeenReversed=has already been reversed ErrorWhileCreating=Error during creation %s ReturnAccount=Return -Clone=Cloner +Clone=Clone AlreadyReturnedAccount=Entry n°%s has already been reversed SuccessReturnedAccount=Entry n°%s has been reversed diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index f5f21c2a867..a3303805451 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1517,7 +1517,7 @@ WatermarkOnDraftInvoices=Watermark on draft invoices (none if empty) PaymentsNumberingModule=Payments numbering model SuppliersPayment=Vendor payments SupplierPaymentSetup=Vendor payments setup -InvoiceCheckPosteriorDate=The invoice date must be more recent than the date of the last invoice of the same type +InvoiceCheckPosteriorDate=The invoice date must the same or later to the date of the last invoice of the same type InvoiceCheckPosteriorDateHelp=Validating an invoice will be forbidden if its date is anterior to the date of last invoice of same type. InvoiceOptionCategoryOfOperations=Display the mention "category of operations" on the invoice. InvoiceOptionCategoryOfOperationsHelp=Depending on the situation, the mention will appear in the form:
- Category of operations: Delivery of goods
- Category of operations: Provision of services
- Category of operations: Mixed - Delivery of goods & provision of services diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 3cc40227cef..881ff1a9a48 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -691,6 +691,6 @@ InputValueIsNotAnNumber=Input value is not a number LimitDepositInvoicePossibilityForConsistency=Limit deposit invoice type to keep consistencies between lines (from proposals or orders) ExtPaymentID=External payment ID ExtPaymentSite=External payment Site -CantConvertToReducAnInvoiceOfThisType=Cant convert to discount an invoice of this type +CantConvertToReducAnInvoiceOfThisType=Can't convert to discount an invoice of this type WithholdingTax=Withholding tax LabelWithholdingExist=The label for Withholding already exists diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 013cac86581..9d47585bdfc 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -916,7 +916,7 @@ Genderother=Other ViewList=List view ViewGantt=Gantt view ViewKanban=Kanban view -ViewKanbanGroupBy=Kanban view (gouped by) +ViewKanbanGroupBy=Kanban view (grouped by) Mandatory=Mandatory Hello=Hello GoodBye=GoodBye diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index a5eb2e4b793..ebad4bdbae6 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -381,4 +381,4 @@ TLS/STARTTLS=TLS/STARTTLS FillExtrafieldWithAi=Fill extrafield with AI content ExtrafieldFiller=Extrafield filler OurProductSelection=Our selection of new products -NoSupportedModulesHaveBeenActivated=The reporting tool can generated dynamic report for some modules only. There is no supported module enabled yet. +NoSupportedModulesHaveBeenActivated=The reporting tool can generate dynamic reports for some modules only. There is no supported module enabled yet. diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index b01f4d2a872..e44886838b9 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -50,5 +50,5 @@ ToReplace=Replace CantMoveNonExistantSerial=Error. You ask a move on a record for a serial that does not exists anymore. May be you take the same serial on same warehouse several times in same shipment or it was used by another shipment. Remove this shipment and prepare another one. TableLotIncompleteRunRepairWithParamStandardEqualConfirmed=Lot table incomplete run repair with parameter '...repair.php?standard=confirmed' IlligalQtyForSerialNumbers= Stock correction required because unique serial number. -ErrorBatchesNeedStockManagement=Error. A product with batch/lot management must be managed in stock. +ErrorBatchesNeedStockManagement=Error. A product with batch/lot management must also be managed in stock. ForceBatchesNeedStockManagement=A product with batch/lot management must be managed in stock (stock management force to yes) diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 8521a485ebc..f52571665bd 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -215,7 +215,8 @@ TimeSpentBy=Time spent by TasksAssignedTo=Tasks assigned to AssignTaskToMe=Assign task to myself AssignTaskToUser=Assign task to %s -SelectTaskToAssign=Select task to assign... +SelectTaskToAssign=Select a task to assign... +SelectAProjectFirst=Select a project first... AssignTask=Assign ProjectOverview=Overview ManageTasks=Use projects to follow tasks and/or report time spent (timesheets) diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index b1505c79b80..4ad17dac539 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -144,3 +144,4 @@ CloneCategoriesUser=Clone the user's categories ConfirmUserClone=Are you sure you want to clone the user: %s? NewEmailUserClone=Email address of the new user SocialNetworksUser=Social networks for user +MyTeam=My team diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 21ec31e5268..57783fd6cfe 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -423,8 +423,8 @@ contactFormPhone = Phone contactFormSubjectEntered = Subject entered contactFormMessageLabel = Message contactFormSuccessAlert = Thank you for your message. We will get back to you shortly. -socials=Reseau sociaux -rgpd=RGPD +socials=Social networks +rgpd=GDPR joinUs=Join US home=Home anonymous=Anonymous diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index c956704492a..64cf27d1083 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -542,6 +542,9 @@ input.buttonpayment, button.buttonpayment, div.buttonpayment { input.short { width: 40px; } +input.shortbis { + width: 48px; +} .nofocusvisible:focus-visible { outline: none; } @@ -3691,6 +3694,9 @@ div.vmenu, td.vmenu { display: none; } +.vmenudisabled { + margin-left: 8px !important; +} /* Force vmenusearchselectcombo with type=text differently than without because beautify with select2 affect vmenusearchselectcombo differently */ input.vmenusearchselectcombo[type=text] { diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 17c38cf3180..92a9c33872a 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -403,7 +403,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { color: #6c6aa8 !important; } .bg-infobox-action{ - color: #b06080 !important; + color: #906080 !important; } .bg-infobox-propal, .bg-infobox-facture, .bg-infobox-commande { color: #65953d !important; @@ -443,7 +443,7 @@ a.vmenu span, span.vmenu, span.vmenu span { color: #6c6aa8; } .infobox-action{ - color: #b06080; + color: #906080; } /* Color for customer object */ .infobox-propal:not(.error), diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index 0ef98599f35..608145db35a 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -100,7 +100,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { color: #6c6aa8 !important; } .bg-infobox-action{ - color: #a47080 !important; + color: #906080 !important; } .bg-infobox-propal, .bg-infobox-facture, .bg-infobox-commande { color: #65953d !important; @@ -143,7 +143,7 @@ div.login_block_other:not(.takepos) a { color: #6c6aa8; } .infobox-action{ - color: #a47080; + color: #906080; } /* Color for customer object */ .infobox-propal:not(.pictotitle):not(.error), @@ -480,7 +480,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { color: #605ca8 !important; } .bg-infobox-action i.fa{ - color: #d84b80 !important; + color: #906080 !important; } .bg-infobox-propal i.fa, .bg-infobox-facture i.fa, diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 13cd736b7ca..4f50f8fead7 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -668,9 +668,13 @@ input, select { input.button.massactionconfirmed { margin: 4px; } + input.short { width: 40px; } +input.shortbis { + width: 48px; +} input:invalid, select:invalid, input.--error , select.--error { border-color: #ea1212; @@ -3781,6 +3785,9 @@ div.vmenu, td.vmenu { display: none; } +.vmenudisabled { + margin-: 8px !important +} .vmenusearchselectcombo { width: px; diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index dc1e9a86f80..4e1fa625917 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -707,7 +707,7 @@ if (isModEnabled('project')) { $help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket'; -$title = $actionobject->getTitle($action); +$title = $actionobject->getTitle($action, $object); llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-ticket page-card'); diff --git a/htdocs/ticket/class/actions_ticket.class.php b/htdocs/ticket/class/actions_ticket.class.php index 9e5cf492aa0..bf9d0acbffe 100644 --- a/htdocs/ticket/class/actions_ticket.class.php +++ b/htdocs/ticket/class/actions_ticket.class.php @@ -169,10 +169,11 @@ class ActionsTicket extends CommonHookActions /** * Get action title * - * @param string $action Type of action - * @return string Title of action + * @param string $action Type of action + * @param Ticket|null $object Object ticket + * @return string Title of action */ - public function getTitle($action = '') + public function getTitle($action = '', $object = null) { global $langs; @@ -181,11 +182,11 @@ class ActionsTicket extends CommonHookActions } elseif ($action == 'edit') { return $langs->trans("EditTicket"); } elseif ($action == 'view') { - return $langs->trans("TicketCard"); + return $langs->trans("Ticket").(is_null($object) ? '' : ' '.$object->ref); } elseif ($action == 'add_message') { return $langs->trans("TicketAddMessage"); } else { - return $langs->trans("TicketsManagement"); + return $langs->trans("Ticket"); } } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 518f2418bc6..ad5a9ad7a22 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3879,13 +3879,12 @@ class User extends CommonObject * fullpath = Full path composed of the ids: "_grandparentid_parentid_id" * * @param int $deleteafterid Removed all users including the leaf $deleteafterid (and all its child) in user tree. - * @param string $filter SQL filter on users. This parameter must not come from user input. + * @param string $filter SQL filter on users. This parameter must NOT come from user input. * @return int<-1,-1>|array,admin:int<0,1>,photo:string,fullpath:string,fullname:string,level:int}> Array of user information (also: $this->users). Note: $this->parentof is also set. */ public function get_full_tree($deleteafterid = 0, $filter = '') { // phpcs:enable - global $conf, $user; global $hookmanager; // Actions hooked (by external module) @@ -3908,7 +3907,7 @@ class User extends CommonObject $sql .= " WHERE u.entity IN (".getEntity('user').")"; } if ($filter) { - $sql .= " AND ".$filter; + $sql .= " AND ".$filter; // already sanitized } dol_syslog(get_class($this)."::get_full_tree get user list", LOG_DEBUG); diff --git a/htdocs/waf.inc.php b/htdocs/waf.inc.php index 05f30703dca..f514b46af26 100644 --- a/htdocs/waf.inc.php +++ b/htdocs/waf.inc.php @@ -92,9 +92,9 @@ function realCharForNumericEntities($matches) } /** - * Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF). - * Warning: Such a protection can't be enough. It is not reliable as it will always be possible to bypass this. Good protection can - * only be guaranteed by escaping data during output. + * Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, SERVER['PHP_SELF']). + * Warning: Such a protection seems enough for SERVER['PHP_SELF'] but can't be enough for GET and POST. It is not reliable as it will always be possible + * to bypass this. Good protection can only be guaranteed by escaping data during output. * * @param string $val Brute value found into $_GET, $_POST or PHP_SELF * @param int<0, 3> $type 0=POST, 1=GET, 2=PHP_SELF, 3=GET without sql reserved keywords (the less tolerant test) @@ -235,7 +235,7 @@ function testSqlAndScriptInject($val, $type) } } if ($type == 2) { - $inj += preg_match('/[:;"\'<>\?\(\){}\$%]/', $val); // PHP_SELF is a file system (or url path without parameters). It can contains spaces. + $inj += preg_match('/[:;"\'<>\?\(\){}\$%#]/', $val); // PHP_SELF is a file system (or url path without parameters). It can contains spaces. } return $inj;