. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * SoftwareLicense Class **/ class SoftwareLicense extends CommonTreeDropdown { use Glpi\Features\Clonable; /// TODO move to CommonDBChild ? // From CommonDBTM public $dohistory = true; static protected $forward_entity_to = ['Infocom']; static $rightname = 'license'; protected $usenotepad = true; public function getCloneRelations() :array { return []; } static function getTypeName($nb = 0) { return _n('License', 'Licenses', $nb); } function pre_updateInDB() { // Clean end alert if expire is after old one if (isset($this->oldvalues['expire']) && ($this->oldvalues['expire'] < $this->fields['expire'])) { $alert = new Alert(); $alert->clear($this->getType(), $this->fields['id'], Alert::END); } } /** * @see CommonDBTM::prepareInputForAdd() **/ function prepareInputForAdd($input) { $input = parent::prepareInputForAdd($input); if (!isset($this->input['softwares_id']) || !$this->input['softwares_id']) { Session::addMessageAfterRedirect(__("Please select a software for this license"), true, ERROR, true); return false; } if (isset($input["id"]) && ($input["id"] > 0)) { $input["_oldID"] = $input["id"]; } unset($input['id']); unset($input['withtemplate']); // Unset to set to default using mysql default value if (empty($input['expire'])) { unset ($input['expire']); } return $input; } /** * @since 0.85 * @see CommonDBTM::prepareInputForUpdate() **/ function prepareInputForUpdate($input) { $input = parent::prepareInputForUpdate($input); // Update number : compute validity indicator if (isset($input['number'])) { $input['is_valid'] = self::computeValidityIndicator($input['id'], $input['number']); } return $input; } /** * Compute licence validity indicator. * * @param $ID ID of the licence * @param $number licence count to check (default -1) * * @since 0.85 * * @return int validity indicator **/ static function computeValidityIndicator($ID, $number = -1) { if (($number >= 0) && ($number < Item_SoftwareLicense::countForLicense($ID, -1))) { return 0; } // Default return 1 return 1; } /** * Update validity indicator of a specific license * @param $ID ID of the licence * * @since 0.85 * * @return void **/ static function updateValidityIndicator($ID) { $lic = new self(); if ($lic->getFromDB($ID)) { $valid = self::computeValidityIndicator($ID, $lic->fields['number']); if ($valid != $lic->fields['is_valid']) { $lic->update(['id' => $ID, 'is_valid' => $valid]); } } } /** * @since 0.84 **/ function cleanDBonPurge() { $this->deleteChildrenAndRelationsFromDb( [ Certificate_Item::class, Item_SoftwareLicense::class, ] ); // Alert does not extends CommonDBConnexity $alert = new Alert(); $alert->cleanDBonItemDelete($this->getType(), $this->fields['id']); } function post_addItem() { $itemtype = 'Software'; $dupid = $this->fields["softwares_id"]; if (isset($this->input["_duplicate_license"])) { $itemtype = 'SoftwareLicense'; $dupid = $this->input["_duplicate_license"]; } // Add infocoms if exists for the licence $infocoms = Infocom::getItemsAssociatedTo($this->getType(), $this->fields['id']); if (!empty($infocoms)) { $override_input['items_id'] = $this->getID(); $infocoms[0]->clone($override_input); } Software::updateValidityIndicator($this->fields["softwares_id"]); } /** * @since 0.85 * @see CommonDBTM::post_updateItem() **/ function post_updateItem($history = 1) { if (in_array("is_valid", $this->updates)) { Software::updateValidityIndicator($this->fields["softwares_id"]); } } /** * @since 0.85 * @see CommonDBTM::post_deleteFromDB() **/ function post_deleteFromDB() { Software::updateValidityIndicator($this->fields["softwares_id"]); } /** * @since 0.84 * * @see CommonDBTM::getPreAdditionalInfosForName **/ function getPreAdditionalInfosForName() { $soft = new Software(); if ($soft->getFromDB($this->fields['softwares_id'])) { return $soft->getName(); } return ''; } function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); $this->addImpactTab($ong, $options); $this->addStandardTab('SoftwareLicense', $ong, $options); $this->addStandardTab('Item_SoftwareLicense', $ong, $options); $this->addStandardTab('Infocom', $ong, $options); $this->addStandardTab('Contract_Item', $ong, $options); $this->addStandardTab('Document_Item', $ong, $options); $this->addStandardTab('KnowbaseItem_Item', $ong, $options); $this->addStandardTab('Ticket', $ong, $options); $this->addStandardTab('Item_Problem', $ong, $options); $this->addStandardTab('Change_Item', $ong, $options); $this->addStandardTab('Notepad', $ong, $options); $this->addStandardTab('Certificate_Item', $ong, $options); $this->addStandardTab('Log', $ong, $options); return $ong; } /** * Print the Software / license form * * @param $ID integer Id of the version or the template to print * @param $options array of possible options: * - target form target * - softwares_id ID of the software for add process * * @return true if displayed false if item not found or not right to display **/ function showForm($ID, $options = []) { $softwares_id = -1; if (isset($options['softwares_id'])) { $softwares_id = $options['softwares_id']; } if ($ID < 0) { // Create item $this->fields['softwares_id'] = $softwares_id; $this->fields['number'] = 1; $soft = new Software(); if ($soft->getFromDB($softwares_id) && in_array($_SESSION['glpiactive_entity'], getAncestorsOf('glpi_entities', $soft->getEntityID()))) { $options['entities_id'] = $soft->getEntityID(); } } $this->initForm($ID, $options); $this->showFormHeader($options); // Restore saved value or override with page parameter if (!isset($options['template_preview'])) { if (isset($_REQUEST)) { $saved = Html::cleanPostForTextArea($_REQUEST); } } foreach ($this->fields as $name => $value) { if (isset($saved[$name]) && empty($this->fields[$name])) { $this->fields[$name] = $saved[$name]; } } echo ""; echo ""; echo "".Software::getTypeName(1).""; echo ""; if ($ID > 0) { $softwares_id = $this->fields["softwares_id"]; echo ""; echo "". Dropdown::getDropdownName("glpi_softwares", $softwares_id).""; } else { Dropdown::show( 'Software', [ 'condition' => ['is_template' => 0, 'is_deleted' => 0], 'entity' => $_SESSION['glpiactive_entity'], 'entity_sons' => $_SESSION['glpiactive_entity_recursive'], 'on_change' => 'this.form.submit()', 'value' => $softwares_id ] ); } echo ""; echo ""; echo "\n"; $tplmark = $this->getAutofillMark('name', $options); echo ""; echo "".sprintf(__('%1$s%2$s'), __('Name'), $tplmark). ""; echo ""; $objectName = autoName($this->fields["name"], "name", (isset($options['withtemplate']) && ( $options['withtemplate']== 2)), $this->getType(), $this->fields["entities_id"]); Html::autocompletionTextField($this, 'name', ['value' => $objectName]); echo ""; echo "".__('Status').""; echo ""; State::dropdown([ 'value' => $this->fields["states_id"], 'entity' => $this->fields["entities_id"], 'condition' => ['is_visible_softwarelicense' => 1] ]); echo "\n"; echo ""; echo "".__('As child of').""; self::dropdown([ 'value' => $this->fields['softwarelicenses_id'], 'name' => 'softwarelicenses_id', 'entity' => $this->fields['entities_id'], 'used' => (($ID > 0) ? getSonsOf($this->getTable(), $ID) : []), 'condition' => ['softwares_id' => $this->fields['softwares_id']] ]); echo ""; echo ""; echo "" . Location::getTypeName(1) . ""; Location::dropdown(['value' => $this->fields["locations_id"], 'entity' => $this->fields["entities_id"]]); echo ""; echo ""._n('Type', 'Types', 1).""; echo ""; SoftwareLicenseType::dropdown(['value' => $this->fields["softwarelicensetypes_id"]]); echo "\n"; echo ""; echo "".__('Technician in charge of the license').""; echo ""; User::dropdown(['name' => 'users_id_tech', 'value' => $this->fields["users_id_tech"], 'right' => 'own_ticket', 'entity' => $this->fields["entities_id"]]); echo ""; echo "".__('Publisher').""; echo ""; Manufacturer::dropdown(['value' => $this->fields["manufacturers_id"]]); echo "\n"; echo ""; echo "".__('Group in charge of the license').""; echo ""; Group::dropdown([ 'name' => 'groups_id_tech', 'value' => $this->fields['groups_id_tech'], 'entity' => $this->fields['entities_id'], 'condition' => ['is_assign' => 1] ]); echo ""; echo "".__('Serial number').""; echo ""; Html::autocompletionTextField($this, "serial"); echo "\n"; echo ""; echo "" . User::getTypeName(1) . ""; echo ""; User::dropdown(['value' => $this->fields["users_id"], 'entity' => $this->fields["entities_id"], 'right' => 'all']); echo ""; $tplmark = $this->getAutofillMark('otherserial', $options); echo "".sprintf(__('%1$s%2$s'), __('Inventory number'), $tplmark); echo ""; echo ""; $objectName = autoName($this->fields["otherserial"], "otherserial", (isset($options['withtemplate']) && ($options['withtemplate'] == 2)), $this->getType(), $this->fields["entities_id"]); Html::autocompletionTextField($this, 'otherserial', ['value' => $objectName]); echo "\n"; echo ""; echo "" . Group::getTypeName(1) . ""; Group::dropdown([ 'value' => $this->fields["groups_id"], 'entity' => $this->fields["entities_id"], 'condition' => ['is_itemgroup' => 1] ]); echo ""; echo "".__('Comments').""; echo ""; echo ""; echo "\n"; echo ""; echo "".__('Version in use').""; echo ""; SoftwareVersion::dropdownForOneSoftware(['name' => "softwareversions_id_use", 'softwares_id' => $this->fields["softwares_id"], 'value' => $this->fields["softwareversions_id_use"]]); echo ""; echo ""; echo "".__('Purchase version').""; echo ""; SoftwareVersion::dropdownForOneSoftware(['name' => "softwareversions_id_buy", 'softwares_id' => $this->fields["softwares_id"], 'value' => $this->fields["softwareversions_id_buy"]]); echo "\n"; echo ""; echo ""._x('quantity', 'Number').""; echo ""; Dropdown::showNumber("number", ['value' => $this->fields["number"], 'min' => 1, 'max' => 10000, 'step' => 1, 'toadd' => [-1 => __('Unlimited')]]); if ($ID > 0) { echo " "; if ($this->fields['is_valid']) { echo ""._x('adjective', 'Valid').''; } else if (!$this->fields['is_valid'] && $this->fields['allow_overquota']) { echo ""._x('adjective', 'Valid (Over Quota)').''; } else { echo ""._x('adjective', 'Invalid').''; } } echo "\n"; echo ""; echo "".__('Allow Over-Quota').""; echo ""; Dropdown::showYesNo('allow_overquota', $this->fields['allow_overquota']); echo "\n"; echo ""; echo "".__('Expiration').""; echo ""; Html::showDateField('expire', ['value' => $this->fields["expire"]]); if ($ID && is_null($this->fields["expire"])) { echo "
".__('Never expire')." "; Html::showToolTip(__('On search engine, use "Expiration contains NULL" to search licenses with no expiration date')); } Alert::displayLastAlert('SoftwareLicense', $ID); echo "\n"; $this->showFormButtons($options); return true; } /** * Is the license may be recursive * * @return boolean **/ function maybeRecursive () { $soft = new Software(); if (isset($this->fields["softwares_id"]) && $soft->getFromDB($this->fields["softwares_id"])) { return $soft->isRecursive(); } return true; } function rawSearchOptions() { $tab = []; // Only use for History (not by search Engine) $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => '1', 'table' => $this->getTable(), 'field' => 'name', 'name' => __('Name'), 'datatype' => 'itemlink', 'massiveaction' => false, 'forcegroupby' => true, 'autocomplete' => true, ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, 'datatype' => 'number', 'forcegroupby' => true ]; $tab = array_merge($tab, Location::rawSearchOptionsToAdd()); $tab[] = [ 'id' => '11', 'table' => $this->getTable(), 'field' => 'serial', 'name' => __('Serial number'), 'datatype' => 'string', 'autocomplete' => true, ]; $tab[] = [ 'id' => '4', 'table' => $this->getTable(), 'field' => 'number', 'name' => __('Number'), 'datatype' => 'number', 'max' => 100, 'toadd' => [ '-1' => 'Unlimited' ] ]; $tab[] = [ 'id' => '5', 'table' => 'glpi_softwarelicensetypes', 'field' => 'name', 'name' => _n('Type', 'Types', 1), 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '6', 'table' => 'glpi_softwareversions', 'field' => 'name', 'linkfield' => 'softwareversions_id_buy', 'name' => __('Purchase version'), 'datatype' => 'dropdown', 'displaywith' => [ '0' => __('states_id') ] ]; $tab[] = [ 'id' => '7', 'table' => 'glpi_softwareversions', 'field' => 'name', 'linkfield' => 'softwareversions_id_use', 'name' => __('Version in use'), 'datatype' => 'dropdown', 'displaywith' => [ '0' => __('states_id') ] ]; $tab[] = [ 'id' => '8', 'table' => $this->getTable(), 'field' => 'expire', 'name' => __('Expiration'), 'datatype' => 'date' ]; $tab[] = [ 'id' => '9', 'table' => $this->getTable(), 'field' => 'is_valid', 'name' => __('Valid'), 'datatype' => 'bool' ]; $tab[] = [ 'id' => '10', 'table' => 'glpi_softwares', 'field' => 'name', 'name' => Software::getTypeName(1), 'datatype' => 'itemlink' ]; $tab[] = [ 'id' => '168', 'table' => $this->getTable(), 'field' => 'allow_overquota', 'name' => __('Allow Over-Quota'), 'datatype' => 'bool' ]; $tab[] = [ 'id' => '13', 'table' => $this->getTable(), 'field' => 'completename', 'name' => __('Father'), 'datatype' => 'itemlink', 'forcegroupby' => true, 'joinparams' => ['condition' => "AND 1=1"] ]; $tab[] = [ 'id' => '16', 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comments'), 'datatype' => 'text' ]; $tab[] = [ 'id' => '24', 'table' => 'glpi_users', 'field' => 'name', 'linkfield' => 'users_id_tech', 'name' => __('Technician in charge of the license'), 'datatype' => 'dropdown', 'right' => 'own_ticket' ]; $tab[] = [ 'id' => '31', 'table' => 'glpi_states', 'field' => 'completename', 'name' => __('Status'), 'datatype' => 'dropdown', 'condition' => ['is_visible_softwarelicense' => 1] ]; $tab[] = [ 'id' => '49', 'table' => 'glpi_groups', 'field' => 'completename', 'linkfield' => 'groups_id_tech', 'name' => __('Group in charge of the license'), 'condition' => ['is_assign' => 1], 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '61', 'table' => $this->getTable(), 'field' => 'template_name', 'name' => __('Template name'), 'datatype' => 'text', 'massiveaction' => false, 'nosearch' => true, 'nodisplay' => true, 'autocomplete' => true, ]; $tab[] = [ 'id' => '70', 'table' => 'glpi_users', 'field' => 'name', 'name' => User::getTypeName(1), 'datatype' => 'dropdown', 'right' => 'all' ]; $tab[] = [ 'id' => '71', 'table' => 'glpi_groups', 'field' => 'completename', 'name' => Group::getTypeName(1), 'condition' => ['is_itemgroup' => 1], 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '80', 'table' => 'glpi_entities', 'field' => 'completename', 'name' => Entity::getTypeName(1), 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '86', 'table' => $this->getTable(), 'field' => 'is_recursive', 'name' => __('Child entities'), 'datatype' => 'bool' ]; $tab[] = [ 'id' => '162', 'table' => $this->getTable(), 'field' => 'otherserial', 'name' => __('Inventory number'), 'massiveaction' => false, 'datatype' => 'string', 'autocomplete' => true, ]; // add objectlock search options $tab = array_merge($tab, ObjectLock::rawSearchOptionsToAdd(get_class($this))); $tab = array_merge($tab, Notepad::rawSearchOptionsToAdd()); return $tab; } static public function rawSearchOptionsToAdd() { $tab = []; $name = static::getTypeName(Session::getPluralNumber()); if (!self::canView()) { return $tab; } $licjoinexpire = ['jointype' => 'child', 'condition' => getEntitiesRestrictRequest(' AND', "NEWTABLE", '', '', true). " AND NEWTABLE.`is_template` = 0 AND (NEWTABLE.`expire` IS NULL OR NEWTABLE.`expire` > NOW())"]; $tab[] = [ 'id' => 'license', 'name' => $name ]; $tab[] = [ 'id' => '160', 'table' => 'glpi_softwarelicenses', 'field' => 'name', 'name' => __('Name'), 'datatype' => 'dropdown', 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '161', 'table' => 'glpi_softwarelicenses', 'field' => 'serial', 'datatype' => 'string', 'name' => __('Serial number'), 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '162', 'table' => 'glpi_softwarelicenses', 'field' => 'otherserial', 'datatype' => 'string', 'name' => __('Inventory number'), 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '163', 'table' => 'glpi_softwarelicenses', 'field' => 'number', 'name' => __('Number of licenses'), 'forcegroupby' => true, 'usehaving' => true, 'datatype' => 'number', 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '164', 'table' => 'glpi_softwarelicensetypes', 'field' => 'name', 'datatype' => 'dropdown', 'name' => _n('Type', 'Types', 1), 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => [ 'beforejoin' => [ 'table' => 'glpi_softwarelicenses', 'joinparams' => $licjoinexpire ] ] ]; $tab[] = [ 'id' => '165', 'table' => 'glpi_softwarelicenses', 'field' => 'comment', 'name' => __('Comments'), 'forcegroupby' => true, 'datatype' => 'text', 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '166', 'table' => 'glpi_softwarelicenses', 'field' => 'expire', 'name' => __('Expiration'), 'forcegroupby' => true, 'datatype' => 'date', 'emptylabel' => 'Never expire', 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; $tab[] = [ 'id' => '167', 'table' => 'glpi_softwarelicenses', 'field' => 'is_valid', 'name' => __('Valid'), 'forcegroupby' => true, 'datatype' => 'bool', 'massiveaction' => false, 'joinparams' => $licjoinexpire ]; return $tab; } /** * Give cron information * * @param $name : task's name * * @return array of information **/ static function cronInfo($name) { return ['description' => __('Send alarms on expired licenses')]; } /** * Cron action on softwares : alert on expired licences * * @param $task to log, if NULL display (default NULL) * * @return 0 : nothing to do 1 : done with success **/ static function cronSoftware($task = null) { global $DB, $CFG_GLPI; $cron_status = 1; if (!$CFG_GLPI['use_notifications']) { return 0; } $message = []; $items_notice = []; $items_end = []; $tonotify = Entity::getEntitiesToNotify('use_licenses_alert'); foreach (array_keys($tonotify) as $entity) { $before = Entity::getUsedConfig('send_licenses_alert_before_delay', $entity); // Check licenses $criteria = [ 'SELECT' => [ 'glpi_softwarelicenses.*', 'glpi_softwares.name AS softname' ], 'FROM' => 'glpi_softwarelicenses', 'INNER JOIN' => [ 'glpi_softwares' => [ 'ON' => [ 'glpi_softwarelicenses' => 'softwares_id', 'glpi_softwares' => 'id' ] ] ], 'LEFT JOIN' => [ 'glpi_alerts' => [ 'ON' => [ 'glpi_softwarelicenses' => 'id', 'glpi_alerts' => 'items_id', [ 'AND' => [ 'glpi_alerts.itemtype' => 'SoftwareLicense' ] ] ] ] ], 'WHERE' => [ 'glpi_alerts.date' => null, 'NOT' => ['glpi_softwarelicenses.expire' => null], new QueryExpression('DATEDIFF('.$DB->quoteName('glpi_softwarelicenses.expire').', CURDATE()) < ' . $before), 'glpi_softwares.is_template' => 0, 'glpi_softwares.is_deleted' => 0, 'glpi_softwares.entities_id' => $entity ] ]; $iterator = $DB->request($criteria); $message = ""; $items = []; while ($license = $iterator->next()) { $name = $license['softname'].' - '.$license['name'].' - '.$license['serial']; //TRANS: %1$s the license name, %2$s is the expiration date $message .= sprintf(__('License %1$s expired on %2$s'), Html::convDate($license["expire"]), $name)."
\n"; $items[$license['id']] = $license; } if (!empty($items)) { $alert = new Alert(); $options['entities_id'] = $entity; $options['licenses'] = $items; if (NotificationEvent::raiseEvent('alert', new self(), $options)) { $entityname = Dropdown::getDropdownName("glpi_entities", $entity); if ($task) { //TRANS: %1$s is the entity, %2$s is the message $task->log(sprintf(__('%1$s: %2$s')."\n", $entityname, $message)); $task->addVolume(1); } else { Session::addMessageAfterRedirect(sprintf(__('%1$s: %2$s'), $entityname, $message)); } $input["type"] = Alert::END; $input["itemtype"] = 'SoftwareLicense'; // add alerts foreach ($items as $ID => $consumable) { $input["items_id"] = $ID; $alert->add($input); unset($alert->fields['id']); } } else { $entityname = Dropdown::getDropdownName('glpi_entities', $entity); //TRANS: %s is entity name $msg = sprintf(__('%1$s: %2$s'), $entityname, __('Send licenses alert failed')); if ($task) { $task->log($msg); } else { Session::addMessageAfterRedirect($msg, false, ERROR); } } } } return $cron_status; } /** * Get number of bought licenses of a version * * @param $softwareversions_id version ID * @param $entity to search for licenses in (default = all active entities) * (default '') * * @return number of installations */ static function countForVersion($softwareversions_id, $entity = '') { global $DB; $result = $DB->request([ 'COUNT' => 'cpt', 'FROM' => 'glpi_softwarelicenses', 'WHERE' => [ 'softwareversions_id_buy' => $softwareversions_id ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', '', $entity) ])->next(); return $result['cpt']; } /** * Get number of licensesof a software * * @param $softwares_id software ID * * @return number of licenses **/ static function countForSoftware($softwares_id) { global $DB; $iterator = $DB->request([ 'COUNT' => 'cpt', 'FROM' => 'glpi_softwarelicenses', 'WHERE' => [ 'softwares_id' => $softwares_id, 'is_template' => 0, 'number' => -1 ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', '', '', true) ]); if ($line = $iterator->next()) { if ($line['cpt'] > 0) { // At least 1 unlimited license, means unlimited return -1; } } $result = $DB->request([ 'SELECT' => ['SUM' => 'number AS numsum'], 'FROM' => 'glpi_softwarelicenses', 'WHERE' => [ 'softwares_id' => $softwares_id, 'is_template' => 0, 'number' => ['>', 0] ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', '', '', true) ])->next(); return ($result['numsum'] ? $result['numsum'] : 0); } /** * Show Licenses of a software * * @param $software Software object * * @return void **/ static function showForSoftware(Software $software) { global $DB; $softwares_id = $software->getField('id'); $license = new self(); if (!$software->can($softwares_id, READ)) { return false; } $columns = ['name' => __('Name'), 'entity' => Entity::getTypeName(1), 'serial' => __('Serial number'), 'number' => _x('quantity', 'Number'), '_affected' => __('Affected items'), 'typename' => _n('Type', 'Types', 1), 'buyname' => __('Purchase version'), 'usename' => __('Version in use'), 'expire' => __('Expiration')]; if (!$software->isRecursive()) { unset($columns['entity']); } 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($columns[$_GET["sort"]])) { $sort = $_GET["sort"]; } else { $sort = ["entity $order", "name $order"]; } // Righ type is enough. Can add a License on a software we have Read access $canedit = Software::canUpdate(); $showmassiveactions = $canedit; // Total Number of events $number = countElementsInTable( "glpi_softwarelicenses", [ 'glpi_softwarelicenses.softwares_id' => $softwares_id, 'glpi_softwarelicenses.is_template' => 0, ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', '', '', true) ); echo "
"; 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'), Software::getTypeName(1), $software->getName())); if ($canedit) { echo ""; } $rand = mt_rand(); $iterator = $DB->request([ 'SELECT' => [ 'glpi_softwarelicenses.*', 'buyvers.name AS buyname', 'usevers.name AS usename', 'glpi_entities.completename AS entity', 'glpi_softwarelicensetypes.name AS typename' ], 'FROM' => 'glpi_softwarelicenses', 'LEFT JOIN' => [ 'glpi_softwareversions AS buyvers' => [ 'ON' => [ 'glpi_softwarelicenses' => 'softwareversions_id_buy', 'buyvers' => 'id' ] ], 'glpi_softwareversions AS usevers' => [ 'ON' => [ 'glpi_softwarelicenses' => 'softwareversions_id_use', 'usevers' => 'id' ] ], 'glpi_entities' => [ 'ON' => [ 'glpi_entities' => 'id', 'glpi_softwarelicenses' => 'entities_id' ] ], 'glpi_softwarelicensetypes' => [ 'ON' => [ 'glpi_softwarelicensetypes' => 'id', 'glpi_softwarelicenses' => 'softwarelicensetypes_id' ] ] ], 'WHERE' => [ 'glpi_softwarelicenses.softwares_id' => $softwares_id, 'glpi_softwarelicenses.is_template' => 0 ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', '', '', true), 'ORDERBY' => $sort, 'START' => (int)$start, 'LIMIT' => (int)$_SESSION['glpilist_limit'] ]); $num_displayed = count($iterator); if ($num_displayed) { // Display the pager Html::printAjaxPager(self::getTypeName(Session::getPluralNumber()), $start, $number); if ($showmassiveactions) { Html::openMassiveActionsForm('mass'.__CLASS__.$rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $num_displayed), 'container' => 'mass'.__CLASS__.$rand, 'extraparams' => ['options' => ['glpi_softwareversions.name' => ['condition' => $DB->quoteName("glpi_softwareversions.softwares_id")." = $softwares_id"], 'glpi_softwarelicenses.name' => ['itemlink_as_string' => true]]]]; Html::showMassiveActions($massiveactionparams); } echo ""; $header_begin = ""; } else { $header_end .= "". "$val"; } } $header_end .= "\n"; echo $header_begin.$header_top.$header_end; $tot_assoc = 0; $tot = 0; while ($data = $iterator->next()) { Session::addToNavigateListItems('SoftwareLicense', $data['id']); $expired = true; if (is_null($data['expire']) || ($data['expire'] > date('Y-m-d'))) { $expired = false; } echo ""; if ($license->canEdit($data['id'])) { echo ""; } else { echo ""; } echo ""; if (isset($columns['entity'])) { echo ""; } echo ""; echo ""; $nb_assoc = Item_SoftwareLicense::countForLicense($data['id']); $tot_assoc += $nb_assoc; $color = ($data['is_valid']?'green':'red'); echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($data['number'] < 0) { // One illimited license, total is illimited $tot = -1; } else if ($tot >= 0) { // Expire license not count if (!$expired) { // Not illimited, add the current number $tot += $data['number']; } } } echo ""; echo ""; echo ""; $color = ($software->fields['is_valid']?'green':'red'); echo ""; echo ""; echo "
"; $header_top = Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header_end = ''; foreach ($columns as $key => $val) { // Non order column if ($key[0] == '_') { $header_end .= "$val
".Html::getMassiveActionCheckBox(__CLASS__, $data["id"])." "; echo $license->getLink(['complete' => true, 'comments' => true]); echo ""; echo $data['entity']; echo "".$data['serial']."". (($data['number'] > 0) ?$data['number']:__('Unlimited'))."".$nb_assoc."".$data['typename']."".$data['buyname']."".$data['usename']."".Html::convDate($data['expire'])."
".__('Total')."".(($tot > 0)?$tot."":__('Unlimited')). "".$tot_assoc."
\n"; if ($showmassiveactions) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } Html::printAjaxPager(self::getTypeName(Session::getPluralNumber()), $start, $number); } else { echo "
".__('No item found')."
"; } echo "
"; } /** * Display debug information for current object **/ function showDebug() { $license = ['softname' => '', 'name' => '', 'serial' => '', 'expire' => '']; $options['entities_id'] = $this->getEntityID(); $options['licenses'] = [$license]; NotificationEvent::debugEvent($this, $options); } /** * Get fields to display in the unicity error message * * @return an array which contains field => label */ function getUnicityFieldsToDisplayInErrorMessage() { return ['id' => __('ID'), 'serial' => __('Serial number'), 'entities_id' => Entity::getTypeName(1), 'softwares_id' => _n('Software', 'Software', 1)]; } function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { $nb = 0; switch ($item->getType()) { case 'Software' : if (!self::canView()) { return ''; } if ($_SESSION['glpishow_count_on_tabs']) { $nb = self::countForSoftware($item->getID()); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), (($nb >= 0) ? $nb : '∞')); break; case 'SoftwareLicense' : if (!self::canView()) { return ''; } if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable( $this->getTable(), ['softwarelicenses_id' => $item->getID()] ); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), (($nb >= 0) ? $nb : '∞')); break; } } return ''; } static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item->getType()=='Software' && self::canView()) { self::showForSoftware($item); } else { if ($item->getType()=='SoftwareLicense' && self::canView()) { self::getSonsOf($item); return true; } } return true; } static function getSonsOf($item) { global $DB; $entity_assign = $item->isEntityAssign(); $nb = 0; $ID = $item->getID(); echo "
"; echo ""; echo ""; $header = ""; if ($entity_assign) { $header .= ""; } $header .= ""; $header .= "\n"; echo $header; $fk = $item->getForeignKeyField(); $crit = [$fk => $ID, 'ORDER' => 'name']; if ($entity_assign) { if ($fk == 'entities_id') { $crit['id'] = $_SESSION['glpiactiveentities']; $crit['id'] += $_SESSION['glpiparententities']; } else { foreach ($_SESSION['glpiactiveentities'] as $key => $value) { $crit['entities_id'][$key] = (string)$value; } } } $nb = 0; foreach ($DB->request($item->getTable(), $crit) as $data) { $nb++; echo ""; echo ""; if ($entity_assign) { echo ""; } echo ""; echo "\n"; } if ($nb) { echo $header; } echo "
".sprintf(__('Sons of %s'), $item->getTreeLink()); echo "
".__('Name')."".Entity::getTypeName(1)."".__('Comments')."
".$data['name']."".Dropdown::getDropdownName("glpi_entities", $data["entities_id"])."".$data['comment']."
\n"; } static function getIcon() { return "fas fa-key"; } }