raviks789 4f38557374 Prevent deletion of data lists that are in use.
Deletion of data lists which are used in icinga objects (through custom variables) or in sync rules is prevented.
2022-02-09 15:17:47 +01:00

222 lines
6.0 KiB
PHP

<?php
namespace Icinga\Module\Director\Objects;
use Exception;
use Icinga\Module\Director\Data\Db\DbObject;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\DuplicateKeyException;
class DirectorDatalist extends DbObject implements ExportInterface
{
protected $table = 'director_datalist';
protected $keyName = 'list_name';
protected $autoincKeyName = 'id';
protected $defaultProperties = array(
'id' => null,
'list_name' => null,
'owner' => null
);
/** @var DirectorDatalistEntry[] */
protected $storedEntries;
public function getUniqueIdentifier()
{
return $this->get('list_name');
}
/**
* @param $plain
* @param Db $db
* @param bool $replace
* @return static
* @throws \Icinga\Exception\NotFoundError
* @throws DuplicateKeyException
*/
public static function import($plain, Db $db, $replace = false)
{
$properties = (array) $plain;
if (isset($properties['originalId'])) {
unset($properties['originalId']);
} else {
$id = null;
}
$name = $properties['list_name'];
if ($replace && static::exists($name, $db)) {
$object = static::load($name, $db);
} elseif (static::exists($name, $db)) {
throw new DuplicateKeyException(
'Data List %s already exists',
$name
);
} else {
$object = static::create([], $db);
}
$object->setProperties($properties);
return $object;
}
public function setEntries($entries)
{
$existing = $this->getStoredEntries();
$new = [];
$seen = [];
$modified = false;
foreach ($entries as $entry) {
$name = $entry->entry_name;
$entry = DirectorDatalistEntry::create((array) $entry);
$seen[$name] = true;
if (isset($existing[$name])) {
$existing[$name]->replaceWith($entry);
if (! $modified && $existing[$name]->hasBeenModified()) {
$modified = true;
}
} else {
$modified = true;
$new[] = $entry;
}
}
foreach (array_keys($existing) as $key) {
if (! isset($seen[$key])) {
$existing[$key]->markForRemoval();
$modified = true;
}
}
foreach ($new as $entry) {
$existing[$entry->get('entry_name')] = $entry;
}
if ($modified) {
$this->hasBeenModified = true;
}
$this->storedEntries = $existing;
ksort($this->storedEntries);
return $this;
}
protected function beforeDelete()
{
if ($this->hasBeenUsed()) {
throw new Exception(
sprintf(
"Cannot delete '%s', as the datalist '%s' is currently being used.",
$this->get('list_name'),
$this->get('list_name')
)
);
}
}
protected function hasBeenUsed()
{
$datalistType = 'Icinga\\Module\\Director\\DataType\\DataTypeDatalist';
$db = $this->getDb();
$dataFieldsCheck = $db->select()
->from(['df' =>'director_datafield'], ['varname'])
->join(
['dfs' => 'director_datafield_setting'],
'dfs.datafield_id = df.id AND dfs.setting_name = \'datalist_id\'',
[]
)
->join(
['l' => 'director_datalist'],
'l.id = dfs.setting_value',
[]
)
->where('datatype = ?', $datalistType)
->where('setting_value = ?', $this->get('id'));
if ($db->fetchOne($dataFieldsCheck)) {
return true;
}
$syncCheck = $db->select()
->from(['sp' =>'sync_property'], ['source_expression'])
->where('sp.destination_field = ?', 'list_id')
->where('sp.source_expression = ?', $this->get('id'));
if ($db->fetchOne($syncCheck)) {
return true;
}
return false;
}
/**
* @throws DuplicateKeyException
*/
public function onStore()
{
if ($this->storedEntries) {
$db = $this->getConnection();
$removedKeys = [];
$myId = $this->get('id');
foreach ($this->storedEntries as $key => $entry) {
if ($entry->shouldBeRemoved()) {
$entry->delete();
$removedKeys[] = $key;
} else {
if (! $entry->hasBeenLoadedFromDb()) {
$entry->set('list_id', $myId);
}
$entry->set('list_id', $myId);
$entry->store($db);
}
}
foreach ($removedKeys as $key) {
unset($this->storedEntries[$key]);
}
}
}
public function export()
{
$plain = (object) $this->getProperties();
$plain->originalId = $plain->id;
unset($plain->id);
$plain->entries = [];
foreach ($this->getStoredEntries() as $key => $entry) {
if ($entry->shouldBeRemoved()) {
continue;
}
$plainEntry = (object) $entry->getProperties();
unset($plainEntry->list_id);
$plain->entries[] = $plainEntry;
}
return $plain;
}
protected function getStoredEntries()
{
if ($this->storedEntries === null) {
if ($id = $this->get('id')) {
$this->storedEntries = DirectorDatalistEntry::loadAllForList($this);
ksort($this->storedEntries);
} else {
$this->storedEntries = [];
}
}
return $this->storedEntries;
}
}