Sindbad~EG File Manager
<?php
/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2022 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\Plugin\Hooks;
/// Common DataBase Relation Table Manager Class
abstract class CommonDBChild extends CommonDBConnexity
{
// Mapping between DB fields
// * definition
public static $itemtype; // Class name or field name (start with itemtype) for link to Parent
public static $items_id; // Field name
// * rights
public static $checkParentRights = self::HAVE_SAME_RIGHT_ON_ITEM;
public static $mustBeAttached = true;
// * log
public static $logs_for_parent = true;
public static $log_history_add = Log::HISTORY_ADD_SUBITEM;
public static $log_history_update = Log::HISTORY_UPDATE_SUBITEM;
public static $log_history_delete = Log::HISTORY_DELETE_SUBITEM;
public static $log_history_lock = Log::HISTORY_LOCK_SUBITEM;
public static $log_history_unlock = Log::HISTORY_UNLOCK_SUBITEM;
/**
* Get request cirteria to search for an item
*
* @since 9.4
*
* @param string $itemtype Item type
* @param integer $items_id Item ID
*
* @return array|null
**/
public static function getSQLCriteriaToSearchForItem($itemtype, $items_id)
{
$criteria = [
'SELECT' => [
static::getIndexName(),
static::$items_id . ' AS items_id'
],
'FROM' => static::getTable(),
'WHERE' => [
static::$items_id => $items_id
]
];
// Check item 1 type
$request = false;
if (preg_match('/^itemtype/', static::$itemtype)) {
$criteria['SELECT'][] = static::$itemtype . ' AS itemtype';
$criteria['WHERE'][static::$itemtype] = $itemtype;
$request = true;
} else {
$criteria['SELECT'][] = new \QueryExpression("'" . static::$itemtype . "' AS itemtype");
if (
($itemtype == static::$itemtype)
|| is_subclass_of($itemtype, static::$itemtype)
) {
$request = true;
}
}
if ($request === true) {
return $criteria;
}
return null;
}
/**
* @since 0.84
**/
public static function canCreate()
{
if ((static::$rightname) && (!Session::haveRight(static::$rightname, CREATE))) {
return false;
}
return static::canChild('canUpdate');
}
/**
* @since 0.84
**/
public static function canView()
{
if ((static::$rightname) && (!Session::haveRight(static::$rightname, READ))) {
return false;
}
return static::canChild('canView');
}
/**
* @since 0.84
**/
public static function canUpdate()
{
if ((static::$rightname) && (!Session::haveRight(static::$rightname, UPDATE))) {
return false;
}
return static::canChild('canUpdate');
}
/**
* @since 0.84
**/
public static function canDelete()
{
if ((static::$rightname) && (!Session::haveRight(static::$rightname, DELETE))) {
return false;
}
return static::canChild('canUpdate');
}
/**
* @since 0.85
**/
public static function canPurge()
{
if ((static::$rightname) && (!Session::haveRight(static::$rightname, PURGE))) {
return false;
}
return static::canChild('canUpdate');
}
/**
* @since 0.84
**/
public function canCreateItem()
{
return $this->canChildItem('canUpdateItem', 'canUpdate');
}
/**
* @since 0.84
**/
public function canViewItem()
{
return $this->canChildItem('canViewItem', 'canView');
}
/**
* @since 0.84
**/
public function canUpdateItem()
{
return $this->canChildItem('canUpdateItem', 'canUpdate');
}
/**
* @since 0.84
**/
public function canDeleteItem()
{
return $this->canChildItem('canUpdateItem', 'canUpdate');
}
/**
* @since 0.84
*
* @param $method
**/
public static function canChild($method)
{
return static::canConnexity(
$method,
static::$checkParentRights,
static::$itemtype,
static::$items_id
);
}
/**
* @since 0.84
*
* @param $methodItem
* @param $methodNotItem
*
* @return boolean
**/
public function canChildItem($methodItem, $methodNotItem)
{
try {
return $this->canConnexityItem(
$methodItem,
$methodNotItem,
static::$checkParentRights,
static::$itemtype,
static::$items_id
);
} catch (CommonDBConnexityItemNotFound $e) {
return !static::$mustBeAttached;
}
}
/**
* Get the item associated with the current object. Rely on CommonDBConnexity::getItemFromArray()
*
* @since 0.84
*
* @param $getFromDB (true by default)
* @param $getEmpty (true by default)
*
* @return object of the concerned item or false on error
**/
public function getItem($getFromDB = true, $getEmpty = true)
{
return $this->getConnexityItem(
static::$itemtype,
static::$items_id,
$getFromDB,
$getEmpty
);
}
/**
* \brief recursively display the items of this
*
* @param array $recursiveItems items of the current elements (see recursivelyGetItems())
* @param string $elementToDisplay what to display : 'Type', 'Name', 'Link'
**/
public static function displayRecursiveItems(array $recursiveItems, $elementToDisplay)
{
if ((!is_array($recursiveItems)) || (count($recursiveItems) == 0)) {
echo __('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 = [];
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 0.84
*
* @return array
**/
public function recursivelyGetItems()
{
$item = $this->getItem();
if ($item !== false) {
if ($item instanceof CommonDBChild) {
return array_merge([$item], $item->recursivelyGetItems());
}
return [$item];
}
return [];
}
/**
* Get the ID of entity assigned to the object
*
* @return integer ID of the entity
**/
public 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;
}
public 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
**/
public 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 boolean
**/
public 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;
}
public 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;
}
public 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);
}
public function prepareInputForUpdate($input)
{
if (!is_array($input)) {
return false;
}
// True if item changed
if (
!$this->checkAttachedItemChangesAllowed($input, [static::$itemtype,
static::$items_id
])
) {
return false;
}
return parent::addNeededInfoToInput($input);
}
/**
* Get the history name of item
*
* @param CommonDBTM $item the other item
* @param string $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)
**/
public function getHistoryNameForItem(CommonDBTM $item, $case)
{
return $this->getNameID(['forceid' => true,
'additional' => true
]);
}
/**
* Actions done after the ADD of the item in the database
*
* @return void
**/
public function post_addItem()
{
$item = $this->getItem();
if ($item === false) {
return;
}
if (
$item->dohistory
&& !(isset($this->input['_no_history']) && $this->input['_no_history'])
&& static::$logs_for_parent
) {
$changes = [
'0',
'',
$this->getHistoryNameForItem($item, 'add'),
];
Log::history(
$item->getID(),
$item->getType(),
$changes,
$this->getType(),
static::$log_history_add
);
}
parent::post_addItem();
}
/**
* Actions done after the UPDATE of the item in the database
*
* @since 0.84
*
* @param integer|boolean $history store changes history ?
*
* @return void
**/
public function post_updateItem($history = 1)
{
if (
!((isset($this->input['_no_history']) && $this->input['_no_history']))
&& static::$logs_for_parent
) {
$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 (array_keys($oldvalues) as $field) {
if (in_array($field, $this->getNonLoggedFields())) {
continue;
}
$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
);
}
}
}
parent::post_updateItem($history);
}
/**
* Actions done after the DELETE of the item in the database
*
* @return void
**/
public 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',
];
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 0.84
*
* @return void
**/
public 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',
addslashes($this->getHistoryNameForItem($item, 'lock')),
'',
];
Log::history(
$item->getID(),
$item->getType(),
$changes,
$this->getType(),
static::$log_history_lock
);
}
}
}
/**
* Actions done after the restore of the item
*
* @since 0.84
*
* @return void
**/
public 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',
'',
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 0.84
*
* @see showAddChildButtonForItemForm()
*
* @param string $field_name the name of the HTML field inside Item's form
* @param string $child_count_js_var the name of the javascript variable containing current child
* number of items
*
* @return string
**/
public static function getJSCodeToAddForItemChild($field_name, $child_count_js_var)
{
return "<input type=\'text\' size=\'40\' " . "name=\'" . $field_name .
"[-'+$child_count_js_var+']\'>";
}
/**
* display the field of a given child
*
* @since 0.84
*
* @see showChildsForItemForm()
*
* @param boolean $canedit true if we can edit the child
* @param string $field_name the name of the HTML field inside Item's form
* @param integer $id id of the child
*
* @return void
**/
public function showChildForItemForm($canedit, $field_name, $id)
{
if ($this->isNewID($this->getID())) {
$value = '';
} else {
$value = $this->getName();
}
$field_name = $field_name . "[$id]";
if ($canedit) {
echo "<input type='text' size='40' name='$field_name' value='$value' class='form-select'>";
} else {
echo "<input type='hidden' name='$field_name' value='$value'>$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 0.84
*
* @todo study if we cannot use these methods for the user emails
* @see showChildsForItemForm(CommonDBTM $item, $field_name)
*
* @param CommonDBTM $item the item on which to add the current CommenDBChild
* @param string $field_name the name of the HTML field inside Item's form
* @param boolean|null $canedit boolean to force rights, NULL to use default behaviour
* @param boolean $display true display or false to return the button HTML code
*
*
* @return void|string the button HTML code if $display is true, void otherwise
**/
public static function showAddChildButtonForItemForm(
CommonDBTM $item,
$field_name,
$canedit = null,
$display = true
) {
$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 = " <script type='text/javascript'>var $child_count_js_var=2; </script>";
$result .= "<span id='add" . $lower_name . "button' class='fa fa-plus pointer'" .
" title=\"" . __s('Add') . "\"" .
"\" onClick=\"var row = " . Html::jsGetElementByID($div_id) . ";
row.append('<br>" .
static::getJSCodeToAddForItemChild($field_name, $child_count_js_var) . "');
$child_count_js_var++;\"
><span class='sr-only'>" . __s('Add') . "</span></span>";
}
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 0.84
*
* @todo study if we cannot use these methods for the user emails
* @see showAddChildButtonForItemForm()
*
* @param CommonDBTM $item the item on which to add the current CommenDBChild
* @param string $field_name the name of the HTML field inside Item's form
* @param boolean|null $canedit boolean to force rights, NULL to use default behaviour
*
* @return void|boolean (display) Returns false if there is a rights error.
**/
public static function showChildsForItemForm(CommonDBTM $item, $field_name, $canedit = null)
{
global $DB;
$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 = [
'FROM' => static::getTable(),
'WHERE' => [
static::$items_id => $item->getID()
]
];
if (preg_match('/^itemtype/', static::$itemtype)) {
$query['WHERE']['itemtype'] = $item->getType();
}
$current_item = new static();
if ($current_item->maybeDeleted()) {
$query['WHERE']['is_deleted'] = 0;
}
$iterator = $DB->request($query);
$count = 0;
foreach ($iterator as $data) {
$current_item->fields = $data;
if ($count) {
echo '<br>';
}
$count++;
$current_item->showChildForItemForm($canedit, $field_name, $current_item->getID());
}
if ($canedit) {
echo "<div id='$div_id'>";
// No Child display field
if ($count == 0) {
$current_item->getEmpty();
$current_item->showChildForItemForm($canedit, $field_name, -1);
}
echo "</div>";
}
}
/**
* 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
**/
public function affectChild($id, $items_id = 0, $itemtype = '')
{
$input = [static::getIndexName() => $id,
static::$items_id => $items_id
];
if (preg_match('/^itemtype/', static::$itemtype)) {
$input[static::$itemtype] = $itemtype;
}
return $this->update($input);
}
final public static function getItemField($itemtype): string
{
if (is_subclass_of($itemtype, 'Rule')) {
$itemtype = 'Rule';
}
if (isset(static::$items_id) && getItemtypeForForeignKeyField(static::$items_id) == $itemtype) {
return static::$items_id;
}
if (isset(static::$itemtype) && preg_match('/^itemtype/', static::$itemtype)) {
return static::$items_id;
}
throw new \RuntimeException('Cannot guess field for itemtype ' . $itemtype . ' on ' . static::class);
}
protected function autoinventoryInformation()
{
echo "<td>" . __('Automatic inventory') . "</td>";
echo "<td>";
if ($this->fields['id'] && $this->fields['is_dynamic']) {
ob_start();
Plugin::doHook(Hooks::AUTOINVENTORY_INFORMATION, $this);
$info = ob_get_clean();
if (empty($info)) {
$info = __('Yes');
}
echo $info;
} else {
echo __('No');
}
echo "</td>";
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists