Linux server.jmdstrack.com 3.10.0-1160.119.1.el7.tuxcare.els10.x86_64 #1 SMP Fri Oct 11 21:40:41 UTC 2024 x86_64
/ home/ jmdstrac/ public_html/ devices/ src/ |
|
<?php /** * --------------------------------------------------------------------- * * GLPI - Gestionnaire Libre de Parc Informatique * * http://glpi-project.org * * @copyright 2015-2023 Teclib' and contributors. * @copyright 2003-2014 by the INDEPNET Development Team. * @licence https://www.gnu.org/licenses/gpl-3.0.html * * --------------------------------------------------------------------- * * LICENSE * * This file is part of GLPI. * * 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * * --------------------------------------------------------------------- */ use Glpi\Application\View\TemplateRenderer; use Glpi\ContentTemplates\Parameters\ChangeParameters; use Glpi\RichText\RichText; /** * Change Class **/ class Change extends CommonITILObject { // From CommonDBTM public $dohistory = true; protected static $forward_entity_to = ['ChangeValidation', 'ChangeCost']; // From CommonITIL public $userlinkclass = 'Change_User'; public $grouplinkclass = 'Change_Group'; public $supplierlinkclass = 'Change_Supplier'; public static $rightname = 'change'; protected $usenotepad = true; const MATRIX_FIELD = 'priority_matrix'; const URGENCY_MASK_FIELD = 'urgency_mask'; const IMPACT_MASK_FIELD = 'impact_mask'; const STATUS_MATRIX_FIELD = 'change_status'; const READMY = 1; const READALL = 1024; // Specific status for changes const REFUSED = 13; const CANCELED = 14; public static function getTypeName($nb = 0) { return _n('Change', 'Changes', $nb); } public function canSolve() { return (self::isAllowedStatus($this->fields['status'], self::SOLVED) // No edition on closed status && !in_array($this->fields['status'], $this->getClosedStatusArray()) && (Session::haveRight(self::$rightname, UPDATE) || (Session::haveRight(self::$rightname, self::READMY) && ($this->isUser(CommonITILActor::ASSIGN, Session::getLoginUserID()) || (isset($_SESSION["glpigroups"]) && $this->haveAGroup( CommonITILActor::ASSIGN, $_SESSION["glpigroups"] )))))); } public static function canView() { return Session::haveRightsOr(self::$rightname, [self::READALL, self::READMY]); } /** * Is the current user have right to show the current change ? * * @return boolean **/ public function canViewItem() { if (!$this->checkEntity(true)) { return false; } return (Session::haveRight(self::$rightname, self::READALL) || (Session::haveRight(self::$rightname, self::READMY) && ($this->isUser(CommonITILActor::REQUESTER, Session::getLoginUserID()) || $this->isUser(CommonITILActor::OBSERVER, Session::getLoginUserID()) || (isset($_SESSION["glpigroups"]) && ($this->haveAGroup(CommonITILActor::REQUESTER, $_SESSION["glpigroups"]) || $this->haveAGroup( CommonITILActor::OBSERVER, $_SESSION["glpigroups"] ))) || ($this->isUser(CommonITILActor::ASSIGN, Session::getLoginUserID()) || (isset($_SESSION["glpigroups"]) && $this->haveAGroup( CommonITILActor::ASSIGN, $_SESSION["glpigroups"] )))))); } /** * Is the current user have right to create the current change ? * * @return boolean **/ public function canCreateItem() { if (!Session::haveAccessToEntity($this->getEntityID())) { return false; } return Session::haveRight(self::$rightname, CREATE); } /** * is the current user could reopen the current change * * @since 9.4.0 * * @return boolean */ public function canReopen() { return Session::haveRight('followup', CREATE) && in_array($this->fields["status"], $this->getClosedStatusArray()) && ($this->isAllowedStatus($this->fields['status'], self::INCOMING) || $this->isAllowedStatus($this->fields['status'], self::EVALUATION)); } public function prepareInputForAdd($input) { $input = parent::prepareInputForAdd($input); if ($input === false) { return false; } if (!isset($input['_skip_auto_assign']) || $input['_skip_auto_assign'] === false) { // Manage auto assign $auto_assign_mode = Entity::getUsedConfig('auto_assign_mode', $input['entities_id']); switch ($auto_assign_mode) { case Entity::CONFIG_NEVER: break; case Entity::AUTO_ASSIGN_HARDWARE_CATEGORY: case Entity::AUTO_ASSIGN_CATEGORY_HARDWARE: // Auto assign tech/group from Category // Changes are not associated to a hardware then both settings behave the same way $input = $this->setTechAndGroupFromItilCategory($input); break; } } return $input; } public function prepareInputForUpdate($input) { $input = $this->transformActorsInput($input); $input = parent::prepareInputForUpdate($input); return $input; } public function pre_deleteItem() { global $CFG_GLPI; if (!isset($this->input['_disablenotif']) && $CFG_GLPI['use_notifications']) { NotificationEvent::raiseEvent('delete', $this); } return true; } public function getSpecificMassiveActions($checkitem = null) { $actions = parent::getSpecificMassiveActions($checkitem); if ($this->canAdminActors()) { $actions[__CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'add_actor'] = __('Add an actor'); $actions[__CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'update_notif'] = __('Set notifications for all actors'); } return $actions; } public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (static::canView()) { switch ($item->getType()) { case __CLASS__: $ong = []; if ($item->canUpdate()) { $ong[1] = __('Statistics'); } return $ong; } } return ''; } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { switch ($item->getType()) { case __CLASS__: switch ($tabnum) { case 1: $item->showStats(); break; } break; } return true; } public function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); $this->addStandardTab(__CLASS__, $ong, $options); $this->addStandardTab('ChangeValidation', $ong, $options); $this->addStandardTab('ChangeCost', $ong, $options); $this->addStandardTab('Itil_Project', $ong, $options); $this->addStandardTab('Change_Problem', $ong, $options); $this->addStandardTab('Change_Ticket', $ong, $options); $this->addStandardTab('Change_Item', $ong, $options); if ($this->hasImpactTab()) { $this->addStandardTab('Impact', $ong, $options); } $this->addStandardTab('KnowbaseItem_Item', $ong, $options); $this->addStandardTab('Notepad', $ong, $options); $this->addStandardTab('Log', $ong, $options); return $ong; } public function cleanDBonPurge() { // CommonITILTask does not extends CommonDBConnexity $ct = new ChangeTask(); $ct->deleteByCriteria(['changes_id' => $this->fields['id']]); $this->deleteChildrenAndRelationsFromDb( [ // Done by parent: Change_Group::class, Change_Item::class, Change_Problem::class, // Done by parent: Change_Supplier::class, Change_Ticket::class, // Done by parent: Change_User::class, ChangeCost::class, ChangeValidation::class, // Done by parent: ITILSolution::class, ] ); parent::cleanDBonPurge(); } public function post_updateItem($history = 1) { global $CFG_GLPI; parent::post_updateItem($history); $donotif = count($this->updates); if (isset($this->input['_forcenotif'])) { $donotif = true; } if (isset($this->input['_disablenotif'])) { $donotif = false; } if ($donotif && $CFG_GLPI["use_notifications"]) { $mailtype = "update"; if ( isset($this->input["status"]) && $this->input["status"] && in_array("status", $this->updates) && in_array($this->input["status"], $this->getSolvedStatusArray()) ) { $mailtype = "solved"; } if ( isset($this->input["status"]) && $this->input["status"] && in_array("status", $this->updates) && in_array($this->input["status"], $this->getClosedStatusArray()) ) { $mailtype = "closed"; } // Read again change to be sure that all data are up to date $this->getFromDB($this->fields['id']); NotificationEvent::raiseEvent($mailtype, $this); } } public function post_addItem() { global $DB; parent::post_addItem(); if (isset($this->input['_tickets_id'])) { $ticket = new Ticket(); if ($ticket->getFromDB($this->input['_tickets_id'])) { $pt = new Change_Ticket(); $pt->add(['tickets_id' => $this->input['_tickets_id'], 'changes_id' => $this->fields['id'] ]); if (!empty($ticket->fields['itemtype']) && $ticket->fields['items_id'] > 0) { $it = new Change_Item(); $it->add(['changes_id' => $this->fields['id'], 'itemtype' => $ticket->fields['itemtype'], 'items_id' => $ticket->fields['items_id'] ]); } //Copy associated elements $iterator = $DB->request([ 'FROM' => Item_Ticket::getTable(), 'WHERE' => [ 'tickets_id' => $this->input['_tickets_id'] ] ]); $assoc = new Change_Item(); foreach ($iterator as $row) { unset($row['tickets_id']); unset($row['id']); $row['changes_id'] = $this->fields['id']; $assoc->add(Toolbox::addslashes_deep($row)); } } } if (isset($this->input['_problems_id'])) { $problem = new Problem(); if ($problem->getFromDB($this->input['_problems_id'])) { $cp = new Change_Problem(); $cp->add(['problems_id' => $this->input['_problems_id'], 'changes_id' => $this->fields['id'] ]); //Copy associated elements $iterator = $DB->request([ 'FROM' => Item_Problem::getTable(), 'WHERE' => [ 'problems_id' => $this->input['_problems_id'] ] ]); $assoc = new Change_Item(); foreach ($iterator as $row) { unset($row['problems_id']); unset($row['id']); $row['changes_id'] = $this->fields['id']; $assoc->add(Toolbox::addslashes_deep($row)); } } } $this->handleNewItemNotifications(); if ( isset($this->input['_from_items_id']) && isset($this->input['_from_itemtype']) ) { $change_item = new Change_Item(); $change_item->add([ 'items_id' => (int)$this->input['_from_items_id'], 'itemtype' => $this->input['_from_itemtype'], 'changes_id' => $this->fields['id'], '_disablenotif' => true ]); } $this->handleItemsIdInput(); } /** * Get default values to search engine to override **/ public static function getDefaultSearchRequest() { $search = ['criteria' => [ 0 => ['field' => 12, 'searchtype' => 'equals', 'value' => 'notold' ] ], 'sort' => 19, 'order' => 'DESC' ]; return $search; } public function rawSearchOptions() { $tab = []; $tab = array_merge($tab, $this->getSearchOptionsMain()); $tab[] = [ 'id' => '68', 'table' => 'glpi_changes_items', 'field' => 'id', 'name' => _x('quantity', 'Number of items'), 'forcegroupby' => true, 'usehaving' => true, 'datatype' => 'count', 'massiveaction' => false, 'joinparams' => [ 'jointype' => 'child' ] ]; $tab[] = [ 'id' => '13', 'table' => 'glpi_changes_items', 'field' => 'items_id', 'name' => _n('Associated element', 'Associated elements', Session::getPluralNumber()), 'datatype' => 'specific', 'comments' => true, 'nosearch' => true, 'additionalfields' => ['itemtype'], 'joinparams' => [ 'jointype' => 'child' ], 'forcegroupby' => true, 'massiveaction' => false ]; $tab[] = [ 'id' => '131', 'table' => 'glpi_changes_items', 'field' => 'itemtype', 'name' => _n('Associated item type', 'Associated item types', Session::getPluralNumber()), 'datatype' => 'itemtypename', 'itemtype_list' => 'ticket_types', 'nosort' => true, 'additionalfields' => ['itemtype'], 'joinparams' => [ 'jointype' => 'child' ], 'forcegroupby' => true, 'massiveaction' => false ]; $tab = array_merge($tab, $this->getSearchOptionsActors()); $tab[] = [ 'id' => 'analysis', 'name' => __('Control list') ]; $tab[] = [ 'id' => '60', 'table' => $this->getTable(), 'field' => 'impactcontent', 'name' => __('Analysis impact'), 'massiveaction' => false, 'datatype' => 'text' ]; $tab[] = [ 'id' => '61', 'table' => $this->getTable(), 'field' => 'controlistcontent', 'name' => __('Control list'), 'massiveaction' => false, 'datatype' => 'text' ]; $tab[] = [ 'id' => '62', 'table' => $this->getTable(), 'field' => 'rolloutplancontent', 'name' => __('Deployment plan'), 'massiveaction' => false, 'datatype' => 'text' ]; $tab[] = [ 'id' => '63', 'table' => $this->getTable(), 'field' => 'backoutplancontent', 'name' => __('Backup plan'), 'massiveaction' => false, 'datatype' => 'text' ]; $tab[] = [ 'id' => '67', 'table' => $this->getTable(), 'field' => 'checklistcontent', 'name' => __('Checklist'), 'massiveaction' => false, 'datatype' => 'text' ]; $tab = array_merge($tab, Notepad::rawSearchOptionsToAdd()); $tab = array_merge($tab, ChangeValidation::rawSearchOptionsToAdd()); $tab = array_merge($tab, ITILFollowup::rawSearchOptionsToAdd()); $tab = array_merge($tab, ChangeTask::rawSearchOptionsToAdd()); $tab = array_merge($tab, $this->getSearchOptionsSolution()); $tab = array_merge($tab, ChangeCost::rawSearchOptionsToAdd()); return $tab; } /** * get the change status list * To be overridden by class * * @param $withmetaforsearch boolean (default false) * * @return array **/ public static function getAllStatusArray($withmetaforsearch = false) { $tab = [self::INCOMING => _x('status', 'New'), self::EVALUATION => __('Evaluation'), self::APPROVAL => _n('Approval', 'Approvals', 1), self::ACCEPTED => _x('status', 'Accepted'), self::WAITING => __('Pending'), self::TEST => _x('change', 'Testing'), self::QUALIFICATION => __('Qualification'), self::SOLVED => __('Applied'), self::OBSERVED => __('Review'), self::CLOSED => _x('status', 'Closed'), self::CANCELED => _x('status', 'Cancelled'), self::REFUSED => _x('status', 'Refused'), ]; if ($withmetaforsearch) { $tab['notold'] = _x('status', 'Not solved'); $tab['notclosed'] = _x('status', 'Not closed'); $tab['process'] = __('Processing'); $tab['old'] = _x('status', 'Solved + Closed'); $tab['all'] = __('All'); } return $tab; } /** * Get the ITIL object closed status list * * @since 0.83 * * @return array **/ public static function getClosedStatusArray() { // To be overridden by class $tab = [ self::CLOSED, self::CANCELED, self::REFUSED, ]; return $tab; } /** * Get the ITIL object solved or observe status list * * @since 0.83 * * @return array **/ public static function getSolvedStatusArray() { // To be overridden by class $tab = [self::OBSERVED, self::SOLVED]; return $tab; } /** * Get the ITIL object new status list * * @since 0.83.8 * * @return array **/ public static function getNewStatusArray() { return [self::INCOMING, self::ACCEPTED, self::EVALUATION, self::APPROVAL]; } /** * Get the ITIL object test, qualification or accepted status list * To be overridden by class * * @since 0.83 * * @return array **/ public static function getProcessStatusArray() { // To be overridden by class $tab = [self::ACCEPTED, self::QUALIFICATION, self::TEST]; return $tab; } public static function getReopenableStatusArray() { return self::getClosedStatusArray(); } public function getRights($interface = 'central') { $values = parent::getRights(); unset($values[READ]); $values[self::READALL] = __('See all'); $values[self::READMY] = __('See (author)'); return $values; } /** * Display changes for an item * * Will also display changes of linked items * * @param CommonDBTM $item * @param boolean|integer $withtemplate * * @return boolean|void **/ public static function showListForItem(CommonDBTM $item, $withtemplate = 0) { global $DB; if (!Session::haveRight(self::$rightname, self::READALL)) { return false; } if ($item->isNewID($item->getID())) { return false; } $restrict = []; $options = [ 'criteria' => [], 'reset' => 'reset', ]; switch ($item->getType()) { case 'User': $restrict['glpi_changes_users.users_id'] = $item->getID(); $options['criteria'][0]['field'] = 4; // status $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = $item->getID(); $options['criteria'][0]['link'] = 'OR'; $options['criteria'][1]['field'] = 66; // status $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = $item->getID(); $options['criteria'][1]['link'] = 'OR'; $options['criteria'][5]['field'] = 5; // status $options['criteria'][5]['searchtype'] = 'equals'; $options['criteria'][5]['value'] = $item->getID(); $options['criteria'][5]['link'] = 'OR'; break; case 'Supplier': $restrict['glpi_changes_suppliers.suppliers_id'] = $item->getID(); $options['criteria'][0]['field'] = 6; $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = $item->getID(); $options['criteria'][0]['link'] = 'AND'; break; case 'Group': // Mini search engine if ($item->haveChildren()) { $tree = Session::getSavedOption(__CLASS__, 'tree', 0); echo "<table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_1'><th>" . __('Last changes') . "</th></tr>"; echo "<tr class='tab_bg_1'><td class='center'>"; echo __('Child groups'); Dropdown::showYesNo( 'tree', $tree, -1, ['on_change' => 'reloadTab("start=0&tree="+this.value)'] ); } else { $tree = 0; } echo "</td></tr></table>"; $restrict['glpi_changes_groups.groups_id'] = ($tree ? getSonsOf('glpi_groups', $item->getID()) : $item->getID()); $options['criteria'][0]['field'] = 71; $options['criteria'][0]['searchtype'] = ($tree ? 'under' : 'equals'); $options['criteria'][0]['value'] = $item->getID(); $options['criteria'][0]['link'] = 'AND'; break; default: $restrict['items_id'] = $item->getID(); $restrict['itemtype'] = $item->getType(); break; } // Link to open a new change if ( $item->getID() && Change::isPossibleToAssignType($item->getType()) && self::canCreate() && !(!empty($withtemplate) && $withtemplate == 2) && (!isset($item->fields['is_template']) || $item->fields['is_template'] == 0) ) { echo "<div class='firstbloc'>"; Html::showSimpleForm( Change::getFormURL(), '_add_fromitem', __('New change for this item...'), [ '_from_itemtype' => $item->getType(), '_from_items_id' => $item->getID(), 'entities_id' => $item->fields['entities_id'] ] ); echo "</div>"; } $criteria = self::getCommonCriteria(); $criteria['WHERE'] = $restrict + getEntitiesRestrictCriteria(self::getTable()); $criteria['LIMIT'] = (int)$_SESSION['glpilist_limit']; $iterator = $DB->request($criteria); $number = count($iterator); // Ticket for the item echo "<div><table class='tab_cadre_fixe'>"; $colspan = 11; if (count($_SESSION["glpiactiveentities"]) > 1) { $colspan++; } if ($number > 0) { Session::initNavigateListItems( 'Change', //TRANS : %1$s is the itemtype name, // %2$s is the name of the item (used for headings of a list) sprintf( __('%1$s = %2$s'), $item->getTypeName(1), $item->getName() ) ); echo "<tr><th colspan='$colspan'>"; //TRANS : %d is the number of problems echo sprintf(_n('Last %d change', 'Last %d changes', $number), $number); echo "</th></tr>"; } else { echo "<tr><th>" . __('No change found.') . "</th></tr>"; } // Ticket list if ($number > 0) { self::commonListHeader(Search::HTML_OUTPUT); foreach ($iterator as $data) { Session::addToNavigateListItems('Problem', $data["id"]); self::showShort($data["id"]); } self::commonListHeader(Search::HTML_OUTPUT); } echo "</table></div>"; // Tickets for linked items $linkeditems = $item->getLinkedItems(); $restrict = []; if (count($linkeditems)) { foreach ($linkeditems as $ltype => $tab) { foreach ($tab as $lID) { $restrict[] = ['AND' => ['itemtype' => $ltype, 'items_id' => $lID]]; } } } if (count($restrict)) { $criteria = self::getCommonCriteria(); $criteria['WHERE'] = ['OR' => $restrict] + getEntitiesRestrictCriteria(self::getTable()); $iterator = $DB->request($criteria); $number = count($iterator); echo "<div class='spaced'><table class='tab_cadre_fixe'>"; echo "<tr><th colspan='$colspan'>"; echo __('Changes on linked items'); echo "</th></tr>"; if ($number > 0) { self::commonListHeader(Search::HTML_OUTPUT); foreach ($iterator as $data) { // Session::addToNavigateListItems(TRACKING_TYPE,$data["id"]); self::showShort($data["id"]); } self::commonListHeader(Search::HTML_OUTPUT); } else { echo "<tr><th>" . __('No change found.') . "</th></tr>"; } echo "</table></div>"; } } /** * Display debug information for current object * * @since 0.90.2 **/ public function showDebug() { NotificationEvent::debugEvent($this); } public static function getDefaultValues($entity = 0) { $default_use_notif = Entity::getUsedConfig('is_notif_enable_default', $_SESSION['glpiactive_entity'], '', 1); return [ '_users_id_requester' => Session::getLoginUserID(), '_users_id_requester_notif' => [ 'use_notification' => $default_use_notif, 'alternative_email' => '' ], '_groups_id_requester' => 0, '_users_id_assign' => 0, '_users_id_assign_notif' => [ 'use_notification' => $default_use_notif, 'alternative_email' => '' ], '_groups_id_assign' => 0, '_users_id_observer' => 0, '_users_id_observer_notif' => [ 'use_notification' => $default_use_notif, 'alternative_email' => '' ], '_suppliers_id_assign_notif' => [ 'use_notification' => $default_use_notif, 'alternative_email' => '' ], '_groups_id_observer' => 0, '_suppliers_id_assign' => 0, 'priority' => 3, 'urgency' => 3, 'impact' => 3, 'content' => '', 'entities_id' => $_SESSION['glpiactive_entity'], 'name' => '', 'itilcategories_id' => 0, 'actiontime' => 0, '_add_validation' => 0, 'users_id_validate' => [], '_tasktemplates_id' => [], 'controlistcontent' => '', 'impactcontent' => '', 'rolloutplancontent' => '', 'backoutplancontent' => '', 'checklistcontent' => '', 'items_id' => 0, '_actors' => [], ]; } /** * Get active changes for an item * * @since 9.5 * * @param string $itemtype Item type * @param integer $items_id ID of the Item * * @return DBmysqlIterator */ public function getActiveChangesForItem($itemtype, $items_id) { global $DB; return $DB->request([ 'SELECT' => [ $this->getTable() . '.id', $this->getTable() . '.name', $this->getTable() . '.priority', ], 'FROM' => $this->getTable(), 'LEFT JOIN' => [ 'glpi_changes_items' => [ 'ON' => [ 'glpi_changes_items' => 'changes_id', $this->getTable() => 'id' ] ] ], 'WHERE' => [ 'glpi_changes_items.itemtype' => $itemtype, 'glpi_changes_items.items_id' => $items_id, $this->getTable() . '.is_deleted' => 0, 'NOT' => [ $this->getTable() . '.status' => array_merge( $this->getSolvedStatusArray(), $this->getClosedStatusArray() ) ] ] ]); } public static function getIcon() { return "ti ti-clipboard-check"; } public static function getItemLinkClass(): string { return Change_Item::class; } public static function getStatusClass($status) { $class = null; $solid = true; switch ($status) { case self::REFUSED: case self::CANCELED: $class = 'circle'; break; default: return parent::getStatusClass($status); } return $class == null ? '' : 'itilstatus ' . ($solid ? 'fas fa-' : 'far fa-') . $class . " " . static::getStatusKey($status); } public static function getStatusKey($status) { switch ($status) { case self::REFUSED: return 'refused'; case self::CANCELED: return 'canceled'; default: return parent::getStatusKey($status); } } public static function getTaskClass() { return ChangeTask::class; } public static function getContentTemplatesParametersClass(): string { return ChangeParameters::class; } /** * @param $start * @param $status (default 'process') * @param $showgroupchanges (true by default) * @since 10.0.0 * */ public static function showCentralList($start, $status = "process", $showgroupchanges = true) { global $DB, $CFG_GLPI; if (!static::canView()) { return false; } $WHERE = [ 'is_deleted' => 0 ]; $search_users_id = [ 'glpi_changes_users.users_id' => Session::getLoginUserID(), 'glpi_changes_users.type' => CommonITILActor::REQUESTER ]; $search_assign = [ 'glpi_changes_users.users_id' => Session::getLoginUserID(), 'glpi_changes_users.type' => CommonITILActor::ASSIGN ]; if ($showgroupchanges) { $search_users_id = [0]; $search_assign = [0]; if (count($_SESSION['glpigroups'])) { $search_users_id = [ 'glpi_changes_groups.groups_id' => $_SESSION['glpigroups'], 'glpi_changes_groups.type' => CommonITILActor::REQUESTER ]; $search_assign = [ 'glpi_changes_groups.groups_id' => $_SESSION['glpigroups'], 'glpi_changes_groups.type' => CommonITILActor::ASSIGN ]; } } switch ($status) { case "waiting": $WHERE = array_merge( $WHERE, $search_assign, ['status' => self::WAITING] ); break; case "process": $WHERE = array_merge( $WHERE, $search_assign, ['status' => [self::ACCEPTED, self::TEST, self::QUALIFICATION]] ); break; default: $WHERE = array_merge( $WHERE, $search_users_id, [ 'status' => array_diff(self::getAllStatusArray(), self::getClosedStatusArray()) ] ); $WHERE['NOT'] = $search_assign; } $criteria = [ 'SELECT' => ['glpi_changes.id'], 'DISTINCT' => true, 'FROM' => 'glpi_changes', 'LEFT JOIN' => [ 'glpi_changes_users' => [ 'ON' => [ 'glpi_changes_users' => 'changes_id', 'glpi_changes' => 'id' ] ], 'glpi_changes_groups' => [ 'ON' => [ 'glpi_changes_groups' => 'changes_id', 'glpi_changes' => 'id' ] ] ], 'WHERE' => $WHERE + getEntitiesRestrictCriteria('glpi_changes'), 'ORDERBY' => 'date_mod DESC' ]; $iterator = $DB->request($criteria); $total_row_count = count($iterator); $displayed_row_count = min((int)$_SESSION['glpidisplay_count_on_home'], $total_row_count); if ($total_row_count > 0) { $options = [ 'criteria' => [], 'reset' => 'reset', ]; $forcetab = ''; if ($showgroupchanges) { switch ($status) { case "waiting": $options['criteria'][0]['field'] = 12; // status $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = self::WAITING; $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 8; // groups_id_assign $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = 'mygroups'; $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Changes on pending status'), $displayed_row_count, $total_row_count) . "</a>"; break; case "process": $options['criteria'][0]['field'] = 12; // status $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = self::EVALUATION; $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 8; // groups_id_assign $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = 'mygroups'; $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Changes to be processed'), $displayed_row_count, $total_row_count) . "</a>"; break; default: $options['criteria'][0]['field'] = 12; // status $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = 'notold'; $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 71; // groups_id $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = 'mygroups'; $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Your changes in progress'), $displayed_row_count, $total_row_count) . "</a>"; } } else { switch ($status) { case "waiting": $options['criteria'][0]['field'] = 12; // status $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = self::WAITING; $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 5; // users_id_assign $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = Session::getLoginUserID(); $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Changes on pending status'), $displayed_row_count, $total_row_count) . "</a>"; break; case "process": $options['criteria'][0]['field'] = 5; // users_id_assign $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = Session::getLoginUserID(); $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 12; // status $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = 'process'; $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Changes to be processed'), $displayed_row_count, $total_row_count) . "</a>"; break; default: $options['criteria'][0]['field'] = 4; // users_id $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = Session::getLoginUserID(); $options['criteria'][0]['link'] = 'AND'; $options['criteria'][1]['field'] = 12; // status $options['criteria'][1]['searchtype'] = 'equals'; $options['criteria'][1]['value'] = 'notold'; $options['criteria'][1]['link'] = 'AND'; $main_header = "<a href=\"" . $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options, '&') . "\">" . Html::makeTitle(__('Your changes in progress'), $displayed_row_count, $total_row_count) . "</a>"; } } $twig_params = [ 'class' => 'table table-borderless table-striped table-hover card-table', 'header_rows' => [ [ [ 'colspan' => 3, 'content' => $main_header ] ], ], 'rows' => [] ]; $i = 0; if ($displayed_row_count > 0) { $twig_params['header_rows'][] = [ [ 'content' => __('ID'), 'style' => 'width: 75px' ], [ 'content' => _n('Requester', 'Requesters', 1), 'style' => 'width: 20%' ], __('Description') ]; foreach ($iterator as $data) { $change = new self(); $rand = mt_rand(); $row = [ 'values' => [] ]; if ($change->getFromDBwithData($data['id'], 0)) { $bgcolor = $_SESSION["glpipriority_" . $change->fields["priority"]]; $name = sprintf(__('%1$s: %2$s'), __('ID'), $change->fields["id"]); $row['values'][] = [ 'class' => 'priority_block', 'content' => "<span style='background: $bgcolor'></span> $name" ]; $requesters = []; if ( isset($change->users[CommonITILActor::REQUESTER]) && count($change->users[CommonITILActor::REQUESTER]) ) { foreach ($change->users[CommonITILActor::REQUESTER] as $d) { if ($d["users_id"] > 0) { $userdata = getUserName($d["users_id"], 2); $name = '<i class="fas fa-sm fa-fw fa-user text-muted me-1"></i>' . $userdata['name']; $requesters[] = $name; } else { $requesters[] = '<i class="fas fa-sm fa-fw fa-envelope text-muted me-1"></i>' . $d['alternative_email']; } } } if ( isset($change->groups[CommonITILActor::REQUESTER]) && count($change->groups[CommonITILActor::REQUESTER]) ) { foreach ($change->groups[CommonITILActor::REQUESTER] as $d) { $requesters[] = '<i class="fas fa-sm fa-fw fa-users text-muted me-1"></i>' . Dropdown::getDropdownName("glpi_groups", $d["groups_id"]); } } $row['values'][] = implode('<br>', $requesters); $link = "<a id='change" . $change->fields["id"] . $rand . "' href='" . Change::getFormURLWithID($change->fields["id"]); if ($forcetab != '') { $link .= "&forcetab=" . $forcetab; } $link .= "'>"; $link .= "<span class='b'>" . $change->fields["name"] . "</span></a>"; $link = sprintf( __('%1$s %2$s'), $link, Html::showToolTip( RichText::getEnhancedHtml($change->fields['content']), ['applyto' => 'change' . $change->fields["id"] . $rand, 'display' => false ] ) ); $row['values'][] = $link; } else { $row['class'] = 'tab_bg_2'; $row['values'] = [ [ 'colspan' => 6, 'content' => "<i>" . __('No ticket in progress.') . "</i>" ] ]; } $twig_params['rows'][] = $row; $i++; if ($i == $displayed_row_count) { break; } } } TemplateRenderer::getInstance()->display('components/table.html.twig', $twig_params); } } /** * Get changes count * * @since 10.0.0 * * @param bool $foruser only for current login user as requester * @param bool $display if false, return html **/ public static function showCentralCount(bool $foruser = false, bool $display = true) { global $DB, $CFG_GLPI; // show a tab with count of jobs in the central and give link if (!static::canView()) { return false; } if (!Session::haveRight(self::$rightname, self::READALL)) { $foruser = true; } $table = self::getTable(); $criteria = [ 'SELECT' => [ 'status', 'COUNT' => '* AS COUNT', ], 'FROM' => $table, 'WHERE' => getEntitiesRestrictCriteria($table), 'GROUP' => 'status' ]; if ($foruser) { $criteria['LEFT JOIN'] = [ 'glpi_changes_users' => [ 'ON' => [ 'glpi_changes_users' => 'changes_id', $table => 'id', [ 'AND' => [ 'glpi_changes_users.type' => CommonITILActor::REQUESTER ] ] ] ] ]; $WHERE = ['glpi_changes_users.users_id' => Session::getLoginUserID()]; if ( isset($_SESSION["glpigroups"]) && count($_SESSION["glpigroups"]) ) { $criteria['LEFT JOIN']['glpi_changes_groups'] = [ 'ON' => [ 'glpi_changes_groups' => 'changes_id', $table => 'id', [ 'AND' => [ 'glpi_changes_groups.type' => CommonITILActor::REQUESTER ] ] ] ]; $WHERE['glpi_changes_groups.groups_id'] = $_SESSION['glpigroups']; } $criteria['WHERE'][] = ['OR' => $WHERE]; } $deleted_criteria = $criteria; $criteria['WHERE']['glpi_changes.is_deleted'] = 0; $deleted_criteria['WHERE']['glpi_changes.is_deleted'] = 1; $iterator = $DB->request($criteria); $deleted_iterator = $DB->request($deleted_criteria); $status = []; foreach (self::getAllStatusArray() as $key => $val) { $status[$key] = 0; } foreach ($iterator as $data) { $status[$data["status"]] = $data["COUNT"]; } $number_deleted = 0; foreach ($deleted_iterator as $data) { $number_deleted += $data["COUNT"]; } $options = []; $options['criteria'][0]['field'] = 12; $options['criteria'][0]['searchtype'] = 'equals'; $options['criteria'][0]['value'] = 'new'; $options['criteria'][0]['link'] = 'AND'; $options['reset'] = 'reset'; $twig_params = [ 'title' => [ 'link' => $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options), 'text' => self::getTypeName(Session::getPluralNumber()), 'icon' => self::getIcon(), ], 'items' => [] ]; foreach ($status as $key => $val) { $options['criteria'][0]['value'] = $key; $twig_params['items'][] = [ 'link' => $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options), 'text' => self::getStatus($key), 'icon' => self::getStatusClass($key), 'count' => $val ]; } $options['criteria'][0]['value'] = 'all'; $options['is_deleted'] = 1; $twig_params['items'][] = [ 'link' => $CFG_GLPI["root_doc"] . "/front/change.php?" . Toolbox::append_params($options), 'text' => __('Deleted'), 'icon' => 'fas fa-trash bg-red-lt', 'count' => $number_deleted ]; $output = TemplateRenderer::getInstance()->render('central/lists/itemtype_count.html.twig', $twig_params); if ($display) { echo $output; } else { return $output; } } /** * @since 10.0.0 * * @param $ID * @param $forcetab string name of the tab to force at the display (default '') **/ public static function showVeryShort($ID, $forcetab = '') { // Prints a job in short form // Should be called in a <table>-segment // Print links or not in case of user view // Make new job object and fill it from database, if success, print it $viewusers = User::canView(); $change = new self(); $rand = mt_rand(); if ($change->getFromDBwithData($ID, 0)) { $bgcolor = $_SESSION["glpipriority_" . $change->fields["priority"]]; $name = sprintf(__('%1$s: %2$s'), __('ID'), $change->fields["id"]); echo "<tr class='tab_bg_2'>"; echo "<td> <div class='priority_block' style='border-color: $bgcolor'> <span style='background: $bgcolor'></span> $name </div> </td>"; echo "<td class='center'>"; if ( isset($change->users[CommonITILActor::REQUESTER]) && count($change->users[CommonITILActor::REQUESTER]) ) { foreach ($change->users[CommonITILActor::REQUESTER] as $d) { if ($d["users_id"] > 0) { $userdata = getUserName($d["users_id"], 2); $name = "<span class='b'>" . $userdata['name'] . "</span>"; if ($viewusers) { $name = sprintf( __('%1$s %2$s'), $name, Html::showToolTip( $userdata["comment"], ['link' => $userdata["link"], 'display' => false ] ) ); } echo $name; } else { echo $d['alternative_email'] . " "; } echo "<br>"; } } if ( isset($change->groups[CommonITILActor::REQUESTER]) && count($change->groups[CommonITILActor::REQUESTER]) ) { foreach ($change->groups[CommonITILActor::REQUESTER] as $d) { echo Dropdown::getDropdownName("glpi_groups", $d["groups_id"]); echo "<br>"; } } echo "</td>"; echo "<td>"; $link = "<a id='change" . $change->fields["id"] . $rand . "' href='" . Change::getFormURLWithID($change->fields["id"]); if ($forcetab != '') { $link .= "&forcetab=" . $forcetab; } $link .= "'>"; $link .= "<span class='b'>" . $change->fields["name"] . "</span></a>"; $link = printf( __('%1$s %2$s'), $link, Html::showToolTip( $change->fields['content'], ['applyto' => 'change' . $change->fields["id"] . $rand, 'display' => false ] ) ); echo "</td>"; // Finish Line echo "</tr>"; } else { echo "<tr class='tab_bg_2'>"; echo "<td colspan='6' ><i>" . __('No change found.') . "</i></td></tr>"; } } }