.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* CommonITILValidation Class
*
* @since 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 [CREATE];
}
static function getPurgeRights() {
return [PURGE];
}
static function getValidateRights() {
return [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 integer $items_id ID of the item
**/
static function canValidate($items_id) {
global $DB;
$iterator = $DB->request([
'SELECT' => ['users_id_validate'],
'FROM' => static::getTable(),
'WHERE' => [
static::$items_id => $items_id,
'users_id_validate' => Session::getLoginUserID()
],
'START' => 0,
'LIMIT' => 1
]);
if (count($iterator) > 0) {
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['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;
}
$itemtype = static::$itemtype;
$input['timeline_position'] = $itemtype::getTimelinePosition($input[static::$items_id], $this->getType(), $input["users_id"]);
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],
'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_notifications"]) {
$options = ['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)) {
Session::addMessageAfterRedirect(sprintf(__('Approval request send to %s'), $user->getName()));
} else {
Session::addMessageAfterRedirect(
sprintf(
__('The selected user (%s) has no valid email address. The request has been created, without email confirmation.'),
$user->getName()
),
false,
ERROR
);
}
}
}
parent::post_addItem();
}
function prepareInputForUpdate($input) {
$forbid_fields = [];
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 = ['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 = ['entities_id', static::$items_id, 'status', 'comment_validation',
'validation_date', 'is_recursive'];
}
if (count($forbid_fields)) {
foreach (array_keys($forbid_fields) as $key) {
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_notifications"];
if (isset($this->input['_disablenotif'])) {
$donotif = false;
}
if ($item->getFromDB($this->fields[static::$items_id])) {
if (count($this->updates)
&& $donotif) {
$options = ['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],
'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],
'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 = ['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 array
**/
static function getAllStatusArray($withmetaforsearch = false, $global = false) {
$tab = [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 string $name select name
* @param array $options 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 string|integer Output string if display option is set to false,
* otherwise random part of dropdown id
**/
static function dropdownStatus($name, $options = []) {
$p = [
'value' => self::WAITING,
'global' => false,
'all' => false,
'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 integer $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 integer $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;
}
/**
* Get item validation demands count for a user
*
* @param $users_id integer User ID
**/
static function getNumberToValidate($users_id) {
global $DB;
$row = $DB->request([
'FROM' => static::getTable(),
'COUNT' => 'cpt',
'WHERE' => [
'status' => self::WAITING,
'users_id_validate' => $users_id
]
])->next();
return $row['cpt'];
}
/**
* Get the number of validations attached to an item having a specified status
*
* @param integer $items_id item ID
* @param integer $status status
**/
static function getTicketStatusNumber($items_id, $status) {
global $DB;
$row = $DB->request([
'FROM' => static::getTable(),
'COUNT' => 'cpt',
'WHERE' => [
static::$items_id => $items_id,
'status' => $status
]
])->next();
return $row['cpt'];
}
/**
* Check if validation already exists
*
* @param $items_id integer item ID
* @param $users_id integer user ID
*
* @since 0.85
*
* @return boolean
**/
static function alreadyExists($items_id, $users_id) {
global $DB;
$iterator = $DB->request([
'FROM' => static::getTable(),
'WHERE' => [
static::$items_id => $items_id,
'users_id_validate' => $users_id
],
'START' => 0,
'LIMIT' => 1
]);
if (count($iterator) > 0) {
return true;
}
return false;
}
/**
* Form for Followup on Massive action
**/
static function showFormMassiveAction() {
global $CFG_GLPI;
$types = ['user' => User::getTypeName(1),
'group' => Group::getTypeName(1)];
$rand = Dropdown::showFromArray("validatortype", $types,
['display_emptychoice' => true]);
$paramsmassaction = ['validatortype' => '__VALUE__',
'entity' => $_SESSION['glpiactive_entity'],
'right' => ['validate_request', 'validate_incident']];
Ajax::updateItemOnSelectEvent("dropdown_validatortype$rand", "show_massiveaction_field",
$CFG_GLPI["root_doc"].
"/ajax/dropdownMassiveActionAddValidator.php",
$paramsmassaction);
echo "
\n";
}
/**
* @since 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 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 = [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 = [$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 CommonDBTM $item
**/
function showSummary(CommonDBTM $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 = [static::$items_id => $tID];
$canadd = $this->can(-1, CREATE, $tmp);
$rand = mt_rand();
if ($canadd) {
$itemtype = static::$itemtype;
echo "