1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeaunamespace ComboStrap\Tag; 4*04fd306cSNickeau 5*04fd306cSNickeauuse ComboStrap\CallStack; 6*04fd306cSNickeauuse ComboStrap\ColorRgb; 7*04fd306cSNickeauuse ComboStrap\Dimension; 8*04fd306cSNickeauuse ComboStrap\FetcherSvg; 9*04fd306cSNickeauuse ComboStrap\IFetcherAbs; 10*04fd306cSNickeauuse ComboStrap\LinkMarkup; 11*04fd306cSNickeauuse ComboStrap\MarkupRef; 12*04fd306cSNickeauuse ComboStrap\MediaMarkup; 13*04fd306cSNickeauuse ComboStrap\PluginUtility; 14*04fd306cSNickeauuse ComboStrap\Position; 15*04fd306cSNickeauuse ComboStrap\TagAttribute\BackgroundAttribute; 16*04fd306cSNickeauuse ComboStrap\TagAttributes; 17*04fd306cSNickeauuse Doku_Renderer_metadata; 18*04fd306cSNickeauuse syntax_plugin_combo_media; 19*04fd306cSNickeau 20*04fd306cSNickeau 21*04fd306cSNickeau/** 22*04fd306cSNickeau * The {@link BackgroundTag background tag} does not render as HTML tag 23*04fd306cSNickeau * but collects data to create a {@link BackgroundAttribute} 24*04fd306cSNickeau * on the parent node 25*04fd306cSNickeau * 26*04fd306cSNickeau * Implementation of a background 27*04fd306cSNickeau * 28*04fd306cSNickeau * 29*04fd306cSNickeau * Cool calm example of moving square background 30*04fd306cSNickeau * https://codepen.io/Lewitje/pen/BNNJjo 31*04fd306cSNickeau * Particles.js 32*04fd306cSNickeau * https://codepen.io/akey96/pen/oNgeQYX 33*04fd306cSNickeau * Gradient positioning above a photo 34*04fd306cSNickeau * https://codepen.io/uzoawili/pen/GypGOy 35*04fd306cSNickeau * Fire flies 36*04fd306cSNickeau * https://codepen.io/mikegolus/pen/Jegvym 37*04fd306cSNickeau * 38*04fd306cSNickeau * z-index:100 could also be on the front 39*04fd306cSNickeau * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index 40*04fd306cSNickeau * https://getbootstrap.com/docs/5.0/layout/z-index/ 41*04fd306cSNickeau */ 42*04fd306cSNickeauclass BackgroundTag 43*04fd306cSNickeau{ 44*04fd306cSNickeau 45*04fd306cSNickeau public const MARKUP_LONG = "background"; 46*04fd306cSNickeau public const MARKUP_SHORT = "bg"; 47*04fd306cSNickeau const LOGICAL_TAG = self::MARKUP_LONG; 48*04fd306cSNickeau 49*04fd306cSNickeau /** 50*04fd306cSNickeau * Function used in the special and enter tag 51*04fd306cSNickeau * @param TagAttributes $attributes 52*04fd306cSNickeau */ 53*04fd306cSNickeau public static function handleEnterAndSpecial(TagAttributes $attributes) 54*04fd306cSNickeau { 55*04fd306cSNickeau 56*04fd306cSNickeau $color = $attributes->getValueAndRemoveIfPresent(ColorRgb::COLOR); 57*04fd306cSNickeau if ($color !== null) { 58*04fd306cSNickeau $attributes->addComponentAttributeValue(BackgroundAttribute::BACKGROUND_COLOR, $color); 59*04fd306cSNickeau } 60*04fd306cSNickeau 61*04fd306cSNickeau } 62*04fd306cSNickeau 63*04fd306cSNickeau /** 64*04fd306cSNickeau * @param CallStack $callStack 65*04fd306cSNickeau * @param TagAttributes $backgroundAttributes 66*04fd306cSNickeau * @param $state 67*04fd306cSNickeau * @return array 68*04fd306cSNickeau */ 69*04fd306cSNickeau public static function setAttributesToParentAndReturnData(CallStack $callStack, TagAttributes $backgroundAttributes, $state): array 70*04fd306cSNickeau { 71*04fd306cSNickeau 72*04fd306cSNickeau /** 73*04fd306cSNickeau * The data array 74*04fd306cSNickeau */ 75*04fd306cSNickeau $data = array(); 76*04fd306cSNickeau 77*04fd306cSNickeau /** 78*04fd306cSNickeau * Set the backgrounds attributes 79*04fd306cSNickeau * to the parent 80*04fd306cSNickeau * There is two state (special and exit) 81*04fd306cSNickeau * Go to the opening call if in exit 82*04fd306cSNickeau */ 83*04fd306cSNickeau if ($state == DOKU_LEXER_EXIT) { 84*04fd306cSNickeau $callStack->moveToEnd(); 85*04fd306cSNickeau $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 86*04fd306cSNickeau } 87*04fd306cSNickeau $parentCall = $callStack->moveToParent(); 88*04fd306cSNickeau 89*04fd306cSNickeau /** @noinspection PhpPointlessBooleanExpressionInConditionInspection */ 90*04fd306cSNickeau if ($parentCall != false) { 91*04fd306cSNickeau if ($parentCall->getTagName() == BackgroundAttribute::BACKGROUNDS) { 92*04fd306cSNickeau /** 93*04fd306cSNickeau * The backgrounds node 94*04fd306cSNickeau * (is already relative) 95*04fd306cSNickeau */ 96*04fd306cSNickeau $parentCall = $callStack->moveToParent(); 97*04fd306cSNickeau } else { 98*04fd306cSNickeau /** 99*04fd306cSNickeau * Another parent node 100*04fd306cSNickeau * With a image background, the node should be relative 101*04fd306cSNickeau */ 102*04fd306cSNickeau if ($backgroundAttributes->hasComponentAttribute(BackgroundAttribute::BACKGROUND_IMAGE)) { 103*04fd306cSNickeau $parentCall->addAttribute(Position::POSITION_ATTRIBUTE, "relative"); 104*04fd306cSNickeau } 105*04fd306cSNickeau } 106*04fd306cSNickeau $backgrounds = $parentCall->getAttribute(BackgroundAttribute::BACKGROUNDS); 107*04fd306cSNickeau if ($backgrounds == null) { 108*04fd306cSNickeau $backgrounds = [$backgroundAttributes->toCallStackArray()]; 109*04fd306cSNickeau } else { 110*04fd306cSNickeau $backgrounds[] = $backgroundAttributes->toCallStackArray(); 111*04fd306cSNickeau } 112*04fd306cSNickeau $parentCall->addAttribute(BackgroundAttribute::BACKGROUNDS, $backgrounds); 113*04fd306cSNickeau 114*04fd306cSNickeau } else { 115*04fd306cSNickeau $data[PluginUtility::EXIT_MESSAGE] = "A background should have a parent"; 116*04fd306cSNickeau } 117*04fd306cSNickeau 118*04fd306cSNickeau /** 119*04fd306cSNickeau * Return the image data for the metadata 120*04fd306cSNickeau * (Metadat is taken only from enter/exit) 121*04fd306cSNickeau */ 122*04fd306cSNickeau if ($state === DOKU_LEXER_EXIT && isset($openingCall)) { 123*04fd306cSNickeau // exit state 124*04fd306cSNickeau $backgroundImage = $backgroundAttributes->getComponentAttributeValue(BackgroundAttribute::BACKGROUND_IMAGE); 125*04fd306cSNickeau $openingCall->setAttribute(BackgroundAttribute::BACKGROUND_IMAGE, $backgroundImage); 126*04fd306cSNickeau } else { 127*04fd306cSNickeau // special state 128*04fd306cSNickeau $data[PluginUtility::ATTRIBUTES] = $backgroundAttributes->toCallStackArray(); 129*04fd306cSNickeau } 130*04fd306cSNickeau return $data; 131*04fd306cSNickeau 132*04fd306cSNickeau } 133*04fd306cSNickeau 134*04fd306cSNickeau /** 135*04fd306cSNickeau * Print only any error 136*04fd306cSNickeau */ 137*04fd306cSNickeau public static function renderExitSpecialHtml($data): string 138*04fd306cSNickeau { 139*04fd306cSNickeau 140*04fd306cSNickeau if (isset($data[PluginUtility::EXIT_MESSAGE])) { 141*04fd306cSNickeau $class = LinkMarkup::TEXT_ERROR_CLASS; 142*04fd306cSNickeau $error = $data[PluginUtility::EXIT_MESSAGE]; 143*04fd306cSNickeau return "<p class=\"$class\">$error</p>" . DOKU_LF; 144*04fd306cSNickeau } 145*04fd306cSNickeau 146*04fd306cSNickeau return ""; 147*04fd306cSNickeau } 148*04fd306cSNickeau 149*04fd306cSNickeau public static function handleExit($handler): array 150*04fd306cSNickeau { 151*04fd306cSNickeau $callStack = CallStack::createFromHandler($handler); 152*04fd306cSNickeau $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall(); 153*04fd306cSNickeau $backgroundAttributes = TagAttributes::createFromCallStackArray($openingTag->getAttributes()) 154*04fd306cSNickeau ->setLogicalTag(BackgroundTag::LOGICAL_TAG); 155*04fd306cSNickeau 156*04fd306cSNickeau /** 157*04fd306cSNickeau * if the media syntax of Combo is not used, try to retrieve the media of dokuwiki 158*04fd306cSNickeau */ 159*04fd306cSNickeau $imageTag = [syntax_plugin_combo_media::TAG, MediaMarkup::INTERNAL_MEDIA_CALL_NAME]; 160*04fd306cSNickeau 161*04fd306cSNickeau /** 162*04fd306cSNickeau * Collect the image if any 163*04fd306cSNickeau */ 164*04fd306cSNickeau while ($actual = $callStack->next()) { 165*04fd306cSNickeau 166*04fd306cSNickeau $tagName = $actual->getTagName(); 167*04fd306cSNickeau if (in_array($tagName, $imageTag)) { 168*04fd306cSNickeau $imageAttribute = $actual->getAttributes(); 169*04fd306cSNickeau if ($tagName == syntax_plugin_combo_media::TAG) { 170*04fd306cSNickeau $backgroundImageAttribute = BackgroundAttribute::fromMediaToBackgroundImageStackArray($imageAttribute); 171*04fd306cSNickeau 172*04fd306cSNickeau /** 173*04fd306cSNickeau * Hack for tile svg 174*04fd306cSNickeau */ 175*04fd306cSNickeau $fill = $openingTag->getAttribute(BackgroundAttribute::BACKGROUND_FILL); 176*04fd306cSNickeau if ($fill === FetcherSvg::TILE_TYPE) { 177*04fd306cSNickeau $ref = $backgroundImageAttribute[MarkupRef::REF_ATTRIBUTE]; 178*04fd306cSNickeau if (!str_contains($ref, TagAttributes::TYPE_KEY) && str_contains($ref, "svg")) { 179*04fd306cSNickeau if (str_contains($ref, "?")) { 180*04fd306cSNickeau $ref = "$ref&type=$fill"; 181*04fd306cSNickeau } else { 182*04fd306cSNickeau $ref = "$ref?type=$fill"; 183*04fd306cSNickeau } 184*04fd306cSNickeau } 185*04fd306cSNickeau $backgroundImageAttribute[MarkupRef::REF_ATTRIBUTE] = $ref; 186*04fd306cSNickeau } 187*04fd306cSNickeau } else { 188*04fd306cSNickeau /** 189*04fd306cSNickeau * As seen in {@link Doku_Handler::media()} 190*04fd306cSNickeau */ 191*04fd306cSNickeau $backgroundImageAttribute = [ 192*04fd306cSNickeau MediaMarkup::MEDIA_DOKUWIKI_TYPE => MediaMarkup::INTERNAL_MEDIA_CALL_NAME, 193*04fd306cSNickeau MediaMarkup::DOKUWIKI_SRC => $imageAttribute[0], 194*04fd306cSNickeau Dimension::WIDTH_KEY => $imageAttribute[3], 195*04fd306cSNickeau Dimension::HEIGHT_KEY => $imageAttribute[4], 196*04fd306cSNickeau IFetcherAbs::CACHE_KEY => $imageAttribute[5] 197*04fd306cSNickeau ]; 198*04fd306cSNickeau } 199*04fd306cSNickeau $backgroundAttributes->addComponentAttributeValue(BackgroundAttribute::BACKGROUND_IMAGE, $backgroundImageAttribute); 200*04fd306cSNickeau $callStack->deleteActualCallAndPrevious(); 201*04fd306cSNickeau } 202*04fd306cSNickeau } 203*04fd306cSNickeau return BackgroundTag::setAttributesToParentAndReturnData($callStack, $backgroundAttributes, DOKU_LEXER_EXIT); 204*04fd306cSNickeau } 205*04fd306cSNickeau 206*04fd306cSNickeau public static function renderEnterTag(): string 207*04fd306cSNickeau { 208*04fd306cSNickeau /** 209*04fd306cSNickeau * background is printed via the {@link BackgroundAttribute::processBackgroundAttributes()} 210*04fd306cSNickeau */ 211*04fd306cSNickeau return ""; 212*04fd306cSNickeau } 213*04fd306cSNickeau 214*04fd306cSNickeau public static function renderMeta(array $data, Doku_Renderer_metadata $renderer) 215*04fd306cSNickeau { 216*04fd306cSNickeau 217*04fd306cSNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 218*04fd306cSNickeau if (isset($attributes[BackgroundAttribute::BACKGROUND_IMAGE])) { 219*04fd306cSNickeau $image = $attributes[BackgroundAttribute::BACKGROUND_IMAGE]; 220*04fd306cSNickeau syntax_plugin_combo_media::registerImageMeta($image, $renderer); 221*04fd306cSNickeau } 222*04fd306cSNickeau 223*04fd306cSNickeau } 224*04fd306cSNickeau} 225