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

This commit is contained in:
Laurent Destailleur
2025-09-08 01:29:45 +02:00
10 changed files with 48 additions and 180 deletions

View File

@@ -13230,78 +13230,6 @@ parameters:
count: 1
path: ../../../htdocs/hrm/admin/admin_hrm.php
-
message: '#^Call to function method_exists\(\) with \$this\(Job\) and ''getNomUrl'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with \$this\(Job\) and ''description'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with Job and ''date_creation'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with Job and ''date_modification'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with Job and ''label'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with Job and ''ref'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function property_exists\(\) with Job and ''status'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Left side of && is always false\.$#'
identifier: booleanAnd.leftAlwaysFalse
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Method Job\:\:fetchAll\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Method Job\:\:getLinesArray\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Method Job\:\:getSkillRankForJob\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Negated boolean expression is always true\.$#'
identifier: booleanNot.alwaysTrue
count: 1
path: ../../../htdocs/hrm/class/job.class.php
-
message: '#^Call to function method_exists\(\) with \$this\(Position\) and ''getNomUrl'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType

View File

@@ -1,9 +1,9 @@
<?php
/*
* Copyright (C) 2013-2016 Jean-François FERRY <hello@librethic.io>
* Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
* Copyright (C) 2018-2023 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2013-2016 Jean-François FERRY <hello@librethic.io>
* Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -91,8 +91,9 @@ class box_last_modified_knowledgerecord extends ModeleBoxes
);
if ($user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
$sql = 'SELECT k.rowid as id, k.date_creation, k.ref, k.lang, k.question, k.status as status';
$sql = 'SELECT k.rowid as id, k.date_creation, GREATEST(k.tms, kef.tms) as date_modification, k.ref, k.lang, k.question, k.status as status';
$sql .= " FROM ".MAIN_DB_PREFIX."knowledgemanagement_knowledgerecord as k";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."knowledgemanagement_knowledgerecord_extrafields as kef ON kef.fk_object = k.rowid";
$sql .= " WHERE k.entity IN (".getEntity('knowledgemanagement').")";
if ($user->socid) {
@@ -101,7 +102,7 @@ class box_last_modified_knowledgerecord extends ModeleBoxes
$sql .= " AND k.status > 0";
$sql .= " ORDER BY k.tms DESC, k.rowid DESC ";
$sql .= " ORDER BY date_modification DESC, k.rowid DESC ";
$sql .= $this->db->plimit($max, 0);
$resql = $this->db->query($sql);
@@ -114,10 +115,12 @@ class box_last_modified_knowledgerecord extends ModeleBoxes
$objp = $this->db->fetch_object($resql);
$datec = $this->db->jdate($objp->date_creation);
$datem = $this->db->jdate($objp->date_modification);
$knowledgerecord = new KnowledgeRecord($this->db);
$knowledgerecord->id = $objp->id;
$knowledgerecord->date_creation = $objp->date_creation;
$knowledgerecord->date_modification = $objp->date_modification;
$knowledgerecord->ref = $objp->ref;
$knowledgerecord->status = $objp->status;
$knowledgerecord->question = $objp->question;
@@ -151,8 +154,8 @@ class box_last_modified_knowledgerecord extends ModeleBoxes
// Date creation
$this->info_box_contents[$i][$r] = array(
'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateCreation").': '.dol_print_date($datec, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datec, 'dayhour', 'tzuserrel'),
'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, 'dayhour', 'tzuserrel'),
);
$r++;

View File

@@ -3,7 +3,7 @@
* Copyright (C) 2011 Dimitri Mouillard <dmouillard@teclib.com>
* Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2016 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
@@ -530,7 +530,7 @@ if (count($typeleaves) == 0) {
print '</td>'."\n";
print '<td class="center">';
print '<a href="'.DOL_URL_ROOT.'/holiday/view_log.php?search_employee='.((int) $users[rowid]).'">'.img_picto($langs->trans('MenuLogCP'), 'list-alt').'</a>';
print '<a href="'.DOL_URL_ROOT.'/holiday/view_log.php?search_employee='.((int) $users['rowid']).'">'.img_picto($langs->trans('MenuLogCP'), 'list-alt').'</a>';
print '</td>';
// Action column

View File

@@ -5,7 +5,7 @@
* Copyright (C) 2021 Jean-Pascal BOUDET <jean-pascal.boudet@atm-consulting.fr>
* Copyright (C) 2021 Grégory BLEMAND <gregory.blemand@atm-consulting.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -135,23 +135,11 @@ class Job extends CommonObject
// END MODULEBUILDER PROPERTIES
// If this object has a subtable with lines
// /**
// * @var string Name of subtable line
// */
// public $table_element_line = 'hrm_jobline';
/**
* @var string Field with ID of parent key if this object has a parent
*/
public $fk_element = 'fk_job';
// /**
// * @var string Name of subtable class that manage subtable lines
// */
// public $class_element_line = 'Jobline';
/**
* @var array<string,string[]> List of child tables. To test if we can delete object.
*/
@@ -256,13 +244,6 @@ class Job extends CommonObject
// Load source object
$result = $object->fetchCommon($fromid);
if ($result > 0 && !empty($object->table_element_line)) {
$object->fetchLines();
}
// get lines so they will be clone
//foreach($this->lines as $line)
// $line->fetch_optionals();
// Reset some properties
unset($object->id);
@@ -270,30 +251,17 @@ class Job extends CommonObject
unset($object->import_key);
// Clear fields
if (property_exists($object, 'ref')) {
$object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
}
if (property_exists($object, 'label')) {
// @phan-suppress-next-line PhanTypeInvalidDimOffset
$object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
}
if (property_exists($object, 'status')) {
$object->status = self::STATUS_DRAFT;
}
if (property_exists($object, 'date_creation')) {
$object->date_creation = dol_now();
}
if (property_exists($object, 'date_modification')) {
$object->date_modification = null;
}
// ...
$object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
$object->label = $langs->trans("CopyOf")." ".$object->label;
$object->date_creation = dol_now();
$object->date_modification = null;
// Clear extrafields that are unique
if (is_array($object->array_options) && count($object->array_options) > 0) {
$extrafields->fetch_name_optionals_label($this->table_element);
foreach ($object->array_options as $key => $option) {
$shortkey = preg_replace('/options_/', '', $key);
if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
//var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
unset($object->array_options[$key]);
}
}
@@ -345,9 +313,7 @@ class Job extends CommonObject
public function fetch($id, $ref = null)
{
$result = $this->fetchCommon($id, $ref);
if ($result > 0 && !empty($this->table_element_line)) {
$this->fetchLines();
}
return $result;
}
@@ -375,7 +341,7 @@ class Job extends CommonObject
* @param string $filter Filter as an Universal Search string.
* Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')'
* @param string $filtermode No more used
* @return array|int int <0 if KO, array of pages if OK
* @return Job[]|int int <0 if KO, array of pages if OK
*/
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
{
@@ -511,7 +477,7 @@ class Job extends CommonObject
$this->db->begin();
// Define new ref
if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
if (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
$num = $this->getNextNumRef();
} else {
$num = $this->ref;
@@ -856,28 +822,8 @@ class Job extends CommonObject
public function LibStatut($status, $mode = 0)
{
// phpcs:enable
return ''; // There is no status on job profile for the moment
/*
if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
global $langs;
//$langs->load("hrm");
$this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
$this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
$this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
$this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
$this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
}
$statusType = 'status'.$status;
//if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
if ($status == self::STATUS_CANCELED) {
$statusType = 'status6';
}
return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
*/
}
/**
@@ -929,7 +875,7 @@ class Job extends CommonObject
/**
* Create an array of lines
*
* @return array|int array of lines if OK, <0 if KO
* @return CommonObjectLine[]|int array of lines if OK, <0 if KO
*/
public function getLinesArray()
{
@@ -984,6 +930,7 @@ class Job extends CommonObject
if (class_exists($classname)) {
$obj = new $classname();
'@phan-var-force ModeleNumRefEvaluation $obj';
/** @var ModeleNumRefEvaluation $obj */
$numref = $obj->getNextValue($this);
if ($numref != '' && $numref != '-1') {
@@ -1019,7 +966,6 @@ class Job extends CommonObject
global $conf, $langs;
$result = 0;
$includedocgeneration = 0;
$langs->load("hrm");
@@ -1035,7 +981,7 @@ class Job extends CommonObject
$modelpath = "core/modules/hrm/doc/";
if ($includedocgeneration && !empty($modele)) {
if (!empty($modele)) {
$result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
}
@@ -1061,7 +1007,7 @@ class Job extends CommonObject
$return .= img_picto('', $this->picto);
$return .= '</span>';
$return .= '<div class="info-box-content">';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(0) : $this->ref).'</span>';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl(0) . '</span>';
if ($selected >= 0) {
$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
@@ -1069,9 +1015,9 @@ class Job extends CommonObject
$return .= '<br><span class="opacitymedium">'.$langs->trans("Type").'</span>';
$return .= ' : <span class="info-box-label ">'.$this->fields['deplacement']['arrayofkeyval'][$this->deplacement].'</span>';
}*/
if (property_exists($this, 'description') && !(empty($this->description))) {
if (empty($this->description)) {
//$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("Description").'</span> : ';
$return .= '<br><span class="info-box-label ">'.(strlen($this->description) > 30 ? dol_substr($this->description, 0, 25).'...' : $this->description).'</span>';
$return .= '<br><span class="info-box-label ">' . dol_trunc($this->description, 25) . '</span>';
}
$return .= '</div>';
$return .= '</div>';
@@ -1082,7 +1028,7 @@ class Job extends CommonObject
/**
* function for get required skills associate to job object
* @param int $id Id of object
* @return array|int list of ids skillranks
* @return int[]|int list of ids skillranks
*/
public function getSkillRankForJob($id)
{
@@ -1100,7 +1046,7 @@ class Job extends CommonObject
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
$skillranks[] = $obj;
$skillranks[] = $obj->rowid;
$i++;
}
$this->db->free($resql);

View File

@@ -195,7 +195,7 @@ if (empty($reshook)) {
$i = 0;
while ($i < count($skillRequire)) {
$skillrank = new SkillRank($db);
$skillrank->createFromClone($user, $skillRequire[$i]->rowid, $id);
$skillrank->createFromClone($user, $skillRequire[$i], $id);
$i++;
}
}
@@ -232,21 +232,6 @@ $title = $langs->trans("Job");
$help_url = '';
llxHeader('', $title, $help_url);
// Example : Adding jquery code
// print '<script type="text/javascript" language="javascript">
// jQuery(document).ready(function() {
// function init_myfunc()
// {
// jQuery("#myid").removeAttr(\'disabled\');
// jQuery("#myid").attr(\'disabled\',\'disabled\');
// }
// init_myfunc();
// jQuery("#mybutton").click(function() {
// init_myfunc();
// });
// });
// </script>';
// Part to create
if ($action == 'create') {

View File

@@ -159,10 +159,12 @@ class KnowledgeRecord extends CommonObject
* @var string
*/
public $url;
/**
* @var int
* @var ?int
*/
public $status;
/**
* @var string
*/
@@ -772,7 +774,7 @@ class KnowledgeRecord extends CommonObject
$nofetch = !empty($params['nofetch']);
$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("KnowledgeRecord").'</u>';
if (isset($this->statut)) {
if (isset($this->status)) {
$datas['picto'] .= ' '.$this->getLibStatut(5);
}
$datas['label'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
@@ -965,9 +967,10 @@ class KnowledgeRecord extends CommonObject
*/
public function info($id)
{
$sql = 'SELECT rowid, date_creation as datec, tms as datem,';
$sql .= ' fk_user_creat, fk_user_modif';
$sql = 'SELECT t.rowid, t.date_creation as datec, GREATEST(t.tms, kef.tms) as datem,';
$sql .= ' t.fk_user_creat, t.fk_user_modif';
$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$this->table_element."_extrafields as kef ON kef.fk_object = t.rowid";
$sql .= ' WHERE t.rowid = '.((int) $id);
$result = $this->db->query($sql);
if ($result) {
@@ -978,7 +981,7 @@ class KnowledgeRecord extends CommonObject
$this->user_creation_id = $obj->fk_user_creat;
$this->user_modification_id = $obj->fk_user_modif;
$this->date_creation = $this->db->jdate($obj->datec);
$this->date_creation = $this->db->jdate($obj->datec);
$this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
}

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2017-2021 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -496,7 +496,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
} else {
$langs->load("errors");
//print dolGetButtonAction($langs->trans('Validate'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=confirm_validate&confirm=yes', '', 0);
print '<a class="butActionRefused" href="" title="'.$langs->trans("ErrorAddAtLeastOneLineFirst").'">'.$langs->trans("Reply").'</a>';
print '<a class="butActionRefused" href="" title="'.$langs->trans("ErrorAddAtLeastOneLineFirst").'">'.$langs->trans("Validate").'</a>';
}
}

View File

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -161,6 +161,7 @@ if ($object->id > 0) {
*/
// Project
if (isModEnabled('project')) {
require_once DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php";
$formproject = new FormProjets($db);
$langs->load("projects");
$morehtmlref .= $langs->trans('Project').' ';

View File

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -141,6 +141,7 @@ if ($object->id) {
*/
// Project
if (isModEnabled('project')) {
require_once DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php";
$formproject = new FormProjets($db);
$langs->load("projects");
$morehtmlref .= $langs->trans('Project').' ';

View File

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -118,6 +118,7 @@ if ($id > 0 || !empty($ref)) {
*/
// Project
if (isModEnabled('project')) {
require_once DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php";
$formproject = new FormProjets($db);
$langs->load("projects");
$morehtmlref .= $langs->trans('Project').' ';