grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026.
--------------------------------------------------------------------------
*/
/** @file
* @brief
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* CommonITILValidation Class
*
* @since version 0.85
**/
abstract class CommonITILValidation extends CommonDBChild {
// From CommonDBTM
public $auto_message_on_action = false;
static public $log_history_add = Log::HISTORY_LOG_SIMPLE_MESSAGE;
static public $log_history_update = Log::HISTORY_LOG_SIMPLE_MESSAGE;
static public $log_history_delete = Log::HISTORY_LOG_SIMPLE_MESSAGE;
const VALIDATE = 1024;
// STATUS
const NONE = 1; // none
const WAITING = 2; // waiting
const ACCEPTED = 3; // accepted
const REFUSED = 4; // rejected
function getItilObjectItemType() {
return str_replace('Validation','',$this->getType());
}
static function getCreateRights() {
return array(CREATE);
}
static function getPurgeRights() {
return array(PURGE);
}
static function getValidateRights() {
return array(static::VALIDATE);
}
function getForbiddenStandardMassiveAction() {
$forbidden = parent::getForbiddenStandardMassiveAction();
$forbidden[] = 'update';
return $forbidden;
}
static function getTypeName($nb=0) {
return _n('Approval', 'Approvals', $nb);
}
static function canCreate() {
return Session::haveRightsOr(static::$rightname, static::getCreateRights());
}
/**
* Is the current user have right to delete the current validation ?
*
* @return boolean
**/
function canCreateItem() {
if (($this->fields["users_id"] == Session::getLoginUserID())
|| Session::haveRightsOr(static::$rightname, static::getCreateRights())) {
return true;
}
return false;
}
static function canView() {
return Session::haveRightsOr(static::$rightname,
array_merge(static::getCreateRights(),
static::getValidateRights(),
static::getPurgeRights()));
}
static function canUpdate() {
return Session::haveRightsOr(static::$rightname,
array_merge(static::getCreateRights(),
static::getValidateRights()));
}
/**
* Is the current user have right to delete the current validation ?
*
* @return boolean
**/
function canDeleteItem() {
if (($this->fields["users_id"] == Session::getLoginUserID())
|| Session::haveRight(static::$rightname, DELETE)) {
return true;
}
return false;
}
/**
* Is the current user have right to update the current validation ?
*
* @return boolean
*/
function canUpdateItem() {
if (!Session::haveRightsOr(static::$rightname, static::getCreateRights())
&& ($this->fields["users_id_validate"] != Session::getLoginUserID())) {
return false;
}
return true;
}
/**
* @param $items_id ID of the item
**/
static function canValidate($items_id) {
global $DB;
$query = "SELECT `users_id_validate`
FROM `".static::getTable()."`
WHERE `".static::$items_id."` = '$items_id'
AND `users_id_validate` = '".Session::getLoginUserID()."'";
$result = $DB->query($query);
if ($DB->numrows($result)) {
return true;
}
return false;
}
function getTabNameForItem(CommonGLPI $item, $withtemplate=0) {
$hidetab = false;
// Hide if no rights on validations
if (!static::canView()) {
$hidetab = true;
}
// No right to create and no validation for current object
if (!$hidetab
&& !Session::haveRightsOr(static::$rightname, static::getCreateRights())
&& !static::canValidate($item->getID())) {
$hidetab = true;
}
if (!$hidetab) {
$nb = 0;
if ($_SESSION['glpishow_count_on_tabs']) {
$restrict = "`".static::$items_id."` = '".$item->getID()."'";
// No rights for create only count asign ones
if (!Session::haveRightsOr(static::$rightname, static::getCreateRights())) {
$restrict .= " AND `users_id_validate` = '".Session::getLoginUserID()."'";
}
$nb = countElementsInTable(static::getTable(),$restrict);
}
return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb);
}
return '';
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) {
$validation = new static();
$validation->showSummary($item);
return true;
}
function post_getEmpty() {
$this->fields["users_id"] = Session::getLoginUserID();
$this->fields["status"] = self::WAITING;
}
function prepareInputForAdd($input) {
$input["users_id"] = 0;
// Only set requester on manual action
if (!isset($input['_auto_import'])
&& !isset($input['_auto_update'])
&& !Session::isCron()) {
$input["users_id"] = Session::getLoginUserID();
}
$input["submission_date"] = $_SESSION["glpi_currenttime"];
$input["status"] = self::WAITING;
if (!isset($input["users_id_validate"]) || ($input["users_id_validate"] <= 0)) {
return false;
}
return parent::prepareInputForAdd($input);
}
function post_addItem() {
global $CFG_GLPI;
$item = new static::$itemtype();
$mailsend = false;
if ($item->getFromDB($this->fields[static::$items_id])) {
// Set global validation to waiting
if (($item->fields['global_validation'] == self::ACCEPTED)
|| ($item->fields['global_validation'] == self::NONE)) {
$input['id'] = $this->fields[static::$items_id];
$input['global_validation'] = self::WAITING;
// to fix lastupdater
if (isset($this->input['_auto_update'])) {
$input['_auto_update'] = $this->input['_auto_update'];
}
// to know update by rules
if (isset($this->input["_rule_process"])) {
$input['_rule_process'] = $this->input["_rule_process"];
}
// No update ticket notif on ticket add
if (isset($this->input["_ticket_add"])) {
$input['_disablenotif'] = true;
}
$item->update($input);
}
if (!isset($this->input['_disablenotif']) && $CFG_GLPI["use_mailing"]) {
$options = array('validation_id' => $this->fields["id"],
'validation_status' => $this->fields["status"]);
$mailsend = NotificationEvent::raiseEvent('validation',$item,$options);
}
if ($mailsend) {
$user = new User();
$user->getFromDB($this->fields["users_id_validate"]);
$email = $user->getDefaultEmail();
if (!empty($email)) {
$message[] = sprintf(__('Approval request send to %s'), $user->getName());
} else {
$error[] = sprintf(__('The selected user (%s) has no valid email address. The request has been created, without email confirmation.'),
$user->getName());
}
}
}
parent::post_addItem();
}
function prepareInputForUpdate($input) {
$forbid_fields = array();
if ($this->fields["users_id_validate"] == Session::getLoginUserID()) {
if (($input["status"] == self::REFUSED)
&& (!isset($input["comment_validation"])
|| ($input["comment_validation"] == ''))) {
Session::addMessageAfterRedirect(__('If approval is denied, specify a reason.'),
false, ERROR);
return false;
}
if ($input["status"] == self::WAITING) {
// $input["comment_validation"] = '';
$input["validation_date"] = 'NULL';
} else {
$input["validation_date"] = $_SESSION["glpi_currenttime"];
}
$forbid_fields = array('entities_id', 'users_id', static::$items_id, 'users_id_validate',
'comment_submission', 'submission_date', 'is_recursive');
} else if (Session::haveRightsOr(static::$rightname, $this->getCreateRights())) { // Update validation request
$forbid_fields = array('entities_id', static::$items_id, 'status', 'comment_validation',
'validation_date', 'is_recursive');
}
if (count($forbid_fields)) {
foreach ($forbid_fields as $key => $val) {
if (isset($input[$key])) {
unset($input[$key]);
}
}
}
return parent::prepareInputForUpdate($input);
}
function post_updateItem($history=1) {
global $CFG_GLPI;
$item = new static::$itemtype();
$donotif = $CFG_GLPI["use_mailing"];
if (isset($this->input['_disablenotif'])) {
$donotif = false;
}
if ($item->getFromDB($this->fields[static::$items_id])) {
if (count($this->updates)
&& $donotif) {
$options = array('validation_id' => $this->fields["id"],
'validation_status' => $this->fields["status"]);
NotificationEvent::raiseEvent('validation_answer', $item, $options);
}
//Set global validation to accepted to define one
if (($item->fields['global_validation'] == self::WAITING)
&& in_array("status", $this->updates)) {
$input['id'] = $this->fields[static::$items_id];
$input['global_validation'] = self::computeValidationStatus($item);
$item->update($input);
}
}
parent::post_updateItem($history);
}
function pre_deleteItem() {
$item = new static::$itemtype();
if ($item->getFromDB($this->fields[static::$items_id])) {
if (($item->fields['global_validation'] == self::WAITING)) {
$input['id'] = $this->fields[static::$items_id];
$input['global_validation'] = self::NONE;
$item->update($input);
}
}
return true;
}
/**
* @see CommonDBConnexity::getHistoryChangeWhenUpdateField
**/
function getHistoryChangeWhenUpdateField($field) {
if ($field == 'status') {
$username = getUserName($this->fields["users_id_validate"]);
$result = array('0', '', '');
if ($this->fields["status"] == self::ACCEPTED) {
//TRANS: %s is the username
$result[2] = sprintf(__('Approval granted by %s'), $username);
} else {
//TRANS: %s is the username
$result[2] = sprintf(__('Update the approval request to %s'), $username);
}
return $result;
}
return false;
}
/**
* @see CommonDBChild::getHistoryNameForItem
**/
function getHistoryNameForItem(CommonDBTM $item, $case) {
$username = getUserName($this->fields["users_id_validate"]);
switch ($case) {
case 'add' :
return sprintf(__('Approval request send to %s'), $username);
case 'delete' :
return sprintf(__('Cancel the approval request to %s'), $username);
}
return '';
}
/**
* get the Ticket validation status list
*
* @param $withmetaforsearch boolean (false by default)
* @param $global boolean (true for global status, with "no validation" option)
* (false by default)
*
* @return an array
**/
static function getAllStatusArray($withmetaforsearch=false, $global=false) {
$tab = array(self::WAITING => __('Waiting for approval'),
self::REFUSED => __('Refused'),
self::ACCEPTED => __('Granted'));
if ($global) {
$tab[self::NONE] = __('Not subject to approval');
if ($withmetaforsearch) {
$tab['can'] = __('Granted + Not subject to approval');
}
}
if ($withmetaforsearch) {
$tab['all'] = __('All');
}
return $tab;
}
/**
* Dropdown of validation status
*
* @param $name select name
* @param $options array of possible options:
* - value : default value (default waiting)
* - all : boolean display all (default false)
* - global : for global validation (default false)
* - display : boolean display or get string ? (default true)
*
* @return nothing (display)
**/
static function dropdownStatus($name, $options=array()) {
$p['value'] = self::WAITING;
$p['global'] = false;
$p['all'] = false;
$p['display'] = true;
if (is_array($options) && count($options)) {
foreach ($options as $key => $val) {
$p[$key] = $val;
}
}
$tab = self::getAllStatusArray($p['all'], $p['global']);
unset($p['all']);
unset($p['global']);
return Dropdown::showFromArray($name, $tab, $p);
}
/**
* Get Ticket validation status Name
*
* @param $value status ID
**/
static function getStatus($value) {
$tab = self::getAllStatusArray(true, true);
// Return $value if not define
return (isset($tab[$value]) ? $tab[$value] : $value);
}
/**
* Get Ticket validation status Color
*
* @param $value status ID
**/
static function getStatusColor($value) {
switch ($value) {
case self::WAITING :
$style = "#FFC65D";
break;
case self::REFUSED :
$style = "#cf9b9b";
break;
case self::ACCEPTED :
$style = "#9BA563";
break;
default :
$style = "#cf9b9b";
}
return $style;
}
/**
* All validations requests for an item have the same status ?
*
* @param $items_id integer item ID
**/
static function isAllValidationsHaveSameStatusForTicket($items_id) {
global $DB;
$query = "SELECT DISTINCT `status`
FROM `".static::getTable()."`
WHERE `".static::$items_id."` = '$items_id'";
$result = $DB->query($query);
return ($DB->numrows($result) == 1);
}
/**
* Get item validation demands count
*
* @param $items_id integer item ID
**/
static function getNumberValidationForTicket($items_id) {
global $DB;
$query = "SELECT COUNT(`id`) AS 'total'
FROM `".static::getTable()."`
WHERE `".static::$items_id."` = '$items_id'";
$result = $DB->query($query);
if ($DB->numrows($result)) {
return $DB->result($result, 0, "total");
}
return false;
}
/**
* Get item validation demands count for a user
*
* @param $users_id integer User ID
**/
static function getNumberToValidate($users_id) {
global $DB;
$query = "SELECT COUNT(`id`) AS 'total'
FROM `".static::getTable()."`
WHERE `status` = '".self::WAITING."'
AND `users_id_validate` = '$users_id'";
$result = $DB->query($query);
if ($DB->numrows($result)) {
return $DB->result($result, 0, "total");
}
return false;
}
/**
* Get the number of validations attached to an item having a specified status
*
* @param $items_id integer item ID
* @param $status status
**/
static function getTicketStatusNumber($items_id, $status) {
global $DB;
$query = "SELECT COUNT(`status`) AS 'total'
FROM `".static::getTable()."`
WHERE `".static::$items_id."` = '$items_id'
AND `status` = '".$status."'";
$result = $DB->query($query);
if ($DB->numrows($result)) {
return $DB->result($result, 0, "total");
}
return false;
}
/**
* Check if validation already exists
*
* @param $items_id integer item ID
* @param $users_id integer user ID
*
* @since version 0.85
*
* @return boolean
**/
static function alreadyExists($items_id, $users_id) {
global $DB;
$query = "SELECT *
FROM `".static::getTable()."`
WHERE `".static::$items_id."` = '$items_id'
AND `users_id_validate` = '".$users_id."'";
$result = $DB->query($query);
if ($DB->numrows($result)) {
return true;
}
return false;
}
/**
* Form for Followup on Massive action
**/
static function showFormMassiveAction() {
global $CFG_GLPI;
$types = array('user' => __('User'),
'group' => __('Group'));
$rand = Dropdown::showFromArray("validatortype", $types,
array('display_emptychoice' => true));
$paramsmassaction = array('validatortype' => '__VALUE__',
'entity' => $_SESSION['glpiactive_entity'],
'right' => array('validate_request', 'validate_incident'));
Ajax::updateItemOnSelectEvent("dropdown_validatortype$rand", "show_massiveaction_field",
$CFG_GLPI["root_doc"].
"/ajax/dropdownMassiveActionAddValidator.php",
$paramsmassaction);
echo "
\n";
}
/**
* @since version 0.85
*
* @see CommonDBTM::showMassiveActionsSubForm()
**/
static function showMassiveActionsSubForm(MassiveAction $ma) {
switch ($ma->getAction()) {
case 'submit_validation' :
static::showFormMassiveAction();
return true;
}
return parent::showMassiveActionsSubForm($ma);
}
/**
* @since version 0.85
*
* @see CommonDBTM::processMassiveActionsForOneItemtype()
**/
static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item,
array $ids) {
switch ($ma->getAction()) {
case 'submit_validation' :
$input = $ma->getInput();
$valid = new static();
foreach ($ids as $id) {
if ($item->getFromDB($id)) {
$input2 = array(static::$items_id => $id,
'comment_submission' => $input['comment_submission']);
if ($valid->can(-1, CREATE, $input2)) {
$users = $input['users_id_validate'];
if (!is_array($users)) {
$users = array($users);
}
$ok = true;
foreach ($users as $user) {
$input2["users_id_validate"] = $user;
if (!$valid->add($input2)) {
$ok = false;
}
}
if ($ok) {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK);
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO);
$ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION));
}
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_NORIGHT);
$ma->addMessage($item->getErrorMessage(ERROR_RIGHT));
}
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO);
$ma->addMessage($item->getErrorMessage(ERROR_NOT_FOUND));
}
}
return;
}
parent::processMassiveActionsForOneItemtype($ma, $item, $ids);
}
/**
* Print the validation list into item
*
* @param $item class
**/
function showSummary($item) {
global $DB, $CFG_GLPI;
if (!Session::haveRightsOr(static::$rightname,
array_merge(static::getCreateRights(),
static::getValidateRights(),
static::getPurgeRights()))) {
return false;
}
$tID = $item->fields['id'];
$tmp = array(static::$items_id => $tID);
$canadd = $this->can(-1, CREATE, $tmp);
$rand = mt_rand();
if ($canadd) {
echo "