grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026. -------------------------------------------------------------------------- */ /** @file * @brief */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * KnowbaseItem Class **/ class KnowbaseItem extends CommonDBTM { // From CommonDBTM public $dohistory = true; // For visibility checks protected $users = array(); protected $groups = array(); protected $profiles = array(); protected $entities = array(); const KNOWBASEADMIN = 1024; const READFAQ = 2048; const PUBLISHFAQ = 4096; static $rightname = 'knowbase'; static function getTypeName($nb=0) { return __('Knowledge base'); } /** * @see CommonGLPI::getMenuShorcut() * * @since version 0.85 **/ static function getMenuShorcut() { return 'b'; } /** * @see CommonGLPI::getMenuName() * * @since version 0.85 **/ static function getMenuName() { if (!Session::haveRight('knowbase', READ)) { return __('FAQ'); } else { return static::getTypeName(Session::getPluralNumber()); } } static function canCreate() { return Session::haveRightsOr(self::$rightname, array(CREATE, self::PUBLISHFAQ)); } /** * @since version 0.85 **/ static function canUpdate() { return Session::haveRightsOr(self::$rightname, array(UPDATE, self::KNOWBASEADMIN)); } static function canView() { global $CFG_GLPI; return (Session::haveRightsOr(self::$rightname, array(READ, self::READFAQ)) || ((Session::getLoginUserID() === false) && $CFG_GLPI["use_public_faq"])); } function canViewItem() { global $CFG_GLPI; if ($this->fields['users_id'] == Session::getLoginUserID()) { return true; } if (Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) { return true; } if ($this->fields["is_faq"]) { return ((Session::haveRightsOr(self::$rightname, array(READ, self::READFAQ)) && $this->haveVisibilityAccess()) || ((Session::getLoginUserID() === false) && $this->isPubliclyVisible())); } return (Session::haveRight(self::$rightname, READ) && $this->haveVisibilityAccess()); } function canUpdateItem() { // Personal knowbase or visibility and write access return (Session::haveRight(self::$rightname, self::KNOWBASEADMIN) || (($_SESSION["glpiactiveprofile"]["interface"] == "central") && ($this->fields['users_id'] == Session::getLoginUserID())) || ((($this->fields["is_faq"] && Session::haveRight(self::$rightname, self::PUBLISHFAQ)) || (!$this->fields["is_faq"] && Session::haveRight(self::$rightname, UPDATE))) && $this->haveVisibilityAccess())); } /** * Get the search page URL for the current classe * * @since version 0.84 * * @param $full path or relative one (true by default) **/ static function getSearchURL($full=true) { global $CFG_GLPI; $dir = ($full ? $CFG_GLPI['root_doc'] : ''); if (isset($_SESSION['glpiactiveprofile']) && ($_SESSION['glpiactiveprofile']['interface'] == "central")) { return "$dir/front/knowbaseitem.php"; } return "$dir/front/helpdesk.faq.php"; } function defineTabs($options=array()) { $ong = array(); $this->addStandardTab(__CLASS__, $ong, $options); $this->addStandardTab('Document_Item', $ong, $options); $this->addStandardTab('KnowbaseItemTranslation',$ong, $options); $this->addStandardTab('Log',$ong, $options); return $ong; } function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { if (!$withtemplate) { $nb = 0; switch ($item->getType()) { case __CLASS__ : $ong[1] = $this->getTypeName(1); if ($item->canUpdateItem()) { if ($_SESSION['glpishow_count_on_tabs']) { $nb = $item->countVisibilities(); } $ong[2] = self::createTabEntry(_n('Target','Targets', Session::getPluralNumber()), $nb); $ong[3] = __('Edit'); } return $ong; } } return ''; } static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) { if ($item->getType() == __CLASS__) { switch($tabnum) { case 1 : $item->showFull(); break; case 2 : $item->showVisibility(); break; case 3 : $item->showForm($item->getID()); break; } } return true; } /** * Actions done at the end of the getEmpty function * *@return nothing **/ function post_getEmpty() { if (Session::haveRight(self::$rightname, self::PUBLISHFAQ) && !Session::haveRight("knowbase", UPDATE)) { $this->fields["is_faq"] = 1; } } /** * @since version 0.85 * @see CommonDBTM::post_addItem() **/ function post_addItem() { if (isset($this->input["_visibility"]) && isset($this->input["_visibility"]['_type']) && !empty($this->input["_visibility"]["_type"])) { $this->input["_visibility"]['knowbaseitems_id'] = $this->getID(); $item = NULL; switch ($this->input["_visibility"]['_type']) { case 'User' : if (isset($this->input["_visibility"]['users_id']) && $this->input["_visibility"]['users_id']) { $item = new KnowbaseItem_User(); } break; case 'Group' : if (isset($this->input["_visibility"]['groups_id']) && $this->input["_visibility"]['groups_id']) { $item = new Group_KnowbaseItem(); } break; case 'Profile' : if (isset($this->input["_visibility"]['profiles_id']) && $this->input["_visibility"]['profiles_id']) { $item = new KnowbaseItem_Profile(); } break; case 'Entity' : $item = new Entity_KnowbaseItem(); break; } if (!is_null($item)) { $item->add($this->input["_visibility"]); Event::log($this->getID(), "knowbaseitem", 4, "tools", //TRANS: %s is the user login sprintf(__('%s adds a target'), $_SESSION["glpiname"])); } } } /** * @since version 0.83 **/ function post_getFromDB() { // Users $this->users = KnowbaseItem_User::getUsers($this->fields['id']); // Entities $this->entities = Entity_KnowbaseItem::getEntities($this->fields['id']); // Group / entities $this->groups = Group_KnowbaseItem::getGroups($this->fields['id']); // Profile / entities $this->profiles = KnowbaseItem_Profile::getProfiles($this->fields['id']); } /** * @see CommonDBTM::cleanDBonPurge() * * @since version 0.83.1 **/ function cleanDBonPurge() { $class = new KnowbaseItem_User(); $class->cleanDBonItemDelete($this->getType(), $this->fields['id']); $class = new Entity_KnowbaseItem(); $class->cleanDBonItemDelete($this->getType(), $this->fields['id']); $class = new Group_KnowbaseItem(); $class->cleanDBonItemDelete($this->getType(), $this->fields['id']); $class = new KnowbaseItem_Profile(); $class->cleanDBonItemDelete($this->getType(), $this->fields['id']); } /** * @since version 0.83 **/ function countVisibilities() { return (count($this->entities) + count($this->users) + count($this->groups) + count($this->profiles)); } /** * Check is this item if visible to everybody (anonymous users) * * @since version 0.83 * * @return Boolean **/ function isPubliclyVisible() { global $CFG_GLPI; if (!$CFG_GLPI['use_public_faq']) { return false; } if (isset($this->entities[0])) { // Browse root entity rights foreach ($this->entities[0] as $entity) { if ($entity['is_recursive']) { return true; } } } return false; } /** * Is the login user have access to KnowbaseItem based on visibility configuration * * @since version 0.83 * * @return boolean **/ function haveVisibilityAccess() { // No public knowbaseitem right : no visibility check if (!Session::haveRightsOr(self::$rightname, array(self::READFAQ, READ))) { return false; } // Author if ($this->fields['users_id'] == Session::getLoginUserID()) { return true; } // Admin if (Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) { return true; } // Users if (isset($this->users[Session::getLoginUserID()])) { return true; } // Groups if (count($this->groups) && isset($_SESSION["glpigroups"]) && count($_SESSION["glpigroups"])) { foreach ($this->groups as $key => $data) { foreach ($data as $group) { if (in_array($group['groups_id'], $_SESSION["glpigroups"])) { // All the group if ($group['entities_id'] < 0) { return true; } // Restrict to entities if (Session::haveAccessToEntity($group['entities_id'], $group['is_recursive'])) { return true; } } } } } // Entities if (count($this->entities) && isset($_SESSION["glpiactiveentities"]) && count($_SESSION["glpiactiveentities"])) { foreach ($this->entities as $key => $data) { foreach ($data as $entity) { if (Session::haveAccessToEntity($entity['entities_id'], $entity['is_recursive'])) { return true; } } } } // Profiles if (count($this->profiles) && isset($_SESSION["glpiactiveprofile"]) && isset($_SESSION["glpiactiveprofile"]['id'])) { if (isset($this->profiles[$_SESSION["glpiactiveprofile"]['id']])) { foreach ($this->profiles[$_SESSION["glpiactiveprofile"]['id']] as $profile) { // All the profile if ($profile['entities_id'] < 0) { return true; } // Restrict to entities if (Session::haveAccessToEntity($profile['entities_id'], $profile['is_recursive'])) { return true; } } } } return false; } /** * Return visibility joins to add to SQL * * @since version 0.83 * * @param $forceall force all joins (false by default) * * @return string joins to add **/ static function addVisibilityJoins($forceall=false) { $join = ''; // Users $join .= " LEFT JOIN `glpi_knowbaseitems_users` ON (`glpi_knowbaseitems_users`.`knowbaseitems_id` = `glpi_knowbaseitems`.`id`) "; // Groups if ($forceall || (isset($_SESSION["glpigroups"]) && count($_SESSION["glpigroups"]))) { $join .= " LEFT JOIN `glpi_groups_knowbaseitems` ON (`glpi_groups_knowbaseitems`.`knowbaseitems_id` = `glpi_knowbaseitems`.`id`) "; } // Profiles if ($forceall || (isset($_SESSION["glpiactiveprofile"]) && isset($_SESSION["glpiactiveprofile"]['id']))) { $join .= " LEFT JOIN `glpi_knowbaseitems_profiles` ON (`glpi_knowbaseitems_profiles`.`knowbaseitems_id` = `glpi_knowbaseitems`.`id`) "; } // Entities if ($forceall || !Session::getLoginUserID() || (isset($_SESSION["glpiactiveentities"]) && count($_SESSION["glpiactiveentities"]))) { $join .= " LEFT JOIN `glpi_entities_knowbaseitems` ON (`glpi_entities_knowbaseitems`.`knowbaseitems_id` = `glpi_knowbaseitems`.`id`) "; } return $join; } /** * Return visibility SQL restriction to add * * @since version 0.83 * * @return string restrict to add **/ static function addVisibilityRestrict() { $restrict = ''; if (Session::getLoginUserID()) { $restrict = "(`glpi_knowbaseitems_users`.`users_id` = '".Session::getLoginUserID()."' "; // Users $restrict .= " OR `glpi_knowbaseitems_users`.`users_id` = '".Session::getLoginUserID()."' "; // Groups if (isset($_SESSION["glpigroups"]) && count($_SESSION["glpigroups"])) { $restrict .= " OR (`glpi_groups_knowbaseitems`.`groups_id` IN ('".implode("','",$_SESSION["glpigroups"])."') AND (`glpi_groups_knowbaseitems`.`entities_id` < 0 ".getEntitiesRestrictRequest("OR", "glpi_groups_knowbaseitems", '', '', true).")) "; } // Profiles if (isset($_SESSION["glpiactiveprofile"]) && isset($_SESSION["glpiactiveprofile"]['id'])) { $restrict .= " OR (`glpi_knowbaseitems_profiles`.`profiles_id` = '".$_SESSION["glpiactiveprofile"]['id']."' AND (`glpi_knowbaseitems_profiles`.`entities_id` < 0 ".getEntitiesRestrictRequest("OR", "glpi_knowbaseitems_profiles", '', '', true).")) "; } // Entities if (isset($_SESSION["glpiactiveentities"]) && count($_SESSION["glpiactiveentities"])) { // Force complete SQL not summary when access to all entities $restrict .= getEntitiesRestrictRequest("OR", "glpi_entities_knowbaseitems", '', '', true, true); } $restrict .= ") "; } else { $restrict = '1'; } return $restrict; } /** * @see CommonDBTM::prepareInputForAdd() **/ function prepareInputForAdd($input) { // set new date if not exists if (!isset($input["date"]) || empty($input["date"])) { $input["date"] = $_SESSION["glpi_currenttime"]; } // set users_id // set title for question if empty if (isset($input["name"]) && empty($input["name"])) { $input["name"] = __('New item'); } if (Session::haveRight(self::$rightname, self::PUBLISHFAQ) && !Session::haveRight(self::$rightname, UPDATE)) { $input["is_faq"] = 1; } if (!Session::haveRight(self::$rightname, self::PUBLISHFAQ) && Session::haveRight(self::$rightname, UPDATE)) { $input["is_faq"] = 0; } return $input; } /** * @see CommonDBTM::prepareInputForUpdate() **/ function prepareInputForUpdate($input) { // set title for question if empty if (isset($input["name"]) && empty($input["name"])) { $input["name"] = __('New item'); } return $input; } /** * Print out an HTML "
" for knowbase item * * @param $ID * @param $options array * - target for the Form * * @return nothing (display the form) **/ function showForm($ID, $options=array()) { global $CFG_GLPI; // show kb item form if (!Session::haveRightsOr(self::$rightname, array(UPDATE, self::PUBLISHFAQ, self::KNOWBASEADMIN))) { return false; } $this->initForm($ID, $options); $canedit = $this->can($ID, UPDATE); // Load ticket solution if (empty($ID) && isset($options['item_itemtype']) && !empty($options['item_itemtype']) && isset($options['item_items_id']) && !empty($options['item_items_id'])) { if ($item = getItemForItemtype($options['item_itemtype'])) { if ($item->getFromDB($options['item_items_id'])) { $this->fields['name'] = $item->getField('name'); $this->fields['answer'] = $item->getField('solution'); if ($item->isField('itilcategories_id')) { $ic = new ItilCategory(); if ($ic->getFromDB($item->getField('itilcategories_id'))) { $this->fields['knowbaseitemcategories_id'] = $ic->getField('knowbaseitemcategories_id'); } } } } } $rand = mt_rand(); Html::initEditorSystem('answer'); $this->initForm($ID, $options); $this->showFormHeader($options); echo ""; echo "".__('Category name').""; echo ""; echo ""; KnowbaseItemCategory::dropdown(array('value' => $this->fields["knowbaseitemcategories_id"])); echo ""; echo ""; if ($this->fields["date"]) { //TRANS: %s is the datetime of insertion printf(__('Created on %s'), Html::convDateTime($this->fields["date"])); } echo ""; if ($this->fields["date_mod"]) { //TRANS: %s is the datetime of update printf(__('Last update on %s'), Html::convDateTime($this->fields["date_mod"])); } echo ""; echo "\n"; echo ""; if (Session::haveRight(self::$rightname, self::PUBLISHFAQ)) { echo "".__('Put this item in the FAQ').""; echo ""; Dropdown::showYesNo('is_faq', $this->fields["is_faq"]); echo ""; } else { echo ""; if ($this->fields["is_faq"]) { _e('This item is part of the FAQ'); } else { _e('This item is not part of the FAQ'); } echo ""; } echo ""; $showuserlink = 0; if (Session::haveRight('user', READ)) { $showuserlink = 1; } if ($this->fields["users_id"]) { //TRANS: %s is the writer name printf(__('%1$s: %2$s'), __('Writer'), getUserName($this->fields["users_id"], $showuserlink)); } echo ""; //TRANS: %d is the number of view if ($ID) { printf(_n('%d view', '%d views', $this->fields["view"]),$this->fields["view"]); } echo ""; echo "\n"; echo ""; echo "".__('Visible since').""; Html::showDateTimeField("begin_date", array('value' => $this->fields["begin_date"], 'timestep' => 1, 'maybeempty' => true, 'canedit' => $canedit)); echo ""; echo "".__('Visible until').""; Html::showDateTimeField("end_date", array('value' => $this->fields["end_date"], 'timestep' => 1, 'maybeempty' => true, 'canedit' => $canedit)); echo ""; echo ""; echo "".__('Subject').""; echo ""; echo ""; echo ""; echo "\n"; echo ""; echo "".__('Content').""; echo ""; $cols = 100; $rows = 30; if (isset($options['_in_modal']) && $options['_in_modal']) { $rows = 15; echo Html::hidden('_in_modal', array('value' => 1)); } echo ""; echo ""; echo "\n"; if ($this->isNewID($ID)) { echo ""; echo ""._n('Target','Targets',1).""; echo ""; $types = array('Entity', 'Group', 'Profile', 'User'); $addrand = Dropdown::showItemTypes('_visibility[_type]', $types); echo ""; $params = array('type' => '__VALUE__', 'right' => 'knowbase', 'prefix' => '_visibility', 'nobutton' => 1); Ajax::updateItemOnSelectEvent("dropdown__visibility__type_".$addrand,"visibility$rand", $CFG_GLPI["root_doc"]."/ajax/visibility.php", $params); echo ""; echo "\n"; } $this->showFormButtons($options); return true; } // function showForm /** * Add kb item to the public FAQ * * @return nothing **/ function addToFaq() { global $DB; $DB->query("UPDATE `".$this->getTable()."` SET `is_faq` = '1' WHERE `id` = '".$this->fields['id']."'"); if (isset($_SESSION['glpi_faqcategories'])) { unset($_SESSION['glpi_faqcategories']); } } /** * Increase the view counter of the current knowbaseitem * * @since version 0.83 */ function updateCounter() { global $DB; //update counter view $query = "UPDATE `glpi_knowbaseitems` SET `view` = `view`+1 WHERE `id` = '".$this->getID()."'"; $DB->query($query); } /** * Print out (html) show item : question and answer * * @param $options array of options * * @return nothing (display item : question and answer) **/ function showFull($options=array()) { global $DB, $CFG_GLPI; if (!$this->can($this->fields['id'], READ)) { return false; } $linkusers_id = true; // show item : question and answer if (((Session::getLoginUserID() === false) && $CFG_GLPI["use_public_faq"]) || ($_SESSION["glpiactiveprofile"]["interface"] == "helpdesk") || !User::canView()) { $linkusers_id = false; } $this->updateCounter(); $knowbaseitemcategories_id = $this->fields["knowbaseitemcategories_id"]; $fullcategoryname = getTreeValueCompleteName("glpi_knowbaseitemcategories", $knowbaseitemcategories_id); $tmp = "".$fullcategoryname.""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
".sprintf(__('%1$s: %2$s'), __('Category'), $tmp); echo "

".__('Subject')."

"; if (KnowbaseItemTranslation::canBeTranslated($this)) { echo KnowbaseItemTranslation::getTranslatedValue($this, 'name'); } else { echo $this->fields["name"]; } echo "

".__('Content')."

\n"; echo "
"; if (KnowbaseItemTranslation::canBeTranslated($this)) { $answer = KnowbaseItemTranslation::getTranslatedValue($this, 'answer'); } else { $answer = $this->fields["answer"]; } echo Toolbox::unclean_html_cross_side_scripting_deep($answer); echo "
"; echo "
"; if ($this->fields["users_id"]) { // Integer because true may be 2 and getUserName return array if ($linkusers_id) { $linkusers_id = 1; } else { $linkusers_id = 0; } printf(__('%1$s: %2$s'), __('Writer'), getUserName($this->fields["users_id"], $linkusers_id)); echo "
"; } if ($this->fields["date"]) { //TRANS: %s is the datetime of update printf(__('Created on %s'), Html::convDateTime($this->fields["date"])); echo "
"; } if ($this->fields["date_mod"]) { //TRANS: %s is the datetime of update printf(__('Last update on %s'), Html::convDateTime($this->fields["date_mod"])); } echo "
"; if ($this->countVisibilities() == 0) { echo "".__('Unpublished')."
"; } printf(_n('%d view', '%d views', $this->fields["view"]), $this->fields["view"]); echo "
"; if ($this->fields["is_faq"]) { _e('This item is part of the FAQ'); } else { _e('This item is not part of the FAQ'); } echo "
"; return true; } /** * Print out an HTML form for Search knowbase item * * @param $options $_GET * * @return nothing (display the form) **/ function searchForm($options) { global $CFG_GLPI; if (!$CFG_GLPI["use_public_faq"] && !Session::haveRightsOr(self::$rightname, array(READ, self::READFAQ))) { return false; } // Default values of parameters $params["contains"] = ""; $params["target"] = $_SERVER['PHP_SELF']; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $params[$key] = $val; } } echo "
"; echo ""; echo ""; echo ""; echo ""; echo "
"; echo ""; echo "
"; if (isset($options['item_itemtype']) && isset($options['item_items_id'])) { echo ""; echo ""; } Html::closeForm(); echo "
"; } /** * Print out an HTML "" for Search knowbase item * * @since version 0.84 * * @param $options $_GET * * @return nothing (display the form) **/ function showBrowseForm($options) { global $CFG_GLPI; if (!$CFG_GLPI["use_public_faq"] && !Session::haveRightsOr(self::$rightname, array(READ, self::READFAQ))) { return false; } // Default values of parameters $params["knowbaseitemcategories_id"] = ""; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $params[$key] = $val; } } $faq = !Session::haveRight(self::$rightname, READ); // Category select not for anonymous FAQ if (Session::getLoginUserID() && !$faq) { echo "
"; echo ""; echo ""; echo ""; echo "
".__('Category')." "; KnowbaseItemCategory::dropdown(array('value' => $params["knowbaseitemcategories_id"])); echo ""; echo "
"; if (isset($options['item_itemtype']) && isset($options['item_items_id'])) { echo ""; echo ""; } Html::closeForm(); echo "
"; } } /** * Print out an HTML form for Search knowbase item * * @since version 0.84 * * @param $options $_GET * * @return nothing (display the form) **/ function showManageForm($options) { global $CFG_GLPI; if (!Session::haveRightsOr(self::$rightname, array(UPDATE, self::PUBLISHFAQ, self::KNOWBASEADMIN))) { return false; } $params['unpublished'] = 'my'; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $params[$key] = $val; } } $faq = !Session::haveRight(self::$rightname, UPDATE); echo "
"; echo ""; echo ""; echo ""; echo "
"; $values = array('myunpublished' => __('My unpublished articles'), 'allmy' => __('All my articles')); if (Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) { $values['allunpublished'] = __('All unpublished articles'); } Dropdown::showFromArray('unpublished', $values, array('value' => $params['unpublished'])); echo ""; echo "
"; Html::closeForm(); echo "
"; } /** * Build request for showList * * @since version 0.83 * * @param $params array (contains, knowbaseitemcategories_id, faq) * @param $type string search type : browse / search (default search) * * @return String : SQL request **/ static function getListRequest(array $params, $type='search') { global $DB; // Lists kb Items $where = ""; $order = ""; $score = ""; $addselect = ""; $join = self::addVisibilityJoins(true); switch ($type) { case 'myunpublished' : break; case 'allmy' : break; case 'allunpublished' : break; default : // Build query if (Session::getLoginUserID() && $type != 'myunpublished') { $where = self::addVisibilityRestrict(); } else { // Anonymous access if (Session::isMultiEntitiesMode()) { $where = " (`glpi_entities_knowbaseitems`.`entities_id` = '0' AND `glpi_entities_knowbaseitems`.`is_recursive` = '1')"; } } break; } if (empty($where)) { $where = '1 = 1'; } if ($params['faq']) { // helpdesk $where .= " AND (`glpi_knowbaseitems`.`is_faq` = '1')"; } if (KnowbaseItemTranslation::isKbTranslationActive() && (countElementsInTable('glpi_knowbaseitemtranslations') > 0)) { $join .= "LEFT JOIN `glpi_knowbaseitemtranslations` ON (`glpi_knowbaseitems`.`id` = `glpi_knowbaseitemtranslations`.`knowbaseitems_id` AND `glpi_knowbaseitemtranslations`.`language` = '".$_SESSION['glpilanguage']."')"; $addselect .= ", `glpi_knowbaseitemtranslations`.`name` AS transname, `glpi_knowbaseitemtranslations`.`answer` AS transanswer "; } // a search with $contains switch ($type) { case 'allmy' : $where .= " AND `glpi_knowbaseitems`.`users_id` = '".Session::getLoginUserID()."'"; break; case 'myunpublished' : $where .= " AND `glpi_knowbaseitems`.`users_id` = '".Session::getLoginUserID()."' AND (`glpi_entities_knowbaseitems`.`entities_id` IS NULL AND `glpi_knowbaseitems_profiles`.`profiles_id` IS NULL AND `glpi_groups_knowbaseitems`.`groups_id` IS NULL AND `glpi_knowbaseitems_users`.`users_id` IS NULL)"; break; case 'allunpublished' : // Only published $where .= " AND (`glpi_entities_knowbaseitems`.`entities_id` IS NULL AND `glpi_knowbaseitems_profiles`.`profiles_id` IS NULL AND `glpi_groups_knowbaseitems`.`groups_id` IS NULL AND `glpi_knowbaseitems_users`.`users_id` IS NULL)"; break; case 'search' : if (strlen($params["contains"]) > 0) { $search = Toolbox::unclean_cross_side_scripting_deep($params["contains"]); $search_wilcard = explode(' ', $search); $search_wilcard = implode('* ', $search_wilcard).'*'; $addscore = array(); if (KnowbaseItemTranslation::isKbTranslationActive() && (countElementsInTable('glpi_knowbaseitemtranslations') > 0)) { $addscore = array('`glpi_knowbaseitemtranslations`.`name`', '`glpi_knowbaseitemtranslations`.`answer`'); } $score = " ,(MATCH(`glpi_knowbaseitems`.`name`, `glpi_knowbaseitems`.`answer`) AGAINST('$search_wilcard' IN BOOLEAN MODE)"; if (!empty($addscore)) { foreach($addscore as $addscore_field) { $score.= " + MATCH($addscore_field) AGAINST('$search_wilcard' IN BOOLEAN MODE)"; } } $score .=" ) AS SCORE "; $where_1 = $where." AND (MATCH(`glpi_knowbaseitems`.`name`, `glpi_knowbaseitems`.`answer`) AGAINST('$search_wilcard' IN BOOLEAN MODE) "; if (!empty($addscore)) { foreach($addscore as $addscore_field) { $where_1.= "OR $addscore_field IS NOT NULL AND MATCH($addscore_field) AGAINST('$search_wilcard' IN BOOLEAN MODE)"; } } $where_1.= ")"; // Add visibility date $where_1 .= " AND (`glpi_knowbaseitems`.`begin_date` IS NULL OR `glpi_knowbaseitems`.`begin_date` < NOW()) AND (`glpi_knowbaseitems`.`end_date` IS NULL OR `glpi_knowbaseitems`.`end_date` > NOW()) "; $order = "ORDER BY `SCORE` DESC"; // preliminar query to allow alternate search if no result with fulltext $query_1 = "SELECT COUNT(`glpi_knowbaseitems`.`id`) FROM `glpi_knowbaseitems` $join WHERE $where_1"; $result_1 = $DB->query($query_1); $numrows_1 = $DB->result($result_1,0,0); if ($numrows_1 <= 0) {// not result this fulltext try with alternate search $search1 = array(/* 1 */ '/\\\"/', /* 2 */ "/\+/", /* 3 */ "/\*/", /* 4 */ "/~/", /* 5 */ "//", /* 7 */ "/\(/", /* 8 */ "/\)/", /* 9 */ "/\-/"); $contains = preg_replace($search1,"", $params["contains"]); $addwhere = ''; if (KnowbaseItemTranslation::isKbTranslationActive() && (countElementsInTable('glpi_knowbaseitemtranslations') > 0)) { $addwhere = " OR `glpi_knowbaseitemtranslations`.`name` ".Search::makeTextSearch($contains)." OR `glpi_knowbaseitemtranslations`.`answer` ".Search::makeTextSearch($contains); } $where .= " AND (`glpi_knowbaseitems`.`name` ".Search::makeTextSearch($contains)." OR `glpi_knowbaseitems`.`answer` ".Search::makeTextSearch($contains)." $addwhere)"; } else { $where = $where_1; } } break; case 'browse' : $where .= " AND (`glpi_knowbaseitems`.`knowbaseitemcategories_id` = '".$params["knowbaseitemcategories_id"]."')"; // Add visibility date $where .= " AND (`glpi_knowbaseitems`.`begin_date` IS NULL OR `glpi_knowbaseitems`.`begin_date` < NOW()) AND (`glpi_knowbaseitems`.`end_date` IS NULL OR `glpi_knowbaseitems`.`end_date` > NOW()) "; $order = " ORDER BY `glpi_knowbaseitems`.`name` ASC"; break; } $query = "SELECT DISTINCT `glpi_knowbaseitems`.*, `glpi_knowbaseitemcategories`.`completename` AS category $addselect $score FROM `glpi_knowbaseitems` $join LEFT JOIN `glpi_knowbaseitemcategories` ON (`glpi_knowbaseitemcategories`.`id` = `glpi_knowbaseitems`.`knowbaseitemcategories_id`) WHERE $where $order"; return $query; } /** * Print out list kb item * * @param $options $_GET * @param $type string search type : browse / search (default search) **/ static function showList($options, $type='search') { global $DB, $CFG_GLPI; // Default values of parameters $params['faq'] = !Session::haveRight(self::$rightname, READ); $params["start"] = "0"; $params["knowbaseitemcategories_id"] = "0"; $params["contains"] = ""; $params["target"] = $_SERVER['PHP_SELF']; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $params[$key] = $val; } } $ki = new self(); switch ($type) { case 'myunpublished' : if (!Session::haveRightsOr(self::$rightname, array(UPDATE, self::PUBLISHFAQ))) { return false; } break; case 'allunpublished' : if (!Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) { return false; } break; default : break; } if (!$params["start"]) { $params["start"] = 0; } $query = self::getListRequest($params, $type); // Get it from database if ($result = $DB->query($query)) { $KbCategory = new KnowbaseItemCategory(); $title = ""; if ($KbCategory->getFromDB($params["knowbaseitemcategories_id"])) { $title = (empty($KbCategory->fields['name']) ?"(".$params['knowbaseitemcategories_id'].")" : $KbCategory->fields['name']); $title = sprintf(__('%1$s: %2$s'), __('Category'), $title); } Session::initNavigateListItems('KnowbaseItem', $title); $numrows = $DB->numrows($result); $list_limit = $_SESSION['glpilist_limit']; $showwriter = in_array($type, array('myunpublished', 'allunpublished', 'allmy')); // Limit the result, if no limit applies, use prior result if (($numrows > $list_limit) && !isset($_GET['export_all'])) { $query_limit = $query ." LIMIT ".intval($params["start"]).", ".intval($list_limit)." "; $result_limit = $DB->query($query_limit); $numrows_limit = $DB->numrows($result_limit); } else { $numrows_limit = $numrows; $result_limit = $result; } if ($numrows_limit > 0) { // Set display type for export if define $output_type = Search::HTML_OUTPUT; if (isset($_GET["display_type"])) { $output_type = $_GET["display_type"]; } // Pager $parameters = "start=".$params["start"]."&knowbaseitemcategories_id=". $params['knowbaseitemcategories_id']."&contains=". $params["contains"]."&is_faq=".$params['faq']; if (isset($options['item_itemtype']) && isset($options['item_items_id'])) { $parameters .= "&item_items_id=".$options['item_items_id']."&item_itemtype=". $options['item_itemtype']; } if ($output_type == Search::HTML_OUTPUT) { Html::printPager($params['start'], $numrows, Toolbox::getItemTypeSearchURL('KnowbaseItem'), $parameters, 'KnowbaseItem'); } $nbcols = 1; // Display List Header echo Search::showHeader($output_type, $numrows_limit+1, $nbcols); echo Search::showNewLine($output_type); $header_num = 1; echo Search::showHeaderItem($output_type, __('Subject'), $header_num); if ($output_type != Search::HTML_OUTPUT) { echo Search::showHeaderItem($output_type, __('Content'), $header_num); } if ($showwriter) { echo Search::showHeaderItem($output_type, __('Writer'), $header_num); } echo Search::showHeaderItem($output_type, __('Category'), $header_num); if (isset($options['item_itemtype']) && isset($options['item_items_id']) && ($output_type == Search::HTML_OUTPUT)) { echo Search::showHeaderItem($output_type, ' ', $header_num); } // Num of the row (1=header_line) $row_num = 1; for ($i=0 ; $i<$numrows_limit ; $i++) { $data = $DB->fetch_assoc($result_limit); Session::addToNavigateListItems('KnowbaseItem', $data["id"]); // Column num $item_num = 1; $row_num++; echo Search::showNewLine($output_type, $i%2); $item = new self; $item->getFromDB($data["id"]); $name = $data["name"]; $answer = $data["answer"]; // Manage translations if (isset($data['transname']) && !empty($data['transname'])) { $name = $data["transname"]; } if (isset($data['transanswer']) && !empty($data['transanswer'])) { $answer = $data["transanswer"]; } if ($output_type == Search::HTML_OUTPUT) { $toadd = ''; if (isset($options['item_itemtype']) && isset($options['item_items_id'])) { $href = " href='#' onClick=\"".Html::jsGetElementbyID('kbshow'.$data["id"]).".dialog('open');\"" ; $toadd = Ajax::createIframeModalWindow('kbshow'.$data["id"], $CFG_GLPI["root_doc"]. "/front/knowbaseitem.form.php?id=".$data["id"], array('display' => false)); } else { $href = " href=\"".$CFG_GLPI['root_doc']."/front/knowbaseitem.form.php?id=". $data["id"]."\" "; } echo Search::showItem($output_type, "
$toadd".Html::resume_text($name, 80)."
". Html::resume_text(Html::clean(Toolbox::unclean_cross_side_scripting_deep($answer)), 600)."
", $item_num, $row_num); } else { echo Search::showItem($output_type, $name, $item_num, $row_num); echo Search::showItem($output_type, Html::clean(Toolbox::unclean_cross_side_scripting_deep(html_entity_decode($answer, ENT_QUOTES, "UTF-8"))), $item_num, $row_num); } $showuserlink = 0; if (Session::haveRight('user', READ)) { $showuserlink = 1; } if ($showwriter) { echo Search::showItem($output_type, getUserName($data["users_id"], $showuserlink), $item_num, $row_num); } $categ = $data["category"]; if ($output_type == Search::HTML_OUTPUT) { $cathref = $ki->getSearchURL()."?knowbaseitemcategories_id=". $data["knowbaseitemcategories_id"].'&forcetab=Knowbase$2'; $categ = "".$categ.''; } echo Search::showItem($output_type, $categ, $item_num, $row_num); if (isset($options['item_itemtype']) && isset($options['item_items_id']) && ($output_type == Search::HTML_OUTPUT)) { $forcetab = $options['item_itemtype']; if (!$_SESSION['glpiticket_timeline'] || $_SESSION['glpiticket_timeline_keep_replaced_tabs']) { $forcetab .= '$2'; //Solution tab } else { $forcetab .= '$1'; //Timeline tab } $content = "". __('Use as a solution').""; echo Search::showItem($output_type, $content, $item_num, $row_num); } // End Line echo Search::showEndLine($output_type); } // Display footer if (($output_type == Search::PDF_OUTPUT_LANDSCAPE) || ($output_type == Search::PDF_OUTPUT_PORTRAIT)) { echo Search::showFooter($output_type, Dropdown::getDropdownName("glpi_knowbaseitemcategories", $params['knowbaseitemcategories_id']), $numrows_limit); } else { echo Search::showFooter($output_type, '', $numrows_limit); } echo "
"; if ($output_type == Search::HTML_OUTPUT) { Html::printPager($params['start'], $numrows, Toolbox::getItemTypeSearchURL('KnowbaseItem'), $parameters, 'KnowbaseItem'); } } else { echo "
".__('No item found')."
"; } } } /** * Print out list recent or popular kb/faq * * @param $type type : recent / popular / not published * * @return nothing (display table) **/ static function showRecentPopular($type) { global $DB, $CFG_GLPI; $faq = !Session::haveRight(self::$rightname, READ); if ($type == "recent") { $orderby = "ORDER BY `date` DESC"; $title = __('Recent entries'); } else if ($type == 'lastupdate') { $orderby = "ORDER BY `date_mod` DESC"; $title = __('Last updated entries'); } else { $orderby = "ORDER BY `view` DESC"; $title = __('Most popular questions'); } $faq_limit = ""; $addselect = ""; // Force all joins for not published to verify no visibility set $join = self::addVisibilityJoins(true); if (Session::getLoginUserID()) { $faq_limit .= "WHERE ".self::addVisibilityRestrict(); } else { // Anonymous access if (Session::isMultiEntitiesMode()) { $faq_limit .= " WHERE (`glpi_entities_knowbaseitems`.`entities_id` = '0' AND `glpi_entities_knowbaseitems`.`is_recursive` = '1')"; } else { $faq_limit .= " WHERE 1"; } } // Only published $faq_limit .= " AND (`glpi_entities_knowbaseitems`.`entities_id` IS NOT NULL OR `glpi_knowbaseitems_profiles`.`profiles_id` IS NOT NULL OR `glpi_groups_knowbaseitems`.`groups_id` IS NOT NULL OR `glpi_knowbaseitems_users`.`users_id` IS NOT NULL)"; // Add visibility date $faq_limit .= " AND (`glpi_knowbaseitems`.`begin_date` IS NULL OR `glpi_knowbaseitems`.`begin_date` < NOW()) AND (`glpi_knowbaseitems`.`end_date` IS NULL OR `glpi_knowbaseitems`.`end_date` > NOW()) "; if ($faq) { // FAQ $faq_limit .= " AND (`glpi_knowbaseitems`.`is_faq` = '1')"; } if (KnowbaseItemTranslation::isKbTranslationActive() && (countElementsInTable('glpi_knowbaseitemtranslations') > 0)) { $join .= "LEFT JOIN `glpi_knowbaseitemtranslations` ON (`glpi_knowbaseitems`.`id` = `glpi_knowbaseitemtranslations`.`knowbaseitems_id` AND `glpi_knowbaseitemtranslations`.`language` = '".$_SESSION['glpilanguage']."')"; $addselect .= ", `glpi_knowbaseitemtranslations`.`name` AS transname, `glpi_knowbaseitemtranslations`.`answer` AS transanswer "; } $query = "SELECT DISTINCT `glpi_knowbaseitems`.* $addselect FROM `glpi_knowbaseitems` $join $faq_limit $orderby LIMIT 10"; $result = $DB->query($query); $number = $DB->numrows($result); if ($number > 0) { echo ""; echo ""; while ($data = $DB->fetch_assoc($result)) { $name = $data['name']; if (isset($data['transname']) && !empty($data['transname'])) { $name = $data['transname']; } echo ""; } echo "
".$title."
"; echo "". Html::resume_text($name,80)."
"; } } function getSearchOptions() { $tab = array(); $tab['common'] = __('Characteristics'); $tab[2]['table'] = $this->getTable(); $tab[2]['field'] = 'id'; $tab[2]['name'] = __('ID'); $tab[2]['massiveaction'] = false; $tab[2]['datatype'] = 'number'; $tab[4]['table'] = 'glpi_knowbaseitemcategories'; $tab[4]['field'] = 'name'; $tab[4]['name'] = __('Category'); $tab[4]['datatype'] = 'dropdown'; $tab[5]['table'] = $this->getTable(); $tab[5]['field'] = 'date'; $tab[5]['name'] = __('Date'); $tab[5]['datatype'] = 'datetime'; $tab[5]['massiveaction'] = false; $tab[6]['table'] = $this->getTable(); $tab[6]['field'] = 'name'; $tab[6]['name'] = __('Subject'); $tab[6]['datatype'] = 'text'; $tab[7]['table'] = $this->getTable(); $tab[7]['field'] = 'answer'; $tab[7]['name'] = __('Content'); $tab[7]['datatype'] = 'text'; $tab[7]['htmltext'] = true; $tab[8]['table'] = $this->getTable(); $tab[8]['field'] = 'is_faq'; $tab[8]['name'] = __('FAQ item'); $tab[8]['datatype'] = 'bool'; $tab[9]['table'] = $this->getTable(); $tab[9]['field'] = 'view'; $tab[9]['name'] = _n('View', 'Views', Session::getPluralNumber()); $tab[9]['datatype'] = 'integer'; $tab[9]['massiveaction'] = false; $tab[10]['table'] = $this->getTable(); $tab[10]['field'] = 'begin_date'; $tab[10]['name'] = __('Visibility start date'); $tab[10]['datatype'] = 'datetime'; $tab[11]['table'] = $this->getTable(); $tab[11]['field'] = 'end_date'; $tab[11]['name'] = __('Visibility end date'); $tab[11]['datatype'] = 'datetime'; $tab[19]['table'] = $this->getTable(); $tab[19]['field'] = 'date_mod'; $tab[19]['name'] = __('Last update'); $tab[19]['datatype'] = 'datetime'; $tab[19]['massiveaction'] = false; $tab[70]['table'] = 'glpi_users'; $tab[70]['field'] = 'name'; $tab[70]['name'] = __('User'); $tab[70]['massiveaction'] = false; $tab[70]['datatype'] = 'dropdown'; $tab[70]['right'] = 'all'; $tab[80]['table'] = 'glpi_entities'; $tab[80]['field'] = 'completename'; $tab[80]['name'] = __('Entity'); $tab[80]['massiveaction'] = false; $tab[80]['datatype'] = 'dropdown'; $tab[86]['table'] = $this->getTable(); $tab[86]['field'] = 'is_recursive'; $tab[86]['name'] = __('Child entities'); $tab[86]['datatype'] = 'bool'; // add objectlock search options $tab += ObjectLock::getSearchOptionsToAdd( get_class($this) ) ; return $tab; } /** * Show visibility config for a knowbaseitem * * @since version 0.83 **/ function showVisibility() { global $DB, $CFG_GLPI; $ID = $this->fields['id']; $canedit = $this->can($ID, UPDATE); echo "
"; $rand = mt_rand(); $nb = count($this->users) + count($this->groups) + count($this->profiles) + count($this->entities); if ($canedit) { echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
".__('Add a target')."
"; $types = array('Entity', 'Group', 'Profile', 'User'); $addrand = Dropdown::showItemTypes('_type', $types); $params = array('type' => '__VALUE__', 'right' => ($this->getField('is_faq') ? 'faq' : 'knowbase')); Ajax::updateItemOnSelectEvent("dropdown__type".$addrand,"visibility$rand", $CFG_GLPI["root_doc"]."/ajax/visibility.php", $params); echo ""; echo "
"; Html::closeForm(); echo "
"; } echo "
"; if ($canedit && $nb) { Html::openMassiveActionsForm('mass'.__CLASS__.$rand); $massiveactionparams = array('num_displayed' => min($_SESSION['glpilist_limit'], $nb), 'container' => 'mass'.__CLASS__.$rand, 'specific_actions' => array('delete' => _x('button', 'Delete permanently')) ); if ($this->fields['users_id'] != Session::getLoginUserID()) { $massiveactionparams['confirm'] = __('Caution! You are not the author of this element. Delete targets can result in loss of access to that element.'); } Html::showMassiveActions($massiveactionparams); } echo ""; $header_begin = ""; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit && $nb) { $header_begin .= ""; } $header_end .= ""; $header_end .= ""; $header_end .= ""; echo $header_begin.$header_top.$header_end; // Users if (count($this->users)) { foreach ($this->users as $key => $val) { foreach ($val as $data) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } } } // Groups if (count($this->groups)) { foreach ($this->groups as $key => $val) { foreach ($val as $data) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } } } // Entity if (count($this->entities)) { foreach ($this->entities as $key => $val) { foreach ($val as $data) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } } } // Profiles if (count($this->profiles)) { foreach ($this->profiles as $key => $val) { foreach ($val as $data) { echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } } } if ($nb) { echo $header_begin.$header_bottom.$header_end; } echo "
"; $header_top .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header_bottom .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header_end .= "".__('Type').""._n('Recipient', 'Recipients', Session::getPluralNumber())."
"; Html::showMassiveActionCheckBox('KnowbaseItem_User',$data["id"]); echo "".__('User')."".getUserName($data['users_id'])."
"; Html::showMassiveActionCheckBox('Group_KnowbaseItem',$data["id"]); echo "".__('Group').""; $names = Dropdown::getDropdownName('glpi_groups', $data['groups_id'],1); $groupname = sprintf(__('%1$s %2$s'), $names["name"], Html::showToolTip($names["comment"], array('display' => false))); if ($data['entities_id'] >= 0) { $groupname = sprintf(__('%1$s / %2$s'), $groupname, Dropdown::getDropdownName('glpi_entities', $data['entities_id'])); if ($data['is_recursive']) { $groupname = sprintf(__('%1$s %2$s'), $groupname, "(".__('R').")"); } } echo $groupname; echo "
"; Html::showMassiveActionCheckBox('Entity_KnowbaseItem',$data["id"]); echo "".__('Entity').""; $names = Dropdown::getDropdownName('glpi_entities', $data['entities_id'],1); $entityname = sprintf(__('%1$s %2$s'), $names["name"], Html::showToolTip($names["comment"], array('display' => false))); if ($data['is_recursive']) { $entityname = sprintf(__('%1$s %2$s'), $entityname, "(".__('R').")"); } echo $entityname; echo "
"; Html::showMassiveActionCheckBox('KnowbaseItem_Profile',$data["id"]); echo ""._n('Profile', 'Profiles', 1).""; $names = Dropdown::getDropdownName('glpi_profiles', $data['profiles_id'], 1); $profilename = sprintf(__('%1$s %2$s'), $names["name"], Html::showToolTip($names["comment"], array('display' => false))); if ($data['entities_id'] >= 0) { $profilename = sprintf(__('%1$s / %2$s'), $profilename, Dropdown::getDropdownName('glpi_entities', $data['entities_id'])); if ($data['is_recursive']) { $profilename = sprintf(__('%1$s %2$s'), $profilename, "(".__('R').")"); } } echo $profilename; echo "
"; if ($canedit && $nb) { $massiveactionparams['ontop'] =false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } echo "
"; // Add items return true; } /** * @since version 0.85 * * @see commonDBTM::getRights() **/ function getRights($interface='central') { if ($interface == 'central') { $values = parent::getRights(); $values[self::KNOWBASEADMIN] = __('Knowledge base administration'); $values[self::PUBLISHFAQ] = __('Publish in the FAQ'); } $values[self::READFAQ] = __('Read the FAQ'); return $values; } } ?>