From 8ca6cc32b2c789a3149861159ad258f2cb9491e3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 14:39:39 +0200 Subject: Adding upstream version 2.11.4. Signed-off-by: Daniel Baumann --- library/Icinga/File/Ini/IniWriter.php | 205 ++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 library/Icinga/File/Ini/IniWriter.php (limited to 'library/Icinga/File/Ini/IniWriter.php') diff --git a/library/Icinga/File/Ini/IniWriter.php b/library/Icinga/File/Ini/IniWriter.php new file mode 100644 index 0000000..f00040e --- /dev/null +++ b/library/Icinga/File/Ini/IniWriter.php @@ -0,0 +1,205 @@ +config = $config; + $this->filename = $filename; + $this->fileMode = $filemode; + $this->options = $options; + } + + /** + * Render the Zend_Config into a config filestring + * + * @return string + */ + public function render() + { + if (file_exists($this->filename)) { + $oldconfig = Config::fromIni($this->filename); + $content = trim(file_get_contents($this->filename)); + } else { + $oldconfig = Config::fromArray(array()); + $content = ''; + } + $doc = IniParser::parseIni($content); + $this->diffPropertyUpdates($this->config, $doc); + $this->diffPropertyDeletions($oldconfig, $this->config, $doc); + $doc = $this->updateSectionOrder($this->config, $doc); + return $doc->render(); + } + + /** + * Write configuration to file and set file mode in case it does not exist yet + * + * @param string $filename + * @param bool $exclusiveLock + * + * @throws Zend_Config_Exception + */ + public function write($filename = null, $exclusiveLock = false) + { + $filePath = isset($filename) ? $filename : $this->filename; + $setMode = false === file_exists($filePath); + + if (file_put_contents($filePath, $this->render(), $exclusiveLock ? LOCK_EX : 0) === false) { + throw new Zend_Config_Exception('Could not write to file "' . $filePath . '"'); + } + + if ($setMode) { + // file was newly created + $mode = $this->fileMode; + if (is_int($this->fileMode) && false === @chmod($filePath, $this->fileMode)) { + throw new Zend_Config_Exception(sprintf('Failed to set file mode "%o" on file "%s"', $mode, $filePath)); + } + } + } + + /** + * Update the order of the sections in the ini file to match the order of the new config + * + * @return Document A new document with the changed section order applied + */ + protected function updateSectionOrder(Config $newconfig, Document $oldDoc) + { + $doc = new Document(); + $dangling = $oldDoc->getCommentsDangling(); + if (isset($dangling)) { + $doc->setCommentsDangling($dangling); + } + foreach ($newconfig->toArray() as $section => $directives) { + $doc->addSection($oldDoc->getSection($section)); + } + return $doc; + } + + /** + * Search for created and updated properties and use the editor to create or update these entries + * + * @param Config $newconfig The config representing the state after the change + * @param Document $doc + * + * @throws ProgrammingError + */ + protected function diffPropertyUpdates(Config $newconfig, Document $doc) + { + foreach ($newconfig->toArray() as $section => $directives) { + if (! is_array($directives)) { + Logger::warning('Section-less property ' . (string)$directives . ' was ignored.'); + continue; + } + if (!$doc->hasSection($section)) { + $domSection = new Section($section); + $doc->addSection($domSection); + } else { + $domSection = $doc->getSection($section); + } + foreach ($directives as $key => $value) { + if ($value === null) { + continue; + } + + if ($value instanceof ConfigObject) { + throw new ProgrammingError('Cannot diff recursive configs'); + } + if ($domSection->hasDirective($key)) { + $domSection->getDirective($key)->setValue($value); + } else { + $dir = new Directive($key); + $dir->setValue($value); + $domSection->addDirective($dir); + } + } + } + } + + /** + * Search for deleted properties and use the editor to delete these entries + * + * @param Config $oldconfig The config representing the state before the change + * @param Config $newconfig The config representing the state after the change + * @param Document $doc + * + * @throws ProgrammingError + */ + protected function diffPropertyDeletions(Config $oldconfig, Config $newconfig, Document $doc) + { + // Iterate over all properties in the old configuration file and remove those that don't + // exist in the new config + foreach ($oldconfig->toArray() as $section => $directives) { + if (! is_array($directives)) { + Logger::warning('Section-less property ' . (string)$directives . ' was ignored.'); + continue; + } + + if ($newconfig->hasSection($section)) { + $newSection = $newconfig->getSection($section); + $oldDomSection = $doc->getSection($section); + foreach ($directives as $key => $value) { + if ($value instanceof ConfigObject) { + throw new ProgrammingError('Cannot diff recursive configs'); + } + if (null === $newSection->get($key) && $oldDomSection->hasDirective($key)) { + $oldDomSection->removeDirective($key); + } + } + } else { + $doc->removeSection($section); + } + } + } +} -- cgit v1.2.3