From f66ab8dae2f3d0418759f81a3a64dc9517a62449 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 14 Apr 2024 15:17:31 +0200 Subject: Adding upstream version 1.10.2. Signed-off-by: Daniel Baumann --- .../Director/DirectorObject/ObjectPurgeHelper.php | 149 +++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 library/Director/DirectorObject/ObjectPurgeHelper.php (limited to 'library/Director/DirectorObject/ObjectPurgeHelper.php') diff --git a/library/Director/DirectorObject/ObjectPurgeHelper.php b/library/Director/DirectorObject/ObjectPurgeHelper.php new file mode 100644 index 0000000..a043965 --- /dev/null +++ b/library/Director/DirectorObject/ObjectPurgeHelper.php @@ -0,0 +1,149 @@ +db = $db; + } + + public function force($force = true) + { + $this->force = $force; + return $this; + } + + public function purge(array $keep, $class, $objectType = null) + { + if (empty($keep) && ! $this->force) { + throw new InvalidArgumentException('I will NOT purge all object unless being forced to do so'); + } + $db = $this->db->getDbAdapter(); + /** @var IcingaObject $class cheating, it's a class name, not an object */ + $dummy = $class::create(); + assert($dummy instanceof IcingaObject); + $keyCols = (array) $dummy->getKeyName(); + if ($objectType !== null) { + $keyCols[] = 'object_type'; + } + + $keepKeys = []; + foreach ($keep as $object) { + if ($object instanceof \stdClass) { + $properties = (array) $object; + // TODO: this is object-specific and to be found in the ::import() function! + unset($properties['fields']); + $object = $class::fromPlainObject($properties); + } elseif (\get_class($object) !== $class) { + throw new InvalidArgumentException( + 'Can keep only matching objects, expected "%s", got "%s', + $class, + \get_class($keep) + ); + } + $key = []; + foreach ($keyCols as $col) { + $key[$col] = $object->get($col); + } + $keepKeys[$this->makeRowKey($key)] = true; + } + + $query = $db->select()->from(['o' => $dummy->getTableName()], $keyCols); + if ($objectType !== null) { + $query->where('object_type = ?', $objectType); + } + $allExisting = []; + foreach ($db->fetchAll($query) as $row) { + $allExisting[$this->makeRowKey($row)] = $row; + } + $remove = []; + foreach ($allExisting as $key => $keyProperties) { + if (! isset($keepKeys[$key])) { + $remove[] = $keyProperties; + } + } + $db->beginTransaction(); + foreach ($remove as $keyProperties) { + $keyColumn = $class::getKeyColumnName(); + if (is_array($keyColumn)) { + $object = $class::load((array) $keyProperties, $this->db); + } else { + $object = $class::load($keyProperties->$keyColumn, $this->db); + } + $object->delete(); + } + $db->commit(); + } + + public static function listObjectTypesAvailableForPurge() + { + return [ + 'Basket', + 'Command', + 'CommandTemplate', + 'Dependency', + 'DirectorJob', + 'ExternalCommand', + 'HostGroup', + 'HostTemplate', + 'IcingaTemplateChoiceHost', + 'IcingaTemplateChoiceService', + 'ImportSource', + 'Notification', + 'NotificationTemplate', + 'ServiceGroup', + 'ServiceSet', + 'ServiceTemplate', + 'SyncRule', + 'TimePeriod', + ]; + } + + public static function objectTypeIsEligibleForPurge($type) + { + return in_array($type, static::listObjectTypesAvailableForPurge(), true); + } + + public static function assertObjectTypesAreEligibleForPurge($types) + { + $invalid = []; + foreach ($types as $type) { + if (! static::objectTypeIsEligibleForPurge($type)) { + $invalid[] = $type; + } + } + + if (empty($invalid)) { + return; + } + + if (count($invalid) === 1) { + $message = sprintf('"%s" is not eligible for purge', $invalid[0]); + } else { + $message = 'The following types are not eligible for purge: ' + . implode(', ', $invalid); + } + + throw new InvalidArgumentException( + "$message. Valid types: " + . implode(', ', static::listObjectTypesAvailableForPurge()) + ); + } + + protected function makeRowKey($row) + { + $row = (array) $row; + ksort($row); + return json_encode($row, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } +} -- cgit v1.2.3