%PDF- %PDF-
Direktori : /var/www/projetos/suporte.iigd.com.br/src/ |
Current File : /var/www/projetos/suporte.iigd.com.br/src/Item_SoftwareVersion.php |
<?php /** * --------------------------------------------------------------------- * * GLPI - Gestionnaire Libre de Parc Informatique * * http://glpi-project.org * * @copyright 2015-2024 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/>. * * --------------------------------------------------------------------- */ class Item_SoftwareVersion extends CommonDBRelation { // From CommonDBRelation public static $itemtype_1 = 'itemtype'; public static $items_id_1 = 'items_id'; public static $itemtype_2 = 'SoftwareVersion'; public static $items_id_2 = 'softwareversions_id'; public static $log_history_1_add = Log::HISTORY_INSTALL_SOFTWARE; public static $log_history_1_delete = Log::HISTORY_UNINSTALL_SOFTWARE; public static $log_history_2_add = Log::HISTORY_INSTALL_SOFTWARE; public static $log_history_2_delete = Log::HISTORY_UNINSTALL_SOFTWARE; public static function getTypeName($nb = 0) { return _n('Installation', 'Installations', $nb); } public function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, 'datatype' => 'number' ]; $tab[] = [ 'id' => '3', 'table' => $this->getTable(), 'field' => 'items_id', 'name' => _n('Associated element', 'Associated elements', Session::getPluralNumber()), 'massiveaction' => false, 'nosort' => true, 'datatype' => 'specific', 'additionalfields' => ['itemtype'] ]; $tab[] = [ 'id' => '4', 'table' => 'glpi_softwareversions', 'field' => 'name', 'name' => _n('Version', 'Versions', 1), 'datatype' => 'dropdown', 'massiveaction' => false ]; $tab[] = [ 'id' => '5', 'table' => $this->getTable(), 'field' => 'itemtype', 'name' => _x('software', 'Request source'), 'datatype' => 'dropdown' ]; return $tab; } public function prepareInputForAdd($input) { if (!isset($input['itemtype']) || !isset($input['items_id'])) { return false; } $itemtype = $input['itemtype']; $item = new $itemtype(); if ( (!isset($input['is_template_item']) && $item->maybeTemplate()) || (!isset($input['is_deleted_item']) && $item->maybeDeleted()) ) { if ($item->getFromDB($input['items_id'])) { if ($item->maybeTemplate()) { $input['is_template_item'] = $item->getField('is_template'); } if ($item->maybeDeleted()) { $input['is_deleted_item'] = $item->getField('is_deleted'); } } else { return false; } } return parent::prepareInputForAdd($input); } public function prepareInputForUpdate($input) { if (isset($input['itemtype']) && isset($input['items_id'])) { $itemtype = $input['itemtype']; $item = new $itemtype(); if ( (!isset($input['is_template_item']) && $item->maybeTemplate()) || (!isset($input['is_deleted_item']) && $item->maybeDeleted()) ) { if ($item->getFromDB($input['items_id'])) { if ($item->maybeTemplate()) { $input['is_template_item'] = $item->getField('is_template'); } if ($item->maybeDeleted()) { $input['is_deleted_item'] = $item->getField('is_deleted'); } } else { return false; } } } return parent::prepareInputForUpdate($input); } public static function showMassiveActionsSubForm(MassiveAction $ma) { switch ($ma->getAction()) { case 'add': Software::dropdownSoftwareToInstall( 'peer_softwareversions_id', $_SESSION["glpiactive_entity"] ); echo Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) . "</span>"; return true; case 'move_version': $input = $ma->getInput(); if (isset($input['options'])) { if (isset($input['options']['move'])) { $options = ['softwares_id' => $input['options']['move']['softwares_id']]; if (isset($input['options']['move']['used'])) { $options['used'] = $input['options']['move']['used']; } SoftwareVersion::dropdownForOneSoftware($options); echo Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']); return true; } } return false; } return parent::showMassiveActionsSubForm($ma); } public static function processMassiveActionsForOneItemtype( MassiveAction $ma, CommonDBTM $item, array $ids ) { switch ($ma->getAction()) { case 'move_version': $input = $ma->getInput(); if (isset($input['softwareversions_id'])) { foreach ($ids as $id) { if ($item->can($id, UPDATE)) { //Process rules if ( $item->update(['id' => $id, 'softwareversions_id' => $input['softwareversions_id'] ]) ) { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); } } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_NORIGHT); $ma->addMessage($item->getErrorMessage(ERROR_RIGHT)); } } } else { $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); } return; case 'add': $itemtoadd = new Item_SoftwareVersion(); if (isset($_POST['peer_softwareversions_id'])) { foreach ($ids as $id) { if ($item->can($id, UPDATE)) { //Process rules if ( $itemtoadd->add([ 'items_id' => $id, 'itemtype' => $item::getType(), 'softwareversions_id' => $_POST['peer_softwareversions_id'] ]) ) { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); $ma->addMessage($itemtoadd->getErrorMessage(ERROR_ON_ACTION)); } } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_NORIGHT); $ma->addMessage($itemtoadd->getErrorMessage(ERROR_RIGHT)); } } } else { $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); } return; } parent::processMassiveActionsForOneItemtype($ma, $item, $ids); } public function updateDatasForItem($itemtype, $items_id) { /** @var \DBmysql $DB */ global $DB; $item = new $itemtype(); if ($item->getFromDB($items_id)) { $result = $DB->update( $this->getTable(), [ 'is_template_item' => $item->maybeTemplate() ? $item->getField('is_template') : 0, 'is_deleted_item' => $item->maybeDeleted() ? $item->getField('is_deleted') : 0 ], [ 'items_id' => $items_id, 'itemtype' => $itemtype ] ); return $result; } return false; } /** * Get number of installed licenses of a version * * @param integer $softwareversions_id version ID * @param string|integer[] $entity to search for item in ('' = all active entities) * * @return integer number of installations **/ public static function countForVersion($softwareversions_id, $entity = '') { /** @var \DBmysql $DB */ global $DB; $item_version_table = self::getTable(__CLASS__); $iterator = $DB->request([ 'SELECT' => ['itemtype'], 'DISTINCT' => true, 'FROM' => $item_version_table, 'WHERE' => [ 'softwareversions_id' => $softwareversions_id ] ]); $target_types = []; foreach ($iterator as $data) { $target_types[] = $data['itemtype']; } $count = 0; foreach ($target_types as $itemtype) { $itemtable = $itemtype::getTable(); $request = [ 'FROM' => 'glpi_items_softwareversions', 'COUNT' => 'cpt', 'INNER JOIN' => [ $itemtable => [ 'FKEY' => [ $itemtable => 'id', 'glpi_items_softwareversions' => 'items_id', [ 'AND' => [ 'glpi_items_softwareversions.itemtype' => $itemtype ] ] ] ] ], 'WHERE' => [ 'glpi_items_softwareversions.softwareversions_id' => $softwareversions_id, 'glpi_items_softwareversions.is_deleted' => 0 ] + getEntitiesRestrictCriteria($itemtable, '', $entity) ]; $item = new $itemtype(); if ($item->maybeDeleted()) { $request['WHERE']["$itemtable.is_deleted"] = 0; } if ($item->maybeTemplate()) { $request['WHERE']["$itemtable.is_template"] = 0; } $count += $DB->request($request)->current()['cpt']; } return $count; } /** * Get number of installed versions of a software * * @param $softwares_id software ID * * @return number of installations **/ public static function countForSoftware($softwares_id) { /** @var \DBmysql $DB */ global $DB; $iterator = $DB->request([ 'SELECT' => ['itemtype'], 'DISTINCT' => true, 'FROM' => 'glpi_softwareversions', 'INNER JOIN' => [ 'glpi_items_softwareversions' => [ 'FKEY' => [ 'glpi_items_softwareversions' => 'softwareversions_id', 'glpi_softwareversions' => 'id' ] ], ], 'WHERE' => [ 'softwares_id' => $softwares_id ] ]); $target_types = []; foreach ($iterator as $data) { $target_types[] = $data['itemtype']; } $count = 0; foreach ($target_types as $itemtype) { $itemtable = $itemtype::getTable(); $request = [ 'FROM' => 'glpi_softwareversions', 'COUNT' => 'cpt', 'INNER JOIN' => [ 'glpi_items_softwareversions' => [ 'FKEY' => [ 'glpi_items_softwareversions' => 'softwareversions_id', 'glpi_softwareversions' => 'id' ] ], $itemtable => [ 'FKEY' => [ $itemtable => 'id', 'glpi_items_softwareversions' => 'items_id', [ 'AND' => [ 'glpi_items_softwareversions.itemtype' => $itemtype ] ] ] ] ], 'WHERE' => [ 'glpi_softwareversions.softwares_id' => $softwares_id, 'glpi_items_softwareversions.is_deleted' => 0 ] + getEntitiesRestrictCriteria($itemtable, '', '', true) ]; $item = new $itemtype(); if ($item->maybeDeleted()) { $request['WHERE']["$itemtable.is_deleted"] = 0; } if ($item->maybeTemplate()) { $request['WHERE']["$itemtable.is_template"] = 0; } $count += $DB->request($request)->current()['cpt']; } return $count; } /** * Show installation of a Software * * @param $software Software object * * @return void **/ public static function showForSoftware(Software $software) { self::showInstallations($software->getField('id'), 'softwares_id'); } /** * Show installation of a Version * * @param $version SoftwareVersion object * * @return void **/ public static function showForVersion(SoftwareVersion $version) { self::showInstallations($version->getField('id'), 'id'); } /** * Show installations of a software * * @param integer $searchID value of the ID to search * @param string $crit to search : softwares_id (software) or id (version) * * @return void **/ private static function showInstallations($searchID, $crit) { /** * @var array $CFG_GLPI * @var \DBmysql $DB */ global $CFG_GLPI, $DB; if (!Software::canView() || !$searchID) { return; } $canedit = Session::haveRightsOr("software", [CREATE, UPDATE, DELETE, PURGE]); $canshowitems = []; $item_version_table = self::getTable(__CLASS__); $refcolumns = [ 'version' => _n('Version', 'Versions', Session::getPluralNumber()), 'item_type' => __('Item type'), 'itemname' => __('Name'), 'entity' => Entity::getTypeName(1), 'serial' => __('Serial number'), 'otherserial' => __('Inventory number'), 'location,itemname' => Location::getTypeName(1), 'state,itemname' => __('Status'), 'groupe,itemname' => Group::getTypeName(1), 'username,itemname' => User::getTypeName(1), 'lname' => SoftwareLicense::getTypeName(Session::getPluralNumber()), 'date_install' => __('Installation date') ]; if ($crit != "softwares_id") { unset($refcolumns['version']); } if (isset($_GET["start"])) { $start = $_GET["start"]; } else { $start = 0; } if (isset($_GET["order"]) && ($_GET["order"] == "DESC")) { $order = "DESC"; } else { $order = "ASC"; } if (isset($_GET["sort"]) && !empty($_GET["sort"]) && isset($refcolumns[$_GET["sort"]])) { // manage several param like location,compname : order first $tmp = explode(",", $_GET["sort"]); $sort = "`" . implode("` $order,`", $tmp) . "`"; } else { if ($crit == "softwares_id") { $sort = "`entity` $order, `version`, `itemname`"; } else { $sort = "`entity` $order, `itemname`"; } } // Total Number of events if ($crit == "softwares_id") { // Software ID $number = self::countForSoftware($searchID); } else { //SoftwareVersion ID $number = self::countForVersion($searchID); } echo "<div class='center'>"; if ($number < 1) { echo "<table class='tab_cadre_fixe'>"; echo "<tr><th>" . __('No item found') . "</th></tr>"; echo "</table></div>\n"; return; } // Display the pager Html::printAjaxPager(self::getTypeName(Session::getPluralNumber()), $start, $number); $queries = []; foreach ($CFG_GLPI['software_types'] as $itemtype) { $canshowitems[$itemtype] = $itemtype::canView(); $itemtable = $itemtype::getTable(); $query = [ 'SELECT' => [ $item_version_table . '.*', 'glpi_softwareversions.name AS version', 'glpi_softwareversions.softwares_id AS sID', 'glpi_softwareversions.id AS vID', "{$itemtable}.name AS itemname", "{$itemtable}.id AS iID", new QueryExpression($DB->quoteValue($itemtype) . " AS " . $DB->quoteName('item_type')), ], 'FROM' => $item_version_table, 'INNER JOIN' => [ 'glpi_softwareversions' => [ 'FKEY' => [ $item_version_table => 'softwareversions_id', 'glpi_softwareversions' => 'id' ] ] ], 'LEFT JOIN' => [ $itemtable => [ 'FKEY' => [ $item_version_table => 'items_id', $itemtable => 'id', [ 'AND' => [ $item_version_table . '.itemtype' => $itemtype ] ] ] ] ], 'WHERE' => [ "glpi_softwareversions.$crit" => $searchID, 'glpi_items_softwareversions.is_deleted' => 0 ] ]; if ($DB->fieldExists($itemtable, 'serial')) { $query['SELECT'][] = $itemtable . '.serial'; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName($itemtable . ".serial") ); } if ($DB->fieldExists($itemtable, 'otherserial')) { $query['SELECT'][] = $itemtable . '.otherserial'; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName($itemtable . ".otherserial") ); } if ($DB->fieldExists($itemtable, 'users_id')) { $query['SELECT'][] = 'glpi_users.name AS username'; $query['SELECT'][] = 'glpi_users.id AS userid'; $query['SELECT'][] = 'glpi_users.realname AS userrealname'; $query['SELECT'][] = 'glpi_users.firstname AS userfirstname'; $query['LEFT JOIN']['glpi_users'] = [ 'FKEY' => [ $itemtable => 'users_id', 'glpi_users' => 'id' ] ]; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName($itemtable . ".username") ); $query['SELECT'][] = new QueryExpression( $DB->quoteValue('-1') . " AS " . $DB->quoteName($itemtable . ".userid") ); $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName($itemtable . ".userrealname") ); $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName($itemtable . ".userfirstname") ); } if ($DB->fieldExists($itemtable, 'entities_id')) { $query['SELECT'][] = 'glpi_entities.completename AS entity'; $query['LEFT JOIN']['glpi_entities'] = [ 'FKEY' => [ $itemtable => 'entities_id', 'glpi_entities' => 'id' ] ]; $query['WHERE'] += getEntitiesRestrictCriteria($itemtable, '', '', true); } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName('entity') ); } if ($DB->fieldExists($itemtable, 'locations_id')) { $query['SELECT'][] = 'glpi_locations.completename AS location'; $query['LEFT JOIN']['glpi_locations'] = [ 'FKEY' => [ $itemtable => 'locations_id', 'glpi_locations' => 'id' ] ]; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName('location') ); } if ($DB->fieldExists($itemtable, 'states_id')) { $query['SELECT'][] = 'glpi_states.name AS state'; $query['LEFT JOIN']['glpi_states'] = [ 'FKEY' => [ $itemtable => 'states_id', 'glpi_states' => 'id' ] ]; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName('state') ); } if ($DB->fieldExists($itemtable, 'groups_id')) { $query['SELECT'][] = 'glpi_groups.name AS groupe'; $query['LEFT JOIN']['glpi_groups'] = [ 'FKEY' => [ $itemtable => 'groups_id', 'glpi_groups' => 'id' ] ]; } else { $query['SELECT'][] = new QueryExpression( $DB->quoteValue('') . " AS " . $DB->quoteName('groupe') ); } if ($DB->fieldExists($itemtable, 'is_deleted')) { $query['WHERE']["{$itemtable}.is_deleted"] = 0; } if ($DB->fieldExists($itemtable, 'is_template')) { $query['WHERE']["{$itemtable}.is_template"] = 0; } $queries[] = $query; } $union = new QueryUnion($queries, true); $criteria = [ 'SELECT' => [], 'FROM' => $union, 'ORDER' => "$sort $order", 'LIMIT' => $_SESSION['glpilist_limit'], 'START' => $start ]; $iterator = $DB->request($criteria); $rand = mt_rand(); if ($data = $iterator->current()) { $softwares_id = $data['sID']; $soft = new Software(); $showEntity = ($soft->getFromDB($softwares_id) && $soft->isRecursive()); $linkUser = User::canView(); $title = $soft->fields["name"]; if ($crit == "id") { $title = sprintf(__('%1$s - %2$s'), $title, $data["version"]); } Session::initNavigateListItems( $data['item_type'], //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'), Software::getTypeName(1), $title ) ); if ($canedit) { $rand = mt_rand(); Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $number), 'container' => 'mass' . __CLASS__ . $rand, 'specific_actions' => [__CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'move_version' => _x('button', 'Move'), 'purge' => _x('button', 'Delete permanently') ] ]; // Options to update version $massiveactionparams['extraparams']['options']['move']['softwares_id'] = $softwares_id; if ($crit == 'softwares_id') { $massiveactionparams['extraparams']['options']['move']['used'] = []; } else { $massiveactionparams['extraparams']['options']['move']['used'] = [$searchID]; } Html::showMassiveActions($massiveactionparams); } echo "<div class='table-responsive'>"; echo "<table class='tab_cadre_fixehov'>"; $header_begin = "<tr>"; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit) { $header_begin .= "<th width='10'>"; $header_top .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); $header_bottom .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); $header_end .= "</th>"; } $columns = $refcolumns; if (!$showEntity) { unset($columns['entity']); } foreach ($columns as $key => $val) { // Non order column if ($key[0] == '_') { $header_end .= "<th>$val</th>"; } else { $header_end .= "<th" . ($sort == "`$key`" ? " class='order_$order'" : '') . ">"; $header_end .= $key !== 'lname' ? "<a href='javascript:reloadTab(\"sort=$key&order=" . (($order == "ASC") ? "DESC" : "ASC") . "&start=0\");'>$val</a>" : $val; $header_end .= "</th>"; } } $header_end .= "</tr>\n"; echo $header_begin . $header_top . $header_end; do { Session::addToNavigateListItems($data['item_type'], $data["iID"]); echo "<tr class='tab_bg_2'>"; if ($canedit) { echo "<td>"; Html::showMassiveActionCheckBox(__CLASS__, $data["id"]); echo "</td>"; } if ($crit == "softwares_id") { echo "<td><a href='" . SoftwareVersion::getFormURLWithID($data['vID']) . "'>" . $data['version'] . "</a></td>"; } $itemname = $data['itemname']; if (empty($itemname) || $_SESSION['glpiis_ids_visible']) { $itemname = sprintf(__('%1$s (%2$s)'), $itemname, $data['iID']); } echo "<td>{$data['item_type']}</td>"; if ($canshowitems[$data['item_type']]) { echo "<td><a href='" . $data['item_type']::getFormURLWithID($data['iID']) . "'>$itemname</a></td>"; } else { echo "<td>" . $itemname . "</td>"; } if ($showEntity) { echo "<td>" . $data['entity'] . "</td>"; } echo "<td>" . $data['serial'] . "</td>"; echo "<td>" . $data['otherserial'] . "</td>"; echo "<td>" . $data['location'] . "</td>"; echo "<td>" . $data['state'] . "</td>"; echo "<td>" . $data['groupe'] . "</td>"; echo "<td>" . formatUserName( $data['userid'], $data['username'], $data['userrealname'], $data['userfirstname'], $linkUser ) . "</td>"; $lics = Item_SoftwareLicense::getLicenseForInstallation( $data['item_type'], $data['iID'], $data['vID'] ); echo "<td>"; if (count($lics)) { foreach ($lics as $lic) { $serial = $lic['serial']; if (!empty($lic['type'])) { $serial = sprintf(__('%1$s (%2$s)'), $serial, $lic['type']); } echo "<a href='" . SoftwareLicense::getFormURLWithID($lic['id']) . "'>" . $lic['name']; echo "</a> - " . $serial; echo "<br>"; } } echo "</td>"; echo "<td>" . Html::convDate($data['date_install']) . "</td>"; echo "</tr>\n"; $iterator->next(); } while ($data = $iterator->current()); echo $header_begin . $header_bottom . $header_end; echo "</table>"; echo "</div>"; if ($canedit) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } } else { // Not found echo __('No item found'); } Html::printAjaxPager(self::getTypeName(Session::getPluralNumber()), $start, $number); echo "</div>"; } /** * Show number of installations per entity * * @param $version SoftwareVersion object * * @return void **/ public static function showForVersionByEntity(SoftwareVersion $version) { /** @var \DBmysql $DB */ global $DB; $softwareversions_id = $version->getField('id'); if (!Software::canView() || !$softwareversions_id) { return; } echo "<div class='center'>"; echo "<table class='tab_cadre'><tr>"; echo "<th>" . Entity::getTypeName(1) . "</th>"; echo "<th>" . self::getTypeName(Session::getPluralNumber()) . "</th>"; echo "</tr>\n"; $tot = 0; $iterator = $DB->request([ 'SELECT' => ['id', 'completename'], 'FROM' => 'glpi_entities', 'WHERE' => getEntitiesRestrictCriteria('glpi_entities'), 'ORDER' => ['completename'] ]); foreach ($iterator as $data) { $nb = self::countForVersion($softwareversions_id, $data['id']); if ($nb > 0) { echo "<tr class='tab_bg_2'><td>" . $data["completename"] . "</td>"; echo "<td class='numeric'>" . $nb . "</td></tr>\n"; $tot += $nb; } } if ($tot > 0) { echo "<tr class='tab_bg_1'><td class='center b'>" . __('Total') . "</td>"; echo "<td class='numeric b'>" . $tot . "</td></tr>\n"; } else { echo "<tr class='tab_bg_1'><td colspan='2 b'>" . __('No item found') . "</td></tr>\n"; } echo "</table></div>"; } /** * Get software related to a given item * * @param CommonDBTM $item Item instance * @param string $sort Field to sort on * @param string $order Sort order * * @return DBmysqlIterator */ public static function getFromItem(CommonDBTM $item, $sort = null, $order = null, array $filters = []): DBmysqlIterator { /** @var \DBmysql $DB */ global $DB; $selftable = self::getTable(__CLASS__); $select = [ 'glpi_softwares.softwarecategories_id', 'glpi_softwares.name AS softname', "glpi_items_softwareversions.id", 'glpi_states.name as state', 'glpi_softwareversions.id AS verid', 'glpi_softwareversions.softwares_id', 'glpi_softwareversions.name AS version', 'glpi_softwareversions.arch AS arch', 'glpi_softwares.is_valid AS softvalid', 'glpi_items_softwareversions.date_install AS dateinstall', "$selftable.is_dynamic" ]; $request = [ 'SELECT' => $select, 'FROM' => $selftable, 'LEFT JOIN' => [ 'glpi_softwareversions' => [ 'FKEY' => [ $selftable => 'softwareversions_id', 'glpi_softwareversions' => 'id' ] ], 'glpi_states' => [ 'FKEY' => [ 'glpi_softwareversions' => 'states_id', 'glpi_states' => 'id' ] ], 'glpi_softwares' => [ 'FKEY' => [ 'glpi_softwareversions' => 'softwares_id', 'glpi_softwares' => 'id' ] ], 'glpi_softwarecategories' => [ 'FKEY' => [ 'glpi_softwares' => 'softwarecategories_id', 'glpi_softwarecategories' => 'id' ] ] ], 'WHERE' => [ "{$selftable}.items_id" => $item->getField('id'), "{$selftable}.itemtype" => $item->getType() ] + getEntitiesRestrictCriteria('glpi_softwares', '', '', true), 'ORDER' => ['softname', 'version'] ]; if (count($filters)) { if (strlen(($filters['name'] ?? ""))) { $request['WHERE']['glpi_softwares.name'] = ['LIKE', '%' . $filters['name'] . '%']; } if (strlen(($filters['state'] ?? ""))) { $request['WHERE']['glpi_states.name'] = ['LIKE', '%' . $filters['state'] . '%']; } if (strlen(($filters['version'] ?? ""))) { $request['WHERE']['glpi_softwareversions.name'] = ['LIKE', '%' . $filters['version'] . '%']; } if (strlen(($filters['arch'] ?? ""))) { $request['WHERE']['glpi_softwareversions.arch'] = ['LIKE', '%' . $filters['arch'] . '%']; } if (isset($filters['is_dynamic']) && $filters['is_dynamic'] != '') { $request['WHERE']["$selftable.is_dynamic"] = $filters['is_dynamic']; } if (strlen(($filters['software_category'] ?? ""))) { $request['WHERE']['glpi_softwarecategories.name'] = ['LIKE', '%' . $filters['software_category'] . '%']; } if (strlen(($filters['date_install'] ?? ""))) { $request['WHERE']['glpi_items_softwareversions.date_install'] = $filters['date_install']; } } if ($item->maybeDeleted()) { $request['WHERE']["{$selftable}.is_deleted"] = 0; } $crit = Session::getSavedOption(__CLASS__, 'criterion', -1); if ($crit > -1) { $request['WHERE']['glpi_softwares.softwarecategories_id'] = (int)$crit; } $iterator = $DB->request($request); return $iterator; } /** * Show software installed on a computer * * @param Computer $comp Computer object * @param integer $withtemplate template case of the view process * * @return void **/ public static function showForItem(CommonDBTM $item, $withtemplate = 0) { /** @var \DBmysql $DB */ global $DB; if (!Software::canView()) { return; } $items_id = $item->getField('id'); $itemtype = $item->getType(); $rand = mt_rand(); $filters = $_GET['filters'] ?? []; $is_filtered = count($filters) > 0; $canedit = Session::haveRightsOr("software", [CREATE, UPDATE, DELETE, PURGE]); $entities_id = $item->fields["entities_id"]; $crit = Session::getSavedOption(__CLASS__, 'criterion', -1); $iterator = self::getFromItem($item, null, null, $filters); if ( (empty($withtemplate) || ($withtemplate != 2)) && $canedit ) { echo "<form method='post' action='" . Item_SoftwareVersion::getFormURL() . "'>"; echo "<div class='spaced'><table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_1'><td class='center'>"; echo _n('Software', 'Software', Session::getPluralNumber()) . " "; echo "<input type='hidden' name='itemtype' value='$itemtype'>"; echo "<input type='hidden' name='items_id' value='$items_id'>"; Software::dropdownSoftwareToInstall("softwareversions_id", $entities_id); echo "</td><td width='20%'>"; echo "<input type='submit' name='add' value=\"" . _sx('button', 'Install') . "\" class='btn btn-primary'>"; echo "</td>"; echo "</tr>\n"; echo "</table></div>\n"; Html::closeForm(); } echo "<div class='spaced'>"; Session::initNavigateListItems( 'Software', //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'), $itemtype::getTypeName(1), $item->getName() ) ); Session::initNavigateListItems( 'SoftwareLicense', //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'), $itemtype::getTypeName(1), $item->getName() ) ); // Mini Search engine echo "<table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_1'><th colspan='2'>" . Software::getTypeName(Session::getPluralNumber()) . "</th></tr>"; echo "<tr class='tab_bg_1'><td>"; echo _n('Category', 'Categories', 1) . "</td><td>"; SoftwareCategory::dropdown(['value' => $crit, 'toadd' => ['-1' => __('All categories')], 'emptylabel' => __('Uncategorized software'), 'on_change' => 'reloadTab("start=0&criterion="+this.value)' ]); echo "</td></tr></table></div>"; $number = count($iterator); $start = (isset($_REQUEST['start']) ? intval($_REQUEST['start']) : 0); if ($start >= $number) { $start = 0; } $installed = []; if ($number || $is_filtered) { echo "<div class='spaced'>"; Html::printAjaxPager('', $start, $number); echo "<div class='table-responsive'>"; if ($canedit) { $rand = mt_rand(); Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $number), 'container' => 'mass' . __CLASS__ . $rand, 'specific_actions' => ['purge' => _x('button', 'Delete permanently')] ]; Html::showMassiveActions($massiveactionparams); } echo "<table class='table table-hover table-striped border my-2'>"; $header_begin = "<tr>"; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit) { $header_begin .= "<th width='10'>"; $header_top .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); $header_bottom .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); $header_end .= "</th>"; } $header_end .= "<th>" . __('Name') . "</th>"; $header_end .= "<th>" . __('Status') . "</th>"; $header_end .= "<th>" . _n('Version', 'Versions', 1) . "</th>"; $header_end .= "<th>" . SoftwareLicense::getTypeName(1) . "</th>"; $header_end .= "<th>" . __('Installation date') . "</th>"; $header_end .= "<th>" . _n('Architecture', 'Architectures', 1) . "</th>"; $header_end .= "<th>" . __('Automatic inventory') . "</th>"; $header_end .= "<th>" . SoftwareCategory::getTypeName(1) . "</th>"; $header_end .= "<th>" . __('Valid license') . "</th>"; $header_end .= "<th> <button class='btn btn-sm show_log_filters " . ($is_filtered ? "btn-secondary" : "btn-outline-secondary") . "'> <i class='fas fa-filter'></i> <span class='d-none d-xl-block'>" . __('Filter') . "</span> </button></th>"; $header_end .= "</tr>"; echo $header_begin . $header_top . $header_end; if ($is_filtered) { echo "<tr class='log_history_filter_row'> <td> <input type='hidden' name='filters[active]' value='1'> </td> <td> <input type='text' class='form-control' name='filters[name]' value='" . ($filters['name'] ?? '') . "'> </td> <td> <input type='text' class='form-control' name='filters[state]' value='" . ($filters['state'] ?? '') . "'> </td> <td> <input type='text' class='form-control' name='filters[version]' value='" . ($filters['version'] ?? '') . "'> </td> <td></td> <td> " . Html::showDateField( "filters[date_install]", [ 'value' => ($filters['date_install'] ?? ''), 'display' => false, ] ) . " </td> <td> <input type='text' class='form-control' name='filters[arch]' value='" . ($filters['arch'] ?? '') . "'> </td> <td>" . Dropdown::showFromArray( "filters[is_dynamic]", [ null => "", '1' => __('Yes'), '0' => __('No'), ], [ 'value' => ($filters['is_dynamic'] ?? null), 'display' => false, ] ) . " </td> <td> <input type='text' class='form-control' name='filters[software_category]'> </td> <td></td> <td></td> </tr>"; } for ($row = 0; $data = $iterator->current(); $row++) { if (($row >= $start) && ($row < ($start + $_SESSION['glpilist_limit']))) { $licids = self::softwareByCategory( $data, $itemtype, $items_id, $withtemplate, $canedit, true ); } else { $licids = self::softwareByCategory( $data, $itemtype, $items_id, $withtemplate, $canedit, false ); } Session::addToNavigateListItems('Software', $data["softwares_id"]); foreach ($licids as $licid) { Session::addToNavigateListItems('SoftwareLicense', $licid); $installed[] = $licid; } $iterator->next(); } echo "<tfoot>"; echo $header_begin . $header_bottom . $header_end; echo "</tfoot>"; echo "</table>"; echo "</div>"; Html::printAjaxPager('', $start, $number); if ($canedit) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } } else { echo "<p class='center b'>" . __('No item found') . "</p>"; } echo "</div>"; if ( (empty($withtemplate) || ($withtemplate != 2)) && $canedit ) { echo "<form method='post' action='" . Item_SoftwareLicense::getFormURL() . "'>"; echo "<div class='spaced'><table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_1'><th colspan='2'>" . SoftwareLicense::getTypeName(Session::getPluralNumber()) . "</th></tr>"; echo "<tr class='tab_bg_1'>"; echo "<td class='center'>"; echo SoftwareLicense::getTypeName(Session::getPluralNumber()) . " "; echo "<input type='hidden' name='itemtype' value='$itemtype'>"; echo "<input type='hidden' name='items_id' value='$items_id'>"; Software::dropdownLicenseToInstall("softwarelicenses_id", $entities_id); echo "</td><td width='20%'>"; echo "<input type='submit' name='add' value=\"" . _sx('button', 'Add') . "\" class='btn btn-primary'>"; echo "</td></tr>"; echo "</table></div>"; Html::closeForm(); } echo "<div class='spaced'>"; // Affected licenses NOT installed $lic_where = []; if (count($installed)) { $lic_where['NOT'] = ['glpi_softwarelicenses.id' => $installed]; } $lic_request = [ 'SELECT' => [ 'glpi_softwarelicenses.*', 'glpi_items_softwarelicenses.id AS linkid', 'glpi_softwares.name AS softname', 'glpi_softwareversions.name AS version', 'glpi_states.name AS state' ], 'FROM' => SoftwareLicense::getTable(), 'INNER JOIN' => [ 'glpi_softwares' => [ 'FKEY' => [ 'glpi_softwarelicenses' => 'softwares_id', 'glpi_softwares' => 'id' ] ] ], 'LEFT JOIN' => [ 'glpi_items_softwarelicenses' => [ 'FKEY' => [ 'glpi_items_softwarelicenses' => 'softwarelicenses_id', 'glpi_softwarelicenses' => 'id' ] ], 'glpi_softwareversions' => [ 'FKEY' => [ 'glpi_softwareversions' => 'id', 'glpi_softwarelicenses' => 'softwareversions_id_use', [ 'AND' => [ 'glpi_softwarelicenses.softwareversions_id_use' => 0, 'glpi_softwarelicenses.softwareversions_id_buy' => new \QueryExpression(DBmysql::quoteName('glpi_softwareversions.id')), ] ] ] ], 'glpi_states' => [ 'FKEY' => [ 'glpi_softwareversions' => 'states_id', 'glpi_states' => 'id' ] ] ], 'WHERE' => [ 'glpi_items_softwarelicenses.items_id' => $items_id, 'glpi_items_softwarelicenses.itemtype' => $itemtype, ] + $lic_where, 'ORDER' => ['softname', 'version'] ]; if ($item->maybeDeleted()) { $lic_request['WHERE']['glpi_items_softwarelicenses.is_deleted'] = 0; } $lic_iterator = $DB->request($lic_request); if ($number = $lic_iterator->count()) { if ($canedit) { $rand = mt_rand(); Html::openMassiveActionsForm('massSoftwareLicense' . $rand); $actions = ['Item_SoftwareLicense' . MassiveAction::CLASS_ACTION_SEPARATOR . 'install' => _x('button', 'Install') ]; if (SoftwareLicense::canUpdate()) { $actions['purge'] = _x('button', 'Delete permanently'); } $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $number), 'container' => 'massSoftwareLicense' . $rand, 'specific_actions' => $actions ]; Html::showMassiveActions($massiveactionparams); } echo "<table class='tab_cadre_fixehov'>"; $header_begin = "<tr>"; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit) { $header_begin .= "<th width='10'>"; $header_top .= Html::getCheckAllAsCheckbox('massSoftwareLicense' . $rand); $header_bottom .= Html::getCheckAllAsCheckbox('massSoftwareLicense' . $rand); $header_end .= "</th>"; } $header_end .= "<th>" . __('Name') . "</th><th>" . __('Status') . "</th>"; $header_end .= "<th>" . _n('Version', 'Versions', 1) . "</th><th>" . SoftwareLicense::getTypeName(1) . "</th>"; $header_end .= "<th>" . __('Installation date') . "</th>"; $header_end .= "</tr>\n"; echo $header_begin . $header_top . $header_end; foreach ($lic_iterator as $data) { self::displaySoftwareByLicense($data, $withtemplate, $canedit); Session::addToNavigateListItems('SoftwareLicense', $data["id"]); } echo $header_begin . $header_bottom . $header_end; echo "</table>"; if ($canedit) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } } else { echo "<p class='center b'>" . __('No item found') . "</p>"; } echo "</div>\n"; } /** * Display a installed software for a category * * @param array $data data used to display * @param string $itemtype Type of the item * @param integer $items_id ID of the item * @param integer $withtemplate template case of the view process * @param boolean $canedit user can edit software ? * @param boolean $display display and calculate if true or just calculate * * @return integer[] Found licenses ids **/ private static function softwareByCategory( $data, $itemtype, $items_id, $withtemplate, $canedit, $display ) { /** @var \DBmysql $DB */ global $DB; $ID = $data["id"]; $verid = $data["verid"]; if ($display) { echo "<tr class='tab_bg_1'>"; if ($canedit) { echo "<td>"; Html::showMassiveActionCheckBox(__CLASS__, $ID); echo "</td>"; } echo "<td>"; echo "<a href='" . Software::getFormURLWithID($data['softwares_id']) . "'>"; echo ($_SESSION["glpiis_ids_visible"] ? sprintf( __('%1$s (%2$s)'), $data["softname"], $data['softwares_id'] ) : $data["softname"]); echo "</a></td>"; echo "<td>" . $data["state"] . "</td>"; echo "<td>" . $data["version"]; echo "</td><td>"; } $iterator = $DB->request([ 'SELECT' => [ 'glpi_softwarelicenses.*', 'glpi_softwarelicensetypes.name AS type' ], 'FROM' => 'glpi_items_softwarelicenses', 'INNER JOIN' => [ 'glpi_softwarelicenses' => [ 'FKEY' => [ 'glpi_items_softwarelicenses' => 'softwarelicenses_id', 'glpi_softwarelicenses' => 'id' ] ] ], 'LEFT JOIN' => [ 'glpi_softwarelicensetypes' => [ 'FKEY' => [ 'glpi_softwarelicenses' => 'softwarelicensetypes_id', 'glpi_softwarelicensetypes' => 'id' ] ] ], 'WHERE' => [ "glpi_items_softwarelicenses.items_id" => $items_id, 'glpi_items_softwarelicenses.itemtype' => $itemtype, 'OR' => [ 'glpi_softwarelicenses.softwareversions_id_use' => $verid, [ 'glpi_softwarelicenses.softwareversions_id_use' => 0, 'glpi_softwarelicenses.softwareversions_id_buy' => $verid ] ] ] ]); $licids = []; foreach ($iterator as $licdata) { $licids[] = $licdata['id']; $licserial = $licdata['serial']; if (!empty($licdata['type'])) { $licserial = sprintf(__('%1$s (%2$s)'), $licserial, $licdata['type']); } if ($display) { echo "<span class='b'>" . $licdata['name'] . "</span> - " . $licserial; $link_item = Toolbox::getItemTypeFormURL('SoftwareLicense'); $link = $link_item . "?id=" . $licdata['id']; $comment = "<table><tr><td>" . __('Name') . "</td><td>" . $licdata['name'] . "</td></tr>" . "<tr><td>" . __('Serial number') . "</td><td>" . $licdata['serial'] . "</td></tr>" . "<tr><td>" . __('Comments') . '</td><td>' . $licdata['comment'] . "</td></tr>" . "</table>"; Html::showToolTip($comment, ['link' => $link]); echo "<br>"; } } if ($display) { if (!count($licids)) { echo " "; } echo "</td>"; echo "<td>" . Html::convDate($data['dateinstall']) . "</td>"; echo "<td>" . $data['arch'] . "</td>"; if (isset($data['is_dynamic'])) { echo "<td>" . Dropdown::getYesNo($data['is_dynamic']) . "</td>"; } echo "<td>" . Dropdown::getDropdownName( "glpi_softwarecategories", $data['softwarecategories_id'] ); echo "</td>"; echo "<td>" . Dropdown::getYesNo($data["softvalid"]) . "</td>"; echo "<td></td>"; // empty td for filter column echo "</tr>\n"; } return $licids; } /** * Display a software for a License (not installed) * * @param array $data data used to display * @param integer $withtemplate template case of the view process * @param boolean $canedit user can edit software ? * * @return void */ private static function displaySoftwareByLicense($data, $withtemplate, $canedit) { $ID = $data['linkid']; $link_item = Toolbox::getItemTypeFormURL('SoftwareLicense'); $link = $link_item . "?id=" . $data['id']; echo "<tr class='tab_bg_1'>"; if ($canedit) { echo "<td>"; if (empty($withtemplate) || ($withtemplate != 2)) { Html::showMassiveActionCheckBox('Item_SoftwareLicense', $ID); } echo "</td>"; } echo "<td>"; echo "<a href='" . Software::getFormURLWithID($data['softwares_id']) . "'>"; echo ($_SESSION["glpiis_ids_visible"] ? sprintf( __('%1$s (%2$s)'), $data["softname"], $data['softwares_id'] ) : $data["softname"]); echo "</a></td>"; echo "<td>" . $data["state"] . "</td>"; echo "<td>" . $data["version"]; $serial = $data["serial"]; if ($data["softwarelicensetypes_id"]) { $serial = sprintf( __('%1$s (%2$s)'), $serial, Dropdown::getDropdownName( "glpi_softwarelicensetypes", $data["softwarelicensetypes_id"] ) ); } echo "</td><td>" . $data["name"]; if (!empty($serial)) { echo " - " . $serial; } $comment = "<table><tr><td>" . __('Name') . "</td>" . "<td>" . $data['name'] . "</td></tr>" . "<tr><td>" . __('Serial number') . "</td><td>" . $data['serial'] . "</td></tr>" . "<tr><td>" . __('Comments') . "</td><td>" . $data['comment'] . "</td></tr></table>"; Html::showToolTip($comment, ['link' => $link]); echo "</td></tr>\n"; } /** * Update version installed on a item * * @param integer $instID ID of the installed software link * @param integer $softwareversions_id ID of the new version * @param boolean $dohistory Do history ? (default 1) * * @return void **/ public function upgrade($instID, $softwareversions_id, $dohistory = true) { if ($this->getFromDB($instID)) { $items_id = $this->fields['items_id']; $itemtype = $this->fields['itemtype']; $this->delete(['id' => $instID]); $this->add([ 'itemtype' => $itemtype, 'items_id' => $items_id, 'softwareversions_id' => $softwareversions_id ]); } } public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { $nb = 0; switch ($item->getType()) { case 'Software': if (!$withtemplate) { if ($_SESSION['glpishow_count_on_tabs']) { $nb = self::countForSoftware($item->getID()); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb); } break; case 'SoftwareVersion': if (!$withtemplate) { if ($_SESSION['glpishow_count_on_tabs']) { $nb = self::countForVersion($item->getID()); } return [1 => __('Summary'), 2 => self::createTabEntry( self::getTypeName(Session::getPluralNumber()), $nb ) ]; } break; default: // Installation allowed for template if (Software::canView()) { if ($_SESSION['glpishow_count_on_tabs']) { $nb = self::countForItem($item); } return self::createTabEntry(Software::getTypeName(Session::getPluralNumber()), $nb); } break; } return ''; } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item->getType() == 'Software') { self::showForSoftware($item); } else if ($item->getType() == 'SoftwareVersion') { switch ($tabnum) { case 1: self::showForVersionByEntity($item); break; case 2: self::showForVersion($item); break; } } else { self::showForItem($item, $withtemplate); } return true; } protected static function getListForItemParams(CommonDBTM $item, $noent = false) { $table = self::getTable(__CLASS__); $params = parent::getListForItemParams($item); unset($params['SELECT'], $params['ORDER']); $params['WHERE'] = [ $table . '.items_id' => $item->getID(), $table . '.itemtype' => $item::getType(), $table . '.is_deleted' => 0 ]; if ($noent === false) { $params['WHERE'] += getEntitiesRestrictCriteria($table, '', '', 'auto'); } return $params; } public static function countForItem(CommonDBTM $item) { /** @var \DBmysql $DB */ global $DB; $params = self::getListForItemParams($item); unset($params['SELECT'], $params['ORDER']); $params['COUNT'] = 'cpt'; $iterator = $DB->request($params); return $iterator->current()['cpt']; } }