%PDF- %PDF-
Direktori : /var/www/projetos/suporte.iigd.com.br/src/ |
Current File : /var/www/projetos/suporte.iigd.com.br/src/CommonGLPI.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/>. * * --------------------------------------------------------------------- */ use Glpi\Application\View\TemplateRenderer; use Glpi\Plugin\Hooks; use Glpi\Toolbox\Sanitizer; /** * Common GLPI object **/ class CommonGLPI implements CommonGLPIInterface { /** * Show the title of the item in the navigation header ? */ protected static $showTitleInNavigationHeader = false; /** * GLPI Item type cache : set dynamically calling getType * * @var integer */ protected $type = -1; /** * Display list on Navigation Header * * @var boolean */ protected $displaylist = true; /** * Show Debug * * @var boolean */ public $showdebug = false; /** * Tab orientation : horizontal or vertical. * * @var string */ public $taborientation = 'horizontal'; /** * Rightname used to check rights to do actions on item. * * @var string */ public static $rightname = ''; /** * Need to get item to show tab * * @var boolean */ public $get_item_to_display_tab = false; protected static $othertabs = []; public function __construct() { } /** * Return the localized name of the current Type * Should be overloaded in each new class * * @param integer $nb Number of items * * @return string **/ public static function getTypeName($nb = 0) { return __('General'); } /** * Return the simplified localized label of the current Type in the context of a form. * Avoid to recall the type in the label (Computer status -> Status) * * Should be overloaded in each new class * * @return string **/ public static function getFieldLabel() { return static::getTypeName(); } /** * Return the type of the object : class name * * @return string **/ public static function getType() { return get_called_class(); } /** * Check rights on CommonGLPI Object (without corresponding table) * Same signature as CommonDBTM::can but in case of this class, we don't check instance rights * so, id and input parameters are unused. * * @param integer $ID ID of the item (-1 if new item) * @param mixed $right Right to check : r / w / recursive / READ / UPDATE / DELETE * @param array $input array of input data (used for adding item) (default NULL) * * @return boolean **/ public function can($ID, $right, array &$input = null) { switch ($right) { case READ: return static::canView(); case UPDATE: return static::canUpdate(); case DELETE: return static::canDelete(); case PURGE: return static::canPurge(); case CREATE: return static::canCreate(); } return false; } /** * Have I the global right to "create" the Object * May be overloaded if needed (ex KnowbaseItem) * * @return boolean **/ public static function canCreate() { if (static::$rightname) { return Session::haveRight(static::$rightname, CREATE); } return false; } /** * Have I the global right to "view" the Object * * Default is true and check entity if the objet is entity assign * * May be overloaded if needed * * @return boolean **/ public static function canView() { if (static::$rightname) { return Session::haveRight(static::$rightname, READ); } return false; } /** * Have I the global right to "update" the Object * * Default is calling canCreate * May be overloaded if needed * * @return boolean **/ public static function canUpdate() { if (static::$rightname) { return Session::haveRight(static::$rightname, UPDATE); } return false; } /** * Have I the global right to "delete" the Object * * May be overloaded if needed * * @return boolean **/ public static function canDelete() { if (static::$rightname) { return Session::haveRight(static::$rightname, DELETE); } return false; } /** * Have I the global right to "purge" the Object * * May be overloaded if needed * * @return boolean **/ public static function canPurge() { if (static::$rightname) { return Session::haveRight(static::$rightname, PURGE); } return false; } /** * Register tab on an objet * * @since 0.83 * * @param string $typeform object class name to add tab on form * @param string $typetab object class name which manage the tab * * @return void **/ public static function registerStandardTab($typeform, $typetab) { if (isset(self::$othertabs[$typeform])) { self::$othertabs[$typeform][] = $typetab; } else { self::$othertabs[$typeform] = [$typetab]; } } /** * Get the array of Tab managed by other types * Getter for plugin (ex PDF) to access protected property * * @since 0.83 * * @param string $typeform object class name to add tab on form * * @return array array of types **/ public static function getOtherTabs($typeform) { if (isset(self::$othertabs[$typeform])) { return self::$othertabs[$typeform]; } return []; } /** * Define tabs to display * * NB : Only called for existing object * * @param array $options Options * - withtemplate is a template view ? * * @return array array containing the tabs **/ public function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); $this->addImpactTab($ong, $options); return $ong; } /** * return all the tabs for current object * * @since 0.83 * * @param array $options Options * - withtemplate is a template view ? * * @return array array containing the tabs **/ final public function defineAllTabs($options = []) { /** @var array $CFG_GLPI */ global $CFG_GLPI; $onglets = []; // Tabs known by the object if ($this->isNewItem()) { $this->addDefaultFormTab($onglets); } else { $onglets = $this->defineTabs($options); } // Object with class with 'addtabon' attribute if ( isset(self::$othertabs[$this->getType()]) && !$this->isNewItem() ) { foreach (self::$othertabs[$this->getType()] as $typetab) { $this->addStandardTab($typetab, $onglets, $options); } } $class = $this->getType(); if ( ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) && (!$this->isNewItem() || $this->showdebug) && (method_exists($class, 'showDebug') || Infocom::canApplyOn($class) || in_array($class, $CFG_GLPI["reservation_types"])) ) { $onglets[-2] = __('Debug'); } return $onglets; } /** * Add standard define tab * * @param string $itemtype itemtype link to the tab * @param array $ong defined tabs * @param array $options options (for withtemplate) * * @return CommonGLPI **/ public function addStandardTab($itemtype, array &$ong, array $options) { $withtemplate = 0; if (isset($options['withtemplate'])) { $withtemplate = $options['withtemplate']; } switch ($itemtype) { default: if ( !is_integer($itemtype) && ($obj = getItemForItemtype($itemtype)) ) { $titles = $obj->getTabNameForItem($this, $withtemplate); if (!is_array($titles)) { $titles = [1 => $titles]; } foreach ($titles as $key => $val) { if (!empty($val)) { $ong[$itemtype . '$' . $key] = $val; } } } break; } return $this; } /** * Add the impact tab if enabled for this item type * * @param array $ong defined tabs * @param array $options options (for withtemplate) * * @return CommonGLPI **/ public function addImpactTab(array &$ong, array $options) { /** @var array $CFG_GLPI */ global $CFG_GLPI; // Check if impact analysis is enabled for this item type if (Impact::isEnabled(static::class)) { $this->addStandardTab('Impact', $ong, $options); } return $this; } /** * Add default tab for form * * @since 0.85 * * @param array $ong Tabs * * @return CommonGLPI **/ public function addDefaultFormTab(array &$ong) { $ong[$this->getType() . '$main'] = $this->getTypeName(1); return $this; } /** * get menu content * * @since 0.85 * * @return false|array array for menu **/ public static function getMenuContent() { $menu = []; $type = static::getType(); $item = new static(); $forbidden = $item->getForbiddenActionsForMenu(); if ($item instanceof CommonDBTM) { if ($item->canView()) { $menu['title'] = $item->getMenuName(); $menu['shortcut'] = $item->getMenuShorcut(); $menu['page'] = $item->getSearchURL(false); $menu['links']['search'] = $item->getSearchURL(false); $menu['links']['lists'] = ""; $menu['lists_itemtype'] = $item->getType(); $menu['icon'] = $item->getIcon(); if ( !in_array('add', $forbidden) && $item->canCreate() ) { if ($item->maybeTemplate()) { $menu['links']['add'] = '/front/setup.templates.php?' . 'itemtype=' . $type . '&add=1'; if (!in_array('template', $forbidden)) { $menu['links']['template'] = '/front/setup.templates.php?' . 'itemtype=' . $type . '&add=0'; } } else { $menu['links']['add'] = $item->getFormURL(false); } } $extra_links = $item->getAdditionalMenuLinks(); if (is_array($extra_links) && count($extra_links)) { $menu['links'] += $extra_links; } } } else { if ( !method_exists($type, 'canView') || $item->canView() ) { $menu['title'] = $item->getMenuName(); $menu['shortcut'] = $item->getMenuShorcut(); $menu['page'] = $item->getSearchURL(false); $menu['links']['search'] = $item->getSearchURL(false); if (method_exists($item, 'getIcon')) { $menu['icon'] = $item->getIcon(); } } } if ($data = $item->getAdditionalMenuOptions()) { $menu['options'] = $data; } if ($data = $item->getAdditionalMenuContent()) { $newmenu = [ strtolower($type) => $menu, ]; // Force overwrite existing menu foreach ($data as $key => $val) { $newmenu[$key] = $val; } $newmenu['is_multi_entries'] = true; $menu = $newmenu; } if (count($menu)) { return $menu; } return false; } /** * get additional menu content * * @since 0.85 * * @return false|array array for menu **/ public static function getAdditionalMenuContent() { return false; } /** * Get forbidden actions for menu : may be add / template * * @since 0.85 * * @return array array of forbidden actions **/ public static function getForbiddenActionsForMenu() { return []; } /** * Get additional menu options * * @since 0.85 * * @return array|false array of additional options, false if no options **/ public static function getAdditionalMenuOptions() { return false; } /** * Get additional menu links * * @since 0.85 * * @return false|array **/ public static function getAdditionalMenuLinks() { return false; } /** * Get menu shortcut * * @since 0.85 * * @return string character menu shortcut key **/ public static function getMenuShorcut() { return ''; } /** * Get menu name * * @since 0.85 * * @return string character menu shortcut key **/ public static function getMenuName() { return static::getTypeName(Session::getPluralNumber()); } /** * Get Tab Name used for itemtype * * NB : Only called for existing object * Must check right on what will be displayed + template * * @since 0.83 * * @param CommonGLPI $item Item on which the tab need to be displayed * @param integer $withtemplate is a template object ? (default 0) * * @return string tab name **/ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { return ''; } /** * show Tab content * * @since 0.83 * * @param CommonGLPI $item Item on which the tab need to be displayed * @param integer $tabnum tab number (default 1) * @param integer $withtemplate is a template object ? (default 0) * * @return boolean **/ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { return false; } /** * display standard tab contents * * @param CommonGLPI $item Item on which the tab need to be displayed * @param string $tab tab name * @param integer $withtemplate is a template object ? (default 0) * @param array $options additional options to pass * * @return boolean true **/ public static function displayStandardTab(CommonGLPI $item, $tab, $withtemplate = 0, $options = []) { switch ($tab) { // All tab case -1: // get tabs and loop over $ong = $item->defineAllTabs(['withtemplate' => $withtemplate]); if (count($ong)) { foreach ($ong as $key => $val) { if ($key != 'empty') { echo "<div class='alltab'>$val</div>"; self::displayStandardTab($item, $key, $withtemplate, $options); } } } return true; case -2: $item->showDebugInfo(); return true; default: $data = explode('$', $tab); $itemtype = $data[0]; // Default set $tabnum = 1; if (isset($data[1])) { $tabnum = $data[1]; } $options['withtemplate'] = $withtemplate; if ($tabnum == 'main') { /** @var CommonDBTM $item */ Plugin::doHook(Hooks::PRE_SHOW_ITEM, ['item' => $item, 'options' => &$options]); $ret = $item->showForm($item->getID(), $options); Plugin::doHook(Hooks::POST_SHOW_ITEM, ['item' => $item, 'options' => $options]); return $ret; } if ( !is_integer($itemtype) && ($itemtype != 'empty') && ($obj = getItemForItemtype($itemtype)) ) { $options['tabnum'] = $tabnum; $options['itemtype'] = $itemtype; Plugin::doHook(Hooks::PRE_SHOW_TAB, [ 'item' => $item, 'options' => &$options]); \Glpi\Debug\Profiler::getInstance()->start(get_class($obj) . '::displayTabContentForItem'); $ret = $obj->displayTabContentForItem($item, $tabnum, $withtemplate); \Glpi\Debug\Profiler::getInstance()->stop(get_class($obj) . '::displayTabContentForItem'); Plugin::doHook(Hooks::POST_SHOW_TAB, ['item' => $item, 'options' => $options]); return $ret; } break; } return false; } /** * create tab text entry * * @param string $text text to display * @param integer $nb number of items (default 0) * * @return string **/ public static function createTabEntry($text, $nb = 0) { if ($nb) { //TRANS: %1$s is the name of the tab, $2$d is number of items in the tab between () $text = sprintf(__('%1$s %2$s'), $text, "<span class='badge'>$nb</span>"); } return $text; } /** * Redirect to the list page from which the item was selected * Default to the search engine for the type * * @return void **/ public function redirectToList() { /** @var array $CFG_GLPI */ global $CFG_GLPI; if ( isset($_GET['withtemplate']) && !empty($_GET['withtemplate']) ) { Html::redirect($CFG_GLPI["root_doc"] . "/front/setup.templates.php?add=0&itemtype=" . $this->getType()); } else if ( isset($_SESSION['glpilisturl'][$this->getType()]) && !empty($_SESSION['glpilisturl'][$this->getType()]) ) { Html::redirect($_SESSION['glpilisturl'][$this->getType()]); } else { Html::redirect($this->getSearchURL()); } } /** * is the current object a new one - Always false here (virtual Objet) * * @since 0.83 * * @return boolean **/ public function isNewItem() { return false; } /** * is the current object a new one - Always true here (virtual Objet) * * @since 0.84 * * @param integer $ID Id to check * * @return boolean **/ public static function isNewID($ID) { return true; } /** * Get the search page URL for the current classe * * @param boolean $full path or relative one (true by default) * * @return string **/ public static function getTabsURL($full = true) { return Toolbox::getItemTypeTabsURL(get_called_class(), $full); } /** * Get the search page URL for the current class * * @param boolean $full path or relative one (true by default) * * @return string **/ public static function getSearchURL($full = true) { return Toolbox::getItemTypeSearchURL(get_called_class(), $full); } /** * Get the form page URL for the current class * * @param boolean $full path or relative one (true by default) * * @return string **/ public static function getFormURL($full = true) { return Toolbox::getItemTypeFormURL(get_called_class(), $full); } /** * Get the form page URL for the current class and point to a specific ID * * @since 0.90 * * @param integer $id Id (default 0) * @param boolean $full Full path or relative one (true by default) * * @return string **/ public static function getFormURLWithID($id = 0, $full = true) { $itemtype = get_called_class(); $link = $itemtype::getFormURL($full); $link .= (strpos($link, '?') ? '&' : '?') . 'id=' . $id; return $link; } /** * Show tabs content * * @since 0.85 * * @param array $options parameters to add to URLs and ajax * - withtemplate is a template view ? * * @return void **/ public function showTabsContent($options = []) { // for objects not in table like central if (isset($this->fields['id'])) { $ID = $this->fields['id']; } else { if (isset($options['id'])) { $ID = $options['id']; } else { $ID = 0; } } $cleaned_options = $options; unset($cleaned_options['id'], $cleaned_options['stock_image']); $target = $_SERVER['PHP_SELF']; $withtemplate = ""; // TODO - There should be a better option than checking whether or not // $options is empty. // See: // - https://github.com/glpi-project/glpi/pull/12929 // - https://github.com/glpi-project/glpi/pull/13101 // - https://github.com/glpi-project/glpi/commit/1d27bf14d4527f748876dcd556f2b995a0bf7684 if (is_array($cleaned_options) && count($cleaned_options)) { if (isset($options['withtemplate'])) { $withtemplate = $options['withtemplate']; } if ($this instanceof CommonITILObject && $this->isNewItem()) { $this->input = $cleaned_options; $this->saveInput(); // $extraparamhtml can be too long in case of ticket with content // (passed in GET in ajax request) unset($cleaned_options['content']); } // prevent double sanitize, because the includes.php sanitize all data $cleaned_options = Sanitizer::unsanitize($cleaned_options); } $onglets = $this->defineAllTabs($options); $display_all = true; if (isset($onglets['no_all_tab'])) { $display_all = false; unset($onglets['no_all_tab']); } if (count($onglets)) { $tabs_url = $this->getTabsURL(); $parsed_url = parse_url($tabs_url); $tab_path = $parsed_url['path']; $tab_params = []; if (array_key_exists('query', $parsed_url)) { parse_str($parsed_url['query'], $tab_params); } $tab_params = array_merge($cleaned_options, $tab_params); $tab_params = array_merge( $tab_params, [ '_target' => $target, '_itemtype' => $this->getType(), 'id' => $ID, ] ); $tabs = []; foreach ($onglets as $key => $val) { $tabs[$key] = ['title' => $val, 'url' => $tab_path, 'params' => Toolbox::append_params(['_glpi_tab' => $key] + $tab_params, '&'), ]; } // Not all tab for templates and if only 1 tab if ( $display_all && empty($withtemplate) && (count($tabs) > 1) ) { $tabs[-1] = ['title' => __('All'), 'url' => $tab_path, 'params' => Toolbox::append_params(['_glpi_tab' => '-1'] + $tab_params, '&'), ]; } Ajax::createTabs( 'tabspanel', 'tabcontent', $tabs, $this->getType(), $ID, $this->taborientation, $options ); } } /** * Show tabs * * @param array $options parameters to add to URLs and ajax * - withtemplate is a template view ? * * @return void **/ public function showNavigationHeader($options = []) { /** @var array $CFG_GLPI */ global $CFG_GLPI; // for objects not in table like central if (isset($this->fields['id'])) { $ID = $this->fields['id']; } else { if (isset($options['id'])) { $ID = $options['id']; } else { $ID = 0; } } $target = $_SERVER['PHP_SELF']; $extraparamhtml = ""; if (is_array($options) && count($options)) { $cleanoptions = $options; if (isset($options['withtemplate'])) { unset($cleanoptions['withtemplate']); } foreach (array_keys($cleanoptions) as $key) { // Do not include id options if (($key[0] == '_') || ($key == 'id')) { unset($cleanoptions[$key]); } } $extraparamhtml = "&" . Toolbox::append_params($cleanoptions, '&'); } if ( !$this->isNewID($ID) && $this->getType() && $this->displaylist ) { $glpilistitems = & $_SESSION['glpilistitems'][$this->getType()]; $glpilisttitle = & $_SESSION['glpilisttitle'][$this->getType()]; $glpilisturl = & $_SESSION['glpilisturl'][$this->getType()]; if ($this instanceof CommonDBChild && $parent = $this->getItem(true, false)) { $glpilisturl = $parent::getFormURLWithID($parent->fields['id'], true); } if (empty($glpilisturl)) { $glpilisturl = $this->getSearchURL(); } // echo "<div id='menu_navigate'>"; $next = $prev = $first = $last = -1; $current = false; if (is_array($glpilistitems)) { $current = array_search($ID, $glpilistitems); if ($current !== false) { if (isset($glpilistitems[$current + 1])) { $next = $glpilistitems[$current + 1]; } if (isset($glpilistitems[$current - 1])) { $prev = $glpilistitems[$current - 1]; } $first = $glpilistitems[0]; if ($first == $ID) { $first = -1; } $last = $glpilistitems[count($glpilistitems) - 1]; if ($last == $ID) { $last = -1; } } } $cleantarget = Html::cleanParametersURL($target); echo "<div class='navigationheader justify-content-sm-between'>"; // First set of header pagination actions, displayed on the left side of the page echo "<div>"; if (!$glpilisttitle) { $glpilisttitle = __s('List'); } $list = "<a href='$glpilisturl' title=\"$glpilisttitle\" class='btn btn-sm btn-icon btn-ghost-secondary' data-bs-toggle='tooltip' data-bs-placement='bottom'> <i class='far fa-lg fa-list-alt'></i> </a>"; $list_shown = false; if ($first < 0) { // Show list icon before the placeholder space for the first pagination button echo $list; $list_shown = true; } echo "<a href='$cleantarget?id=$first$extraparamhtml' class='btn btn-sm btn-icon btn-ghost-secondary " . ($first >= 0 ? '' : 'bs-invisible') . "' title=\"" . __s('First') . "\" data-bs-toggle='tooltip' data-bs-placement='bottom'> <i class='fa-lg ti ti-chevrons-left'></i> </a>"; if (!$list_shown && $prev < 0) { // Show list icon before the placeholder space for the "prev" pagination button echo $list; $list_shown = true; } echo "<a href='$cleantarget?id=$prev$extraparamhtml' id='previouspage' class='btn btn-sm btn-icon btn-ghost-secondary " . ($prev >= 0 ? '' : 'bs-invisible') . "' title=\"" . __s('Previous') . "\" data-bs-toggle='tooltip' data-bs-placement='bottom'> <i class='fa-lg ti ti-chevron-left'></i> </a>"; if ($prev >= 0) { $js = '$("body").keydown(function(e) { if ($("input, textarea").is(":focus") === false) { if(e.keyCode == 37 && e.ctrlKey) { window.location = $("#previouspage").attr("href"); } } });'; echo Html::scriptBlock($js); } // If both first and prev buttons shown, the list should be added now if (!$list_shown) { echo $list; } echo "</div>"; if (static::$showTitleInNavigationHeader && $this instanceof CommonDBTM) { echo "<h3 class='navigationheader-title strong d-flex align-items-center'>"; if (method_exists($this, 'getStatusIcon') && $this->isField('status')) { echo "<span class='me-1'>" . $this->getStatusIcon($this->fields['status']) . '</span>'; } echo $this->getNameID([ 'forceid' => $this instanceof CommonITILObject ]); if ($this->isField('is_deleted') && $this->fields['is_deleted']) { $title = $this->isField('date_mod') ? sprintf(__s('Item has been deleted on %s'), Html::convDateTime($this->fields['date_mod'])) : __s('Deleted'); echo "<span class='mx-2 bg-danger status rounded-1' title=\"" . $title . "\" data-bs-toggle='tooltip'> <i class='ti ti-trash'></i>"; echo __s('Deleted'); echo "</span>"; } echo "</h3>"; } else { echo TemplateRenderer::getInstance()->render('components/form/header_content.html.twig', [ 'item' => $this, 'params' => $options, 'in_navheader' => true, 'header_toolbar' => $this->getFormHeaderToolbar(), ]); } // Second set of header pagination actions, displayed on the right side of the page echo "<div>"; echo "<span class='m-1 ms-3 " . ($current !== false ? '' : 'bs-invisible') . "'>" . ($current + 1) . "/" . count($glpilistitems ?? []) . "</span>"; echo "<a href='$cleantarget?id=$next$extraparamhtml' id='nextpage' class='btn btn-sm btn-icon btn-ghost-secondary " . ($next >= 0 ? '' : 'bs-invisible') . "' title=\"" . __s('Next') . "\" data-bs-toggle='tooltip' data-bs-placement='bottom'>" . "<i class='fa-lg ti ti-chevron-right'></i> </a>"; if ($next >= 0) { $js = '$("body").keydown(function(e) { if ($("input, textarea").is(":focus") === false) { if(e.keyCode == 39 && e.ctrlKey) { window.location = $("#nextpage").attr("href"); } } });'; echo Html::scriptBlock($js); } echo "<a href='$cleantarget?id=$last $extraparamhtml' class='btn btn-sm btn-icon btn-ghost-secondary " . ($last >= 0 ? '' : 'bs-invisible') . "' title=\"" . __s('Last') . "\" data-bs-toggle='tooltip' data-bs-placement='bottom'>" . "<i class='fa-lg ti ti-chevrons-right'></i></a>"; echo "</div>"; echo "</div>"; // .navigationheader } } /** * Compute the name to be used in the main header of this item * * @return string */ public function getHeaderName(): string { $name = ''; if (isset($this->fields['id']) && ($this instanceof CommonDBTM)) { $name = $this->getName(); if ($_SESSION['glpiis_ids_visible'] || empty($name)) { $name = sprintf(__('%1$s - ID %2$d'), $name, $this->fields['id']); } } return Sanitizer::unsanitize($name); } /** * Display item with tabs * * @since 0.85 * * @param array $options Options * show_nav_header (default true): show navigation header (link to list of items) * * @return void */ public function display($options = []) { // Item might already be loaded, skip load and rights checks $item_loaded = $options['loaded'] ?? false; unset($options['loaded']); if (!$item_loaded) { if ( $this instanceof CommonDBTM && isset($options['id']) && !$this->isNewID($options['id']) ) { if (!$this->getFromDB($options['id'])) { Html::displayNotFoundError(); } } // in case of lefttab layout, we couldn't see "right error" message if ( $this->get_item_to_display_tab && isset($_GET["id"]) && $_GET["id"] && !$this->can($_GET["id"], READ) ) { // This triggers from a profile switch. // If we don't have right, redirect instead to central page Toolbox::handleProfileChangeRedirect(); Html::displayRightError(); } } // try to lock object // $options must contains the id of the object, and if locked by manageObjectLock will contains 'locked' => 1 ObjectLock::manageObjectLock(get_class($this), $options); // manage custom options passed to tabs if (isset($_REQUEST['tab_params']) && is_array($_REQUEST['tab_params'])) { $options += $_REQUEST['tab_params']; } echo "<div class='d-flex flex-column'>"; echo "<div class='row'>"; if ($this instanceof CommonDBTM) { TemplateRenderer::getInstance()->display('layout/parts/saved_searches.html.twig', [ 'itemtype' => $this->getType(), ]); } echo "<div class='col'>"; if (($options['show_nav_header'] ?? true)) { $this->showNavigationHeader($options); } $this->showTabsContent($options); echo "</div>"; echo "</div>"; } /** * List infos in debug tab * * @return void **/ public function showDebugInfo() { /** @var array $CFG_GLPI */ global $CFG_GLPI; if (method_exists($this, 'showDebug')) { $this->showDebug(); } if (!($this instanceof CommonDBTM)) { return; } $class = $this->getType(); if (Infocom::canApplyOn($class)) { $infocom = new Infocom(); if ($infocom->getFromDBforDevice($class, $this->fields['id'])) { $infocom->showDebug(); } } if (in_array($class, $CFG_GLPI["reservation_types"])) { $resitem = new ReservationItem(); if ($resitem->getFromDBbyItem($class, $this->fields['id'])) { $resitem->showDebugResa(); } } } /** * Update $_SESSION to set the display options. * * @since 0.84 * * @param array $input data to update * @param string $sub_itemtype sub itemtype if needed (default '') * * @return void **/ public static function updateDisplayOptions($input = [], $sub_itemtype = '') { $options = static::getAvailableDisplayOptions(); if (count($options)) { if (empty($sub_itemtype)) { $display_options = &$_SESSION['glpi_display_options'][self::getType()]; } else { $display_options = &$_SESSION['glpi_display_options'][self::getType()][$sub_itemtype]; } // reset if (isset($input['reset'])) { foreach ($options as $option_group) { foreach ($option_group as $option_name => $attributs) { $display_options[$option_name] = $attributs['default']; } } } else { foreach ($options as $option_group) { foreach ($option_group as $option_name => $attributs) { if (isset($input[$option_name]) && ($input[$option_name] == 'on')) { $display_options[$option_name] = true; } else { $display_options[$option_name] = false; } } } } // Store new display options for user if ($uid = Session::getLoginUserID()) { $user = new User(); if ($user->getFromDB($uid)) { $user->update([ 'id' => $uid, 'display_options' => Sanitizer::sanitize(exportArrayToDB($_SESSION['glpi_display_options'])) ]); } } } } /** * Load display options to $_SESSION * * @since 0.84 * * @param string $sub_itemtype sub itemtype if needed (default '') * * @return void **/ public static function getDisplayOptions($sub_itemtype = '') { if (!isset($_SESSION['glpi_display_options'])) { // Load display_options from user table $_SESSION['glpi_display_options'] = []; if ($uid = Session::getLoginUserID()) { $user = new User(); if ($user->getFromDB($uid)) { $_SESSION['glpi_display_options'] = importArrayFromDB($user->fields['display_options']); } } } if (!isset($_SESSION['glpi_display_options'][self::getType()])) { $_SESSION['glpi_display_options'][self::getType()] = []; } if (!empty($sub_itemtype)) { if (!isset($_SESSION['glpi_display_options'][self::getType()][$sub_itemtype])) { $_SESSION['glpi_display_options'][self::getType()][$sub_itemtype] = []; } $display_options = &$_SESSION['glpi_display_options'][self::getType()][$sub_itemtype]; } else { $display_options = &$_SESSION['glpi_display_options'][self::getType()]; } // Load default values if not set $options = static::getAvailableDisplayOptions(); if (count($options)) { foreach ($options as $option_group) { foreach ($option_group as $option_name => $attributs) { if (!isset($display_options[$option_name])) { $display_options[$option_name] = $attributs['default']; } } } } return $display_options; } /** * Show display options * * @since 0.84 * * @param string $sub_itemtype sub_itemtype if needed (default '') * * @return void **/ public static function showDislayOptions($sub_itemtype = '') { /** @var array $CFG_GLPI */ global $CFG_GLPI; $options = static::getAvailableDisplayOptions(); if (count($options)) { if (empty($sub_itemtype)) { $display_options = $_SESSION['glpi_display_options'][self::getType()]; } else { $display_options = $_SESSION['glpi_display_options'][self::getType()][$sub_itemtype]; } echo "<div class='center'>"; echo "\n<form method='get' action='" . $CFG_GLPI['root_doc'] . "/front/display.options.php'>\n"; echo "<input type='hidden' name='itemtype' value='NetworkPort'>\n"; echo "<input type='hidden' name='sub_itemtype' value='$sub_itemtype'>\n"; echo "<table class='tab_cadre'>"; echo "<tr><th colspan='2'>" . __s('Display options') . "</th></tr>\n"; echo "<tr><td colspan='2'>"; echo "<input type='submit' class='btn btn-primary' name='reset' value=\"" . __('Reset display options') . "\">"; echo "</td></tr>\n"; foreach ($options as $option_group_name => $option_group) { if (count($option_group) > 0) { echo "<tr><th colspan='2'>$option_group_name</th></tr>\n"; foreach ($option_group as $option_name => $attributs) { echo "<tr>"; echo "<td>"; echo "<input type='checkbox' name='$option_name' " . ($display_options[$option_name] ? 'checked' : '') . ">"; echo "</td>"; echo "<td>" . $attributs['name'] . "</td>"; echo "</tr>\n"; } } } echo "<tr><td colspan='2' class='center'>"; echo "<input type='submit' class='btn btn-primary' name='update' value=\"" . _sx('button', 'Save') . "\">"; echo "</td></tr>\n"; echo "</table>"; echo "</form>"; echo "</div>"; } } /** * Get available display options array * * @since 0.84 * * @return array all the options **/ public static function getAvailableDisplayOptions() { return []; } /** * Get link for display options * * @since 0.84 * * @param string $sub_itemtype sub itemtype if needed for display options * * @return string **/ public static function getDisplayOptionsLink($sub_itemtype = '') { /** @var array $CFG_GLPI */ global $CFG_GLPI; $rand = mt_rand(); $link = "<span class='fa fa-wrench pointer' title=\""; $link .= __s('Display options') . "\" "; $link .= " data-bs-toggle='modal' data-bs-target='#displayoptions$rand'"; $link .= "><span class='sr-only'>" . __s('Display options') . "</span></span>"; $link .= Ajax::createIframeModalWindow( "displayoptions" . $rand, $CFG_GLPI['root_doc'] . "/front/display.options.php?itemtype=" . static::getType() . "&sub_itemtype=$sub_itemtype", ['display' => false, 'width' => 600, 'height' => 500, 'reloadonclose' => true ] ); return $link; } /** * Get error message for item * * @since 0.85 * * @param integer $error error type see define.php for ERROR_* * @param string $object string to use instead of item link (default '') * * @return string **/ public function getErrorMessage($error, $object = '') { if (empty($object) && $this instanceof CommonDBTM) { $object = $this->getLink(); } switch ($error) { case ERROR_NOT_FOUND: return sprintf(__('%1$s: %2$s'), $object, __('Unable to get item')); case ERROR_RIGHT: return sprintf(__('%1$s: %2$s'), $object, __('Authorization error')); case ERROR_COMPAT: return sprintf(__('%1$s: %2$s'), $object, __('Incompatible items')); case ERROR_ON_ACTION: return sprintf(__('%1$s: %2$s'), $object, __('Error on executing the action')); case ERROR_ALREADY_DEFINED: return sprintf(__('%1$s: %2$s'), $object, __('Item already defined')); } return ''; } /** * Get links to Faq **/ public function getKBLinks() { /** * @var array $CFG_GLPI * @var \DBmysql $DB */ global $CFG_GLPI, $DB; if (!($this instanceof CommonDBTM)) { return ''; } $ret = ''; $title = __s('FAQ'); if (Session::getCurrentInterface() == 'central') { $title = __s('Knowledge base'); } $iterator = $DB->request([ 'SELECT' => [KnowbaseItem::getTable() . '.*'], 'FROM' => KnowbaseItem::getTable(), 'WHERE' => [ KnowbaseItem_Item::getTable() . '.items_id' => $this->fields['id'], KnowbaseItem_Item::getTable() . '.itemtype' => $this->getType(), ], 'INNER JOIN' => [ KnowbaseItem_Item::getTable() => [ 'ON' => [ KnowbaseItem_Item::getTable() => KnowbaseItem::getForeignKeyField(), KnowbaseItem::getTable() => 'id' ] ] ], 'ORDER' => [ KnowbaseItem::getTable() => 'name' ] ]); $found_kbitem = []; foreach ($iterator as $line) { $found_kbitem[$line['id']] = $line; $kbitem_ids[$line['id']] = $line['id']; } if (count($found_kbitem)) { $rand = mt_rand(); $kbitem = new KnowbaseItem(); $kbitem->getFromDB(reset($found_kbitem)['id']); $ret .= "<div class='faqadd_block'>"; $ret .= "<label for='display_faq_chkbox$rand'>"; $ret .= "<i class='ti ti-zoom-question'></i>"; $ret .= "</label>"; $ret .= "<input type='checkbox' class='display_faq_chkbox' id='display_faq_chkbox$rand'>"; $ret .= "<div class='faqadd_entries' style='position:relative;'>"; if (count($found_kbitem) == 1) { $ret .= "<div class='faqadd_block_content' id='faqadd_block_content$rand'>"; $ret .= $kbitem->showFull(['display' => false]); $ret .= "</div>"; // .faqadd_block_content } else { $ret .= Html::scriptBlock(" var getKnowbaseItemAnswer$rand = function() { var knowbaseitems_id = $('#dropdown_knowbaseitems_id$rand').val(); $('#faqadd_block_content$rand').load( '" . $CFG_GLPI['root_doc'] . "/ajax/getKnowbaseItemAnswer.php', { 'knowbaseitems_id': knowbaseitems_id } ); }; "); $ret .= "<label for='dropdown_knowbaseitems_id$rand'>" . KnowbaseItem::getTypeName() . "</label> "; $ret .= KnowbaseItem::dropdown([ 'value' => reset($found_kbitem)['id'], 'display' => false, 'rand' => $rand, 'condition' => [ KnowbaseItem::getTable() . '.id' => $kbitem_ids ], 'on_change' => "getKnowbaseItemAnswer$rand()" ]); $ret .= "<div class='faqadd_block_content' id='faqadd_block_content$rand'>"; $ret .= $kbitem->showFull(['display' => false]); $ret .= "</div>"; // .faqadd_block_content } $ret .= "</div>"; // .faqadd_entries $ret .= "</div>"; // .faqadd_block } return $ret; } /** * Get array of extra form header toolbar buttons * @return array Array of HTML elements */ protected function getFormHeaderToolbar(): array { return []; } }