137748cd8SNickeau<?php 237748cd8SNickeau/** 337748cd8SNickeau * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved. 437748cd8SNickeau * 537748cd8SNickeau * This source code is licensed under the GPL license found in the 637748cd8SNickeau * COPYING file in the root directory of this source tree. 737748cd8SNickeau * 837748cd8SNickeau * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 937748cd8SNickeau * @author ComboStrap <support@combostrap.com> 1037748cd8SNickeau * 1137748cd8SNickeau */ 1237748cd8SNickeau 1337748cd8SNickeaunamespace ComboStrap; 1437748cd8SNickeau 1537748cd8SNickeauuse dokuwiki\Extension\SyntaxPlugin; 16*c3437056SNickeauuse dokuwiki\Parsing\ParserMode\Internallink; 1737748cd8SNickeauuse syntax_plugin_combo_media; 1837748cd8SNickeau 191fa8c418SNickeaurequire_once(__DIR__ . '/PluginUtility.php'); 2037748cd8SNickeau 2137748cd8SNickeau/** 2237748cd8SNickeau * Class InternalMedia 2337748cd8SNickeau * Represent a media link 2437748cd8SNickeau * 2537748cd8SNickeau * 2637748cd8SNickeau * @package ComboStrap 2737748cd8SNickeau * 2837748cd8SNickeau * Wrapper around {@link Doku_Handler_Parse_Media} 2937748cd8SNickeau * 3037748cd8SNickeau * Not that for dokuwiki the `type` key of the attributes is the `call` 3137748cd8SNickeau * and therefore determine the function in an render 3237748cd8SNickeau * (ie {@link \Doku_Renderer::internalmedialink()} or {@link \Doku_Renderer::externalmedialink()} 3337748cd8SNickeau * 341fa8c418SNickeau * This is a link to a media (pdf, image, ...). 351fa8c418SNickeau * It's used to check the media type and to 361fa8c418SNickeau * take over if the media type is an image 3737748cd8SNickeau */ 381fa8c418SNickeauabstract class MediaLink 3937748cd8SNickeau{ 4037748cd8SNickeau 4137748cd8SNickeau 4237748cd8SNickeau /** 4337748cd8SNickeau * The dokuwiki type and mode name 4437748cd8SNickeau * (ie call) 4537748cd8SNickeau * * ie {@link MediaLink::EXTERNAL_MEDIA_CALL_NAME} 4637748cd8SNickeau * or {@link MediaLink::INTERNAL_MEDIA_CALL_NAME} 4737748cd8SNickeau * 4837748cd8SNickeau * The dokuwiki type (internalmedia/externalmedia) 4937748cd8SNickeau * is saved in a `type` key that clash with the 5037748cd8SNickeau * combostrap type. To avoid the clash, we renamed it 5137748cd8SNickeau */ 5237748cd8SNickeau const MEDIA_DOKUWIKI_TYPE = 'dokuwiki_type'; 5337748cd8SNickeau const INTERNAL_MEDIA_CALL_NAME = "internalmedia"; 5437748cd8SNickeau const EXTERNAL_MEDIA_CALL_NAME = "externalmedia"; 5537748cd8SNickeau 5637748cd8SNickeau const CANONICAL = "image"; 5737748cd8SNickeau 5837748cd8SNickeau /** 5937748cd8SNickeau * This attributes does not apply 6037748cd8SNickeau * to a URL 6137748cd8SNickeau * They are only for the tag (img, svg, ...) 6237748cd8SNickeau * or internal 6337748cd8SNickeau */ 6437748cd8SNickeau const NON_URL_ATTRIBUTES = [ 651fa8c418SNickeau MediaLink::ALIGN_KEY, 661fa8c418SNickeau MediaLink::LINKING_KEY, 6737748cd8SNickeau TagAttributes::TITLE_KEY, 6837748cd8SNickeau Hover::ON_HOVER_ATTRIBUTE, 6937748cd8SNickeau Animation::ON_VIEW_ATTRIBUTE, 7037748cd8SNickeau MediaLink::MEDIA_DOKUWIKI_TYPE, 7137748cd8SNickeau MediaLink::DOKUWIKI_SRC 7237748cd8SNickeau ]; 7337748cd8SNickeau 7437748cd8SNickeau /** 7537748cd8SNickeau * This attribute applies 7637748cd8SNickeau * to a image url (img, svg, ...) 7737748cd8SNickeau */ 7837748cd8SNickeau const URL_ATTRIBUTES = [ 7937748cd8SNickeau Dimension::WIDTH_KEY, 8037748cd8SNickeau Dimension::HEIGHT_KEY, 8137748cd8SNickeau CacheMedia::CACHE_KEY, 8237748cd8SNickeau ]; 8337748cd8SNickeau 8437748cd8SNickeau /** 8537748cd8SNickeau * Default image linking value 8637748cd8SNickeau */ 8737748cd8SNickeau const CONF_DEFAULT_LINKING = "defaultImageLinking"; 8837748cd8SNickeau const LINKING_LINKONLY_VALUE = "linkonly"; 8937748cd8SNickeau const LINKING_DETAILS_VALUE = 'details'; 9037748cd8SNickeau const LINKING_NOLINK_VALUE = 'nolink'; 9137748cd8SNickeau 9237748cd8SNickeau /** 9337748cd8SNickeau * @deprecated 2021-06-12 9437748cd8SNickeau */ 9537748cd8SNickeau const LINK_PATTERN = "{{\s*([^|\s]*)\s*\|?.*}}"; 9637748cd8SNickeau 9737748cd8SNickeau const LINKING_DIRECT_VALUE = 'direct'; 9837748cd8SNickeau 9937748cd8SNickeau /** 10037748cd8SNickeau * Only used by Dokuwiki 10137748cd8SNickeau * Contains the path and eventually an anchor 10237748cd8SNickeau * never query parameters 10337748cd8SNickeau */ 10437748cd8SNickeau const DOKUWIKI_SRC = "src"; 10537748cd8SNickeau /** 10637748cd8SNickeau * Link value: 10737748cd8SNickeau * * 'nolink' 10837748cd8SNickeau * * 'direct': directly to the image 10937748cd8SNickeau * * 'linkonly': show only a url 11037748cd8SNickeau * * 'details': go to the details media viewer 11137748cd8SNickeau * 11237748cd8SNickeau * @var 11337748cd8SNickeau */ 11437748cd8SNickeau const LINKING_KEY = 'linking'; 11537748cd8SNickeau const ALIGN_KEY = 'align'; 11637748cd8SNickeau 11737748cd8SNickeau 11837748cd8SNickeau private $lazyLoad = null; 11937748cd8SNickeau 12037748cd8SNickeau 12137748cd8SNickeau /** 1221fa8c418SNickeau * The path of the media 1231fa8c418SNickeau * @var Media[] 12437748cd8SNickeau */ 1251fa8c418SNickeau private $media; 12637748cd8SNickeau 12737748cd8SNickeau 12837748cd8SNickeau /** 12937748cd8SNickeau * Image constructor. 1301fa8c418SNickeau * @param Image $media 13137748cd8SNickeau * 13237748cd8SNickeau * Protected and not private 13337748cd8SNickeau * to allow cascading init 13437748cd8SNickeau * If private, the parent attributes are null 13537748cd8SNickeau */ 1361fa8c418SNickeau protected function __construct(Media $media) 13737748cd8SNickeau { 1381fa8c418SNickeau $this->media = $media; 13937748cd8SNickeau } 14037748cd8SNickeau 14137748cd8SNickeau 14237748cd8SNickeau /** 143*c3437056SNickeau * Create an image from dokuwiki {@link Internallink internal call media attributes} 144*c3437056SNickeau * 145*c3437056SNickeau * Dokuwiki extracts already the width, height and align property 14637748cd8SNickeau * @param array $callAttributes 14737748cd8SNickeau * @return MediaLink 14837748cd8SNickeau */ 14937748cd8SNickeau public static function createFromIndexAttributes(array $callAttributes) 15037748cd8SNickeau { 151*c3437056SNickeau $src = $callAttributes[0]; 15237748cd8SNickeau $title = $callAttributes[1]; 15337748cd8SNickeau $align = $callAttributes[2]; 15437748cd8SNickeau $width = $callAttributes[3]; 15537748cd8SNickeau $height = $callAttributes[4]; 15637748cd8SNickeau $cache = $callAttributes[5]; 15737748cd8SNickeau $linking = $callAttributes[6]; 15837748cd8SNickeau 15937748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 16037748cd8SNickeau $tagAttributes->addComponentAttributeValue(TagAttributes::TITLE_KEY, $title); 16137748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::ALIGN_KEY, $align); 16237748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::WIDTH_KEY, $width); 16337748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::HEIGHT_KEY, $height); 16437748cd8SNickeau $tagAttributes->addComponentAttributeValue(CacheMedia::CACHE_KEY, $cache); 16537748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::LINKING_KEY, $linking); 16637748cd8SNickeau 167*c3437056SNickeau return self::createMediaLinkFromId($src, $tagAttributes); 16837748cd8SNickeau 16937748cd8SNickeau } 17037748cd8SNickeau 17137748cd8SNickeau /** 17237748cd8SNickeau * A function to explicitly create an internal media from 17337748cd8SNickeau * a call stack array (ie key string and value) that we get in the {@link SyntaxPlugin::render()} 17437748cd8SNickeau * from the {@link MediaLink::toCallStackArray()} 17537748cd8SNickeau * 17637748cd8SNickeau * @param $attributes - the attributes created by the function {@link MediaLink::getParseAttributes()} 17737748cd8SNickeau * @param $rev - the mtime 178*c3437056SNickeau * @return null|MediaLink 17937748cd8SNickeau */ 180*c3437056SNickeau public static function createFromCallStackArray($attributes, $rev = null): ?MediaLink 18137748cd8SNickeau { 18237748cd8SNickeau 18337748cd8SNickeau if (!is_array($attributes)) { 18437748cd8SNickeau // Debug for the key_exist below because of the following message: 18537748cd8SNickeau // `PHP Warning: key_exists() expects parameter 2 to be array, array given` 18637748cd8SNickeau LogUtility::msg("The `attributes` parameter is not an array. Value ($attributes)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 18737748cd8SNickeau } 18837748cd8SNickeau 18937748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 19037748cd8SNickeau 191*c3437056SNickeau $src = $attributes[self::DOKUWIKI_SRC]; 192*c3437056SNickeau if ($src === null) { 193*c3437056SNickeau /** 194*c3437056SNickeau * Dokuwiki parse already the src and create the path and the attributes 195*c3437056SNickeau * The new model will not, we check if we are in the old mode 196*c3437056SNickeau */ 197*c3437056SNickeau $src = $attributes[PagePath::PROPERTY_NAME]; 198*c3437056SNickeau if ($src === null) { 199*c3437056SNickeau LogUtility::msg("src is mandatory for an image link and was not passed"); 200*c3437056SNickeau return null; 201*c3437056SNickeau } 202*c3437056SNickeau } 203*c3437056SNickeau $dokuUrl = DokuwikiUrl::createFromUrl($src); 204*c3437056SNickeau $scheme = $dokuUrl->getScheme(); 205*c3437056SNickeau switch ($scheme) { 206*c3437056SNickeau case DokuFs::SCHEME: 207*c3437056SNickeau $id = $dokuUrl->getPath(); 208*c3437056SNickeau // the id is always absolute, except in a link 209*c3437056SNickeau // It may be relative, transform it as absolute 210*c3437056SNickeau global $ID; 211*c3437056SNickeau resolve_mediaid(getNS($ID), $id, $exists); 212*c3437056SNickeau $path = DokuPath::createMediaPathFromId($id, $rev); 213*c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 214*c3437056SNickeau case InterWikiPath::scheme: 215*c3437056SNickeau $path = InterWikiPath::create($dokuUrl->getPath()); 216*c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 217*c3437056SNickeau case InternetPath::scheme: 218*c3437056SNickeau $path = InternetPath::create($dokuUrl->getPath()); 219*c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 220*c3437056SNickeau default: 221*c3437056SNickeau LogUtility::msg("The media with the scheme ($scheme) are not yet supported. Media Source: $src"); 222*c3437056SNickeau return null; 22337748cd8SNickeau 224*c3437056SNickeau } 225*c3437056SNickeau 22637748cd8SNickeau 22737748cd8SNickeau } 22837748cd8SNickeau 22937748cd8SNickeau /** 23037748cd8SNickeau * @param $match - the match of the renderer (just a shortcut) 23137748cd8SNickeau * @return MediaLink 23237748cd8SNickeau */ 23337748cd8SNickeau public static function createFromRenderMatch($match) 23437748cd8SNickeau { 23537748cd8SNickeau 23637748cd8SNickeau /** 23737748cd8SNickeau * The parsing function {@link Doku_Handler_Parse_Media} has some flow / problem 23837748cd8SNickeau * * It keeps the anchor only if there is no query string 23937748cd8SNickeau * * It takes the first digit as the width (ie media.pdf?page=31 would have a width of 31) 24037748cd8SNickeau * * `src` is not only the media path but may have a anchor 24137748cd8SNickeau * We parse it then 24237748cd8SNickeau */ 24337748cd8SNickeau 24437748cd8SNickeau 24537748cd8SNickeau /** 24637748cd8SNickeau * * Delete the opening and closing character 24737748cd8SNickeau * * create the url and description 24837748cd8SNickeau */ 24937748cd8SNickeau $match = preg_replace(array('/^\{\{/', '/\}\}$/u'), '', $match); 25037748cd8SNickeau $parts = explode('|', $match, 2); 25137748cd8SNickeau $description = null; 25237748cd8SNickeau $url = $parts[0]; 25337748cd8SNickeau if (isset($parts[1])) { 25437748cd8SNickeau $description = $parts[1]; 25537748cd8SNickeau } 25637748cd8SNickeau 25737748cd8SNickeau /** 25837748cd8SNickeau * Media Alignment 25937748cd8SNickeau */ 26037748cd8SNickeau $rightAlign = (bool)preg_match('/^ /', $url); 26137748cd8SNickeau $leftAlign = (bool)preg_match('/ $/', $url); 26237748cd8SNickeau $url = trim($url); 26337748cd8SNickeau 26437748cd8SNickeau // Logic = what's that ;)... 26537748cd8SNickeau if ($leftAlign & $rightAlign) { 26637748cd8SNickeau $align = 'center'; 26737748cd8SNickeau } else if ($rightAlign) { 26837748cd8SNickeau $align = 'right'; 26937748cd8SNickeau } else if ($leftAlign) { 27037748cd8SNickeau $align = 'left'; 27137748cd8SNickeau } else { 27237748cd8SNickeau $align = null; 27337748cd8SNickeau } 27437748cd8SNickeau 27537748cd8SNickeau /** 27637748cd8SNickeau * The combo attributes array 27737748cd8SNickeau */ 278*c3437056SNickeau $dokuwikiUrl = DokuwikiUrl::createFromUrl($url); 279*c3437056SNickeau $parsedAttributes = $dokuwikiUrl->toArray(); 280*c3437056SNickeau $path = $dokuwikiUrl->getPath(); 281*c3437056SNickeau $linkingKey = $dokuwikiUrl->getQueryParameter(MediaLink::LINKING_KEY); 282*c3437056SNickeau if ($linkingKey === null) { 283*c3437056SNickeau $linkingKey = PluginUtility::getConfValue(self::CONF_DEFAULT_LINKING, self::LINKING_DIRECT_VALUE); 28437748cd8SNickeau } 285*c3437056SNickeau $parsedAttributes[MediaLink::LINKING_KEY] = $linkingKey; 28637748cd8SNickeau 28737748cd8SNickeau /** 28837748cd8SNickeau * Media Type 28937748cd8SNickeau */ 290*c3437056SNickeau $scheme = $dokuwikiUrl->getScheme(); 291*c3437056SNickeau if ($scheme === DokuFs::SCHEME) { 29237748cd8SNickeau $mediaType = MediaLink::INTERNAL_MEDIA_CALL_NAME; 293*c3437056SNickeau } else { 294*c3437056SNickeau $mediaType = MediaLink::EXTERNAL_MEDIA_CALL_NAME; 29537748cd8SNickeau } 29637748cd8SNickeau 29737748cd8SNickeau 29837748cd8SNickeau /** 29937748cd8SNickeau * src in dokuwiki is the path and the anchor if any 30037748cd8SNickeau */ 30137748cd8SNickeau $src = $path; 30237748cd8SNickeau if (isset($parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]) != null) { 30337748cd8SNickeau $src = $src . "#" . $parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]; 30437748cd8SNickeau } 30537748cd8SNickeau 30637748cd8SNickeau /** 30737748cd8SNickeau * To avoid clash with the combostrap component type 30837748cd8SNickeau * ie this is also a ComboStrap attribute where we set the type of a SVG (icon, illustration, background) 30937748cd8SNickeau * we store the media type (ie external/internal) in another key 31037748cd8SNickeau * 31137748cd8SNickeau * There is no need to repeat the attributes as the arrays are merged 31237748cd8SNickeau * into on but this is also an informal code to show which attributes 31337748cd8SNickeau * are only Dokuwiki Native 31437748cd8SNickeau * 31537748cd8SNickeau */ 31637748cd8SNickeau $dokuwikiAttributes = array( 31737748cd8SNickeau self::MEDIA_DOKUWIKI_TYPE => $mediaType, 31837748cd8SNickeau self::DOKUWIKI_SRC => $src, 31937748cd8SNickeau Dimension::WIDTH_KEY => $parsedAttributes[Dimension::WIDTH_KEY], 32037748cd8SNickeau Dimension::HEIGHT_KEY => $parsedAttributes[Dimension::HEIGHT_KEY], 32137748cd8SNickeau CacheMedia::CACHE_KEY => $parsedAttributes[CacheMedia::CACHE_KEY], 3221fa8c418SNickeau TagAttributes::TITLE_KEY => $description, 32337748cd8SNickeau MediaLink::ALIGN_KEY => $align, 32437748cd8SNickeau MediaLink::LINKING_KEY => $parsedAttributes[MediaLink::LINKING_KEY], 32537748cd8SNickeau ); 32637748cd8SNickeau 32737748cd8SNickeau /** 32837748cd8SNickeau * Merge standard dokuwiki attributes and 32937748cd8SNickeau * parsed attributes 33037748cd8SNickeau */ 33137748cd8SNickeau $mergedAttributes = PluginUtility::mergeAttributes($dokuwikiAttributes, $parsedAttributes); 33237748cd8SNickeau 33337748cd8SNickeau /** 33437748cd8SNickeau * If this is an internal media, 33537748cd8SNickeau * we are using our implementation 33637748cd8SNickeau * and we have a change on attribute specification 33737748cd8SNickeau */ 33837748cd8SNickeau if ($mediaType == MediaLink::INTERNAL_MEDIA_CALL_NAME) { 33937748cd8SNickeau 34037748cd8SNickeau /** 34137748cd8SNickeau * The align attribute on an image parse 34237748cd8SNickeau * is a float right 34337748cd8SNickeau * ComboStrap does a difference between a block right and a float right 34437748cd8SNickeau */ 34537748cd8SNickeau if ($mergedAttributes[self::ALIGN_KEY] === "right") { 34637748cd8SNickeau unset($mergedAttributes[self::ALIGN_KEY]); 34737748cd8SNickeau $mergedAttributes[FloatAttribute::FLOAT_KEY] = "right"; 34837748cd8SNickeau } 34937748cd8SNickeau 35037748cd8SNickeau 35137748cd8SNickeau } 35237748cd8SNickeau 35337748cd8SNickeau return self::createFromCallStackArray($mergedAttributes); 35437748cd8SNickeau 35537748cd8SNickeau } 35637748cd8SNickeau 35737748cd8SNickeau 35837748cd8SNickeau public 359*c3437056SNickeau function setLazyLoad($false): MediaLink 36037748cd8SNickeau { 36137748cd8SNickeau $this->lazyLoad = $false; 362*c3437056SNickeau return $this; 36337748cd8SNickeau } 36437748cd8SNickeau 36537748cd8SNickeau public 36637748cd8SNickeau function getLazyLoad() 36737748cd8SNickeau { 36837748cd8SNickeau return $this->lazyLoad; 36937748cd8SNickeau } 37037748cd8SNickeau 37137748cd8SNickeau 37237748cd8SNickeau /** 373*c3437056SNickeau * Create a media link from a wiki id 37437748cd8SNickeau * 37537748cd8SNickeau * 376*c3437056SNickeau * @param $wikiId - dokuwiki id 377*c3437056SNickeau * @param TagAttributes|null $tagAttributes 378*c3437056SNickeau * @param string|null $rev 37937748cd8SNickeau * @return MediaLink 38037748cd8SNickeau */ 38137748cd8SNickeau public 382*c3437056SNickeau static function createMediaLinkFromId($wikiId, ?string $rev = '', TagAttributes $tagAttributes = null) 38337748cd8SNickeau { 38437748cd8SNickeau if (is_object($rev)) { 38537748cd8SNickeau LogUtility::msg("rev should not be an object", LogUtility::LVL_MSG_ERROR, "support"); 38637748cd8SNickeau } 38737748cd8SNickeau if ($tagAttributes == null) { 38837748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 38937748cd8SNickeau } else { 39037748cd8SNickeau if (!($tagAttributes instanceof TagAttributes)) { 39137748cd8SNickeau LogUtility::msg("TagAttributes is not an instance of Tag Attributes", LogUtility::LVL_MSG_ERROR, "support"); 39237748cd8SNickeau } 39337748cd8SNickeau } 39437748cd8SNickeau 395*c3437056SNickeau $dokuPath = DokuPath::createMediaPathFromId($wikiId, $rev); 396*c3437056SNickeau return self::createMediaLinkFromPath($dokuPath, $tagAttributes); 397*c3437056SNickeau 398*c3437056SNickeau } 399*c3437056SNickeau 40037748cd8SNickeau /** 401*c3437056SNickeau * @param Path $path 402*c3437056SNickeau * @param null $tagAttributes 403*c3437056SNickeau * @return RasterImageLink|SvgImageLink|ThirdMediaLink 40437748cd8SNickeau */ 405*c3437056SNickeau public static function createMediaLinkFromPath(Path $path, $tagAttributes = null) 4061fa8c418SNickeau { 407*c3437056SNickeau 40837748cd8SNickeau /** 40937748cd8SNickeau * Processing 41037748cd8SNickeau */ 411*c3437056SNickeau $mime = $path->getMime(); 412*c3437056SNickeau if ($path->getExtension() === "svg") { 41337748cd8SNickeau /** 41437748cd8SNickeau * The mime type is set when uploading, not when 41537748cd8SNickeau * viewing. 41637748cd8SNickeau * Because they are internal image, the svg was already uploaded 41737748cd8SNickeau * Therefore, no authorization scheme here 41837748cd8SNickeau */ 419*c3437056SNickeau $mime = Mime::create(Mime::SVG); 42037748cd8SNickeau } 42137748cd8SNickeau 422*c3437056SNickeau if ($mime === null) { 423*c3437056SNickeau LogUtility::msg("The mime type of the media ($path) is <a href=\"https://www.dokuwiki.org/mime\">unknown (not in the configuration file)</a>", LogUtility::LVL_MSG_ERROR); 424*c3437056SNickeau $media = new ImageRaster($path, $tagAttributes); 425*c3437056SNickeau return new RasterImageLink($media); 42637748cd8SNickeau } 42737748cd8SNickeau 428*c3437056SNickeau if (!$mime->isImage()) { 429*c3437056SNickeau LogUtility::msg("The type ($mime) of media ($path) is not an image", LogUtility::LVL_MSG_DEBUG, "image"); 430*c3437056SNickeau $media = new ThirdMedia($path, $tagAttributes); 431*c3437056SNickeau return new ThirdMediaLink($media); 432*c3437056SNickeau } 433*c3437056SNickeau 434*c3437056SNickeau if ($mime->toString() === Mime::SVG) { 435*c3437056SNickeau $media = new ImageSvg($path, $tagAttributes); 436*c3437056SNickeau return new SvgImageLink($media); 437*c3437056SNickeau } 438*c3437056SNickeau 439*c3437056SNickeau $media = new ImageRaster($path, $tagAttributes); 440*c3437056SNickeau return new RasterImageLink($media); 441*c3437056SNickeau 442*c3437056SNickeau 44337748cd8SNickeau } 44437748cd8SNickeau 44537748cd8SNickeau 44637748cd8SNickeau /** 44737748cd8SNickeau * A function to set explicitly which array format 44837748cd8SNickeau * is used in the returned data of a {@link SyntaxPlugin::handle()} 44937748cd8SNickeau * (which ultimately is stored in the {@link CallStack) 45037748cd8SNickeau * 45137748cd8SNickeau * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()} 45237748cd8SNickeau * that is indexed by number (ie without property name) 45337748cd8SNickeau * 45437748cd8SNickeau * 45537748cd8SNickeau * Return the same array than with the {@link self::parse()} method 45637748cd8SNickeau * that is used in the {@link CallStack} 45737748cd8SNickeau * 45837748cd8SNickeau * @return array of key string and value 45937748cd8SNickeau */ 460*c3437056SNickeau public 461*c3437056SNickeau function toCallStackArray(): array 46237748cd8SNickeau { 46337748cd8SNickeau /** 46437748cd8SNickeau * Trying to stay inline with the dokuwiki key 46537748cd8SNickeau * We use the 'src' attributes as id 46637748cd8SNickeau * 46737748cd8SNickeau * src is a path (not an id) 46837748cd8SNickeau */ 46937748cd8SNickeau $array = array( 470*c3437056SNickeau PagePath::PROPERTY_NAME => $this->getMedia()->getPath()->toString() 47137748cd8SNickeau ); 47237748cd8SNickeau 47337748cd8SNickeau 47437748cd8SNickeau // Add the extra attribute 4751fa8c418SNickeau return array_merge($this->getMedia()->getAttributes()->toCallStackArray(), $array); 47637748cd8SNickeau 47737748cd8SNickeau 47837748cd8SNickeau } 47937748cd8SNickeau 48037748cd8SNickeau 48137748cd8SNickeau public 48237748cd8SNickeau static function isInternalMediaSyntax($text) 48337748cd8SNickeau { 48437748cd8SNickeau return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text); 48537748cd8SNickeau } 48637748cd8SNickeau 48737748cd8SNickeau 48837748cd8SNickeau public 48937748cd8SNickeau function __toString() 49037748cd8SNickeau { 491*c3437056SNickeau $media = $this->getMedia(); 492*c3437056SNickeau $dokuPath = $media->getPath(); 493*c3437056SNickeau if ($dokuPath !== null) { 494*c3437056SNickeau return $dokuPath->getDokuwikiId(); 495*c3437056SNickeau } else { 496*c3437056SNickeau return $media->__toString(); 497*c3437056SNickeau } 49837748cd8SNickeau } 49937748cd8SNickeau 50037748cd8SNickeau private 50137748cd8SNickeau function getAlign() 50237748cd8SNickeau { 5031fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::ALIGN_KEY); 50437748cd8SNickeau } 50537748cd8SNickeau 50637748cd8SNickeau private 50737748cd8SNickeau function getLinking() 50837748cd8SNickeau { 5091fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::LINKING_KEY); 51037748cd8SNickeau } 51137748cd8SNickeau 51237748cd8SNickeau 51337748cd8SNickeau /** 51437748cd8SNickeau * @return string - the HTML of the image inside a link if asked 51537748cd8SNickeau */ 51637748cd8SNickeau public 5171fa8c418SNickeau function renderMediaTagWithLink(): string 51837748cd8SNickeau { 51937748cd8SNickeau 52037748cd8SNickeau /** 52137748cd8SNickeau * Link to the media 52237748cd8SNickeau * 52337748cd8SNickeau */ 5241fa8c418SNickeau $mediaLink = TagAttributes::createEmpty(); 52537748cd8SNickeau // https://www.dokuwiki.org/config:target 52637748cd8SNickeau global $conf; 52737748cd8SNickeau $target = $conf['target']['media']; 5281fa8c418SNickeau $mediaLink->addHtmlAttributeValueIfNotEmpty("target", $target); 52937748cd8SNickeau if (!empty($target)) { 5301fa8c418SNickeau $mediaLink->addHtmlAttributeValue("rel", 'noopener'); 53137748cd8SNickeau } 53237748cd8SNickeau 53337748cd8SNickeau /** 53437748cd8SNickeau * Do we add a link to the image ? 53537748cd8SNickeau */ 5361fa8c418SNickeau $media = $this->getMedia(); 537*c3437056SNickeau $dokuPath = $media->getPath(); 538*c3437056SNickeau if (!($dokuPath instanceof DokuPath)) { 539*c3437056SNickeau LogUtility::msg("Media Link are only supported on media from the internal library ($media)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 540*c3437056SNickeau return ""; 541*c3437056SNickeau } 5421fa8c418SNickeau $linking = $this->getLinking(); 54337748cd8SNickeau switch ($linking) { 54437748cd8SNickeau case self::LINKING_LINKONLY_VALUE: // show only a url 54537748cd8SNickeau $src = ml( 546*c3437056SNickeau $dokuPath->getDokuwikiId(), 54737748cd8SNickeau array( 548*c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5491fa8c418SNickeau 'cache' => $media->getCache(), 550*c3437056SNickeau 'rev' => $dokuPath->getRevision() 55137748cd8SNickeau ) 55237748cd8SNickeau ); 5531fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 5541fa8c418SNickeau $title = $media->getTitle(); 55537748cd8SNickeau if (empty($title)) { 556*c3437056SNickeau $title = $media->getType(); 55737748cd8SNickeau } 5581fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . $title . "</a>"; 55937748cd8SNickeau case self::LINKING_NOLINK_VALUE: 56037748cd8SNickeau return $this->renderMediaTag(); 56137748cd8SNickeau default: 56237748cd8SNickeau case self::LINKING_DIRECT_VALUE: 56337748cd8SNickeau //directly to the image 56437748cd8SNickeau $src = ml( 565*c3437056SNickeau $dokuPath->getDokuwikiId(), 56637748cd8SNickeau array( 567*c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5681fa8c418SNickeau 'cache' => $media->getCache(), 569*c3437056SNickeau 'rev' => $dokuPath->getRevision() 57037748cd8SNickeau ), 57137748cd8SNickeau true 57237748cd8SNickeau ); 5731fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 574*c3437056SNickeau return $mediaLink->toHtmlEnterTag("a") . $this->renderMediaTag() . "</a>"; 57537748cd8SNickeau 57637748cd8SNickeau case self::LINKING_DETAILS_VALUE: 57737748cd8SNickeau //go to the details media viewer 57837748cd8SNickeau $src = ml( 579*c3437056SNickeau $dokuPath->getDokuwikiId(), 58037748cd8SNickeau array( 581*c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5821fa8c418SNickeau 'cache' => $media->getCache(), 583*c3437056SNickeau 'rev' => $dokuPath->getRevision() 58437748cd8SNickeau ), 58537748cd8SNickeau false 58637748cd8SNickeau ); 5871fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 5881fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . 58937748cd8SNickeau $this->renderMediaTag() . 59037748cd8SNickeau "</a>"; 59137748cd8SNickeau 59237748cd8SNickeau } 59337748cd8SNickeau 59437748cd8SNickeau 59537748cd8SNickeau } 59637748cd8SNickeau 59737748cd8SNickeau 59837748cd8SNickeau /** 59937748cd8SNickeau * @return string - the HTML of the image 60037748cd8SNickeau */ 601*c3437056SNickeau public 602*c3437056SNickeau 603*c3437056SNickeau abstract function renderMediaTag(): string; 6041fa8c418SNickeau 60537748cd8SNickeau 60637748cd8SNickeau /** 6071fa8c418SNickeau * The file 6081fa8c418SNickeau * @return Media 60937748cd8SNickeau */ 6101fa8c418SNickeau public function getMedia(): Media 6111fa8c418SNickeau { 6121fa8c418SNickeau return $this->media; 6131fa8c418SNickeau } 61437748cd8SNickeau 61537748cd8SNickeau 61637748cd8SNickeau} 617