summaryrefslogtreecommitdiffstats
path: root/library/Director/Web/Table/Dependency
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:43:12 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:43:12 +0000
commitcd989f9c3aff968e19a3aeabc4eb9085787a6673 (patch)
treefbff2135e7013f196b891bbde54618eb050e4aaf /library/Director/Web/Table/Dependency
parentInitial commit. (diff)
downloadicingaweb2-module-director-upstream.tar.xz
icingaweb2-module-director-upstream.zip
Adding upstream version 1.10.2.upstream/1.10.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/Director/Web/Table/Dependency')
-rw-r--r--library/Director/Web/Table/Dependency/DependencyInfoTable.php101
-rw-r--r--library/Director/Web/Table/Dependency/Html.php74
2 files changed, 175 insertions, 0 deletions
diff --git a/library/Director/Web/Table/Dependency/DependencyInfoTable.php b/library/Director/Web/Table/Dependency/DependencyInfoTable.php
new file mode 100644
index 0000000..28aa856
--- /dev/null
+++ b/library/Director/Web/Table/Dependency/DependencyInfoTable.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Icinga\Module\Director\Web\Table\Dependency;
+
+use Icinga\Application\Modules\Module;
+use Icinga\Module\Director\Application\DependencyChecker;
+use Icinga\Web\Url;
+
+class DependencyInfoTable
+{
+ protected $module;
+
+ protected $checker;
+
+ public function __construct(DependencyChecker $checker, Module $module)
+ {
+ $this->module = $module;
+ $this->checker = $checker;
+ }
+
+ protected function linkToModule($name, $icon)
+ {
+ return Html::link(
+ Html::escape($name),
+ Html::webUrl('config/module', ['name' => $name]),
+ [
+ 'class' => "icon-$icon"
+ ]
+ );
+ }
+
+ public function render()
+ {
+ $html = '<table class="common-table table-row-selectable">
+<thead>
+<tr>
+ <th>' . Html::escape($this->translate('Module name')) . '</th>
+ <th>' . Html::escape($this->translate('Required')) . '</th>
+ <th>' . Html::escape($this->translate('Installed')) . '</th>
+</tr>
+</thead>
+<tbody data-base-target="_next">
+';
+ foreach ($this->checker->getDependencies($this->module) as $dependency) {
+ $name = $dependency->getName();
+ $isLibrary = substr($name, 0, 11) === 'icinga-php-';
+ $rowAttributes = $isLibrary ? ['data-base-target' => '_self'] : null;
+ if ($dependency->isSatisfied()) {
+ if ($dependency->isSatisfied()) {
+ $icon = 'ok';
+ } else {
+ $icon = 'cancel';
+ }
+ $link = $isLibrary ? $this->noLink($name, $icon) : $this->linkToModule($name, $icon);
+ $installed = $dependency->getInstalledVersion();
+ } elseif ($dependency->isInstalled()) {
+ $installed = sprintf('%s (%s)', $dependency->getInstalledVersion(), $this->translate('disabled'));
+ $link = $this->linkToModule($name, 'cancel');
+ } else {
+ $installed = $this->translate('missing');
+ $repository = $isLibrary ? $name : "icingaweb2-module-$name";
+ $link = sprintf(
+ '%s (%s)',
+ $this->noLink($name, 'cancel'),
+ Html::linkToGitHub(Html::escape($this->translate('more')), 'Icinga', $repository)
+ );
+ }
+
+ $html .= $this->htmlRow([
+ $link,
+ Html::escape($dependency->getRequirement()),
+ Html::escape($installed)
+ ], $rowAttributes);
+ }
+
+ return $html . '</tbody>
+</table>
+';
+ }
+
+ protected function noLink($label, $icon)
+ {
+ return Html::link(Html::escape($label), Url::fromRequest()->with('rnd', rand(1, 100000)), [
+ 'class' => "icon-$icon"
+ ]);
+ }
+
+ protected function translate($string)
+ {
+ return \mt('director', $string);
+ }
+
+ protected function htmlRow(array $cols, $rowAttributes)
+ {
+ $content = '';
+ foreach ($cols as $escapedContent) {
+ $content .= Html::tag('td', null, $escapedContent);
+ }
+ return Html::tag('tr', $rowAttributes, $content);
+ }
+}
diff --git a/library/Director/Web/Table/Dependency/Html.php b/library/Director/Web/Table/Dependency/Html.php
new file mode 100644
index 0000000..092f799
--- /dev/null
+++ b/library/Director/Web/Table/Dependency/Html.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Icinga\Module\Director\Web\Table\Dependency;
+
+use Icinga\Web\Url;
+use InvalidArgumentException;
+
+/**
+ * Minimal HTML helper, as we might be forced to run without ipl
+ */
+class Html
+{
+ public static function tag($tag, $attributes = [], $escapedContent = null)
+ {
+ $result = "<$tag";
+ if (! empty($attributes)) {
+ foreach ($attributes as $name => $value) {
+ if (! preg_match('/^[a-z][a-z0-9:-]*$/i', $name)) {
+ throw new InvalidArgumentException("Invalid attribute name: '$name'");
+ }
+
+ $result .= " $name=\"" . self::escapeAttributeValue($value) . '"';
+ }
+ }
+
+ return "$result>$escapedContent</$tag>";
+ }
+
+ public static function webUrl($path, $params)
+ {
+ return Url::fromPath($path, $params);
+ }
+
+ public static function link($escapedLabel, $url, $attributes = [])
+ {
+ return static::tag('a', [
+ 'href' => $url,
+ ] + $attributes, $escapedLabel);
+ }
+
+ public static function linkToGitHub($escapedLabel, $namespace, $repository)
+ {
+ return static::link(
+ $escapedLabel,
+ 'https://github.com/' . urlencode($namespace) . '/' . urlencode($repository),
+ [
+ 'target' => '_blank',
+ 'rel' => 'noreferrer',
+ 'class' => 'icon-forward'
+ ]
+ );
+ }
+
+ protected static function escapeAttributeValue($value)
+ {
+ $value = str_replace('"', '&quot;', $value);
+ // Escape ambiguous ampersands
+ return preg_replace_callback('/&[0-9A-Z]+;/i', function ($match) {
+ $subject = $match[0];
+
+ if (htmlspecialchars_decode($subject, ENT_COMPAT | ENT_HTML5) === $subject) {
+ // Ambiguous ampersand
+ return str_replace('&', '&amp;', $subject);
+ }
+
+ return $subject;
+ }, $value);
+ }
+
+ public static function escape($any)
+ {
+ return htmlspecialchars($any);
+ }
+}