diff options
| author | Ron Lucke <lucke@elan-ev.de> | 2025-07-14 09:36:18 +0200 |
|---|---|---|
| committer | Ron Lucke <lucke@elan-ev.de> | 2025-07-14 09:36:18 +0200 |
| commit | 4355ded9bc56e0b06fbceffe61ddc37061cc3bc7 (patch) | |
| tree | 348493b6b0fd1286b86f213e5077413b97cf9747 /lib/classes/Icon.php | |
| parent | 1e59dd2dacc51b3313d7780b66d4bf72e0484f86 (diff) | |
Color-Themes-System, fixes #5361
Closes #5361
Merge request studip/studip!4038
Diffstat (limited to 'lib/classes/Icon.php')
| -rw-r--r-- | lib/classes/Icon.php | 100 |
1 files changed, 92 insertions, 8 deletions
diff --git a/lib/classes/Icon.php b/lib/classes/Icon.php index ad1327c..bec9bdd 100644 --- a/lib/classes/Icon.php +++ b/lib/classes/Icon.php @@ -41,6 +41,7 @@ class Icon implements JsonSerializable protected string $role; protected array $attributes = []; + private static array $svg_cache = []; /** * This is the magical Role to Color mapping. @@ -153,7 +154,7 @@ class Icon implements JsonSerializable */ public function getShape() { - return $this->shapeToPath($this->shape); + return $this->shapeToPath(); } /** @@ -197,7 +198,7 @@ class Icon implements JsonSerializable */ public function __toString() { - return $this->asImg(); + return $this->asSvg(); } public function jsonSerialize(): mixed @@ -227,6 +228,78 @@ class Icon implements JsonSerializable ); } + public function asSvg($size = self::SIZE_DEFAULT, $view_attributes = []): string + { + if (self::isStatic($this->shape)) { + return $this->asImg($size, $view_attributes); + } + + if (is_array($size)) { + [$view_attributes, $size] = [$size, $size['size'] ?? self::SIZE_DEFAULT]; + } + + $cacheKey = md5(json_encode([ + 'role' => $this->role, + 'shape' => $this->shape, + 'size' => $size, + 'attrs' => $view_attributes + ])); + + if (isset(self::$svg_cache[$cacheKey])) { + return self::$svg_cache[$cacheKey]; + } + + $path = __DIR__ . '/../../public/assets/images/icons/' . self::roleToColor($this->role) . '/' . $this->shapeToPath($this->shape) . '.svg'; + $roleClass = $this->role ? 'icon-role-' . $this->role : ''; + + $classes = trim("studip-icon $roleClass"); + if (!empty($view_attributes['class'])) { + $classes .= ' ' . $view_attributes['class']; + } + $view_attributes['class'] = $classes; + + $titleTag = ''; + if (!empty($view_attributes['title'])) { + $titleTag = '<title>' . htmlspecialchars($view_attributes['title']) . '</title>'; + unset($view_attributes['title']); // Entfernt 'title' aus den View-Attributen, da es separat hinzugefügt wird + } + + $attrString = $this->buildSvgAttributes($view_attributes); + + if (!file_exists($path)) { + return ''; + } + + $svgContent = file_get_contents($path); + + $svgContent = preg_replace('/fill="(?!none)[^"]+"/', 'fill="currentColor"', $svgContent); + + $svgContent = preg_replace('/(width|height)="[^"]+"/', '', $svgContent); + if ($size !== false) { + $svgContent = preg_replace('/<svg([^>]+)>/', '<svg$1 style="width:' . $size . 'px;height:' . $size . 'px">', $svgContent); + } + + $svgContent = preg_replace_callback('/<svg([^>]+)>/', function($matches) use ($attrString) { + return '<svg' . $matches[1] . ' ' . $attrString . '>'; + }, $svgContent); + + if (!empty($titleTag)) { + $svgContent = preg_replace('/(<svg[^>]*>)/', '$1' . $titleTag, $svgContent, 1); + } + + self::$svg_cache[$cacheKey] = $svgContent; + return $svgContent; + } + + private function buildSvgAttributes(array $attributes): string + { + $attrString = ''; + foreach ($attributes as $key => $value) { + $attrString .= sprintf(' %s="%s"', htmlspecialchars($key, ENT_QUOTES, 'UTF-8'), htmlspecialchars($value, ENT_QUOTES, 'UTF-8')); + } + return trim($attrString); + } + /** * Renders the icon inside an input html tag. * @@ -236,16 +309,27 @@ class Icon implements JsonSerializable * into the rendered output * @return String containing the html representation for the icon. */ - public function asInput($size = null, $view_attributes = []) + public function asInput($size = self::SIZE_DEFAULT, $view_attributes = []) { if (is_array($size)) { - [$view_attributes, $size] = [$size, null]; + [$view_attributes, $size] = [$size, self::SIZE_DEFAULT]; } + + $view_attributes['tabindex'] ??= '0'; + $view_attributes['role'] ??= 'button'; + + $text = isset($view_attributes['text']) ? htmlReady($view_attributes['text']) : ''; + + $svgContent = $this->asSvg($size, $view_attributes); + return sprintf( - '<input type="image" %s>', - arrayToHtmlAttributes( - $this->prepareHTMLAttributes($size, $view_attributes) - ) + '<label class="icon-button undecorated"> + <input type="submit" hidden %s> + %s%s + </label>', + arrayToHtmlAttributes($this->prepareHTMLAttributes($size, $view_attributes)), + $svgContent, + $text ); } |
