summaryrefslogtreecommitdiffstats
path: root/library/Icinga/File/Ini/Dom
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/File/Ini/Dom')
-rw-r--r--library/Icinga/File/Ini/Dom/Comment.php37
-rw-r--r--library/Icinga/File/Ini/Dom/Directive.php166
-rw-r--r--library/Icinga/File/Ini/Dom/Document.php132
-rw-r--r--library/Icinga/File/Ini/Dom/Section.php190
4 files changed, 525 insertions, 0 deletions
diff --git a/library/Icinga/File/Ini/Dom/Comment.php b/library/Icinga/File/Ini/Dom/Comment.php
new file mode 100644
index 0000000..c202d0f
--- /dev/null
+++ b/library/Icinga/File/Ini/Dom/Comment.php
@@ -0,0 +1,37 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\File\Ini\Dom;
+
+/**
+ * A single comment-line in an INI file
+ */
+class Comment
+{
+ /**
+ * The comment text
+ *
+ * @var string
+ */
+ protected $content;
+
+ /**
+ * Set the text content of this comment
+ *
+ * @param $content
+ */
+ public function setContent($content)
+ {
+ $this->content = $content;
+ }
+
+ /**
+ * Render this comment into INI markup
+ *
+ * @return string
+ */
+ public function render()
+ {
+ return ';' . $this->content;
+ }
+}
diff --git a/library/Icinga/File/Ini/Dom/Directive.php b/library/Icinga/File/Ini/Dom/Directive.php
new file mode 100644
index 0000000..4279a5f
--- /dev/null
+++ b/library/Icinga/File/Ini/Dom/Directive.php
@@ -0,0 +1,166 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\File\Ini\Dom;
+
+use Icinga\Exception\ConfigurationError;
+
+/**
+ * A key value pair in a Section
+ */
+class Directive
+{
+ /**
+ * The value of this configuration directive
+ *
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * The immutable name of this configuration directive
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * Comments added one line before this directive
+ *
+ * @var Comment[] The comment lines
+ */
+ protected $commentsPre = null;
+
+ /**
+ * Comment added at the end of the same line
+ *
+ * @var Comment
+ */
+ protected $commentPost = null;
+
+ /**
+ * @param string $key The name of this configuration directive
+ *
+ * @throws ConfigurationError
+ */
+ public function __construct($key)
+ {
+ $this->key = trim($key);
+ if (strlen($this->key) < 1) {
+ throw new ConfigurationError(sprintf('Ini error: empty directive key.'));
+ }
+ }
+
+ /**
+ * Return the name of this directive
+ *
+ * @return string
+ */
+ public function getKey()
+ {
+ return $this->key;
+ }
+
+ /**
+ * Return the value of this configuration directive
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Set the value of this configuration directive
+ *
+ * @param string $value
+ */
+ public function setValue($value)
+ {
+ $this->value = trim($value);
+ }
+
+ /**
+ * Set the comments to be rendered on the line before this directive
+ *
+ * @param Comment[] $comments
+ */
+ public function setCommentsPre(array $comments)
+ {
+ $this->commentsPre = $comments;
+ }
+
+ /**
+ * Return the comments to be rendered on the line before this directive
+ *
+ * @return Comment[]
+ */
+ public function getCommentsPre()
+ {
+ return $this->commentsPre;
+ }
+
+ /**
+ * Set the comment rendered on the same line of this directive
+ *
+ * @param Comment $comment
+ */
+ public function setCommentPost(Comment $comment)
+ {
+ $this->commentPost = $comment;
+ }
+
+ /**
+ * Render this configuration directive into INI markup
+ *
+ * @return string
+ */
+ public function render()
+ {
+ $str = '';
+ if (! empty($this->commentsPre)) {
+ $comments = array();
+ foreach ($this->commentsPre as $comment) {
+ $comments[] = $comment->render();
+ }
+ $str = implode(PHP_EOL, $comments) . PHP_EOL;
+ }
+ $str .= sprintf('%s = "%s"', $this->sanitizeKey($this->key), $this->sanitizeValue($this->value));
+ if (isset($this->commentPost)) {
+ $str .= ' ' . $this->commentPost->render();
+ }
+ return $str;
+ }
+
+ /**
+ * Assure that the given identifier contains no newlines and pending or trailing whitespaces
+ *
+ * @param $str The string to sanitize
+ *
+ * @return string
+ */
+ protected function sanitizeKey($str)
+ {
+ return trim(str_replace(PHP_EOL, ' ', $str));
+ }
+
+ /**
+ * Escape the significant characters in directive values, normalize line breaks and assure that
+ * the character contains no linebreaks
+ *
+ * @param $str The string to sanitize
+ *
+ * @return mixed|string
+ */
+ protected function sanitizeValue($str)
+ {
+ $str = trim($str);
+ $str = str_replace('\\', '\\\\', $str);
+ $str = str_replace('"', '\"', $str);
+ $str = str_replace("\r", '\r', $str);
+ $str = str_replace("\n", '\n', $str);
+
+ return $str;
+ }
+}
diff --git a/library/Icinga/File/Ini/Dom/Document.php b/library/Icinga/File/Ini/Dom/Document.php
new file mode 100644
index 0000000..f38f33e
--- /dev/null
+++ b/library/Icinga/File/Ini/Dom/Document.php
@@ -0,0 +1,132 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\File\Ini\Dom;
+
+class Document
+{
+ /**
+ * The sections of this INI file
+ *
+ * @var Section[]
+ */
+ protected $sections = array();
+
+ /**
+ * The comemnts at file end that belong to no particular section
+ *
+ * @var Comment[]
+ */
+ protected $commentsDangling;
+
+ /**
+ * Append a section to the end of this INI file
+ *
+ * @param Section $section
+ */
+ public function addSection(Section $section)
+ {
+ $this->sections[$section->getName()] = $section;
+ }
+
+ /**
+ * Return whether this INI file has the section with the given key
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function hasSection($name)
+ {
+ return isset($this->sections[trim($name)]);
+ }
+
+ /**
+ * Return the section with the given name
+ *
+ * @param string $name
+ *
+ * @return Section
+ */
+ public function getSection($name)
+ {
+ return $this->sections[trim($name)];
+ }
+
+ /**
+ * Set the section with the given name
+ *
+ * @param string $name
+ * @param Section $section
+ *
+ * @return Section
+ */
+ public function setSection($name, Section $section)
+ {
+ return $this->sections[trim($name)] = $section;
+ }
+
+ /**
+ * Remove the section with the given name
+ *
+ * @param string $name
+ */
+ public function removeSection($name)
+ {
+ unset($this->sections[trim($name)]);
+ }
+
+ /**
+ * Set the dangling comments at file end that belong to no particular directive
+ *
+ * @param Comment[] $comments
+ */
+ public function setCommentsDangling(array $comments)
+ {
+ $this->commentsDangling = $comments;
+ }
+
+ /**
+ * Get the dangling comments at file end that belong to no particular directive
+ *
+ * @return array
+ */
+ public function getCommentsDangling()
+ {
+ return $this->commentsDangling;
+ }
+
+ /**
+ * Render this document into the corresponding INI markup
+ *
+ * @return string
+ */
+ public function render()
+ {
+ $sections = array();
+ foreach ($this->sections as $section) {
+ $sections []= $section->render();
+ }
+ $str = implode(PHP_EOL, $sections);
+ if (! empty($this->commentsDangling)) {
+ foreach ($this->commentsDangling as $comment) {
+ $str .= PHP_EOL . $comment->render();
+ }
+ }
+ return $str;
+ }
+
+ /**
+ * Convert $this to an array
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $a = array();
+ foreach ($this->sections as $section) {
+ $a[$section->getName()] = $section->toArray();
+ }
+ return $a;
+ }
+}
diff --git a/library/Icinga/File/Ini/Dom/Section.php b/library/Icinga/File/Ini/Dom/Section.php
new file mode 100644
index 0000000..f877c87
--- /dev/null
+++ b/library/Icinga/File/Ini/Dom/Section.php
@@ -0,0 +1,190 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\File\Ini\Dom;
+
+use Icinga\Exception\ConfigurationError;
+
+/**
+ * A section in an INI file
+ */
+class Section
+{
+ /**
+ * The immutable name of this section
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * All configuration directives of this section
+ *
+ * @var Directive[]
+ */
+ protected $directives = array();
+
+ /**
+ * Comments added one line before this section
+ *
+ * @var Comment[]
+ */
+ protected $commentsPre;
+
+ /**
+ * Comment added at the end of the same line
+ *
+ * @var string
+ */
+ protected $commentPost;
+
+ /**
+ * @param string $name The immutable name of this section
+ *
+ * @throws ConfigurationError When the section name is empty or contains brackets
+ */
+ public function __construct($name)
+ {
+ $this->name = trim($name);
+ if (strlen($this->name) < 1) {
+ throw new ConfigurationError('Ini file error: empty section identifier');
+ } elseif (strpos($name, '[') !== false || strpos($name, ']') !== false) {
+ throw new ConfigurationError(
+ 'Ini file error: Section name "%s" must not contain any brackets ([, ])',
+ $name
+ );
+ }
+ }
+
+ /**
+ * Append a directive to the end of this section
+ *
+ * @param Directive $directive The directive to append
+ */
+ public function addDirective(Directive $directive)
+ {
+ $this->directives[$directive->getKey()] = $directive;
+ }
+
+ /**
+ * Remove the directive with the given name
+ *
+ * @param string $key They name of the directive to remove
+ */
+ public function removeDirective($key)
+ {
+ unset($this->directives[$key]);
+ }
+
+ /**
+ * Return whether this section has a directive with the given key
+ *
+ * @param string $key The name of the directive
+ *
+ * @return bool
+ */
+ public function hasDirective($key)
+ {
+ return isset($this->directives[$key]);
+ }
+
+ /**
+ * Get the directive with the given key
+ *
+ * @param $key string
+ *
+ * @return Directive
+ */
+ public function getDirective($key)
+ {
+ return $this->directives[$key];
+ }
+
+ /**
+ * Return the name of this section
+ *
+ * @return string The name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set the comments to be rendered on the line before this section
+ *
+ * @param Comment[] $comments
+ */
+ public function setCommentsPre(array $comments)
+ {
+ $this->commentsPre = $comments;
+ }
+
+ /**
+ * Set the comment rendered on the same line of this section
+ *
+ * @param Comment $comment
+ */
+ public function setCommentPost(Comment $comment)
+ {
+ $this->commentPost = $comment;
+ }
+
+ /**
+ * Render this section into INI markup
+ *
+ * @return string
+ */
+ public function render()
+ {
+ $dirs = '';
+ $i = 0;
+ foreach ($this->directives as $directive) {
+ $comments = $directive->getCommentsPre();
+ $dirs .= (($i++ > 0 && ! empty($comments)) ? PHP_EOL : '')
+ . $directive->render() . PHP_EOL;
+ }
+ $cms = '';
+ if (! empty($this->commentsPre)) {
+ foreach ($this->commentsPre as $comment) {
+ $comments[] = $comment->render();
+ }
+ $cms = implode(PHP_EOL, $comments) . PHP_EOL;
+ }
+ $post = '';
+ if (isset($this->commentPost)) {
+ $post = ' ' . $this->commentPost->render();
+ }
+ return $cms . sprintf('[%s]', $this->sanitize($this->name)) . $post . PHP_EOL . $dirs;
+ }
+
+ /**
+ * Escape the significant characters in sections and normalize line breaks
+ *
+ * @param $str The string to sanitize
+ *
+ * @return mixed
+ */
+ protected function sanitize($str)
+ {
+ $str = trim($str);
+ $str = str_replace('\\', '\\\\', $str);
+ $str = str_replace('"', '\\"', $str);
+ $str = str_replace(';', '\\;', $str);
+ return str_replace(PHP_EOL, ' ', $str);
+ }
+
+ /**
+ * Convert $this to an array
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $a = array();
+ foreach ($this->directives as $directive) {
+ $a[$directive->getKey()] = $directive->getValue();
+ }
+ return $a;
+ }
+}