diff --git a/src/Ticket.php b/src/Ticket.php index de5df696077b..ae328f4f3c3d 100644 --- a/src/Ticket.php +++ b/src/Ticket.php @@ -5395,6 +5395,7 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0) self::$rightname, [self::READALL, self::READMY, self::READASSIGN, CREATE] ) + && !Session::haveRightsOr(TicketValidation::$rightname, TicketValidation::getValidateRights()) ) { return false; } @@ -5404,65 +5405,23 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0) } $criteria = self::getCommonCriteria(); - $restrict = []; - $options = [ - 'criteria' => [], - 'reset' => 'reset', - ]; + $restrict = self::getListForItemRestrict($item); + $criteria['WHERE'] = $restrict + getEntitiesRestrictCriteria(self::getTable()); + $criteria['WHERE']['glpi_tickets.is_deleted'] = 0; + $criteria['LIMIT'] = (int)$_SESSION['glpilist_limit']; switch (get_class($item)) { - case User::class: - $restrict['glpi_tickets_users.users_id'] = $item->getID(); - $restrict['glpi_tickets_users.type'] = CommonITILActor::REQUESTER; - - $options['criteria'][0]['field'] = 4; // status - $options['criteria'][0]['searchtype'] = 'equals'; - $options['criteria'][0]['value'] = $item->getID(); - $options['criteria'][0]['link'] = 'AND'; - break; - case SLA::class: - $restrict[] = [ - 'OR' => [ - 'slas_id_tto' => $item->getID(), - 'slas_id_ttr' => $item->getID() - ] - ]; $criteria['ORDERBY'] = 'glpi_tickets.time_to_resolve DESC'; - - $options['criteria'][0]['field'] = 30; - $options['criteria'][0]['searchtype'] = 'equals'; - $options['criteria'][0]['value'] = $item->getID(); - $options['criteria'][0]['link'] = 'AND'; break; case OLA::class: - $restrict[] = [ - 'OR' => [ - 'olas_id_tto' => $item->getID(), - 'olas_id_ttr' => $item->getID() - ] - ]; $criteria['ORDERBY'] = 'glpi_tickets.internal_time_to_resolve DESC'; - - $options['criteria'][0]['field'] = 30; - $options['criteria'][0]['searchtype'] = 'equals'; - $options['criteria'][0]['value'] = $item->getID(); - $options['criteria'][0]['link'] = 'AND'; - break; - - case Supplier::class: - $restrict['glpi_suppliers_tickets.suppliers_id'] = $item->getID(); - $restrict['glpi_suppliers_tickets.type'] = CommonITILActor::ASSIGN; - - $options['criteria'][0]['field'] = 6; - $options['criteria'][0]['searchtype'] = 'equals'; - $options['criteria'][0]['value'] = $item->getID(); - $options['criteria'][0]['link'] = 'AND'; break; case Group::class: - // Mini search engine + // Mini search engine + /** @var Group $item */ if ($item->haveChildren()) { $tree = Session::getSavedOption(__CLASS__, 'tree', 0); echo ""; @@ -5479,56 +5438,10 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0) $tree = 0; } echo "
"; - - $restrict['glpi_groups_tickets.groups_id'] = ($tree ? getSonsOf('glpi_groups', $item->getID()) : $item->getID()); - $restrict['glpi_groups_tickets.type'] = CommonITILActor::REQUESTER; - - $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['glpi_items_tickets.items_id'] = $item->getID(); - $restrict['glpi_items_tickets.itemtype'] = $item->getType(); - - // you can only see your tickets - if (!Session::haveRight(self::$rightname, self::READALL)) { - $or = [ - 'glpi_tickets.users_id_recipient' => Session::getLoginUserID(), - [ - 'AND' => [ - 'glpi_tickets_users.tickets_id' => new \QueryExpression('glpi_tickets.id'), - 'glpi_tickets_users.users_id' => Session::getLoginUserID() - ] - ] - ]; - if (count($_SESSION['glpigroups'])) { - $or['glpi_groups_tickets.groups_id'] = $_SESSION['glpigroups']; - } - $restrict[] = ['OR' => $or]; - } - - $options['criteria'][0]['field'] = 12; - $options['criteria'][0]['searchtype'] = 'equals'; - $options['criteria'][0]['value'] = 'all'; - $options['criteria'][0]['link'] = 'AND'; - - $options['metacriteria'][0]['itemtype'] = $item->getType(); - $options['metacriteria'][0]['field'] = Search::getOptionNumber( - $item->getType(), - 'id' - ); - $options['metacriteria'][0]['searchtype'] = 'equals'; - $options['metacriteria'][0]['value'] = $item->getID(); - $options['metacriteria'][0]['link'] = 'AND'; + /** @var CommonDBTM $item */ break; } - $criteria['WHERE'] = $restrict + getEntitiesRestrictCriteria(self::getTable()); - $criteria['WHERE']['glpi_tickets.is_deleted'] = 0; - $criteria['LIMIT'] = (int)$_SESSION['glpilist_limit']; $iterator = $DB->request($criteria); $number = count($iterator); @@ -5590,6 +5503,7 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0) ) ); + $options = self::getListForItemSearchOptionsCriteria($item); echo ""; $title = sprintf(_n('Last %d ticket', 'Last %d tickets', $number), $number); $link = " [ + self::getTable() => 'id', + 'glpi_ticketvalidations' => 'tickets_id' + ] + ]; + return $criteria; } @@ -7077,4 +6998,145 @@ public static function getContentTemplatesParametersClass(): string { return TicketParameters::class; } + + public static function getListForItemRestrict(CommonDBTM $item) + { + $restrict = []; + + switch (get_class($item)) { + case User::class: + $restrict['glpi_tickets_users.users_id'] = $item->getID(); + $restrict['glpi_tickets_users.type'] = CommonITILActor::REQUESTER; + break; + + case SLA::class: + $restrict[] = [ + 'OR' => [ + 'slas_id_tto' => $item->getID(), + 'slas_id_ttr' => $item->getID() + ] + ]; + break; + + case OLA::class: + $restrict[] = [ + 'OR' => [ + 'olas_id_tto' => $item->getID(), + 'olas_id_ttr' => $item->getID() + ] + ]; + break; + + case Supplier::class: + $restrict['glpi_suppliers_tickets.suppliers_id'] = $item->getID(); + $restrict['glpi_suppliers_tickets.type'] = CommonITILActor::ASSIGN; + break; + + case Group::class: + /** @var Group $item */ + if ($item->haveChildren()) { + $tree = Session::getSavedOption(__CLASS__, 'tree', 0); + } else { + $tree = 0; + } + $restrict['glpi_groups_tickets.groups_id'] = ($tree ? getSonsOf('glpi_groups', $item->getID()) : $item->getID()); + $restrict['glpi_groups_tickets.type'] = CommonITILActor::REQUESTER; + /** @var CommonDBTM $item */ + break; + + default: + $restrict['glpi_items_tickets.items_id'] = $item->getID(); + $restrict['glpi_items_tickets.itemtype'] = $item->getType(); + // you can only see your tickets + if (!Session::haveRight(self::$rightname, self::READALL)) { + $or = [ + 'glpi_tickets.users_id_recipient' => Session::getLoginUserID(), + [ + 'AND' => [ + 'glpi_tickets_users.tickets_id' => new \QueryExpression('glpi_tickets.id'), + 'glpi_tickets_users.users_id' => Session::getLoginUserID() + ] + ] + ]; + if (Session::haveRightsOr(TicketValidation::$rightname, [TicketValidation::VALIDATEINCIDENT, TicketValidation::VALIDATEREQUEST])) { + $or[] = [ + 'AND' => [ + 'glpi_ticketvalidations.tickets_id' => new \QueryExpression('glpi_tickets.id'), + 'glpi_ticketvalidations.users_id_validate' => Session::getLoginUserID(), + ] + ]; + } + if (count($_SESSION['glpigroups'])) { + $or['glpi_groups_tickets.groups_id'] = $_SESSION['glpigroups']; + } + $restrict[] = ['OR' => $or]; + } + } + + return $restrict; + } + + private static function getListForItemSearchOptionsCriteria(CommonDBTM $item): array + { + $options = [ + 'criteria' => [], + 'reset' => 'reset', + ]; + + switch (get_class($item)) { + case User::class: + $options['criteria'][0]['field'] = 4; // status + $options['criteria'][0]['searchtype'] = 'equals'; + $options['criteria'][0]['value'] = $item->getID(); + $options['criteria'][0]['link'] = 'AND'; + break; + + case SLA::class: + case OLA::class: + $options['criteria'][0]['field'] = 30; + $options['criteria'][0]['searchtype'] = 'equals'; + $options['criteria'][0]['value'] = $item->getID(); + $options['criteria'][0]['link'] = 'AND'; + break; + + case Supplier::class: + $options['criteria'][0]['field'] = 6; + $options['criteria'][0]['searchtype'] = 'equals'; + $options['criteria'][0]['value'] = $item->getID(); + $options['criteria'][0]['link'] = 'AND'; + break; + + case Group::class: + /** @var Group $item */ + if ($item->haveChildren()) { + $tree = Session::getSavedOption(__CLASS__, 'tree', 0); + } else { + $tree = 0; + } + $options['criteria'][0]['field'] = 71; + $options['criteria'][0]['searchtype'] = ($tree ? 'under' : 'equals'); + $options['criteria'][0]['value'] = $item->getID(); + $options['criteria'][0]['link'] = 'AND'; + /** @var CommonDBTM $item */ + break; + + default: + $options['criteria'][0]['field'] = 12; + $options['criteria'][0]['searchtype'] = 'equals'; + $options['criteria'][0]['value'] = 'all'; + $options['criteria'][0]['link'] = 'AND'; + + $options['metacriteria'][0]['itemtype'] = $item->getType(); + $options['metacriteria'][0]['field'] = Search::getOptionNumber( + $item->getType(), + 'id' + ); + $options['metacriteria'][0]['searchtype'] = 'equals'; + $options['metacriteria'][0]['value'] = $item->getID(); + $options['metacriteria'][0]['link'] = 'AND'; + break; + } + + return $options; + } } diff --git a/tests/functional/Ticket.php b/tests/functional/Ticket.php index 54501692afe1..271445f623ec 100644 --- a/tests/functional/Ticket.php +++ b/tests/functional/Ticket.php @@ -54,6 +54,7 @@ use Ticket_User; use TicketValidation; use User; +use Session; /* Test for inc/ticket.class.php */ @@ -6984,4 +6985,70 @@ public function testRestrictedDropdownValues() $this->array($values['results'])->size->isGreaterThan(1); $this->boolean($fn_dropdown_has_id($values['results'], $not_my_tickets_id))->isTrue(); } + + public function testGetCommonCriteria() + { + global $DB; + + $this->login('tech', 'tech'); + + $item = new \Project(); + $item->add([ + 'name' => $this->getUniqueString(), + ]); + $this->boolean($item->isNewItem())->isFalse(); + + // Find tickets already in the entity + $request = \Ticket::getCommonCriteria(); + $request['WHERE'] = $this->callPrivateMethod(new \Ticket(), 'getListForItemRestrict', $item); + $request['WHERE'] = $request['WHERE'] + getEntitiesRestrictCriteria(\Ticket::getTable()); + $result = $DB->request($request); + $existing_tickets = $result->count(); + + // Create a ticket with no actor and a valdiator + $ticket = new \Ticket(); + $ticket->add([ + 'name' => __FUNCTION__, + 'content' => __FUNCTION__, + 'entities_id' => $this->getTestRootEntity(true), + 'users_id_recipient' => getItemByTypeName(User::class, 'tech', true), + ]); + $this->boolean($ticket->isNewItem())->isFalse(); + + $item_ticket = new \Item_Ticket(); + $item_ticket->add([ + 'tickets_id' => $ticket->getID(), + 'itemtype' => $item->getType(), + 'items_id' => $item->getID(), + ]); + $this->boolean($item_ticket->isNewItem())->isFalse(); + + $user = new \Ticket_User(); + $users = $user->find([ + 'tickets_id' => $ticket->getID(), + ]); + $this->integer(count($users))->IsEqualTo(0); + + $this->login('post-only', 'postonly'); + $_SESSION['glpiactiveprofile'][\TicketValidation::$rightname] = \TicketValidation::VALIDATEINCIDENT + \TicketValidation::VALIDATEREQUEST; + + // Check the ticket is not found + $request['WHERE'] = $this->callPrivateMethod(new \Ticket(), 'getListForItemRestrict', $item); + $request['WHERE'] = $request['WHERE'] + getEntitiesRestrictCriteria(\Ticket::getTable()); + $result = $DB->request($request); + $this->integer($result->count())->isEqualTo($existing_tickets); + + $ticket_valdiation = new TicketValidation(); + $ticket_valdiation->add([ + 'tickets_id' => $ticket->getID(), + 'entities_id' => $ticket->fields['entities_id'], + 'users_id_validate' => Session::getLoginUserID(), + 'timeline_position' => 1, + ]); + $this->boolean($ticket_valdiation->isNewItem())->isFalse(); + + // Check the ticket under valdiation is found + $result = $DB->request($request); + $this->integer($result->count())->isEqualTo($existing_tickets + 1); + } }