grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026. -------------------------------------------------------------------------- */ /** @file * @brief */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /// Common DataBase Relation Table Manager Class abstract class CommonDBChild extends CommonDBConnexity { // Mapping between DB fields // * definition static public $itemtype; // Class name or field name (start with itemtype) for link to Parent static public $items_id; // Field name // * rights static public $checkParentRights = self::HAVE_SAME_RIGHT_ON_ITEM; static public $mustBeAttached = true; // * log static public $logs_for_parent = true; static public $log_history_add = Log::HISTORY_ADD_SUBITEM; static public $log_history_update = Log::HISTORY_UPDATE_SUBITEM; static public $log_history_delete = Log::HISTORY_DELETE_SUBITEM; static public $log_history_lock = Log::HISTORY_LOCK_SUBITEM; static public $log_history_unlock = Log::HISTORY_UNLOCK_SUBITEM; /** * @since version 0.84 * * @param $itemtype * @param $items_id * * @return string **/ static function getSQLRequestToSearchForItem($itemtype, $items_id) { $conditions = array(); $fields = array('`'.static::getIndexName().'`'); // Check item 1 type $condition_id = "`".static::$items_id."` = '$items_id'"; $fields[] = "`".static::$items_id."` as items_id"; if (preg_match('/^itemtype/', static::$itemtype)) { $fields[] = "`".static::$itemtype."` AS itemtype"; $condition = "($condition_id AND `".static::$itemtype."` = '$itemtype')"; } else { $fields[] = "'".static::$itemtype."' AS itemtype"; if (($itemtype == static::$itemtype) || is_subclass_of($itemtype, static::$itemtype)) { $condition = $condition_id; } } if (isset($condition)) { return "SELECT ".implode(', ', $fields)." FROM `".static::getTable()."` WHERE $condition"; } return ''; } /** * @since version 0.84 **/ static function canCreate() { if ((static::$rightname) && (!Session::haveRight(static::$rightname, CREATE))) { return false; } return static::canChild('canUpdate'); } /** * @since version 0.84 **/ static function canView() { if ((static::$rightname) && (!Session::haveRight(static::$rightname, READ))) { return false; } return static::canChild('canView'); } /** * @since version 0.84 **/ static function canUpdate() { if ((static::$rightname) && (!Session::haveRight(static::$rightname, UPDATE))) { return false; } return static::canChild('canUpdate'); } /** * @since version 0.84 **/ static function canDelete() { if ((static::$rightname) && (!Session::haveRight(static::$rightname, DELETE))) { return false; } return static::canChild('canUpdate'); } /** * @since version 0.85 **/ static function canPurge() { if ((static::$rightname) && (!Session::haveRight(static::$rightname, PURGE))) { return false; } return static::canChild('canUpdate'); } /** * @since version 0.84 **/ function canCreateItem() { return $this->canChildItem('canUpdateItem', 'canUpdate'); } /** * @since version 0.84 **/ function canViewItem() { return $this->canChildItem('canViewItem', 'canView'); } /** * @since version 0.84 **/ function canUpdateItem() { return $this->canChildItem('canUpdateItem', 'canUpdate'); } /** * @since version 0.84 **/ function canDeleteItem() { return $this->canChildItem('canUpdateItem', 'canUpdate'); } /** * @since version 0.84 * * @param $method **/ static function canChild($method) { return static::canConnexity($method, static::$checkParentRights, static::$itemtype, static::$items_id); } /** * @since version 0.84 * * @param $methodItem * @param $methodNotItem * * @return boolean **/ function canChildItem($methodItem, $methodNotItem) { try { return static::canConnexityItem($methodItem, $methodNotItem, static::$checkParentRights, static::$itemtype, static::$items_id, $item); } catch (CommonDBConnexityItemNotFound $e) { return !static::$mustBeAttached; } } /** * Get the item associated with the current object. Rely on CommonDBConnexity::getItemFromArray() * * @since version 0.84 * * @param $getFromDB (true by default) * @param $getEmpty (true by default) * * @return object of the concerned item or false on error **/ function getItem($getFromDB=true, $getEmpty=true) { return $this->getConnexityItem(static::$itemtype, static::$items_id, $getFromDB, $getEmpty); } /** * \brief recursively display the items of this * * @param $recursiveItems array of the items of the current elements (see recursivelyGetItems()) * @param $elementToDisplay what to display : 'Type', 'Name', 'Link' **/ static function displayRecursiveItems(array $recursiveItems, $elementToDisplay) { if ((!is_array($recursiveItems)) || (count($recursiveItems) == 0)) { _e('Item not linked to an object'); return; } switch ($elementToDisplay) { case 'Type' : $masterItem = $recursiveItems[count($recursiveItems) - 1]; echo $masterItem->getTypeName(1); break; case 'Name' : case 'Link' : $items_elements = array(); foreach ($recursiveItems as $item) { if ($elementToDisplay == 'Name') { $items_elements[] = $item->getName(); } else { $items_elements[] = $item->getLink(); } } echo implode(' < ', $items_elements); break; } } /** * Get all the items associated with the current object by recursive requests * * @since version 0.84 * * @return an array containing all the items **/ function recursivelyGetItems() { $item = $this->getItem(); if ($item !== false) { if ($item instanceof CommonDBChild) { return array_merge(array($item), $item->recursivelyGetItems()); } return array($item); } return array(); } /** * Get the ID of entity assigned to the object * * @return ID of the entity **/ function getEntityID () { // Case of Duplicate Entity info to child if (parent::isEntityAssign()) { return parent::getEntityID(); } $item = $this->getItem(); if (($item !== false) && ($item->isEntityAssign())) { return $item->getEntityID(); } return -1; } function isEntityAssign() { // Case of Duplicate Entity info to child if (parent::isEntityAssign()) { return true; } $item = $this->getItem(false); if ($item !== false) { return $item->isEntityAssign(); } return false; } /** * Is the object may be recursive * * @return boolean **/ function maybeRecursive() { // Case of Duplicate Entity info to child if (parent::maybeRecursive()) { return true; } $item = $this->getItem(false); if ($item !== false) { return $item->maybeRecursive(); } return false; } /** * Is the object recursive * * @return booleanDONT_CHECK_ITEM_RIGHTS **/ function isRecursive () { // Case of Duplicate Entity info to child if (parent::maybeRecursive()) { return parent::isRecursive(); } $item = $this->getItem(); if ($item !== false) { return $item->isRecursive(); } return false; } /** * @since version 0.84 **/ function addNeededInfoToInput($input) { // is entity missing and forwarding on ? if ($this->tryEntityForwarding() && !isset($input['entities_id'])) { // Merge both arrays to ensure all the fields are defined for the following checks $completeinput = array_merge($this->fields, $input); // Set the item to allow parent::prepareinputforadd to get the right item ... if ($itemToGetEntity = static::getItemFromArray(static::$itemtype, static::$items_id, $completeinput)) { if (($itemToGetEntity instanceof CommonDBTM) && $itemToGetEntity->isEntityForwardTo(get_called_class())) { $input['entities_id'] = $itemToGetEntity->getEntityID(); $input['is_recursive'] = intval($itemToGetEntity->isRecursive()); } else { // No entity link : set default values $input['entities_id'] = 0; $input['is_recursive'] = 0; } } } return $input; } /** * @since version 0.84 **/ function prepareInputForAdd($input) { if (!is_array($input)) { return false; } // Check item exists if (static::$mustBeAttached && !$this->getItemFromArray(static::$itemtype, static::$items_id,$input)) { return false; } return $this->addNeededInfoToInput($input); } /** * @since version 0.84 **/ function prepareInputForUpdate($input) { if (!is_array($input)) { return false; } // True if item changed if (!parent::checkAttachedItemChangesAllowed($input, array(static::$itemtype, static::$items_id))) { return false; } return parent::addNeededInfoToInput($input); } /** * Get the history name of item * * @param $item the other item * @param $case : can be overwrite by object * - 'add' when this CommonDBChild is added (to and item) * - 'update item previous' transfert : this is removed from the old item * - 'update item next' transfert : this is added to the new item * - 'delete' when this CommonDBChild is remove (from an item) * * @return (string) the name of the entry for the database (ie. : correctly slashed) **/ function getHistoryNameForItem(CommonDBTM $item, $case) { return $this->getNameID(array('forceid' => true, 'additional' => true)); } /** * Actions done after the ADD of the item in the database * * @return nothing **/ function post_addItem() { if ((isset($this->input['_no_history']) && $this->input['_no_history']) || !static::$logs_for_parent) { return; } $item = $this->getItem(); if (($item !== false) && $item->dohistory) { $changes[0] = '0'; $changes[1] = ""; $changes[2] = $this->getHistoryNameForItem($item, 'add'); Log::history($item->getID(), $item->getType(), $changes, $this->getType(), static::$log_history_add); } } /** * Actions done after the UPDATE of the item in the database * * @since version 0.84 * * @param $history store changes history ? (default 1) * * @return nothing **/ function post_updateItem($history=1) { if ((isset($this->input['_no_history']) && $this->input['_no_history']) || !static::$logs_for_parent) { return; } $items_for_log = $this->getItemsForLog(static::$itemtype, static::$items_id); // Whatever case : we log the changes $oldvalues = $this->oldvalues; unset($oldvalues[static::$itemtype]); unset($oldvalues[static::$items_id]); $item = $items_for_log['new']; if (($item !== false) && $item->dohistory) { foreach ($oldvalues as $field => $value) { $changes = $this->getHistoryChangeWhenUpdateField($field); if ((!is_array($changes)) || (count($changes) != 3)) { continue; } Log::history($item->getID(), $item->getType(), $changes, $this->getType(), static::$log_history_update); } } if (isset($items_for_log['previous'])) { // Have updated the connexity relation $prevItem = $items_for_log['previous']; $newItem = $items_for_log['new']; if (($prevItem !== false) && $prevItem->dohistory) { $changes[0] = '0'; $changes[1] = addslashes($this->getHistoryNameForItem($prevItem, 'update item previous')); $changes[2] = ''; Log::history($prevItem->getID(), $prevItem->getType(), $changes, $this->getType(), static::$log_history_delete); } if (($newItem !== false) && $newItem->dohistory) { $changes[0] = '0'; $changes[1] = ''; $changes[2] = addslashes($this->getHistoryNameForItem($newItem, 'update item next')); Log::history($newItem->getID(), $newItem->getType(), $changes, $this->getType(), static::$log_history_add); } } } /** * Actions done after the DELETE of the item in the database * *@return nothing **/ function post_deleteFromDB() { if ((isset($this->input['_no_history']) && $this->input['_no_history']) || !static::$logs_for_parent) { return; } $item = $this->getItem(); if (($item !== false) && $item->dohistory) { $changes[0] = '0'; if (static::$log_history_delete == Log::HISTORY_LOG_SIMPLE_MESSAGE) { $changes[1] = ''; $changes[2] = addslashes($this->getHistoryNameForItem($item, 'delete')); } else { $changes[1] = addslashes($this->getHistoryNameForItem($item, 'delete')); $changes[2] = ''; } Log::history($item->getID(), $item->getType(), $changes, $this->getType(), static::$log_history_delete); } } /** * Actions done when item flag deleted is set to an item * * @since version 0.84 * * @return nothing **/ function cleanDBonMarkDeleted() { if ((isset($this->input['_no_history']) && $this->input['_no_history']) || !static::$logs_for_parent) { return; } if ($this->useDeletedToLockIfDynamic() && $this->isDynamic()) { $item = $this->getItem(); if (($item !== false) && $item->dohistory) { $changes[0] = '0'; $changes[1] = addslashes($this->getHistoryNameForItem($item, 'lock')); $changes[2] = ''; Log::history($item->getID(), $item->getType(), $changes, $this->getType(), static::$log_history_lock); } } } /** * Actions done after the restore of the item * * @since version 0.84 * * @return nothing **/ function post_restoreItem() { if ((isset($this->input['_no_history']) && $this->input['_no_history']) || !static::$logs_for_parent) { return; } if ($this->useDeletedToLockIfDynamic() && $this->isDynamic()) { $item = $this->getItem(); if (($item !== false) && $item->dohistory) { $changes[0] = '0'; $changes[1] = ''; $changes[2] = addslashes($this->getHistoryNameForItem($item, 'unlock')); Log::history($item->getID(), $item->getType(), $changes, $this->getType(), static::$log_history_unlock); } } } /** * get the Javascript "code" to add to the form when clicking on "+" * * @since version 0.84 * * @see showAddChildButtonForItemForm() * * @param $field_name the name of the HTML field inside Item's form * @param $child_count_js_var the name of the javascript variable containing current child number * of items * * @return (string) the code **/ static function getJSCodeToAddForItemChild($field_name, $child_count_js_var) { return ""; } /** * display the field of a given child * * @since version 0.84 * * @see showChildsForItemForm() * * @param $canedit true if we can edit the child * @param $field_name the name of the HTML field inside Item's form * @param $id id of the child * * @return nothing (display only) **/ function showChildForItemForm($canedit, $field_name, $id) { if ($this->isNewID($this->getID())) { $value = ''; } else { $value = $this->getName(); } $field_name = $field_name."[$id]"; if ($canedit) { echo ""; } else { echo "$value" ; } } /** * We can add several single CommonDBChild to a given Item. In such case, we display a "+" * button and the fields already entered * This method display the "+" button * * @since version 0.84 * * @todo study if we cannot use these methods for the user emails * @see showChildsForItemForm(CommonDBTM $item, $field_name) * * @param $item CommonDBTM object: the item on which to add the current CommenDBChild * @param $field_name the name of the HTML field inside Item's form * @param $canedit (default NULL) NULL to use default behaviour * @param $display boolean true display or false to return the button HTML code (true by default) * * * @return the button HTML code if $display is true **/ static function showAddChildButtonForItemForm(CommonDBTM $item, $field_name, $canedit=NULL, $display=true) { global $CFG_GLPI; $items_id = $item->getID(); if (is_null($canedit)) { if ($item->isNewItem()) { if (!$item->canCreate()) { return false; } $canedit = $item->canUpdate(); } else { if (!$item->can($items_id, READ)) { return false; } $canedit = $item->can($items_id, UPDATE); } } $result = ''; if ($canedit) { $lower_name = strtolower(get_called_class()); $child_count_js_var = 'nb'.$lower_name.'s'; $div_id = "add_".$lower_name."_to_".$item->getType()."_".$items_id; // Beware : -1 is for the first element added ... $result = " "; $result .= "". "\""." . static::getJSCodeToAddForItemChild($field_name, $child_count_js_var)."'); $child_count_js_var++;\" class='pointer' src='".$CFG_GLPI["root_doc"]."/pics/add_dropdown.png'>"; } if ($display) { echo $result; } else { return $result; } } /** * We can add several single CommonDBChild to a given Item. In such case, we display a "+" * button and the fields already entered. * This method display the fields * * @since version 0.84 * * @todo study if we cannot use these methods for the user emails * @see showAddChildButtonForItemForm() * * @param $item CommonDBTM object the item on which to add the current CommenDBChild * @param $field_name the name of the HTML field inside Item's form * @param $canedit (default NULL) NULL to use default behaviour * * @return nothing (display only) **/ static function showChildsForItemForm(CommonDBTM $item, $field_name, $canedit=NULL) { global $DB, $CFG_GLPI; $items_id = $item->getID(); if (is_null($canedit)) { if ($item->isNewItem()) { if (!$item->canCreate()) { return false; } $canedit = $item->canUpdate(); } else { if (!$item->can($items_id, READ)) { return false; } $canedit = $item->can($items_id, UPDATE); } } $lower_name = strtolower(get_called_class()); $div_id = "add_".$lower_name."_to_".$item->getType()."_".$items_id; // To be sure not to load bad datas from this table if ($items_id == 0) { $items_id = -99; } $query = "SELECT * FROM `" . static::getTable() . "` WHERE `".static::$items_id."` = '".$item->getID()."'"; if (preg_match('/^itemtype/', static::$itemtype)) { $query .= " AND `itemtype` = '".$item->getType()."'"; } $current_item = new static(); if ($current_item->maybeDeleted()) { $query .= " AND `is_deleted` = '0'"; } $count = 0; foreach ($DB->request($query) as $data) { $current_item->fields = $data; if ($count) { echo '
'; } $count++; $current_item->showChildForItemForm($canedit, $field_name, $current_item->getID()); } if ($canedit) { echo "
"; // No Child display field if ($count == 0) { $current_item->getEmpty(); $current_item->showChildForItemForm($canedit, $field_name, -1); } echo "
"; } } /** * Affect a CommonDBChild to a given item. By default, unaffect it * * @param $id integer the id of the CommonDBChild to affect * @param $items_id integer the id of the new item (default 0) * @param $itemtype string the type of the new item (default '') * * @return boolean : true on success **/ function affectChild($id, $items_id=0, $itemtype='') { $input = array(static::getIndexName() => $id, static::$items_id => $items_id); if (preg_match('/^itemtype/', static::$itemtype)) { $input[static::$itemtype] = $itemtype; } return $this->update($input); } } ?>