From 6eca9445423546c78f2fc77110f1cf66d1d66985 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Willms Date: Thu, 8 Jan 2026 15:28:22 +0100 Subject: fix handling of style attributes in Icon::asSvg() by using HTMLAttributes class, fixes #6147 Closes #6147 Merge request studip/studip!4662 --- lib/classes/Icon.php | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/lib/classes/Icon.php b/lib/classes/Icon.php index 2ddc4a1..509664e 100644 --- a/lib/classes/Icon.php +++ b/lib/classes/Icon.php @@ -249,14 +249,10 @@ class Icon implements JsonSerializable 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']; + $path = __DIR__ . '/../../public/assets/images/icons/' . self::roleToColor($this->role) . '/' . $this->shapeToPath() . '.svg'; + if (!file_exists($path)) { + return ''; } - $view_attributes['class'] = $classes; $titleTag = ''; if (!empty($view_attributes['title'])) { @@ -264,23 +260,21 @@ class Icon implements JsonSerializable unset($view_attributes['title']); // Entfernt 'title' aus den View-Attributen, da es separat hinzugefügt wird } - $attrString = $this->buildSvgAttributes($view_attributes); + $attributes = HTMLAttributes::from($view_attributes); + $attributes->addAttribute('class', 'studip-icon'); + if ($this->role) { + $attributes->addAttribute('class', "icon-role-{$this->role}"); + } - if (!file_exists($path)) { - return ''; + if ($size !== false) { + $attributes->addAttribute('style', "width: {$size}px; height: {$size}px"); } $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('/]+)>/', '', $svgContent); - } - - $svgContent = preg_replace_callback('/]+)>/', function($matches) use ($attrString) { - return ''; + $svgContent = preg_replace_callback('/]+)>/', function($matches) use ($attributes) { + return 'asString() . '>'; }, $svgContent); if (!empty($titleTag)) { @@ -291,15 +285,6 @@ class Icon implements JsonSerializable 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. * -- cgit v1.0