.
* ---------------------------------------------------------------------
*/
use Glpi\Event;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* KnowbaseItem Class
**/
class KnowbaseItem extends CommonDBVisible implements ExtraVisibilityCriteria {
// From CommonDBTM
public $dohistory = true;
// For visibility checks
protected $users = [];
protected $groups = [];
protected $profiles = [];
protected $entities = [];
protected $items = [];
const KNOWBASEADMIN = 1024;
const READFAQ = 2048;
const PUBLISHFAQ = 4096;
const COMMENTS = 8192;
static $rightname = 'knowbase';
static function getTypeName($nb = 0) {
return __('Knowledge base');
}
/**
* @see CommonGLPI::getMenuShorcut()
*
* @since 0.85
**/
static function getMenuShorcut() {
return 'b';
}
function getName($options = []) {
if (KnowbaseItemTranslation::canBeTranslated($this)) {
return KnowbaseItemTranslation::getTranslatedValue($this);
}
return parent::getName();
}
/**
* @see CommonGLPI::getMenuName()
*
* @since 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, [CREATE, self::PUBLISHFAQ]);
}
/**
* @since 0.85
**/
static function canUpdate() {
return Session::haveRightsOr(self::$rightname, [UPDATE, self::KNOWBASEADMIN]);
}
static function canView() {
global $CFG_GLPI;
return (Session::haveRightsOr(self::$rightname, [READ, self::READFAQ])
|| ((Session::getLoginUserID() === false) && $CFG_GLPI["use_public_faq"]));
}
function canViewItem() {
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, [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::getCurrentInterface() == "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()));
}
/**
* Check if current user can comment on KB entries
*
* @return boolean
*/
public function canComment() {
return $this->canViewItem() && Session::haveRight(self::$rightname, self::COMMENTS);
}
/**
* Get the search page URL for the current classe
*
* @since 0.84
*
* @param boolean $full path or relative one
**/
static function getSearchURL($full = true) {
global $CFG_GLPI;
$dir = ($full ? $CFG_GLPI['root_doc'] : '');
if (Session::getCurrentInterface() == "central") {
return "$dir/front/knowbaseitem.php";
}
return "$dir/front/helpdesk.faq.php";
}
/**
* Get the form page URL for the current classe
*
* @param boolean $full path or relative one
**/
static function getFormURL($full = true) {
global $CFG_GLPI;
$dir = ($full ? $CFG_GLPI['root_doc'] : '');
if (Session::getCurrentInterface() == "central") {
return "$dir/front/knowbaseitem.form.php";
}
return "$dir/front/helpdesk.faq.php";
}
function defineTabs($options = []) {
$ong = [];
$this->addStandardTab(__CLASS__, $ong, $options);
$this->addStandardTab('KnowbaseItem_Item', $ong, $options);
$this->addStandardTab('Document_Item', $ong, $options);
$this->addStandardTab('KnowbaseItemTranslation', $ong, $options);
$this->addStandardTab('Log', $ong, $options);
$this->addStandardTab('KnowbaseItem_Revision', $ong, $options);
$this->addStandardTab('KnowbaseItem_Comment', $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 void
**/
function post_getEmpty() {
if (Session::haveRight(self::$rightname, self::PUBLISHFAQ)
&& !Session::haveRight("knowbase", UPDATE)) {
$this->fields["is_faq"] = 1;
}
}
/**
* @since 0.85
* @see CommonDBTM::post_addItem()
**/
function post_addItem() {
// add screenshots
$this->input = $this->addFiles(
$this->input, [
'force_update' => true,
'content_field' => 'answer',
'name' => 'answer',
]
);
// Add documents
$this->input = $this->addFiles($this->input, ['force_update' => true]);
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"]));
}
}
if (isset($this->input['_do_item_link']) && $this->input['_do_item_link'] == 1) {
$params = [
'knowbaseitems_id' => $this->getID(),
'itemtype' => $this->input['_itemtype'],
'items_id' => $this->input['_items_id']
];
$kb_item_item = new KnowbaseItem_Item();
$kb_item_item->add($params);
}
}
/**
* @since 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']);
//Linked kb items
$this->knowbase_items = KnowbaseItem_Item::getItems($this);
}
/**
* @see CommonDBTM::cleanDBonPurge()
*
* @since 0.83.1
**/
function cleanDBonPurge() {
$this->deleteChildrenAndRelationsFromDb(
[
Entity_KnowbaseItem::class,
Group_KnowbaseItem::class,
KnowbaseItem_Item::class,
KnowbaseItem_Profile::class,
KnowbaseItem_User::class,
KnowbaseItemTranslation::class,
]
);
/// KnowbaseItem_Comment does not extends CommonDBConnexity
$kbic = new KnowbaseItem_Comment();
$kbic->deleteByCriteria(['knowbaseitems_id' => $this->fields['id']]);
/// KnowbaseItem_Revision does not extends CommonDBConnexity
$kbir = new KnowbaseItem_Revision();
$kbir->deleteByCriteria(['knowbaseitems_id' => $this->fields['id']]);
}
/**
* Check is this item if visible to everybody (anonymous users)
*
* @since 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;
}
public function haveVisibilityAccess() {
// No public knowbaseitem right : no visibility check
if (!Session::haveRightsOr(self::$rightname, [self::READFAQ, READ])) {
return false;
}
// KB Admin
if (Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) {
return true;
}
return parent::haveVisibilityAccess();
}
/**
* Return visibility joins to add to SQL
*
* @since 0.83
*
* @param boolean $forceall force all joins
*
* @return string joins to add
**/
static function addVisibilityJoins($forceall = false) {
//not deprecated because used in self::getListRequest and self::showRecentPopular
global $DB;
//get and clean criteria
$criteria = self::getVisibilityCriteria($forceall);
unset($criteria['WHERE']);
$criteria['FROM'] = self::getTable();
$it = new \DBmysqlIterator(null);
$it->buildQuery($criteria);
$sql = $it->getSql();
$sql = str_replace(
'SELECT * FROM '.$DB->quoteName(self::getTable()).'',
'',
$sql
);
return $sql;
}
/**
* Return visibility SQL restriction to add
*
* @since 0.83
*
* @return string restrict to add
**/
static function addVisibilityRestrict() {
//not deprecated because used in self::getListRequest and self::showRecentPopular
global $DB;
//get and clean criteria
$criteria = self::getVisibilityCriteria();
unset($criteria['LEFT JOIN']);
$criteria['FROM'] = self::getTable();
$it = new \DBmysqlIterator(null);
$it->buildQuery($criteria);
$sql = $it->getSql();
$sql = str_replace(
'SELECT * FROM '.$DB->quoteName(self::getTable()).'',
'',
$sql
);
$sql = preg_replace('/.*WHERE /', '', $sql);
//No where restrictions. Add a placeholder for compatibility with later restrictions
if (strlen(trim($sql)) == 0) {
$sql = "1";
}
return $sql;
}
/**
* Return visibility joins to add to DBIterator parameters
*
* @since 9.2
*
* @param boolean $forceall force all joins (false by default)
*
* @return array
*/
static public function getVisibilityCriteria(bool $forceall = false): array {
global $CFG_GLPI;
$is_public_faq_context = !Session::getLoginUserID() && $CFG_GLPI["use_public_faq"];
$has_session_groups = isset($_SESSION["glpigroups"]) && count($_SESSION["glpigroups"]);
$has_active_profile = isset($_SESSION["glpiactiveprofile"])
&& isset($_SESSION["glpiactiveprofile"]['id']);
$has_active_entity = isset($_SESSION["glpiactiveentities"])
&& count($_SESSION["glpiactiveentities"]);
$where = [];
$join = [
'glpi_knowbaseitems_users' => [
'ON' => [
'glpi_knowbaseitems_users' => 'knowbaseitems_id',
'glpi_knowbaseitems' => 'id'
]
]
];
if ($forceall || $has_session_groups) {
$join['glpi_groups_knowbaseitems'] = [
'ON' => [
'glpi_groups_knowbaseitems' => 'knowbaseitems_id',
'glpi_knowbaseitems' => 'id'
]
];
}
if ($forceall || $has_active_profile) {
$join['glpi_knowbaseitems_profiles'] = [
'ON' => [
'glpi_knowbaseitems_profiles' => 'knowbaseitems_id',
'glpi_knowbaseitems' => 'id'
]
];
}
if ($forceall || $has_active_entity || $is_public_faq_context) {
$join['glpi_entities_knowbaseitems'] = [
'ON' => [
'glpi_entities_knowbaseitems' => 'knowbaseitems_id',
'glpi_knowbaseitems' => 'id'
]
];
}
if (Session::haveRight(self::$rightname, self::KNOWBASEADMIN)) {
return [
'LEFT JOIN' => $join,
'WHERE' => [],
];
}
// Users
if (Session::getLoginUserID()) {
$where['OR'] = [
'glpi_knowbaseitems.users_id' => Session::getLoginUserID(),
'glpi_knowbaseitems_users.users_id' => Session::getLoginUserID(),
];
// public faq
if (!Session::haveRight(self::$rightname, READ)) {
$where['AND']['glpi_knowbaseitems.is_faq'] = 1;
}
} else if ($is_public_faq_context) {
$where = [
"glpi_knowbaseitems.is_faq" => 1,
];
if (Session::isMultiEntitiesMode()) {
$where += [
"glpi_entities_knowbaseitems.entities_id" => 0,
"glpi_entities_knowbaseitems.is_recursive" => 1,
];
}
} else {
$where = [
0
];
}
// Groups
if ($forceall || $has_session_groups) {
if (Session::getLoginUserID()) {
$restrict = getEntitiesRestrictCriteria('glpi_groups_knowbaseitems', '', '', true, true);
$where['OR'][] = [
'glpi_groups_knowbaseitems.groups_id' => count($_SESSION["glpigroups"])
? $_SESSION["glpigroups"]
: [-1],
'OR' => [
'glpi_groups_knowbaseitems.entities_id' => ['<', '0'],
] + $restrict
];
}
}
// Profiles
if ($forceall || $has_active_profile) {
if (Session::getLoginUserID()) {
$where['OR'][] = [
'glpi_knowbaseitems_profiles.profiles_id' => $_SESSION["glpiactiveprofile"]['id'],
'OR' => [
'glpi_knowbaseitems_profiles.entities_id' => ['<', '0'],
getEntitiesRestrictCriteria('glpi_knowbaseitems_profiles', '', '', true, true)
]
];
}
}
// Entities
if ($forceall || $has_active_entity) {
if (Session::getLoginUserID()) {
$restrict = getEntitiesRestrictCriteria('glpi_entities_knowbaseitems', '', '', true, true);
if (count($restrict)) {
$where['OR'] = $where['OR'] + $restrict;
} else {
$where['glpi_entities_knowbaseitems.entities_id'] = null;
}
}
}
$criteria = ['LEFT JOIN' => $join];
if (count($where)) {
$criteria['WHERE'] = $where;
}
return $criteria;
}
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;
}
function prepareInputForUpdate($input) {
// set title for question if empty
if (isset($input["name"]) && empty($input["name"])) {
$input["name"] = __('New item');
}
return $input;
}
function post_updateItem($history = 1) {
// Update screenshots
$this->input = $this->addFiles(
$this->input,
[
'force_update' => true,
'content_field' => 'answer',
'name' => 'answer',
]
);
// add uploaded documents
$this->input = $this->addFiles(
$this->input,
[
'force_update' => true,
]
);
}
/**
* Print out an HTML "