icingaweb2-module-director/library/Director/DirectorObject/Automation/BasketSnapshotFieldResolver...

225 lines
5.9 KiB
PHP

<?php
namespace Icinga\Module\Director\DirectorObject\Automation;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Objects\DirectorDatafield;
use Icinga\Module\Director\Objects\IcingaObject;
class BasketSnapshotFieldResolver
{
/** @var BasketSnapshot */
protected $snapshot;
/** @var \Icinga\Module\Director\Data\Db\DbConnection */
protected $targetDb;
/** @var array|null */
protected $requiredIds;
protected $objects;
/** @var int */
protected $nextNewId = 1;
/** @var array|null */
protected $idMap;
/** @var DirectorDatafield[]|null */
protected $targetFields;
public function __construct($objects, Db $targetDb)
{
$this->objects = $objects;
$this->targetDb = $targetDb;
}
/**
* @param Db $db
* @return DirectorDatafield[]
* @throws \Icinga\Exception\NotFoundError
*/
public function loadCurrentFields(Db $db)
{
$fields = [];
foreach ($this->getRequiredIds() as $id) {
$fields[$id] = DirectorDatafield::loadWithAutoIncId((int) $id, $db);
}
return $fields;
}
/**
* @throws \Icinga\Exception\NotFoundError
* @throws \Icinga\Module\Director\Exception\DuplicateKeyException
*/
public function storeNewFields()
{
foreach ($this->getTargetFields() as $id => $field) {
if ($field->hasBeenModified()) {
$field->store();
$this->idMap[$id] = $field->get('id');
}
}
}
/**
* @param IcingaObject $new
* @param $object
* @throws \Icinga\Exception\NotFoundError
* @throws \Zend_Db_Adapter_Exception
*/
public function relinkObjectFields(IcingaObject $new, $object)
{
if (! $new->supportsFields() || ! isset($object->fields)) {
return;
}
$fieldMap = $this->getIdMap();
$objectId = (int) $new->get('id');
$table = $new->getTableName() . '_field';
$objectKey = $new->getShortTableName() . '_id';
$existingFields = [];
$db = $this->targetDb->getDbAdapter();
foreach ($db->fetchAll(
$db->select()->from($table)->where("$objectKey = ?", $objectId)
) as $mapping) {
$existingFields[(int) $mapping->datafield_id] = $mapping;
}
foreach ($object->fields as $field) {
$id = $fieldMap[(int) $field->datafield_id];
if (isset($existingFields[$id])) {
unset($existingFields[$id]);
} else {
$db->insert($table, [
$objectKey => $objectId,
'datafield_id' => $id,
'is_required' => $field->is_required,
'var_filter' => $field->var_filter,
]);
}
}
if (! empty($existingFields)) {
$db->delete(
$table,
$db->quoteInto(
"$objectKey = $objectId AND datafield_id IN (?)",
array_keys($existingFields)
)
);
}
}
/**
* @param object $object
* @throws \Icinga\Exception\NotFoundError
*/
public function tweakTargetIds($object)
{
$forward = $this->getIdMap();
$map = array_flip($forward);
if (isset($object->fields)) {
foreach ($object->fields as $field) {
$id = $field->datafield_id;
if (isset($map[$id])) {
$field->datafield_id = $map[$id];
} else {
$field->datafield_id = "(NEW)";
}
}
}
}
/**
* @return int
*/
protected function getNextNewId()
{
return $this->nextNewId++;
}
protected function getRequiredIds()
{
if ($this->requiredIds === null) {
if (isset($this->objects['Datafield'])) {
$this->requiredIds = array_keys($this->objects['Datafield']);
} else {
$ids = [];
foreach ($this->objects as $typeName => $objects) {
foreach ($objects as $key => $object) {
if (isset($object->fields)) {
foreach ($object->fields as $field) {
$ids[$field->datafield_id] = true;
}
}
}
}
$this->requiredIds = array_keys($ids);
}
}
return $this->requiredIds;
}
/**
* @param $type
* @return object[]
*/
protected function getObjectsByType($type)
{
if (isset($this->objects->$type)) {
return $this->objects->$type;
} else {
return [];
}
}
/**
* @return DirectorDatafield[]
* @throws \Icinga\Exception\NotFoundError
*/
protected function getTargetFields()
{
if ($this->targetFields === null) {
$this->calculateIdMap();
}
return $this->targetFields;
}
/**
* @throws \Icinga\Exception\NotFoundError
*/
protected function getIdMap()
{
if ($this->idMap === null) {
$this->calculateIdMap();
}
return $this->idMap;
}
/**
* @throws \Icinga\Exception\NotFoundError
*/
protected function calculateIdMap()
{
$this->idMap = [];
$this->targetFields = [];
foreach ($this->getObjectsByType('Datafield') as $id => $object) {
// Hint: import() doesn't store!
$new = DirectorDatafield::import($object, $this->targetDb);
if ($new->hasBeenLoadedFromDb()) {
$newId = (int) $new->get('id');
} else {
$newId = sprintf('NEW(%s)', $this->getNextNewId());
}
$this->idMap[$id] = $newId;
$this->targetFields[$id] = $new;
}
}
}