1<?php 2 3namespace ComboStrap; 4 5use Doku_Handler; 6use Doku_Renderer_metadata; 7use Exception; 8use syntax_plugin_combo_link; 9use syntax_plugin_combo_media; 10use syntax_plugin_combo_note; 11use syntax_plugin_combo_tooltip; 12 13class IconTag 14{ 15 16 const CANONICAL = "icon"; 17 public const TAG = "icon"; 18 19 public static function handleSpecial(TagAttributes $tagAttributes, Doku_Handler $handler): array 20 { 21 // Get the parameters 22 $callStack = CallStack::createFromHandler($handler); 23 $parent = $callStack->moveToParent(); 24 $context = ""; 25 if ($parent !== false) { 26 $context = $parent->getTagName(); 27 if ($context === syntax_plugin_combo_link::TAG) { 28 $context = $parent->getTagName(); 29 } 30 } 31 /** 32 * Color setting should know the color of its parent 33 * For now, we don't set any color if the parent is a button, note, link 34 * As a header is not a parent, we may say that if the icon is contained, the default 35 * branding color is not set ? 36 */ 37 $requestedColor = $tagAttributes->getValue(ColorRgb::COLOR); 38 if ( 39 $requestedColor === null && 40 Site::isBrandingColorInheritanceEnabled() && 41 !in_array($context, [ 42 ButtonTag::MARKUP_LONG, 43 syntax_plugin_combo_note::TAG, 44 syntax_plugin_combo_link::TAG 45 ]) 46 ) { 47 48 $requestedWidth = $tagAttributes->getValue(Dimension::WIDTH_KEY, FetcherSvg::DEFAULT_ICON_LENGTH); 49 50 // By default, a character icon 51 $color = Site::getSecondaryColor(); 52 try { 53 $requestedWidthInPx = ConditionalLength::createFromString($requestedWidth)->toPixelNumber(); 54 if ($requestedWidthInPx > 36) { 55 // Illustrative icon 56 $color = Site::getPrimaryColor(); 57 } 58 } catch (ExceptionBadArgument $e) { 59 LogUtility::error("The requested icon width ($requestedWidth) is not a conform width. Error: " . $e->getMessage(), self::CANONICAL, $e); 60 } 61 62 if ($color !== null) { 63 $tagAttributes->setComponentAttributeValue(ColorRgb::COLOR, $color); 64 } 65 } 66 return array(PluginUtility::CONTEXT => $context); 67 } 68 69 public static function exceptionHandling(Exception $e, $tagAttribute): string 70 { 71 $errorClass = syntax_plugin_combo_media::SVG_RENDERING_ERROR_CLASS; 72 $message = "Icon ({$tagAttribute->getValue("name")}). Error while rendering: {$e->getMessage()}"; 73 $html = "<span class=\"text-danger $errorClass\">" . hsc(trim($message)) . "</span>"; 74 LogUtility::warning($message, self::CANONICAL, $e); 75 return $html; 76 } 77 78 /** 79 * @param TagAttributes $tagAttributes 80 * @return string 81 */ 82 public static function renderEmptyTag(TagAttributes $tagAttributes): string 83 { 84 85 try { 86 return Icon::createFromTagAttributes($tagAttributes) 87 ->toHtml(); 88 } catch (\Exception $e) { 89 // catch all 90 return IconTag::exceptionHandling($e, $tagAttributes); 91 } 92 93 } 94 95 /** 96 * @param Doku_Renderer_metadata $renderer 97 * @param $tagAttribute 98 * @return void 99 */ 100 public static function metadata(Doku_Renderer_metadata $renderer, $tagAttribute) 101 { 102 103 try { 104 $mediaPath = Icon::createFromTagAttributes($tagAttribute)->getFetchSvg()->getSourcePath(); 105 } catch (ExceptionCompile $e) { 106 // error is already fired in the renderer 107 return; 108 } 109 if (FileSystems::exists($mediaPath)) { 110 syntax_plugin_combo_media::registerFirstImage($renderer, $mediaPath); 111 } 112 } 113 114 public static function handleEnter(TagAttributes $tagAttributes, Doku_Handler $handler): array 115 { 116 return self::handleSpecial($tagAttributes, $handler); 117 } 118 119 public static function handleExit(Doku_Handler $handler): array 120 { 121 $callStack = CallStack::createFromHandler($handler); 122 $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 123 return array( 124 PluginUtility::ATTRIBUTES => $openingCall->getAttributes(), 125 PluginUtility::CONTEXT => $openingCall->getContext() 126 ); 127 } 128 129 public static function renderEnterTag(TagAttributes $tagAttributes): string 130 { 131 $tooltip = $tagAttributes->getValueAndRemoveIfPresent(Tooltip::TOOLTIP_ATTRIBUTE); 132 $html = ""; 133 if ($tooltip !== null) { 134 /** 135 * If there is a tooltip, we need 136 * to start with a span to wrap the svg with it 137 */ 138 139 140 $tooltipTag = TagAttributes::createFromCallStackArray([Tooltip::TOOLTIP_ATTRIBUTE => $tooltip]) 141 ->addClassName(syntax_plugin_combo_tooltip::TOOLTIP_CLASS_INLINE_BLOCK); 142 $html .= $tooltipTag->toHtmlEnterTag("span"); 143 } 144 /** 145 * Print the icon 146 */ 147 $html .= IconTag::renderEmptyTag($tagAttributes); 148 /** 149 * Close the span if we are in a tooltip context 150 */ 151 if ($tooltip !== null) { 152 $html .= "</span>"; 153 } 154 return $html; 155 } 156} 157