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; 16c3437056SNickeauuse dokuwiki\Parsing\ParserMode\Internallink; 17*82a60d03SNickeauuse syntax_plugin_combo_card; 1837748cd8SNickeauuse syntax_plugin_combo_media; 1937748cd8SNickeau 201fa8c418SNickeaurequire_once(__DIR__ . '/PluginUtility.php'); 2137748cd8SNickeau 2237748cd8SNickeau/** 2337748cd8SNickeau * Class InternalMedia 2437748cd8SNickeau * Represent a media link 2537748cd8SNickeau * 2637748cd8SNickeau * 2737748cd8SNickeau * @package ComboStrap 2837748cd8SNickeau * 2937748cd8SNickeau * Wrapper around {@link Doku_Handler_Parse_Media} 3037748cd8SNickeau * 3137748cd8SNickeau * Not that for dokuwiki the `type` key of the attributes is the `call` 3237748cd8SNickeau * and therefore determine the function in an render 3337748cd8SNickeau * (ie {@link \Doku_Renderer::internalmedialink()} or {@link \Doku_Renderer::externalmedialink()} 3437748cd8SNickeau * 351fa8c418SNickeau * This is a link to a media (pdf, image, ...). 361fa8c418SNickeau * It's used to check the media type and to 371fa8c418SNickeau * take over if the media type is an image 3837748cd8SNickeau */ 391fa8c418SNickeauabstract class MediaLink 4037748cd8SNickeau{ 4137748cd8SNickeau 4237748cd8SNickeau 4337748cd8SNickeau /** 4437748cd8SNickeau * The dokuwiki type and mode name 4537748cd8SNickeau * (ie call) 4637748cd8SNickeau * * ie {@link MediaLink::EXTERNAL_MEDIA_CALL_NAME} 4737748cd8SNickeau * or {@link MediaLink::INTERNAL_MEDIA_CALL_NAME} 4837748cd8SNickeau * 4937748cd8SNickeau * The dokuwiki type (internalmedia/externalmedia) 5037748cd8SNickeau * is saved in a `type` key that clash with the 5137748cd8SNickeau * combostrap type. To avoid the clash, we renamed it 5237748cd8SNickeau */ 5337748cd8SNickeau const MEDIA_DOKUWIKI_TYPE = 'dokuwiki_type'; 5437748cd8SNickeau const INTERNAL_MEDIA_CALL_NAME = "internalmedia"; 5537748cd8SNickeau const EXTERNAL_MEDIA_CALL_NAME = "externalmedia"; 5637748cd8SNickeau 5737748cd8SNickeau const CANONICAL = "image"; 5837748cd8SNickeau 5937748cd8SNickeau /** 6037748cd8SNickeau * This attributes does not apply 6137748cd8SNickeau * to a URL 6237748cd8SNickeau * They are only for the tag (img, svg, ...) 6337748cd8SNickeau * or internal 6437748cd8SNickeau */ 6537748cd8SNickeau const NON_URL_ATTRIBUTES = [ 661fa8c418SNickeau MediaLink::ALIGN_KEY, 671fa8c418SNickeau MediaLink::LINKING_KEY, 6837748cd8SNickeau TagAttributes::TITLE_KEY, 6937748cd8SNickeau Hover::ON_HOVER_ATTRIBUTE, 7037748cd8SNickeau Animation::ON_VIEW_ATTRIBUTE, 7137748cd8SNickeau MediaLink::MEDIA_DOKUWIKI_TYPE, 7237748cd8SNickeau MediaLink::DOKUWIKI_SRC 7337748cd8SNickeau ]; 7437748cd8SNickeau 7537748cd8SNickeau /** 7637748cd8SNickeau * This attribute applies 7737748cd8SNickeau * to a image url (img, svg, ...) 7837748cd8SNickeau */ 7937748cd8SNickeau const URL_ATTRIBUTES = [ 8037748cd8SNickeau Dimension::WIDTH_KEY, 8137748cd8SNickeau Dimension::HEIGHT_KEY, 8237748cd8SNickeau CacheMedia::CACHE_KEY, 8337748cd8SNickeau ]; 8437748cd8SNickeau 8537748cd8SNickeau /** 8637748cd8SNickeau * Default image linking value 8737748cd8SNickeau */ 8837748cd8SNickeau const CONF_DEFAULT_LINKING = "defaultImageLinking"; 8937748cd8SNickeau const LINKING_LINKONLY_VALUE = "linkonly"; 9037748cd8SNickeau const LINKING_DETAILS_VALUE = 'details'; 9137748cd8SNickeau const LINKING_NOLINK_VALUE = 'nolink'; 9237748cd8SNickeau 9337748cd8SNickeau /** 9437748cd8SNickeau * @deprecated 2021-06-12 9537748cd8SNickeau */ 9637748cd8SNickeau const LINK_PATTERN = "{{\s*([^|\s]*)\s*\|?.*}}"; 9737748cd8SNickeau 9837748cd8SNickeau const LINKING_DIRECT_VALUE = 'direct'; 9937748cd8SNickeau 10037748cd8SNickeau /** 10137748cd8SNickeau * Only used by Dokuwiki 10237748cd8SNickeau * Contains the path and eventually an anchor 10337748cd8SNickeau * never query parameters 10437748cd8SNickeau */ 10537748cd8SNickeau const DOKUWIKI_SRC = "src"; 10637748cd8SNickeau /** 10737748cd8SNickeau * Link value: 10837748cd8SNickeau * * 'nolink' 10937748cd8SNickeau * * 'direct': directly to the image 11037748cd8SNickeau * * 'linkonly': show only a url 11137748cd8SNickeau * * 'details': go to the details media viewer 11237748cd8SNickeau * 11337748cd8SNickeau * @var 11437748cd8SNickeau */ 11537748cd8SNickeau const LINKING_KEY = 'linking'; 11637748cd8SNickeau const ALIGN_KEY = 'align'; 11737748cd8SNickeau 11837748cd8SNickeau 11937748cd8SNickeau private $lazyLoad = null; 12037748cd8SNickeau 12137748cd8SNickeau 12237748cd8SNickeau /** 1231fa8c418SNickeau * The path of the media 1241fa8c418SNickeau * @var Media[] 12537748cd8SNickeau */ 1261fa8c418SNickeau private $media; 12737748cd8SNickeau 12837748cd8SNickeau 12937748cd8SNickeau /** 13037748cd8SNickeau * Image constructor. 1311fa8c418SNickeau * @param Image $media 13237748cd8SNickeau * 13337748cd8SNickeau * Protected and not private 13437748cd8SNickeau * to allow cascading init 13537748cd8SNickeau * If private, the parent attributes are null 13637748cd8SNickeau */ 1371fa8c418SNickeau protected function __construct(Media $media) 13837748cd8SNickeau { 1391fa8c418SNickeau $this->media = $media; 14037748cd8SNickeau } 14137748cd8SNickeau 14237748cd8SNickeau 14337748cd8SNickeau /** 144c3437056SNickeau * Create an image from dokuwiki {@link Internallink internal call media attributes} 145c3437056SNickeau * 146c3437056SNickeau * Dokuwiki extracts already the width, height and align property 14737748cd8SNickeau * @param array $callAttributes 14837748cd8SNickeau * @return MediaLink 14937748cd8SNickeau */ 15037748cd8SNickeau public static function createFromIndexAttributes(array $callAttributes) 15137748cd8SNickeau { 152c3437056SNickeau $src = $callAttributes[0]; 15337748cd8SNickeau $title = $callAttributes[1]; 15437748cd8SNickeau $align = $callAttributes[2]; 15537748cd8SNickeau $width = $callAttributes[3]; 15637748cd8SNickeau $height = $callAttributes[4]; 15737748cd8SNickeau $cache = $callAttributes[5]; 15837748cd8SNickeau $linking = $callAttributes[6]; 15937748cd8SNickeau 16037748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 16137748cd8SNickeau $tagAttributes->addComponentAttributeValue(TagAttributes::TITLE_KEY, $title); 16237748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::ALIGN_KEY, $align); 16337748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::WIDTH_KEY, $width); 16437748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::HEIGHT_KEY, $height); 16537748cd8SNickeau $tagAttributes->addComponentAttributeValue(CacheMedia::CACHE_KEY, $cache); 16637748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::LINKING_KEY, $linking); 16737748cd8SNickeau 168c3437056SNickeau return self::createMediaLinkFromId($src, $tagAttributes); 16937748cd8SNickeau 17037748cd8SNickeau } 17137748cd8SNickeau 17237748cd8SNickeau /** 17337748cd8SNickeau * A function to explicitly create an internal media from 17437748cd8SNickeau * a call stack array (ie key string and value) that we get in the {@link SyntaxPlugin::render()} 17537748cd8SNickeau * from the {@link MediaLink::toCallStackArray()} 17637748cd8SNickeau * 17737748cd8SNickeau * @param $attributes - the attributes created by the function {@link MediaLink::getParseAttributes()} 17837748cd8SNickeau * @param $rev - the mtime 179c3437056SNickeau * @return null|MediaLink 18037748cd8SNickeau */ 181c3437056SNickeau public static function createFromCallStackArray($attributes, $rev = null): ?MediaLink 18237748cd8SNickeau { 18337748cd8SNickeau 18437748cd8SNickeau if (!is_array($attributes)) { 18537748cd8SNickeau // Debug for the key_exist below because of the following message: 18637748cd8SNickeau // `PHP Warning: key_exists() expects parameter 2 to be array, array given` 18737748cd8SNickeau LogUtility::msg("The `attributes` parameter is not an array. Value ($attributes)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 18837748cd8SNickeau } 18937748cd8SNickeau 19037748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 19137748cd8SNickeau 192c3437056SNickeau $src = $attributes[self::DOKUWIKI_SRC]; 193c3437056SNickeau if ($src === null) { 194c3437056SNickeau /** 195c3437056SNickeau * Dokuwiki parse already the src and create the path and the attributes 196c3437056SNickeau * The new model will not, we check if we are in the old mode 197c3437056SNickeau */ 198c3437056SNickeau $src = $attributes[PagePath::PROPERTY_NAME]; 199c3437056SNickeau if ($src === null) { 200c3437056SNickeau LogUtility::msg("src is mandatory for an image link and was not passed"); 201c3437056SNickeau return null; 202c3437056SNickeau } 203c3437056SNickeau } 204c3437056SNickeau $dokuUrl = DokuwikiUrl::createFromUrl($src); 205c3437056SNickeau $scheme = $dokuUrl->getScheme(); 206c3437056SNickeau switch ($scheme) { 207c3437056SNickeau case DokuFs::SCHEME: 208c3437056SNickeau $id = $dokuUrl->getPath(); 209c3437056SNickeau // the id is always absolute, except in a link 210c3437056SNickeau // It may be relative, transform it as absolute 211c3437056SNickeau global $ID; 212c3437056SNickeau resolve_mediaid(getNS($ID), $id, $exists); 213c3437056SNickeau $path = DokuPath::createMediaPathFromId($id, $rev); 214c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 215c3437056SNickeau case InterWikiPath::scheme: 216c3437056SNickeau $path = InterWikiPath::create($dokuUrl->getPath()); 217c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 218c3437056SNickeau case InternetPath::scheme: 219c3437056SNickeau $path = InternetPath::create($dokuUrl->getPath()); 220c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 221c3437056SNickeau default: 222c3437056SNickeau LogUtility::msg("The media with the scheme ($scheme) are not yet supported. Media Source: $src"); 223c3437056SNickeau return null; 22437748cd8SNickeau 225c3437056SNickeau } 226c3437056SNickeau 22737748cd8SNickeau 22837748cd8SNickeau } 22937748cd8SNickeau 23037748cd8SNickeau /** 23137748cd8SNickeau * @param $match - the match of the renderer (just a shortcut) 23237748cd8SNickeau * @return MediaLink 23337748cd8SNickeau */ 23437748cd8SNickeau public static function createFromRenderMatch($match) 23537748cd8SNickeau { 23637748cd8SNickeau 23737748cd8SNickeau /** 23837748cd8SNickeau * The parsing function {@link Doku_Handler_Parse_Media} has some flow / problem 23937748cd8SNickeau * * It keeps the anchor only if there is no query string 24037748cd8SNickeau * * It takes the first digit as the width (ie media.pdf?page=31 would have a width of 31) 24137748cd8SNickeau * * `src` is not only the media path but may have a anchor 24237748cd8SNickeau * We parse it then 24337748cd8SNickeau */ 24437748cd8SNickeau 24537748cd8SNickeau 24637748cd8SNickeau /** 24737748cd8SNickeau * * Delete the opening and closing character 24837748cd8SNickeau * * create the url and description 24937748cd8SNickeau */ 25037748cd8SNickeau $match = preg_replace(array('/^\{\{/', '/\}\}$/u'), '', $match); 25137748cd8SNickeau $parts = explode('|', $match, 2); 25237748cd8SNickeau $description = null; 25337748cd8SNickeau $url = $parts[0]; 25437748cd8SNickeau if (isset($parts[1])) { 25537748cd8SNickeau $description = $parts[1]; 25637748cd8SNickeau } 25737748cd8SNickeau 25837748cd8SNickeau /** 25937748cd8SNickeau * Media Alignment 26037748cd8SNickeau */ 26137748cd8SNickeau $rightAlign = (bool)preg_match('/^ /', $url); 26237748cd8SNickeau $leftAlign = (bool)preg_match('/ $/', $url); 26337748cd8SNickeau $url = trim($url); 26437748cd8SNickeau 26537748cd8SNickeau // Logic = what's that ;)... 26637748cd8SNickeau if ($leftAlign & $rightAlign) { 26737748cd8SNickeau $align = 'center'; 26837748cd8SNickeau } else if ($rightAlign) { 26937748cd8SNickeau $align = 'right'; 27037748cd8SNickeau } else if ($leftAlign) { 27137748cd8SNickeau $align = 'left'; 27237748cd8SNickeau } else { 27337748cd8SNickeau $align = null; 27437748cd8SNickeau } 27537748cd8SNickeau 27637748cd8SNickeau /** 27737748cd8SNickeau * The combo attributes array 27837748cd8SNickeau */ 279c3437056SNickeau $dokuwikiUrl = DokuwikiUrl::createFromUrl($url); 280c3437056SNickeau $parsedAttributes = $dokuwikiUrl->toArray(); 281c3437056SNickeau $path = $dokuwikiUrl->getPath(); 282c3437056SNickeau $linkingKey = $dokuwikiUrl->getQueryParameter(MediaLink::LINKING_KEY); 283c3437056SNickeau if ($linkingKey === null) { 284c3437056SNickeau $linkingKey = PluginUtility::getConfValue(self::CONF_DEFAULT_LINKING, self::LINKING_DIRECT_VALUE); 28537748cd8SNickeau } 286c3437056SNickeau $parsedAttributes[MediaLink::LINKING_KEY] = $linkingKey; 28737748cd8SNickeau 28837748cd8SNickeau /** 28937748cd8SNickeau * Media Type 29037748cd8SNickeau */ 291c3437056SNickeau $scheme = $dokuwikiUrl->getScheme(); 292c3437056SNickeau if ($scheme === DokuFs::SCHEME) { 29337748cd8SNickeau $mediaType = MediaLink::INTERNAL_MEDIA_CALL_NAME; 294c3437056SNickeau } else { 295c3437056SNickeau $mediaType = MediaLink::EXTERNAL_MEDIA_CALL_NAME; 29637748cd8SNickeau } 29737748cd8SNickeau 29837748cd8SNickeau 29937748cd8SNickeau /** 30037748cd8SNickeau * src in dokuwiki is the path and the anchor if any 30137748cd8SNickeau */ 30237748cd8SNickeau $src = $path; 30337748cd8SNickeau if (isset($parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]) != null) { 30437748cd8SNickeau $src = $src . "#" . $parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]; 30537748cd8SNickeau } 30637748cd8SNickeau 30737748cd8SNickeau /** 30837748cd8SNickeau * To avoid clash with the combostrap component type 30937748cd8SNickeau * ie this is also a ComboStrap attribute where we set the type of a SVG (icon, illustration, background) 31037748cd8SNickeau * we store the media type (ie external/internal) in another key 31137748cd8SNickeau * 31237748cd8SNickeau * There is no need to repeat the attributes as the arrays are merged 31337748cd8SNickeau * into on but this is also an informal code to show which attributes 31437748cd8SNickeau * are only Dokuwiki Native 31537748cd8SNickeau * 31637748cd8SNickeau */ 31737748cd8SNickeau $dokuwikiAttributes = array( 31837748cd8SNickeau self::MEDIA_DOKUWIKI_TYPE => $mediaType, 31937748cd8SNickeau self::DOKUWIKI_SRC => $src, 32037748cd8SNickeau Dimension::WIDTH_KEY => $parsedAttributes[Dimension::WIDTH_KEY], 32137748cd8SNickeau Dimension::HEIGHT_KEY => $parsedAttributes[Dimension::HEIGHT_KEY], 32237748cd8SNickeau CacheMedia::CACHE_KEY => $parsedAttributes[CacheMedia::CACHE_KEY], 3231fa8c418SNickeau TagAttributes::TITLE_KEY => $description, 32437748cd8SNickeau MediaLink::ALIGN_KEY => $align, 32537748cd8SNickeau MediaLink::LINKING_KEY => $parsedAttributes[MediaLink::LINKING_KEY], 32637748cd8SNickeau ); 32737748cd8SNickeau 32837748cd8SNickeau /** 32937748cd8SNickeau * Merge standard dokuwiki attributes and 33037748cd8SNickeau * parsed attributes 33137748cd8SNickeau */ 33237748cd8SNickeau $mergedAttributes = PluginUtility::mergeAttributes($dokuwikiAttributes, $parsedAttributes); 33337748cd8SNickeau 33437748cd8SNickeau /** 33537748cd8SNickeau * If this is an internal media, 33637748cd8SNickeau * we are using our implementation 33737748cd8SNickeau * and we have a change on attribute specification 33837748cd8SNickeau */ 33937748cd8SNickeau if ($mediaType == MediaLink::INTERNAL_MEDIA_CALL_NAME) { 34037748cd8SNickeau 34137748cd8SNickeau /** 34237748cd8SNickeau * The align attribute on an image parse 34337748cd8SNickeau * is a float right 34437748cd8SNickeau * ComboStrap does a difference between a block right and a float right 34537748cd8SNickeau */ 34637748cd8SNickeau if ($mergedAttributes[self::ALIGN_KEY] === "right") { 34737748cd8SNickeau unset($mergedAttributes[self::ALIGN_KEY]); 34837748cd8SNickeau $mergedAttributes[FloatAttribute::FLOAT_KEY] = "right"; 34937748cd8SNickeau } 35037748cd8SNickeau 35137748cd8SNickeau 35237748cd8SNickeau } 35337748cd8SNickeau 35437748cd8SNickeau return self::createFromCallStackArray($mergedAttributes); 35537748cd8SNickeau 35637748cd8SNickeau } 35737748cd8SNickeau 35837748cd8SNickeau 35937748cd8SNickeau public 360c3437056SNickeau function setLazyLoad($false): MediaLink 36137748cd8SNickeau { 36237748cd8SNickeau $this->lazyLoad = $false; 363c3437056SNickeau return $this; 36437748cd8SNickeau } 36537748cd8SNickeau 36637748cd8SNickeau public 36737748cd8SNickeau function getLazyLoad() 36837748cd8SNickeau { 36937748cd8SNickeau return $this->lazyLoad; 37037748cd8SNickeau } 37137748cd8SNickeau 37237748cd8SNickeau 37337748cd8SNickeau /** 374c3437056SNickeau * Create a media link from a wiki id 37537748cd8SNickeau * 37637748cd8SNickeau * 377c3437056SNickeau * @param $wikiId - dokuwiki id 378c3437056SNickeau * @param TagAttributes|null $tagAttributes 379c3437056SNickeau * @param string|null $rev 38037748cd8SNickeau * @return MediaLink 38137748cd8SNickeau */ 38237748cd8SNickeau public 383c3437056SNickeau static function createMediaLinkFromId($wikiId, ?string $rev = '', TagAttributes $tagAttributes = null) 38437748cd8SNickeau { 38537748cd8SNickeau if (is_object($rev)) { 38637748cd8SNickeau LogUtility::msg("rev should not be an object", LogUtility::LVL_MSG_ERROR, "support"); 38737748cd8SNickeau } 38837748cd8SNickeau if ($tagAttributes == null) { 38937748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 39037748cd8SNickeau } else { 39137748cd8SNickeau if (!($tagAttributes instanceof TagAttributes)) { 39237748cd8SNickeau LogUtility::msg("TagAttributes is not an instance of Tag Attributes", LogUtility::LVL_MSG_ERROR, "support"); 39337748cd8SNickeau } 39437748cd8SNickeau } 39537748cd8SNickeau 396c3437056SNickeau $dokuPath = DokuPath::createMediaPathFromId($wikiId, $rev); 397c3437056SNickeau return self::createMediaLinkFromPath($dokuPath, $tagAttributes); 398c3437056SNickeau 399c3437056SNickeau } 400c3437056SNickeau 40137748cd8SNickeau /** 402c3437056SNickeau * @param Path $path 403c3437056SNickeau * @param null $tagAttributes 404c3437056SNickeau * @return RasterImageLink|SvgImageLink|ThirdMediaLink 40537748cd8SNickeau */ 406c3437056SNickeau public static function createMediaLinkFromPath(Path $path, $tagAttributes = null) 4071fa8c418SNickeau { 408c3437056SNickeau 40937748cd8SNickeau /** 41037748cd8SNickeau * Processing 41137748cd8SNickeau */ 412c3437056SNickeau $mime = $path->getMime(); 413c3437056SNickeau if ($path->getExtension() === "svg") { 41437748cd8SNickeau /** 41537748cd8SNickeau * The mime type is set when uploading, not when 41637748cd8SNickeau * viewing. 41737748cd8SNickeau * Because they are internal image, the svg was already uploaded 41837748cd8SNickeau * Therefore, no authorization scheme here 41937748cd8SNickeau */ 420c3437056SNickeau $mime = Mime::create(Mime::SVG); 42137748cd8SNickeau } 42237748cd8SNickeau 423c3437056SNickeau if ($mime === null) { 424c3437056SNickeau 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); 425c3437056SNickeau $media = new ImageRaster($path, $tagAttributes); 426c3437056SNickeau return new RasterImageLink($media); 42737748cd8SNickeau } 42837748cd8SNickeau 429c3437056SNickeau if (!$mime->isImage()) { 430c3437056SNickeau LogUtility::msg("The type ($mime) of media ($path) is not an image", LogUtility::LVL_MSG_DEBUG, "image"); 431c3437056SNickeau $media = new ThirdMedia($path, $tagAttributes); 432c3437056SNickeau return new ThirdMediaLink($media); 433c3437056SNickeau } 434c3437056SNickeau 435c3437056SNickeau if ($mime->toString() === Mime::SVG) { 436c3437056SNickeau $media = new ImageSvg($path, $tagAttributes); 437c3437056SNickeau return new SvgImageLink($media); 438c3437056SNickeau } 439c3437056SNickeau 440c3437056SNickeau $media = new ImageRaster($path, $tagAttributes); 441c3437056SNickeau return new RasterImageLink($media); 442c3437056SNickeau 443c3437056SNickeau 44437748cd8SNickeau } 44537748cd8SNickeau 44637748cd8SNickeau 44737748cd8SNickeau /** 44837748cd8SNickeau * A function to set explicitly which array format 44937748cd8SNickeau * is used in the returned data of a {@link SyntaxPlugin::handle()} 45037748cd8SNickeau * (which ultimately is stored in the {@link CallStack) 45137748cd8SNickeau * 45237748cd8SNickeau * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()} 45337748cd8SNickeau * that is indexed by number (ie without property name) 45437748cd8SNickeau * 45537748cd8SNickeau * 45637748cd8SNickeau * Return the same array than with the {@link self::parse()} method 45737748cd8SNickeau * that is used in the {@link CallStack} 45837748cd8SNickeau * 45937748cd8SNickeau * @return array of key string and value 46037748cd8SNickeau */ 461c3437056SNickeau public 462c3437056SNickeau function toCallStackArray(): array 46337748cd8SNickeau { 46437748cd8SNickeau /** 46537748cd8SNickeau * Trying to stay inline with the dokuwiki key 46637748cd8SNickeau * We use the 'src' attributes as id 46737748cd8SNickeau * 46837748cd8SNickeau * src is a path (not an id) 46937748cd8SNickeau */ 47037748cd8SNickeau $array = array( 471c3437056SNickeau PagePath::PROPERTY_NAME => $this->getMedia()->getPath()->toString() 47237748cd8SNickeau ); 47337748cd8SNickeau 47437748cd8SNickeau 47537748cd8SNickeau // Add the extra attribute 4761fa8c418SNickeau return array_merge($this->getMedia()->getAttributes()->toCallStackArray(), $array); 47737748cd8SNickeau 47837748cd8SNickeau 47937748cd8SNickeau } 48037748cd8SNickeau 48137748cd8SNickeau 48237748cd8SNickeau public 48337748cd8SNickeau static function isInternalMediaSyntax($text) 48437748cd8SNickeau { 48537748cd8SNickeau return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text); 48637748cd8SNickeau } 48737748cd8SNickeau 48837748cd8SNickeau 48937748cd8SNickeau public 49037748cd8SNickeau function __toString() 49137748cd8SNickeau { 492c3437056SNickeau $media = $this->getMedia(); 493c3437056SNickeau $dokuPath = $media->getPath(); 494c3437056SNickeau if ($dokuPath !== null) { 495c3437056SNickeau return $dokuPath->getDokuwikiId(); 496c3437056SNickeau } else { 497c3437056SNickeau return $media->__toString(); 498c3437056SNickeau } 49937748cd8SNickeau } 50037748cd8SNickeau 50137748cd8SNickeau private 50237748cd8SNickeau function getAlign() 50337748cd8SNickeau { 5041fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::ALIGN_KEY); 50537748cd8SNickeau } 50637748cd8SNickeau 50737748cd8SNickeau private 50837748cd8SNickeau function getLinking() 50937748cd8SNickeau { 5101fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::LINKING_KEY); 51137748cd8SNickeau } 51237748cd8SNickeau 51337748cd8SNickeau 51437748cd8SNickeau /** 51537748cd8SNickeau * @return string - the HTML of the image inside a link if asked 51637748cd8SNickeau */ 51737748cd8SNickeau public 5181fa8c418SNickeau function renderMediaTagWithLink(): string 51937748cd8SNickeau { 52037748cd8SNickeau 52137748cd8SNickeau /** 52237748cd8SNickeau * Link to the media 52337748cd8SNickeau * 52437748cd8SNickeau */ 5251fa8c418SNickeau $mediaLink = TagAttributes::createEmpty(); 52637748cd8SNickeau // https://www.dokuwiki.org/config:target 52737748cd8SNickeau global $conf; 52837748cd8SNickeau $target = $conf['target']['media']; 5291fa8c418SNickeau $mediaLink->addHtmlAttributeValueIfNotEmpty("target", $target); 53037748cd8SNickeau if (!empty($target)) { 5311fa8c418SNickeau $mediaLink->addHtmlAttributeValue("rel", 'noopener'); 53237748cd8SNickeau } 53337748cd8SNickeau 53437748cd8SNickeau /** 53537748cd8SNickeau * Do we add a link to the image ? 53637748cd8SNickeau */ 5371fa8c418SNickeau $media = $this->getMedia(); 538c3437056SNickeau $dokuPath = $media->getPath(); 539c3437056SNickeau if (!($dokuPath instanceof DokuPath)) { 540c3437056SNickeau LogUtility::msg("Media Link are only supported on media from the internal library ($media)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 541c3437056SNickeau return ""; 542c3437056SNickeau } 5431fa8c418SNickeau $linking = $this->getLinking(); 54437748cd8SNickeau switch ($linking) { 54537748cd8SNickeau case self::LINKING_LINKONLY_VALUE: // show only a url 54637748cd8SNickeau $src = ml( 547c3437056SNickeau $dokuPath->getDokuwikiId(), 54837748cd8SNickeau array( 549c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5501fa8c418SNickeau 'cache' => $media->getCache(), 551c3437056SNickeau 'rev' => $dokuPath->getRevision() 55237748cd8SNickeau ) 55337748cd8SNickeau ); 5541fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 5551fa8c418SNickeau $title = $media->getTitle(); 55637748cd8SNickeau if (empty($title)) { 557c3437056SNickeau $title = $media->getType(); 55837748cd8SNickeau } 5591fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . $title . "</a>"; 56037748cd8SNickeau case self::LINKING_NOLINK_VALUE: 56137748cd8SNickeau return $this->renderMediaTag(); 56237748cd8SNickeau default: 56337748cd8SNickeau case self::LINKING_DIRECT_VALUE: 56437748cd8SNickeau //directly to the image 56537748cd8SNickeau $src = ml( 566c3437056SNickeau $dokuPath->getDokuwikiId(), 56737748cd8SNickeau array( 568c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5691fa8c418SNickeau 'cache' => $media->getCache(), 570c3437056SNickeau 'rev' => $dokuPath->getRevision() 57137748cd8SNickeau ), 57237748cd8SNickeau true 57337748cd8SNickeau ); 5741fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 575c3437056SNickeau return $mediaLink->toHtmlEnterTag("a") . $this->renderMediaTag() . "</a>"; 57637748cd8SNickeau 57737748cd8SNickeau case self::LINKING_DETAILS_VALUE: 57837748cd8SNickeau //go to the details media viewer 57937748cd8SNickeau $src = ml( 580c3437056SNickeau $dokuPath->getDokuwikiId(), 58137748cd8SNickeau array( 582c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 5831fa8c418SNickeau 'cache' => $media->getCache(), 584c3437056SNickeau 'rev' => $dokuPath->getRevision() 58537748cd8SNickeau ), 58637748cd8SNickeau false 58737748cd8SNickeau ); 5881fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 5891fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . 59037748cd8SNickeau $this->renderMediaTag() . 59137748cd8SNickeau "</a>"; 59237748cd8SNickeau 59337748cd8SNickeau } 59437748cd8SNickeau 59537748cd8SNickeau 59637748cd8SNickeau } 59737748cd8SNickeau 59837748cd8SNickeau 59937748cd8SNickeau /** 60037748cd8SNickeau * @return string - the HTML of the image 60137748cd8SNickeau */ 602c3437056SNickeau public 603c3437056SNickeau 604c3437056SNickeau abstract function renderMediaTag(): string; 6051fa8c418SNickeau 60637748cd8SNickeau 60737748cd8SNickeau /** 6081fa8c418SNickeau * The file 6091fa8c418SNickeau * @return Media 61037748cd8SNickeau */ 6111fa8c418SNickeau public function getMedia(): Media 6121fa8c418SNickeau { 6131fa8c418SNickeau return $this->media; 6141fa8c418SNickeau } 61537748cd8SNickeau 61637748cd8SNickeau 617*82a60d03SNickeau 61837748cd8SNickeau} 619