205 lines
6.6 KiB
PHP
205 lines
6.6 KiB
PHP
<?php
|
|
/**
|
|
* ---------------------------------------------------------------------
|
|
* GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2015-2020 Teclib' and contributors.
|
|
*
|
|
* http://glpi-project.org
|
|
*
|
|
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
|
*
|
|
* ---------------------------------------------------------------------
|
|
*
|
|
* LICENSE
|
|
*
|
|
* This file is part of GLPI.
|
|
*
|
|
* GLPI 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GLPI 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 GLPI. If not, see <http://www.gnu.org/licenses/>.
|
|
* ---------------------------------------------------------------------
|
|
*/
|
|
|
|
if (!defined('GLPI_ROOT')) {
|
|
die("Sorry. You can't access this file directly");
|
|
}
|
|
|
|
/// Class CommonImplicitTreeDropdown : Manage implicit tree, ie., trees that cannot be manage by
|
|
/// the user. For instance, Network hierarchy only depends on network addresses and netmasks.
|
|
/// @since 0.84
|
|
class CommonImplicitTreeDropdown extends CommonTreeDropdown {
|
|
|
|
public $can_be_translated = true;
|
|
|
|
|
|
|
|
function getForbiddenStandardMassiveAction() {
|
|
|
|
$forbidden = parent::getForbiddenStandardMassiveAction();
|
|
$forbidden[] = 'CommonTreeDropdown'.MassiveAction::CLASS_ACTION_SEPARATOR.'move_under';
|
|
return $forbidden;
|
|
}
|
|
|
|
|
|
/**
|
|
* Method that must be overloaded. This method provides the ancestor of the current item
|
|
* according to $this->input
|
|
*
|
|
* @return integer the id of the current object ancestor
|
|
**/
|
|
function getNewAncestor() {
|
|
return 0; // By default, we rattach to the root element
|
|
}
|
|
|
|
|
|
/**
|
|
* Method that must be overloaded. This method provides the list of all potential sons of the
|
|
* current item according to $this->fields.
|
|
*
|
|
* @return array of IDs of the potential sons
|
|
**/
|
|
function getPotentialSons() {
|
|
return []; // By default, we don't have any son
|
|
}
|
|
|
|
function prepareInputForAdd($input) {
|
|
|
|
$input[$this->getForeignKeyField()] = $this->getNewAncestor();
|
|
// We call the parent to manage tree
|
|
return parent::prepareInputForAdd($input);
|
|
}
|
|
|
|
function prepareInputForUpdate($input) {
|
|
|
|
$input[$this->getForeignKeyField()] = $this->getNewAncestor();
|
|
// We call the parent to manage tree
|
|
return parent::prepareInputForUpdate($input);
|
|
}
|
|
|
|
function post_addItem() {
|
|
|
|
$this->alterElementInsideTree("add");
|
|
parent::post_addItem();
|
|
}
|
|
|
|
function post_updateItem($history = 1) {
|
|
|
|
$this->alterElementInsideTree("update");
|
|
parent::post_updateItem($history);
|
|
}
|
|
|
|
function pre_deleteItem() {
|
|
|
|
$this->alterElementInsideTree("delete");
|
|
return parent::pre_deleteItem();
|
|
}
|
|
|
|
|
|
/**
|
|
* The haveChildren=false must be define to be sure that CommonDropdown allows the deletion of a
|
|
* node of the tree
|
|
**/
|
|
function haveChildren() {
|
|
return false;
|
|
}
|
|
|
|
|
|
// Key function to manage the children of the node
|
|
private function alterElementInsideTree($step) {
|
|
global $DB;
|
|
|
|
switch ($step) {
|
|
case 'add' :
|
|
$newParent = $this->input[$this->getForeignKeyField()];
|
|
$potentialSons = $this->getPotentialSons();
|
|
break;
|
|
|
|
case 'update' :
|
|
$oldParent = $this->fields[$this->getForeignKeyField()];
|
|
$newParent = $this->input[$this->getForeignKeyField()];
|
|
$potentialSons = $this->getPotentialSons();
|
|
break;
|
|
|
|
case 'delete' :
|
|
$oldParent = $this->fields[$this->getForeignKeyField()];
|
|
$potentialSons = []; // Because there is no future sons !
|
|
break;
|
|
}
|
|
|
|
/** Here :
|
|
* $oldParent contains the old parent, to check its sons to attach them to it
|
|
* $newParent contains the new parent, to check its sons to potentially attach them to this
|
|
* item.
|
|
* $potentialSons list ALL potential childrens (sons as well as grandsons). That is use to
|
|
* update them. (See getPotentialSons())
|
|
**/
|
|
|
|
if ($step != "add" && count($potentialSons)) { // Because there is no old sons of new node
|
|
// First, get all my current direct sons (old ones) that are not new potential sons
|
|
$iterator = $DB->request([
|
|
'SELECT' => ['id'],
|
|
'FROM' => $this->getTable(),
|
|
'WHERE' => [
|
|
$this->getForeignKeyField() => $this->getID(),
|
|
'NOT' => ['id' => $potentialSons]
|
|
]
|
|
]);
|
|
$oldSons = [];
|
|
while ($oldSon = $iterator->next()) {
|
|
$oldSons[] = $oldSon["id"];
|
|
}
|
|
if (count($oldSons) > 0) { // Then make them pointing to old parent
|
|
$DB->update(
|
|
$this->getTable(), [
|
|
$this->getForeignKeyField() => $oldParent
|
|
], [
|
|
'id' => $oldSons
|
|
]
|
|
);
|
|
// Then, regenerate the old sons to reflect there new ancestors
|
|
$this->regenerateTreeUnderID($oldParent, true, true);
|
|
$this->cleanParentsSons($oldParent);
|
|
}
|
|
}
|
|
|
|
if ($step != "delete" && count($potentialSons)) { // Because ther is no new sons for deleted nodes
|
|
// And, get all direct sons of my new Father that must be attached to me (ie : that are
|
|
// potential sons
|
|
$iterator = $DB->request([
|
|
'SELECT' => ['id'],
|
|
'FROM' => $this->getTable(),
|
|
'WHERE' => [
|
|
$this->getForeignKeyField() => $newParent,
|
|
'id' => $potentialSons
|
|
]
|
|
]);
|
|
$newSons = [];
|
|
while ($newSon = $iterator->next()) {
|
|
$newSons[] = $newSon["id"];
|
|
}
|
|
if (count($newSons) > 0) { // Then make them pointing to me
|
|
$DB->update(
|
|
$this->getTable(), [
|
|
$this->getForeignKeyField() => $this->getID()
|
|
], [
|
|
'id' => $newSons
|
|
]
|
|
);
|
|
// Then, regenerate the new sons to reflect there new ancestors
|
|
$this->regenerateTreeUnderID($this->getID(), true, true);
|
|
$this->cleanParentsSons();
|
|
}
|
|
}
|
|
}
|
|
}
|