. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * This class manages locks * Lock management is available for objects and link between objects. It relies on the use of * a is_dynamic field, to incidate if item supports lock, and is_deleted field to incidate if the * item or link is locked * By setting is_deleted to 0 again, the item is unlock * * Note : GLPI's core supports locks for objects. It's up to the external inventory tool to manage * locks for fields * * @since 0.84 **/ class Lock { static function getTypeName($nb = 0) { return _n('Lock', 'Locks', $nb); } /** * Display form to unlock fields and links * * @param CommonDBTM $item the source item **/ static function showForItem(CommonDBTM $item) { global $DB; $ID = $item->getID(); $itemtype = $item->getType(); $header = false; //If user doesn't have update right on the item, lock form must not be displayed if (!$item->isDynamic() || !$item->can($item->fields['id'], UPDATE)) { return false; } echo "
"; echo "
"; echo "\n"; echo "\n"; echo ""; echo ""; //Use a hook to allow external inventory tools to manage per field lock $results = Plugin::doHookFunction('display_locked_fields', ['item' => $item, 'header' => $header]); $header |= $results['header']; //Special locks for computers only if ($itemtype == 'Computer') { $computer_item = new Computer_Item(); //Locks for items recorded in glpi_computers_items table $types = ['Monitor', 'Peripheral', 'Printer']; foreach ($types as $type) { $params = ['is_dynamic' => 1, 'is_deleted' => 1, 'computers_id' => $ID, 'itemtype' => $type]; $params['FIELDS'] = ['id', 'items_id']; $first = true; foreach ($DB->request('glpi_computers_items', $params) as $line) { /** @var CommonDBTM $asset */ $asset = new $type(); $asset->getFromDB($line['items_id']); if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } } //items disks $item_disk = new Item_Disk(); $params = [ 'is_dynamic' => 1, 'is_deleted' => 1, 'items_id' => $ID, 'itemtype' => $itemtype ]; $params['FIELDS'] = ['id', 'name']; $first = true; foreach ($DB->request($item_disk->getTable(), $params) as $line) { if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } $computer_vm = new ComputerVirtualMachine(); $params = ['is_dynamic' => 1, 'is_deleted' => 1, 'computers_id' => $ID]; $params['FIELDS'] = ['id', 'name']; $first = true; foreach ($DB->request($computer_vm->getTable(), $params) as $line) { if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } } //Software versions $item_sv = new Item_SoftwareVersion(); $item_sv_table = Item_SoftwareVersion::getTable(); $iterator = $DB->request([ 'SELECT' => [ 'isv.id AS id', 'sv.name AS version', 's.name AS software' ], 'FROM' => "{$item_sv_table} AS isv", 'LEFT JOIN' => [ 'glpi_softwareversions AS sv' => [ 'FKEY' => [ 'isv' => 'softwareversions_id', 'sv' => 'id' ] ], 'glpi_softwares AS s' => [ 'FKEY' => [ 'sv' => 'softwares_id', 's' => 'id' ] ] ], 'WHERE' => [ 'isv.is_deleted' => 1, 'isv.is_dynamic' => 1, 'isv.items_id' => $ID, 'isv.itemtype' => $itemtype, ] ]); echo "\n"; while ($data = $iterator->next()) { echo ""; echo ""; echo ""; echo "\n"; } //Software licenses $item_sl = new Item_SoftwareLicense(); $item_sl_table = Item_SoftwareLicense::getTable(); $iterator = $DB->request([ 'SELECT' => [ 'isl.id AS id', 'sl.name AS version', 's.name AS software' ], 'FROM' => "{$item_sl_table} AS isl", 'LEFT JOIN' => [ 'glpi_softwarelicenses AS sl' => [ 'FKEY' => [ 'isl' => 'softwarelicenses_id', 'sl' => 'id' ] ], 'glpi_softwares AS s' => [ 'FKEY' => [ 'sl' => 'softwares_id', 's' => 'id' ] ] ], 'WHERE' => [ 'isl.is_deleted' => 1, 'isl.is_dynamic' => 1, 'isl.items_id' => $ID, 'isl.itemtype' => $itemtype, ] ]); echo "\n"; while ($data = $iterator->next()) { echo ""; echo ""; echo ""; echo "\n"; } $first = true; $networkport = new NetworkPort(); $params = ['is_dynamic' => 1, 'is_deleted' => 1, 'items_id' => $ID, 'itemtype' => $itemtype]; $params['FIELDS'] = ['id']; foreach ($DB->request($networkport->getTable(), $params) as $line) { $networkport->getFromDB($line['id']); if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } $first = true; $networkname = new NetworkName(); $params = [ 'glpi_networknames.is_dynamic' => 1, 'glpi_networknames.is_deleted' => 1, 'glpi_networknames.itemtype' => 'NetworkPort', 'glpi_networknames.items_id' => new QueryExpression($DB->quoteName('glpi_networkports.id')), 'glpi_networkports.items_id' => $ID, 'glpi_networkports.itemtype' => $itemtype ]; $params['FIELDS'] = ['glpi_networknames' => 'id']; foreach ($DB->request(['glpi_networknames', 'glpi_networkports'], $params) as $line) { $networkname->getFromDB($line['id']); if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } $first = true; $ipaddress = new IPAddress(); $params = [ 'glpi_ipaddresses.is_dynamic' => 1, 'glpi_ipaddresses.is_deleted' => 1, 'glpi_ipaddresses.itemtype' => 'NetworkName', 'glpi_ipaddresses.items_id' => new QueryExpression($DB->quoteName('glpi_networknames.id')), 'glpi_networknames.itemtype' => 'NetworkPort', 'glpi_networknames.items_id' => new QueryExpression($DB->quoteName('glpi_networkports.id')), 'glpi_networkports.items_id' => $ID, 'glpi_networkports.itemtype' => $itemtype ]; $params['FIELDS'] = ['glpi_ipaddresses' => 'id']; foreach ($DB->request(['glpi_ipaddresses', 'glpi_networknames', 'glpi_networkports'], $params) as $line) { $ipaddress->getFromDB($line['id']); if ($first) { echo "\n"; $first = false; } echo ""; echo ""; echo ""; echo "\n"; } $types = Item_Devices::getDeviceTypes(); $nb = 0; foreach ($types as $type) { $nb += countElementsInTable(getTableForItemType($type), ['items_id' => $ID, 'itemtype' => $itemtype, 'is_dynamic' => 1, 'is_deleted' => 1 ]); } if ($nb) { echo "\n"; foreach ($types as $type) { $type_item = new $type(); $associated_type = str_replace('Item_', '', $type); $associated_table = getTableForItemType($associated_type); $fk = getForeignKeyFieldForTable($associated_table); $iterator = $DB->request([ 'SELECT' => [ 'i.id', 't.designation AS name' ], 'FROM' => getTableForItemType($type) . ' AS i', 'LEFT JOIN' => [ "$associated_table AS t" => [ 'ON' => [ 't' => 'id', 'i' => $fk ] ] ], 'WHERE' => [ 'itemtype' => $itemtype, 'items_id' => $ID, 'is_dynamic' => 1, 'is_deleted' => 1 ] ]); while ($data = $iterator->next()) { echo ""; echo ""; echo "\n"; } } } if ($header) { echo "\n"; echo "
".__('Locked items')."
".$type::getTypeName(Session::getPluralNumber())."
"; if ($computer_item->can($line['id'], UPDATE) || $computer_item->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $asset->getName() . "
".$item_disk->getTypeName(Session::getPluralNumber())."
"; if ($item_disk->can($line['id'], UPDATE) || $item_disk->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $line['name'] . "
".$computer_vm->getTypeName(Session::getPluralNumber())."
"; if ($computer_vm->can($line['id'], UPDATE) || $computer_vm->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $line['name'] . "
".Software::getTypeName(Session::getPluralNumber())."
"; if ($item_sv->can($data['id'], UPDATE) || $item_sv->can($data['id'], PURGE)) { $header = true; echo ""; } echo "" . $data['software']." ".$data['version'] . "
".SoftwareLicense::getTypeName(Session::getPluralNumber())."
"; if ($item_sl->can($data['id'], UPDATE) || $item_sl->can($data['id'], PURGE)) { $header = true; echo ""; } echo "" . $data['software']." ".$data['version'] . "
".$networkport->getTypeName(Session::getPluralNumber())."
"; if ($networkport->can($line['id'], UPDATE) || $networkport->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $networkport->getName() . "
".NetworkName::getTypeName(Session::getPluralNumber())."
"; if ($networkname->can($line['id'], UPDATE) || $networkname->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $networkname->getName() . "
".IPAddress::getTypeName(Session::getPluralNumber())."
"; if ($ipaddress->can($line['id'], UPDATE) || $ipaddress->can($line['id'], PURGE)) { $header = true; echo ""; } echo "" . $ipaddress->getName() . "
"._n('Component', 'Components', Session::getPluralNumber())."
"; if ($type_item->can($data['id'], UPDATE) || $type_item->can($data['id'], PURGE)) { $header = true; echo ""; } echo ""; printf(__('%1$s: %2$s'), $associated_type::getTypeName(), $data['name']); echo "
"; echo Html::getCheckAllAsCheckbox('lock_form'); echo " 
"; Html::openArrowMassives('lock_form', true); Html::closeArrowMassives(['unlock' => _sx('button', 'Unlock'), 'purge' => _sx('button', 'Delete permanently')]); } else { echo ""; echo "". __('No locked item').""; echo ""; } Html::closeForm(); echo "
\n"; } /** * @see CommonGLPI::getTabNameForItem() * * @param $item CommonGLPI object * @param $withtemplate (default 0) **/ function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if ($item->isDynamic() && $item->can($item->fields['id'], UPDATE)) { return Lock::getTypeName(Session::getPluralNumber()); } return ''; } /** * @param $item CommonGLPI object * @param $tabnum (default 1) * @param $withtemplate (default 0) **/ static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item->isDynamic() && $item->can($item->fields['id'], UPDATE)) { self::showForItem($item); } return true; } /** * Get infos to build an SQL query to get locks fields in a table * * @param string $itemtype itemtype of the item to look for locked fields * @param string $baseitemtype itemtype of the based item * * @return array which contains necessary informations to build the SQL query **/ static function getLocksQueryInfosByItemType($itemtype, $baseitemtype) { global $DB; $condition = []; $table = false; $field = ''; $type = $itemtype; switch ($itemtype) { case 'Peripheral' : case 'Monitor' : case 'Printer' : case 'Phone' : $condition = ['itemtype' => $itemtype, 'is_dynamic' => 1, 'is_deleted' => 1]; $table = 'glpi_computers_items'; $field = 'computers_id'; $type = 'Computer_Item'; break; case 'NetworkPort' : $condition = ['itemtype' => $baseitemtype, 'is_dynamic' => 1, 'is_deleted' => 1]; $table = 'glpi_networkports'; $field = 'items_id'; break; case 'NetworkName' : $condition = [ 'glpi_networknames.is_dynamic' => 1, 'glpi_networknames.is_deleted' => 1, 'glpi_networknames.itemtype' => 'NetworkPort', 'glpi_networknames.items_id' => new QueryExpression($DB->quoteName('glpi_networkports.id')), 'glpi_networkports.itemtype' => $baseitemtype ]; $condition['FIELDS'] = ['glpi_networknames' => 'id']; $table = ['glpi_networknames', 'glpi_networkports']; $field = 'glpi_networkports.items_id'; break; case 'IPAddress' : $condition = [ 'glpi_ipaddresses.is_dynamic' => 1, 'glpi_ipaddresses.is_deleted' => 1, 'glpi_ipaddresses.itemtype' => 'NetworkName', 'glpi_ipaddresses.items_id' => 'glpi_networknames.id', 'glpi_networknames.itemtype' => 'NetworkPort', 'glpi_networknames.items_id' => 'glpi_networkports.id', 'glpi_networkports.itemtype' => $baseitemtype]; $condition['FIELDS'] = ['glpi_ipaddresses' => 'id']; $table = ['glpi_ipaddresses', 'glpi_networknames', 'glpi_networkports']; $field = 'glpi_networkports.items_id'; break; case 'Item_Disk' : $condition = [ 'is_dynamic' => 1, 'is_deleted' => 1, 'itemtype' => $itemtype ]; $table = Item_Disk::getTable(); $field = 'items_id'; break; case 'ComputerVirtualMachine' : $condition = [ 'is_dynamic' => 1, 'is_deleted' => 1, 'itemtype' => $itemtype]; $table = 'glpi_computervirtualmachines'; $field = 'computers_id'; break; case 'SoftwareVersion' : $condition = [ 'is_dynamic' => 1, 'is_deleted' => 1, 'itemtype' => $itemtype]; $table = 'glpi_items_softwareversions'; $field = 'items_id'; $type = 'Item_SoftwareVersion'; break; default : // Devices if (preg_match('/^Item\_Device/', $itemtype)) { $condition = ['itemtype' => $baseitemtype, 'is_dynamic' => 1, 'is_deleted' => 1]; $table = getTableForItemType($itemtype); $field = 'items_id'; } } return ['condition' => $condition, 'table' => $table, 'field' => $field, 'type' => $type]; } /** * @since 0.85 * * @see CommonDBTM::getMassiveActionsForItemtype() **/ static function getMassiveActionsForItemtype(array &$actions, $itemtype, $is_deleted = 0, CommonDBTM $checkitem = null) { $action_name = __CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.'unlock'; if (Session::haveRight('computer', UPDATE) && ($itemtype == 'Computer')) { $actions[$action_name] = __('Unlock components'); } } /** * @since 0.85 * * @see CommonDBTM::showMassiveActionsSubForm() **/ static function showMassiveActionsSubForm(MassiveAction $ma) { switch ($ma->getAction()) { case 'unlock' : $types = ['Monitor' => _n('Monitor', 'Monitors', Session::getPluralNumber()), 'Peripheral' => Peripheral::getTypeName(Session::getPluralNumber()), 'Printer' => Printer::getTypeName(Session::getPluralNumber()), 'SoftwareVersion' => SoftwareVersion::getTypeName(Session::getPluralNumber()), 'NetworkPort' => NetworkPort::getTypeName(Session::getPluralNumber()), 'NetworkName' => NetworkName::getTypeName(Session::getPluralNumber()), 'IPAddress' => IPAddress::getTypeName(Session::getPluralNumber()), 'Item_Disk' => Item_Disk::getTypeName(Session::getPluralNumber()), 'Device' => _n('Component', 'Components', Session::getPluralNumber()), 'ComputerVirtualMachine' => ComputerVirtualMachine::getTypeName(Session::getPluralNumber())]; echo __('Select the type of the item that must be unlock'); echo "

\n"; Dropdown::showFromArray('attached_item', $types, ['multiple' => true, 'size' => 5, 'values' => array_keys($types)]); echo "

".Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']); return true; } return false; } /** * @since 0.85 * * @see CommonDBTM::processMassiveActionsForOneItemtype() **/ static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $baseitem, array $ids) { global $DB; switch ($ma->getAction()) { case 'unlock' : $input = $ma->getInput(); if (isset($input['attached_item'])) { $attached_items = $input['attached_item']; if (($device_key = array_search('Device', $attached_items)) !== false) { unset($attached_items[$device_key]); $attached_items = array_merge($attached_items, Item_Devices::getDeviceTypes()); } $links = []; foreach ($attached_items as $attached_item) { $infos = self::getLocksQueryInfosByItemType($attached_item, $baseitem->getType()); if ($item = getItemForItemtype($infos['type'])) { $infos['item'] = $item; $links[$attached_item] = $infos; } } foreach ($ids as $id) { $action_valid = false; foreach ($links as $infos) { $infos['condition'][$infos['field']] = $id; $locked_items = $DB->request($infos['table'], $infos['condition']); if ($locked_items->count() === 0) { $action_valid = true; continue; } foreach ($locked_items as $data) { // Restore without history $action_valid = $infos['item']->restore(['id' => $data['id']]); } } $baseItemType = $baseitem->getType(); if ($action_valid) { $ma->itemDone($baseItemType, $id, MassiveAction::ACTION_OK); } else { $ma->itemDone($baseItemType, $id, MassiveAction::ACTION_KO); $erroredItem = new $baseItemType(); $erroredItem->getFromDB($id); $ma->addMessage($erroredItem->getErrorMessage(ERROR_ON_ACTION)); } } } return; } } }