diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:43:12 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:43:12 +0000 |
commit | cd989f9c3aff968e19a3aeabc4eb9085787a6673 (patch) | |
tree | fbff2135e7013f196b891bbde54618eb050e4aaf /library/Director/Web/Table/Dependency | |
parent | Initial commit. (diff) | |
download | icingaweb2-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.php | 101 | ||||
-rw-r--r-- | library/Director/Web/Table/Dependency/Html.php | 74 |
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('"', '"', $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('&', '&', $subject); + } + + return $subject; + }, $value); + } + + public static function escape($any) + { + return htmlspecialchars($any); + } +} |