Current File : /home/escuelai/public_html/it/src/Dashboard/Provider.php |
<?php
/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2022 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/>.
*
* ---------------------------------------------------------------------
*/
namespace Glpi\Dashboard;
use Change;
use CommonDBTM;
use CommonITILActor;
use CommonITILObject;
use CommonITILValidation;
use CommonTreeDropdown;
use CommonDevice;
use Config;
use DBConnection;
use Group;
use Group_Ticket;
use ITILCategory;
use Problem;
use Profile_User;
use QueryExpression;
use QuerySubQuery;
use Search;
use Session;
use Stat;
use Ticket;
use Ticket_User;
use Toolbox;
use User;
/**
* Provider class
**/
class Provider
{
/**
* Retrieve the number of element for a given item
*
* @param CommonDBTM|null object to count
*
* @param array $params default values for
* - 'apply_filters' values from dashboard filters
*
* @return array :
* - 'number'
* - 'url'
* - 'label'
* - 'icon'
*/
public static function bigNumberItem(CommonDBTM $item = null, array $params = []): array
{
$DB = DBConnection::getReadConnection();
$default_params = [
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$i_table = $item::getTable();
$where = [];
if (isset($item->fields['is_deleted'])) {
$where['is_deleted'] = 0;
}
if (isset($item->fields['is_template'])) {
$where['is_template'] = 0;
}
if ($item instanceof User) {
$where += getEntitiesRestrictCriteria(Profile_User::getTable());
$request = [
'SELECT' => ['COUNT DISTINCT' => $item::getTableField($item::getIndexName()) . ' as cpt'],
'FROM' => $i_table,
'INNER JOIN' => [
Profile_User::getTable() => [
'FKEY' => [
Profile_User::getTable() => 'users_id',
User::getTable() => 'id',
]
]
] ,
'WHERE' => $where
];
} else {
if ($item->isEntityAssign()) {
$where += getEntitiesRestrictCriteria($item::getTable());
}
$request = [
'SELECT' => ['COUNT DISTINCT' => $item::getTableField($item::getIndexName()) . ' as cpt'],
'FROM' => $i_table,
'WHERE' => $where
];
}
$criteria = array_merge_recursive(
$request,
self::getFiltersCriteria($i_table, $params['apply_filters']),
$item instanceof Ticket ? Ticket::getCriteriaFromProfile() : []
);
$iterator = $DB->request($criteria);
$result = $iterator->current();
$nb_items = $result['cpt'];
$search_criteria = [
[
self::getSearchFiltersCriteria($i_table, $params['apply_filters'])
]
];
$search_url = $item::getSearchURL();
$url = $search_url . (str_contains($search_url, '?') ? '&' : '?') . Toolbox::append_params([
$search_criteria,
'reset' => 'reset',
]);
return [
'number' => $nb_items,
'url' => $url,
'label' => $item::getTypeName($nb_items),
'icon' => $item::getIcon(),
];
}
/**
* @method self::bigNumberItem
* @method self::nbItemByFk
*/
public static function __callStatic(string $name = "", array $arguments = [])
{
if (strpos($name, 'bigNumber') !== false) {
$itemtype = str_replace('bigNumber', '', $name);
if (is_subclass_of($itemtype, 'CommonDBTM')) {
$item = new $itemtype();
$item->getEmpty();
return self::bigNumberItem($item, $arguments[0] ?? []);
}
}
if (
strpos($name, 'multipleNumber') !== false
&& strpos($name, 'By') !== false
) {
$tmp = str_replace('multipleNumber', '', $name);
$tmp = explode('By', $tmp);
if (count($tmp) === 2) {
$itemtype = $tmp[0];
$fk_itemtype = $tmp[1];
return self::nbItemByFk(
new $itemtype(),
new $fk_itemtype(),
$arguments[0] ?? []
);
}
}
if (strpos($name, 'getArticleList') !== false) {
$itemtype = str_replace('getArticleList', '', $name);
if (is_subclass_of($itemtype, 'CommonDBTM')) {
$item = new $itemtype();
$item->getEmpty();
return self::articleListItem($item, $arguments[0] ?? []);
}
}
}
/**
* Count number of tickets for a given case
*
* @param string $case:
* - 'notold': not closed or solved tickets
* - 'late': late tickets
* - 'waiting_validation': tickets waiting validation for connected user
* - 'incoming': ticket with incoming status
* - 'waiting': ticket with waiting status
* - 'assigned': ticket with assigned status
* - 'planned': ticket with planned status
* - 'solved': ticket with solved status
* - 'closed': ticket with closed status
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array :
* - 'number'
* - 'url'
* - 'label'
* - 'icon'
*/
public static function nbTicketsGeneric(
string $case = "",
array $params = []
): array {
$DBread = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => Ticket::getIcon(),
'apply_filters' => [],
'validation_check_user' => false,
];
$params = array_merge($default_params, $params);
$nb_tickets = 0;
$query_criteria = [];
$search_criteria = [];
$skip = false;
$notold = [
'field' => 12,
'searchtype' => 'equals',
'value' => 'notold',
];
$table = Ticket::getTable();
$query_criteria = [
'SELECT' => [
'COUNT DISTINCT' => "$table.id AS cpt",
],
'FROM' => $table,
'WHERE' => [
"$table.is_deleted" => 0,
] + getEntitiesRestrictCriteria($table),
];
$query_criteria = array_merge_recursive(
$query_criteria,
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($table, $params['apply_filters'])
);
switch ($case) {
case 'notold':
$search_criteria = [$notold];
$params['label'] = _x('status', 'Not solved');
$query_criteria['WHERE'] += [
"$table.status" => Ticket::getNotSolvedStatusArray(),
];
break;
case 'late':
$params['icon'] = "far fa-clock";
$params['label'] = __("Late tickets");
$search_criteria = array_merge([$notold], [
[
'link' => 'AND',
'criteria' => [
[
'field' => 82,
'searchtype' => 'equals',
'value' => 1,
], [
'link' => 'OR',
'field' => 182,
'searchtype' => 'equals',
'value' => 1,
], [
'link' => 'OR',
'field' => 159,
'searchtype' => 'equals',
'value' => 1,
], [
'link' => 'OR',
'field' => 187,
'searchtype' => 'equals',
'value' => 1,
]
]
]
]);
$query_criteria['WHERE']["$table.status"] = Ticket::getNotSolvedStatusArray();
$query_criteria['WHERE'][] = [
'OR' => [
CommonITILObject::generateSLAOLAComputation('time_to_resolve', 'glpi_tickets'),
CommonITILObject::generateSLAOLAComputation('internal_time_to_resolve', 'glpi_tickets'),
CommonITILObject::generateSLAOLAComputation('time_to_own', 'glpi_tickets'),
CommonITILObject::generateSLAOLAComputation('internal_time_to_own', 'glpi_tickets'),
]
];
break;
case 'waiting_validation':
$params['icon'] = "far fa-eye";
$params['label'] = __("Tickets waiting for validation");
$search_criteria = [
[
'field' => 55,
'searchtype' => 'equals',
'value' => CommonITILValidation::WAITING,
]
];
if ($params['validation_check_user']) {
$search_criteria[] = [
'link' => 'AND',
'field' => 59,
'searchtype' => 'equals',
'value' => Session::getLoginUserID(),
];
}
$where = [
'glpi_ticketvalidations.status' => CommonITILValidation::WAITING,
];
if ($params['validation_check_user']) {
$where['glpi_ticketvalidations.users_id_validate'] = Session::getLoginUserID();
}
$query_criteria = array_merge_recursive($query_criteria, [
'LEFT JOIN' => [
'glpi_ticketvalidations' => [
'ON' => [
'glpi_ticketvalidations' => 'tickets_id',
$table => 'id'
]
]
],
'WHERE' => $where,
]);
break;
// Statuses speciale cases (no break)
case 'incoming':
$status = Ticket::INCOMING;
$params['icon'] = Ticket::getIcon();
$params['label'] = __("Incoming tickets");
$skip = true;
//no break
case 'waiting':
if (!$skip) {
$status = Ticket::WAITING;
$params['icon'] = "fas fa-pause-circle";
$params['label'] = __("Pending tickets");
$skip = true;
}
//no break
case 'assigned':
if (!$skip) {
$status = Ticket::ASSIGNED;
$params['icon'] = "fas fa-users";
$params['label'] = __("Assigned tickets");
$skip = true;
}
//no break
case 'planned':
if (!$skip) {
$status = Ticket::PLANNED;
$params['icon'] = "fas fa-calendar-check";
$params['label'] = __("Planned tickets");
$skip = true;
}
//no break
case 'solved':
if (!$skip) {
$status = Ticket::SOLVED;
$params['icon'] = "far fa-check-square";
$params['label'] = __("Solved tickets");
$skip = true;
}
//no break
case 'closed':
if (!$skip) {
$status = Ticket::CLOSED;
$params['icon'] = "fas fa-archive";
$params['label'] = __("Closed tickets");
$skip = true;
}
//no break
case 'status':
if (!$skip) {
$status = Ticket::INCOMING;
}
$search_criteria = [
[
'field' => 12,
'searchtype' => 'equals',
'value' => $status,
]
];
$query_criteria = array_merge_recursive($query_criteria, [
'WHERE' => [
"$table.status" => $status,
]
]);
break;
}
$search_criteria['criteria'] = self::getSearchFiltersCriteria($table, $params['apply_filters']);
$url = Ticket::getSearchURL() . "?" . Toolbox::append_params([
'criteria' => $search_criteria,
'reset' => 'reset'
]);
$iterator = $DBread->request($query_criteria);
$result = $iterator->current();
$nb_tickets = $result['cpt'];
return [
'number' => $nb_tickets,
'url' => $url,
'label' => $params['label'],
'icon' => $params['icon'],
's_criteria' => $search_criteria,
'itemtype' => 'Ticket',
];
}
public static function nbTicketsByAgreementStatusAndTechnician(
array $params = []
): array {
$DBread = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => 'fas fa-stopwatch',
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$query_criteria = [];
$table = Ticket::getTable();
$ticketUserTable = Ticket_User::getTable();
$userTable = User::getTable();
$ownExceeded = Ticket::generateSLAOLAComputation('time_to_own', $table);
$resolveExceeded = Ticket::generateSLAOLAComputation('time_to_resolve', $table);
$slaState = "IF ($ownExceeded AND $resolveExceeded, 3, IF ($resolveExceeded, 2, IF ($ownExceeded, 1, 0)))";
$config = Config::getConfigurationValues('core');
if ($config['names_format'] == User::FIRSTNAME_BEFORE) {
$first = "firstname";
$second = "realname";
} else {
$first = "realname";
$second = "firstname";
}
$friendlyName = "CONCAT(`$userTable`.$first, ' ', `$userTable`.$second)";
$query_criteria = [
'COUNT' => 'cpt',
'SELECT' => [
new QueryExpression("$friendlyName as `username`"),
"$userTable.name",
new QueryExpression("$slaState as `sla_state`"),
],
'FROM' => $table,
'INNER JOIN' => [
"$ticketUserTable as ul" => [
'FKEY' => [
'ul' => 'tickets_id',
$table => 'id',
[
'AND' => [
"ul.type" => Ticket_User::ASSIGN
]
]
],
],
$userTable => [
'FKEY' => [
$userTable => 'id',
'ul' => 'users_id',
],
],
],
'WHERE' => [
"$table.is_deleted" => 0,
] + getEntitiesRestrictCriteria($table),
'GROUPBY' => [
'sla_state',
"$userTable.id",
],
'ORDER' => [
'sla_state DESC',
'cpt DESC',
"$userTable.id",
]
];
unset($params['apply_filters']['group_tech']);
$query_filter = self::getFiltersCriteria($table, $params['apply_filters']);
unset($query_filter['LEFT JOIN']["$ticketUserTable as ul"]);
$query_criteria = array_merge_recursive(
$query_criteria,
Ticket::getCriteriaFromProfile(),
$query_filter
);
$allLate = [];
$resolveLate = [];
$ownLate = [];
$onTime = [];
$names = [];
$data = [];
// Get data and sort by is_late status
$iterator = $DBread->request($query_criteria);
foreach ($iterator as $row) {
switch ($row['sla_state']) {
case 3: // Own and resolve are both late
$allLate[$row['name']] = $row['cpt'];
break;
case 2: // Resolve is late
$resolveLate[$row['name']] = $row['cpt'];
break;
case 1: // own is late
$ownLate[$row['name']] = $row['cpt'];
break;
case 0:
$onTime[$row['name']] = $row['cpt'];
}
$names[$row['name']] = $row['username'];
}
// set legend for each serie
$data['series'][0]['name'] = __('Late own and resolve');
$data['series'][1]['name'] = __('Late resolve');
$data['series'][2]['name'] = __('Late own');
$data['series'][3]['name'] = __('On time');
$data['series'][0]['data'] = [];
$data['series'][1]['data'] = [];
$data['series'][2]['data'] = [];
$data['series'][3]['data'] = [];
// ensure thare are 2 values per user (late and in time)
foreach ($names as $name => $username) {
if (!isset($allLate[$name])) {
$allLate[$name] = 0;
}
if (!isset($resolveLate[$name])) {
$resolveLate[$name] = 0;
}
if (!isset($ownLate[$name])) {
$ownLate[$name] = 0;
}
if (!isset($onTime[$name])) {
$onTime[$name] = 0;
}
$label = $username ?? $name;
$data['labels'][] = $label;
array_unshift($data['series'][0]['data'], $allLate[$name]);
array_unshift($data['series'][1]['data'], $resolveLate[$name]);
array_unshift($data['series'][2]['data'], $ownLate[$name]);
array_unshift($data['series'][3]['data'], $onTime[$name]);
}
if (count($data['series'][0]['data']) < 1) {
$data['series'][0]['data'] = [];
$data['series'][1]['data'] = [];
$data['series'][2]['data'] = [];
$data['series'][3]['data'] = [];
$data['labels'] = [];
$data['nodata'] = true;
}
return [
'label' => __('Tickets by SLA status and by technician'),
'data' => $data,
'icon' => $params['icon'],
];
}
public static function nbTicketsByAgreementStatusAndTechnicianGroup(
array $params = []
): array {
$DBread = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => 'fas fa-stopwatch',
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$query_criteria = [];
$table = Ticket::getTable();
$ticketGroupTable = Group_Ticket::getTable();
$groupTable = Group::getTable();
$ownExceeded = Ticket::generateSLAOLAComputation('time_to_own', $table);
$resolveExceeded = Ticket::generateSLAOLAComputation('time_to_resolve', $table);
$slaState = "IF ($ownExceeded AND $resolveExceeded, 3, IF ($resolveExceeded, 2, IF ($ownExceeded, 1, 0)))";
$query_criteria = [
'COUNT' => 'cpt',
'SELECT' => [
"$groupTable.name",
new QueryExpression("$slaState as `sla_state`"),
],
'FROM' => $table,
'INNER JOIN' => [
"$ticketGroupTable as gl" => [
'FKEY' => [
'gl' => 'tickets_id',
$table => 'id',
[
'AND' => [
"gl.type" => Ticket_User::ASSIGN
]
]
],
],
$groupTable => [
'FKEY' => [
$groupTable => 'id',
'gl' => 'groups_id',
],
],
],
'WHERE' => [
"$table.is_deleted" => 0,
] + getEntitiesRestrictCriteria($table),
'GROUPBY' => [
'sla_state',
"$groupTable.id",
],
'ORDER' => [
'sla_state DESC',
'cpt DESC',
"$groupTable.id",
]
];
unset($params['apply_filters']['user_tech']);
$query_filter = self::getFiltersCriteria($table, $params['apply_filters']);
unset($query_filter['LEFT JOIN']["$ticketGroupTable as gl"]);
$query_criteria = array_merge_recursive(
$query_criteria,
Ticket::getCriteriaFromProfile(),
$query_filter
);
$allLate = [];
$resolveLate = [];
$ownLate = [];
$onTime = [];
$names = [];
$data = [];
// Get data and sort by is_late status
$iterator = $DBread->request($query_criteria);
foreach ($iterator as $row) {
switch ($row['sla_state']) {
case 3: // Own and resolve are both late
$allLate[$row['name']] = $row['cpt'];
break;
case 2: // Resolve is late
$resolveLate[$row['name']] = $row['cpt'];
break;
case 1: // own is late
$ownLate[$row['name']] = $row['cpt'];
break;
case 0:
$onTime[$row['name']] = $row['cpt'];
}
$names[$row['name']] = $row['name'];
}
// set legend for each serie
$data['series'][0]['name'] = __('Late own and resolve');
$data['series'][1]['name'] = __('Late resolve');
$data['series'][2]['name'] = __('Late own');
$data['series'][3]['name'] = __('On time');
$data['series'][0]['data'] = [];
$data['series'][1]['data'] = [];
$data['series'][2]['data'] = [];
$data['series'][3]['data'] = [];
// ensure thare are 2 values per user (late and in time)
foreach ($names as $name => $username) {
if (!isset($allLate[$name])) {
$allLate[$name] = 0;
}
if (!isset($resolveLate[$name])) {
$resolveLate[$name] = 0;
}
if (!isset($ownLate[$name])) {
$ownLate[$name] = 0;
}
if (!isset($onTime[$name])) {
$onTime[$name] = 0;
}
$label = $username ?? $name;
$data['labels'][] = $label;
array_unshift($data['series'][0]['data'], $allLate[$name]);
array_unshift($data['series'][1]['data'], $resolveLate[$name]);
array_unshift($data['series'][2]['data'], $ownLate[$name]);
array_unshift($data['series'][3]['data'], $onTime[$name]);
}
if (count($data['series'][0]['data']) < 1) {
$data['series'][0]['data'] = [];
$data['series'][1]['data'] = [];
$data['series'][2]['data'] = [];
$data['series'][3]['data'] = [];
$data['labels'] = [];
$data['nodata'] = true;
}
return [
'label' => __('Tickets by SLA status and by technician group'),
'data' => $data,
'icon' => $params['icon'],
];
}
/**
* Get multiple counts of computer by a specific foreign key
*
* @param CommonDBTM $item main item to count
* @param CommonDBTM $fk_item groupby by this item (we will find the foreign key in the main item)
* @param array $params values for:
* - 'title' of the card
* - 'icon' of the card
* - 'searchoption_id' id corresponding to FK search option
* - 'limit' max data to return
* - 'join_key' LEFT, INNER, etc JOIN
* - 'apply_filters' values from dashboard filters
*
* @return array :
* - 'data': [
* 'url'
* 'number'
* 'label'
* ]
* - 'label'
* - 'icon'
*/
public static function nbItemByFk(
CommonDBTM $item = null,
CommonDBTM $fk_item = null,
array $params = []
): array {
$DB = DBConnection::getReadConnection();
$c_table = $item::getTable();
$fk_table = $fk_item::getTable();
$fk_itemtype = $fk_item::getType();
// try to autodetect searchoption id
$searchoptions = $item->rawSearchOptions();
$found_so = array_filter($searchoptions, function ($searchoption) use ($fk_table) {
return isset($searchoption['table']) && $searchoption['table'] === $fk_table;
});
$found_so = array_shift($found_so);
$found_so_id = $found_so['id'] ?? 0;
$default_params = [
'label' => "",
'searchoption_id' => $found_so_id,
'icon' => $fk_item::getIcon() ?? $item::getIcon(),
'limit' => 50,
'join_key' => 'LEFT JOIN',
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$where = [];
if ($item->maybeDeleted()) {
$where["$c_table.is_deleted"] = 0;
}
if ($item->maybeTemplate()) {
$where["$c_table.is_template"] = 0;
}
$name = 'name';
if ($fk_item instanceof CommonTreeDropdown) {
$name = 'completename';
}
if ($fk_item instanceof CommonDevice) {
$name = 'designation';
}
if ($item->isEntityAssign()) {
$where += getEntitiesRestrictCriteria($c_table, '', '', $item->maybeRecursive());
}
$criteria = array_merge_recursive(
[
'SELECT' => [
"$fk_table.$name AS fk_name",
"$fk_table.id AS fk_id",
'COUNT DISTINCT' => "$c_table.id AS cpt",
],
'FROM' => $c_table,
$params['join_key'] => [
$fk_table => [
'ON' => [
$fk_table => 'id',
$c_table => getForeignKeyFieldForItemType($fk_itemtype),
]
]
],
'GROUPBY' => "$fk_table.$name",
'ORDERBY' => "cpt DESC",
'LIMIT' => $params['limit'],
],
count($where) ? ['WHERE' => $where] : [],
self::getFiltersCriteria($c_table, $params['apply_filters']),
$item instanceof Ticket ? Ticket::getCriteriaFromProfile() : []
);
$iterator = $DB->request($criteria);
$search_criteria = [
'criteria' => [
[
'field' => $params['searchoption_id'],
'searchtype' => 'equals',
'value' => 0
],
self::getSearchFiltersCriteria($fk_table, $params['apply_filters'])
],
'reset' => 'reset',
];
$url = $item::getSearchURL();
$url .= (strpos($url, '?') !== false ? '&' : '?') . 'reset';
$data = [];
foreach ($iterator as $result) {
$search_criteria['criteria'][0]['value'] = $result['fk_id'] ?? 0;
$data[] = [
'number' => $result['cpt'],
'label' => $result['fk_name'] ?? __("without"),
'url' => $url . '&' . Toolbox::append_params($search_criteria),
];
}
if (count($data) === 0) {
$data = [
'nodata' => true
];
}
return [
'data' => $data,
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* Get a list of article for an compatible item (with date,name,text fields)
*
* @param CommonDBTM $item the itemtype to list
* @param array $params default values for
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function articleListItem(CommonDBTM $item = null, array $params = []): array
{
$DB = DBConnection::getReadConnection();
$default_params = [
'icon' => $item::getIcon(),
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$i_table = $item::getTable();
$criteria = array_merge_recursive(
[
'SELECT' => "$i_table.*",
'FROM' => $i_table
],
self::getFiltersCriteria($i_table, $params['apply_filters'])
);
$iterator = $DB->request($criteria);
$data = [];
foreach ($iterator as $line) {
$data[] = [
'date' => $line['date'] ?? '',
'label' => $line['name'] ?? '',
'content' => $line['text'] ?? '',
'author' => User::getFriendlyNameById($line['users_id'] ?? 0),
'url' => $item::getFormURLWithID($line['id']),
];
}
$nb_items = count($data);
if ($nb_items === 0) {
$data = [
'nodata' => true
];
}
return [
'data' => $data,
'number' => $nb_items,
'url' => $item::getSearchURL(),
'label' => $item::getTypeName($nb_items),
'icon' => $item::getIcon(),
];
}
/**
* get multiple count of ticket by month
*
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function ticketsOpened(array $params = []): array
{
$DB = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => Ticket::getIcon(),
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$t_table = Ticket::getTable();
$criteria = array_merge_recursive(
[
'SELECT' => [
'COUNT DISTINCT' => "$t_table.id as nb_tickets",
new QueryExpression("DATE_FORMAT(" . $DB->quoteName("date") . ", '%Y-%m') AS ticket_month")
],
'FROM' => $t_table,
'WHERE' => [
"$t_table.is_deleted" => 0,
] + getEntitiesRestrictCriteria($t_table),
'GROUPBY' => 'ticket_month',
'ORDER' => 'ticket_month ASC'
],
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($t_table, $params['apply_filters'])
);
$iterator = $DB->request($criteria);
$s_criteria = [
'criteria' => [
[
'link' => 'AND',
'field' => 15,
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 15,
'searchtype' => 'lessthan',
'value' => null
],
],
'reset' => 'reset'
];
$data = [];
foreach ($iterator as $result) {
list($start_day, $end_day) = self::formatMonthyearDates($result['ticket_month']);
$s_criteria['criteria'][0]['value'] = $start_day;
$s_criteria['criteria'][1]['value'] = $end_day;
$data[] = [
'number' => $result['nb_tickets'],
'label' => $result['ticket_month'],
'url' => Ticket::getSearchURL() . "?" . Toolbox::append_params($s_criteria),
];
}
return [
'data' => $data,
'distributed' => false,
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* Get ticket evolution by opened, solved, closed, late series and months group
*
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function getTicketsEvolution(array $params = []): array
{
$default_params = [
'label' => "",
'icon' => Ticket::getIcon(),
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$year = date("Y") - 15;
$begin = date("Y-m-d", mktime(1, 0, 0, (int)date("m"), (int)date("d"), $year));
$end = date("Y-m-d");
if (
isset($params['apply_filters']['dates'])
&& count($params['apply_filters']['dates']) == 2
) {
$begin = date("Y-m-d", strtotime($params['apply_filters']['dates'][0]));
$end = date("Y-m-d", strtotime($params['apply_filters']['dates'][1]));
unset($params['apply_filters']['dates']);
}
$t_table = Ticket::getTable();
$series = [
'inter_total' => [
'name' => _nx('ticket', 'Opened', 'Opened', Session::getPluralNumber()),
'search' => [
'criteria' => [
[
'link' => 'AND',
'field' => 15, // creation date
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 15, // creation date
'searchtype' => 'lessthan',
'value' => null
],self::getSearchFiltersCriteria($t_table, $params['apply_filters']),
],
'reset' => 'reset'
]
],
'inter_solved' => [
'name' => _nx('ticket', 'Solved', 'Solved', Session::getPluralNumber()),
'search' => [
'criteria' => [
[
'link' => 'AND',
'field' => 17, // solve date
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 17, // solve date
'searchtype' => 'lessthan',
'value' => null
],self::getSearchFiltersCriteria($t_table, $params['apply_filters']),
],
'reset' => 'reset'
]
],
'inter_solved_late' => [
'name' => __('Late'),
'search' => [
'criteria' => [
[
'link' => 'AND',
'field' => 17, // solve date
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 17, // solve date
'searchtype' => 'lessthan',
'value' => null
], [
'link' => 'AND',
'field' => 82, // time_to_resolve exceed solve date
'searchtype' => 'equals',
'value' => 1
],self::getSearchFiltersCriteria($t_table, $params['apply_filters']),
],
'reset' => 'reset'
]
],
'inter_closed' => [
'name' => __('Closed'),
'search' => [
'criteria' => [
[
'link' => 'AND',
'field' => 16, // close date
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 16, // close date
'searchtype' => 'lessthan',
'value' => null
],self::getSearchFiltersCriteria($t_table, $params['apply_filters']),
],
'reset' => 'reset'
]
],
];
$filters = array_merge_recursive(
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($t_table, $params['apply_filters'])
);
$i = 0;
$monthsyears = [];
foreach ($series as $stat_type => &$serie) {
$values = Stat::constructEntryValues(
'Ticket',
$stat_type,
$begin,
$end,
"",
"",
"",
$filters
);
if ($i === 0) {
$monthsyears = array_keys($values);
}
$values = array_values($values);
foreach ($values as $index => $number) {
$current_monthyear = $monthsyears[$index];
list($start_day, $end_day) = self::formatMonthyearDates($current_monthyear);
$serie['search']['criteria'][0]['value'] = $start_day;
$serie['search']['criteria'][1]['value'] = $end_day;
$serie['data'][$index] = [
'value' => $number,
'url' => Ticket::getSearchURL() . "?" . Toolbox::append_params($serie['search']),
];
}
$i++;
}
return [
'data' => [
'labels' => $monthsyears,
'series' => array_values($series),
],
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* get ticket by their curent status and their opening date
*
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function getTicketsStatus(array $params = []): array
{
$DB = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => Ticket::getIcon(),
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$statuses = Ticket::getAllStatusArray();
$t_table = Ticket::getTable();
$sub_query = array_merge_recursive(
[
'DISTINCT' => true,
'SELECT' => ["$t_table.*"],
'FROM' => $t_table,
'WHERE' => [
"$t_table.is_deleted" => 0,
] + getEntitiesRestrictCriteria($t_table),
],
// limit count for profiles with limited rights
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($t_table, $params['apply_filters'])
);
$criteria = [
'SELECT' => [
new QueryExpression(
"FROM_UNIXTIME(UNIX_TIMESTAMP(" . $DB->quoteName("{$t_table}_distinct.date") . "),'%Y-%m') AS period"
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::INCOMING . ", 1, 0))
as " . $DB->quoteValue(_x('status', 'New'))
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::ASSIGNED . ", 1, 0))
as " . $DB->quoteValue(_x('status', 'Processing (assigned)'))
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::PLANNED . ", 1, 0))
as " . $DB->quoteValue(_x('status', 'Processing (planned)'))
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::WAITING . ", 1, 0))
as " . $DB->quoteValue(__('Pending'))
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::SOLVED . ", 1, 0))
as " . $DB->quoteValue(_x('status', 'Solved'))
),
new QueryExpression(
"SUM(IF({$t_table}_distinct.status = " . Ticket::CLOSED . ", 1, 0))
as " . $DB->quoteValue(_x('status', 'Closed'))
),
],
'FROM' => new QuerySubQuery($sub_query, "{$t_table}_distinct"),
'ORDER' => 'period ASC',
'GROUP' => ['period']
];
$iterator = $DB->request($criteria);
$s_criteria = [
'criteria' => [
[
'link' => 'AND',
'field' => 12, // status
'searchtype' => 'equals',
'value' => null
], [
'link' => 'AND',
'field' => 15, // creation date
'searchtype' => 'morethan',
'value' => null
], [
'link' => 'AND',
'field' => 15, // creation date
'searchtype' => 'lessthan',
'value' => null
],
self::getSearchFiltersCriteria($t_table, $params['apply_filters'])
],
'reset' => 'reset'
];
$data = [
'labels' => [],
'series' => []
];
foreach ($iterator as $result) {
list($start_day, $end_day) = self::formatMonthyearDates($result['period']);
$s_criteria['criteria'][1]['value'] = $start_day;
$s_criteria['criteria'][2]['value'] = $end_day;
$data['labels'][] = $result['period'];
$tmp = $result;
unset($tmp['period'], $tmp['nb_tickets']);
$i = 0;
foreach ($tmp as $label2 => $value) {
$status_key = array_search($label2, $statuses);
$s_criteria['criteria'][0]['value'] = $status_key;
$data['series'][$i]['name'] = $label2;
$data['series'][$i]['data'][] = [
'value' => (int) $value,
'url' => Ticket::getSearchURL() . "?" . Toolbox::append_params($s_criteria),
];
$i++;
}
}
return [
'data' => $data,
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* Get numbers of tickets grouped by actors
*
* @param string $case cound be:
* - user_requester
* - group_requester
* - user_observer
* - group_observer
* - user_assign
* - group_assign
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function nbTicketsActor(
string $case = "",
array $params = []
): array {
$DBread = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => null,
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$t_table = Ticket::getTable();
$li_table = Ticket_User::getTable();
$ug_table = User::getTable();
$n_fields = [
"$ug_table.firstname as first",
"$ug_table.realname as second",
];
$where = [
"$t_table.is_deleted" => 0,
];
$case_array = explode('_', $case);
if ($case_array[0] == 'user') {
$where["$ug_table.is_deleted"] = 0;
$params['icon'] = $params['icon'] ?? User::getIcon();
} else if ($case_array[0] == 'group') {
$li_table = Group_Ticket::getTable();
$ug_table = Group::getTable();
$n_fields = [
"$ug_table.completename as first"
];
$params['icon'] = $params['icon'] ?? Group::getIcon();
}
$type = 0;
switch ($case) {
case "user_requester":
$type = CommonITILActor::REQUESTER;
$soption = 4;
break;
case "group_requester":
$type = CommonITILActor::REQUESTER;
$soption = 71;
break;
case "user_observer":
$type = CommonITILActor::OBSERVER;
$soption = 66;
break;
case "group_observer":
$type = CommonITILActor::OBSERVER;
$soption = 65;
break;
case "user_assign":
$type = CommonITILActor::ASSIGN;
$soption = 5;
break;
case "group_assign":
$type = CommonITILActor::ASSIGN;
$soption = 8;
break;
}
$criteria = array_merge_recursive(
[
'SELECT' => array_merge([
'COUNT DISTINCT' => "$t_table.id AS nb_tickets",
"$ug_table.id as actor_id",
], $n_fields),
'FROM' => $t_table,
'INNER JOIN' => [
$li_table => [
'ON' => [
$li_table => getForeignKeyFieldForItemType("Ticket"),
$t_table => 'id',
[
'AND' => [
"$li_table.type" => $type
]
]
]
],
$ug_table => [
'ON' => [
$li_table => getForeignKeyFieldForTable($ug_table),
$ug_table => 'id'
]
]
],
'GROUPBY' => "$ug_table.id",
'ORDER' => 'nb_tickets DESC',
'WHERE' => $where + getEntitiesRestrictCriteria($t_table),
],
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($t_table, $params['apply_filters'])
);
$iterator = $DBread->request($criteria);
$s_criteria = [
'criteria' => [
[
'link' => 'AND',
'field' => $soption,
'searchtype' => 'equals',
'value' => null
],
self::getSearchFiltersCriteria($t_table, $params['apply_filters']),
],
'reset' => 'reset'
];
$data = [];
foreach ($iterator as $result) {
$s_criteria['criteria'][0]['value'] = $result['actor_id'];
$data[] = [
'number' => $result['nb_tickets'],
'label' => $result['first'] . " " . ($result['second'] ?? ""),
'url' => Ticket::getSearchURL() . "?" . Toolbox::append_params($s_criteria),
];
}
return [
'data' => $data,
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* get average stats (takeintoaccoutn, solve/close delay, waiting) of ticket by month
*
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function averageTicketTimes(array $params = [])
{
$DBread = DBConnection::getReadConnection();
$default_params = [
'label' => "",
'icon' => "fas fa-stopwatch",
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$t_table = Ticket::getTable();
$criteria = array_merge_recursive(
[
'SELECT' => [
new QueryExpression("DATE_FORMAT(" . $DBread->quoteName("date") . ", '%Y-%m') AS period"),
new QueryExpression("AVG(" . $DBread->quoteName("takeintoaccount_delay_stat") . ") AS avg_takeintoaccount_delay_stat"),
new QueryExpression("AVG(" . $DBread->quoteName("waiting_duration") . ") AS avg_waiting_duration"),
new QueryExpression("AVG(" . $DBread->quoteName("solve_delay_stat") . ") AS avg_solve_delay_stat"),
new QueryExpression("AVG(" . $DBread->quoteName("close_delay_stat") . ") AS close_delay_stat"),
],
'FROM' => $t_table,
'WHERE' => [
'is_deleted' => 0,
] + getEntitiesRestrictCriteria($t_table),
'ORDER' => 'period ASC',
'GROUP' => ['period']
],
Ticket::getCriteriaFromProfile(),
self::getFiltersCriteria($t_table, $params['apply_filters'])
);
$iterator = $DBread->request($criteria);
$data = [
'labels' => [],
'series' => [
[
'name' => __("Time to own"),
'data' => []
], [
'name' => __("Waiting time"),
'data' => []
], [
'name' => __("Time to resolve"),
'data' => []
], [
'name' => __("Time to close"),
'data' => []
]
]
];
foreach ($iterator as $r) {
$data['labels'][] = $r['period'];
$tmp = $r;
unset($tmp['period']);
$data['series'][0]['data'][] = round($r['avg_takeintoaccount_delay_stat'] / HOUR_TIMESTAMP, 1);
$data['series'][1]['data'][] = round($r['avg_waiting_duration'] / HOUR_TIMESTAMP, 1);
$data['series'][2]['data'][] = round($r['avg_solve_delay_stat'] / HOUR_TIMESTAMP, 1);
$data['series'][3]['data'][] = round($r['close_delay_stat'] / HOUR_TIMESTAMP, 1);
}
return [
'data' => $data,
'label' => $params['label'],
'icon' => $params['icon'],
];
}
/**
* get multiple count of ticket by status and month
*
* @param array $params default values for
* - 'title' of the card
* - 'icon' of the card
* - 'apply_filters' values from dashboard filters
*
* @return array
*/
public static function getTicketSummary(array $params = [])
{
$default_params = [
'label' => "",
'icon' => "",
'apply_filters' => [],
];
$params = array_merge($default_params, $params);
$incoming = self::nbTicketsGeneric('incoming', $params);
$assigned = self::nbTicketsGeneric('assigned', $params);
$waiting = self::nbTicketsGeneric('waiting', $params);
$tovalidate = self::nbTicketsGeneric('waiting_validation', $params);
$closed = self::nbTicketsGeneric('closed', $params);
$solved = self::nbTicketsGeneric('solved', $params);
return [
'data' => [
[
'number' => $incoming['number'],
'label' => __("New"),
'url' => $incoming['url'],
'color' => '#3bc519',
], [
'number' => $assigned['number'],
'label' => __("Assigned"),
'url' => $assigned['url'],
'color' => '#f1cd29',
], [
'number' => $waiting['number'],
'label' => __("Pending"),
'url' => $waiting['url'],
'color' => '#f1a129',
], [
'number' => $tovalidate['number'],
'label' => __("To validate"),
'url' => $tovalidate['url'],
'color' => '#266ae9',
], [
'number' => $solved['number'],
'label' => __("Solved"),
'url' => $solved['url'],
'color' => '#edc949',
], [
'number' => $closed['number'],
'label' => __("Closed"),
'url' => $closed['url'],
'color' => '#555555',
]
],
'label' => $params['label'],
'icon' => $params['icon'],
];
}
public static function formatMonthyearDates(string $monthyear): array
{
$rawdate = explode('-', $monthyear);
$year = $rawdate[0];
$month = $rawdate[1];
$monthtime = mktime(0, 0, 0, $month, 1, $year);
$start_day = date("Y-m-d H:i:s", strtotime("first day of this month", $monthtime));
$end_day = date("Y-m-d H:i:s", strtotime("first day of next month", $monthtime));
return [$start_day, $end_day];
}
private static function getSearchOptionID(string $table, string $name, string $tableToSearch): int
{
$data = Search::getOptions(getItemTypeForTable($table), true);
$sort = [];
foreach ($data as $ref => $opt) {
if (isset($opt['field'])) {
$sort[$ref] = $opt['linkfield'] . "-" . $opt['table'];
}
}
return array_search($name . "-" . $tableToSearch, $sort);
}
final public static function getSearchFiltersCriteria(string $table = "", array $apply_filters = [])
{
$DB = DBConnection::getReadConnection();
$s_criteria = [];
if (
$DB->fieldExists($table, 'date')
&& isset($apply_filters['dates'])
&& count($apply_filters['dates']) == 2
) {
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date", $table), $apply_filters['dates'], 'begin');
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date", $table), $apply_filters['dates'], 'end');
}
//exclude itilobject already processed with 'date'
if (
!in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
]) && $DB->fieldExists($table, 'date_creation')
&& isset($apply_filters['dates'])
&& count($apply_filters['dates']) == 2
) {
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date_creation", $table), $apply_filters['dates'], 'begin');
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date_creation", $table), $apply_filters['dates'], 'end');
}
if (
$DB->fieldExists($table, 'date_mod')
&& isset($apply_filters['dates_mod'])
&& count($apply_filters['dates_mod']) == 2
) {
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date_mod", $table), $apply_filters['dates_mod'], 'begin');
$s_criteria['criteria'][] = self::getDatesSearchCriteria(self::getSearchOptionID($table, "date_mod", $table), $apply_filters['dates_mod'], 'end');
}
if (
$DB->fieldExists($table, 'itilcategories_id')
&& isset($apply_filters['itilcategory'])
&& (int) $apply_filters['itilcategory'] > 0
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'itilcategories_id', 'glpi_itilcategories'), // itilcategory
'searchtype' => 'under',
'value' => (int) $apply_filters['itilcategory']
];
}
if (
$DB->fieldExists($table, 'requesttypes_id')
&& isset($apply_filters['requesttype'])
&& (int) $apply_filters['requesttype'] > 0
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'requesttypes_id', 'glpi_requesttypes'), // request type
'searchtype' => 'equals',
'value' => (int) $apply_filters['requesttype']
];
}
if (
$DB->fieldExists($table, 'locations_id')
&& isset($apply_filters['location'])
&& (int) $apply_filters['location'] > 0
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'locations_id', 'glpi_locations'), // location
'searchtype' => 'equals',
'value' => (int) $apply_filters['location']
];
}
if (
$DB->fieldExists($table, 'manufacturers_id')
&& isset($apply_filters['manufacturer'])
&& (int) $apply_filters['manufacturer'] > 0
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'manufacturers_id', 'glpi_manufacturers'), // manufacturer
'searchtype' => 'equals',
'value' => (int) $apply_filters['manufacturer']
];
}
if (isset($apply_filters['group_tech'])) {
$groups_id = null;
if ((int) $apply_filters['group_tech'] > 0) {
$groups_id = (int) $apply_filters['group_tech'];
} else if ($apply_filters['group_tech'] == 'mygroups') {
$groups_id = 'mygroups';
}
if ($groups_id != null) {
if ($DB->fieldExists($table, 'groups_id_tech')) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'groups_id_tech', 'glpi_groups'), // group tech
'searchtype' => 'equals',
'value' => $groups_id
];
} else if (
in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
])
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => 8, // group tech
'searchtype' => 'equals',
'value' => $groups_id
];
}
}
}
if (
isset($apply_filters['user_tech'])
&& (int) $apply_filters['user_tech'] > 0
) {
if ($DB->fieldExists($table, 'users_id_tech')) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => self::getSearchOptionID($table, 'users_id_tech', 'glpi_users'),// tech
'searchtype' => 'equals',
'value' => (int) $apply_filters['user_tech']
];
} else if (
in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
])
) {
$s_criteria['criteria'][] = [
'link' => 'AND',
'field' => 5,// tech
'searchtype' => 'equals',
'value' => (int) $apply_filters['user_tech']
];
}
}
return $s_criteria;
}
public static function getFiltersCriteria(string $table = "", array $apply_filters = [])
{
$DB = DBConnection::getReadConnection();
$where = [];
$join = [];
if (
($DB->fieldExists($table, 'date'))
&& isset($apply_filters['dates'])
&& count($apply_filters['dates']) == 2
) {
$where += self::getDatesCriteria("$table.date", $apply_filters['dates']);
}
//exclude itilobject already processed with 'date'
if (
(!in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
]) && $DB->fieldExists($table, 'date_creation'))
&& isset($apply_filters['dates'])
&& count($apply_filters['dates']) == 2
) {
$where += self::getDatesCriteria("$table.date_creation", $apply_filters['dates']);
}
if (
$DB->fieldExists($table, 'date_mod')
&& isset($apply_filters['dates_mod'])
&& count($apply_filters['dates_mod']) == 2
) {
$where += self::getDatesCriteria("$table.date_mod", $apply_filters['dates_mod']);
}
if (
$DB->fieldExists($table, 'itilcategories_id')
&& isset($apply_filters['itilcategory'])
&& (int) $apply_filters['itilcategory'] > 0
) {
$where += [
"$table.itilcategories_id" => getSonsOf(ITILCategory::getTable(), (int) $apply_filters['itilcategory'])
];
}
if (
$DB->fieldExists($table, 'requesttypes_id')
&& isset($apply_filters['requesttype'])
&& (int) $apply_filters['requesttype'] > 0
) {
$where += [
"$table.requesttypes_id" => (int) $apply_filters['requesttype']
];
}
if (
$DB->fieldExists($table, 'locations_id')
&& isset($apply_filters['location'])
&& (int) $apply_filters['location'] > 0
) {
$where += [
"$table.locations_id" => (int) $apply_filters['location']
];
}
if (
$DB->fieldExists($table, 'manufacturers_id')
&& isset($apply_filters['manufacturer'])
&& (int) $apply_filters['manufacturer'] > 0
) {
$where += [
"$table.manufacturers_id" => (int) $apply_filters['manufacturer']
];
}
if (isset($apply_filters['group_tech'])) {
$groups_id = null;
if ((int) $apply_filters['group_tech'] > 0) {
$groups_id = (int) $apply_filters['group_tech'];
} else if ($apply_filters['group_tech'] == 'mygroups') {
$groups_id = $_SESSION['glpigroups'];
}
if ($groups_id != null) {
if ($DB->fieldExists($table, 'groups_id_tech')) {
$where += [
"$table.groups_id_tech" => $groups_id
];
} else if (
in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
])
) {
$itemtype = getItemTypeForTable($table);
$main_item = getItemForItemtype($itemtype);
$grouplink = $main_item->grouplinkclass;
$gl_table = $grouplink::getTable();
$fk = $main_item->getForeignKeyField();
$join += [
"$gl_table as gl" => [
'ON' => [
'gl' => $fk,
$table => 'id',
]
]
];
$where += [
"gl.type" => \CommonITILActor::ASSIGN,
"gl.groups_id" => $groups_id
];
}
}
}
if (isset($apply_filters['user_tech'])) {
$users_id = null;
if ((int) $apply_filters['user_tech'] > 0) {
$users_id = (int) $apply_filters['user_tech'];
} else if ($apply_filters['user_tech'] == 'myself') {
$users_id = $_SESSION['glpiID'];
}
if ($users_id !== null) {
if ($DB->fieldExists($table, 'users_id_tech')) {
$where += [
"$table.users_id_tech" => $users_id,
];
} else if (
in_array($table, [
Ticket::getTable(),
Change::getTable(),
Problem::getTable(),
])
) {
$itemtype = getItemTypeForTable($table);
$main_item = getItemForItemtype($itemtype);
$userlink = $main_item->userlinkclass;
$ul_table = $userlink::getTable();
$fk = $main_item->getForeignKeyField();
$join += [
"$ul_table as ul" => [
'ON' => [
'ul' => $fk,
$table => 'id',
]
]
];
$where += [
"ul.type" => \CommonITILActor::ASSIGN,
"ul.users_id" => $users_id,
];
}
}
}
$criteria = [];
if (count($where)) {
$criteria['WHERE'] = $where;
}
if (count($join)) {
$criteria['LEFT JOIN'] = $join;
}
return $criteria;
}
private static function getDatesCriteria(string $field = "", array $dates = []): array
{
$begin = strtotime($dates[0]);
$end = strtotime($dates[1]);
return [
[$field => ['>=', date('Y-m-d', $begin)]],
[$field => ['<=', date('Y-m-d', $end)]],
];
}
private static function getDatesSearchCriteria(int $searchoption_id, array $dates = [], $when = 'begin'): array
{
if ($when == "begin") {
$begin = strtotime($dates[0]);
return [
'link' => 'AND',
'field' => $searchoption_id, // creation date
'searchtype' => 'morethan',
'value' => date('Y-m-d 00:00:00', $begin)
];
} else {
$end = strtotime($dates[1]);
return [
'link' => 'AND',
'field' => $searchoption_id, // creation date
'searchtype' => 'lessthan',
'value' => date('Y-m-d 00:00:00', $end)
];
}
}
}