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 15*4cadd4f8SNickeauuse dokuwiki\Action\Plugin; 1637748cd8SNickeauuse dokuwiki\Extension\SyntaxPlugin; 17c3437056SNickeauuse dokuwiki\Parsing\ParserMode\Internallink; 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 118*4cadd4f8SNickeau /** 119*4cadd4f8SNickeau * The method to lazy load resources (Ie media) 120*4cadd4f8SNickeau */ 121*4cadd4f8SNickeau const LAZY_LOAD_METHOD = "lazy-method"; 122*4cadd4f8SNickeau const LAZY_LOAD_METHOD_HTML_VALUE = "html-attribute"; 123*4cadd4f8SNickeau const LAZY_LOAD_METHOD_LOZAD_VALUE = "lozad"; 124*4cadd4f8SNickeau const UNKNOWN_MIME = "unknwon"; 125*4cadd4f8SNickeau /** 126*4cadd4f8SNickeau * @var string 127*4cadd4f8SNickeau */ 128*4cadd4f8SNickeau private $lazyLoadMethod; 12937748cd8SNickeau 13037748cd8SNickeau private $lazyLoad = null; 13137748cd8SNickeau 13237748cd8SNickeau 13337748cd8SNickeau /** 1341fa8c418SNickeau * The path of the media 1351fa8c418SNickeau * @var Media[] 13637748cd8SNickeau */ 1371fa8c418SNickeau private $media; 138*4cadd4f8SNickeau private $linking; 139*4cadd4f8SNickeau private $linkingClass; 14037748cd8SNickeau 14137748cd8SNickeau 14237748cd8SNickeau /** 14337748cd8SNickeau * Image constructor. 1441fa8c418SNickeau * @param Image $media 14537748cd8SNickeau * 14637748cd8SNickeau * Protected and not private 14737748cd8SNickeau * to allow cascading init 14837748cd8SNickeau * If private, the parent attributes are null 14937748cd8SNickeau */ 1501fa8c418SNickeau protected function __construct(Media $media) 15137748cd8SNickeau { 1521fa8c418SNickeau $this->media = $media; 15337748cd8SNickeau } 15437748cd8SNickeau 15537748cd8SNickeau 15637748cd8SNickeau /** 157c3437056SNickeau * Create an image from dokuwiki {@link Internallink internal call media attributes} 158c3437056SNickeau * 159c3437056SNickeau * Dokuwiki extracts already the width, height and align property 16037748cd8SNickeau * @param array $callAttributes 16137748cd8SNickeau * @return MediaLink 16237748cd8SNickeau */ 16337748cd8SNickeau public static function createFromIndexAttributes(array $callAttributes) 16437748cd8SNickeau { 165c3437056SNickeau $src = $callAttributes[0]; 16637748cd8SNickeau $title = $callAttributes[1]; 16737748cd8SNickeau $align = $callAttributes[2]; 16837748cd8SNickeau $width = $callAttributes[3]; 16937748cd8SNickeau $height = $callAttributes[4]; 17037748cd8SNickeau $cache = $callAttributes[5]; 17137748cd8SNickeau $linking = $callAttributes[6]; 17237748cd8SNickeau 17337748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 17437748cd8SNickeau $tagAttributes->addComponentAttributeValue(TagAttributes::TITLE_KEY, $title); 17537748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::ALIGN_KEY, $align); 17637748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::WIDTH_KEY, $width); 17737748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::HEIGHT_KEY, $height); 17837748cd8SNickeau $tagAttributes->addComponentAttributeValue(CacheMedia::CACHE_KEY, $cache); 17937748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::LINKING_KEY, $linking); 18037748cd8SNickeau 181c3437056SNickeau return self::createMediaLinkFromId($src, $tagAttributes); 18237748cd8SNickeau 18337748cd8SNickeau } 18437748cd8SNickeau 18537748cd8SNickeau /** 18637748cd8SNickeau * A function to explicitly create an internal media from 18737748cd8SNickeau * a call stack array (ie key string and value) that we get in the {@link SyntaxPlugin::render()} 18837748cd8SNickeau * from the {@link MediaLink::toCallStackArray()} 18937748cd8SNickeau * 19037748cd8SNickeau * @param $attributes - the attributes created by the function {@link MediaLink::getParseAttributes()} 19137748cd8SNickeau * @param $rev - the mtime 192c3437056SNickeau * @return null|MediaLink 19337748cd8SNickeau */ 194c3437056SNickeau public static function createFromCallStackArray($attributes, $rev = null): ?MediaLink 19537748cd8SNickeau { 19637748cd8SNickeau 19737748cd8SNickeau if (!is_array($attributes)) { 19837748cd8SNickeau // Debug for the key_exist below because of the following message: 19937748cd8SNickeau // `PHP Warning: key_exists() expects parameter 2 to be array, array given` 20037748cd8SNickeau LogUtility::msg("The `attributes` parameter is not an array. Value ($attributes)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 20137748cd8SNickeau } 20237748cd8SNickeau 20337748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 20437748cd8SNickeau 205c3437056SNickeau $src = $attributes[self::DOKUWIKI_SRC]; 206c3437056SNickeau if ($src === null) { 207c3437056SNickeau /** 208c3437056SNickeau * Dokuwiki parse already the src and create the path and the attributes 209c3437056SNickeau * The new model will not, we check if we are in the old mode 210c3437056SNickeau */ 211c3437056SNickeau $src = $attributes[PagePath::PROPERTY_NAME]; 212c3437056SNickeau if ($src === null) { 213c3437056SNickeau LogUtility::msg("src is mandatory for an image link and was not passed"); 214c3437056SNickeau return null; 215c3437056SNickeau } 216c3437056SNickeau } 217c3437056SNickeau $dokuUrl = DokuwikiUrl::createFromUrl($src); 218c3437056SNickeau $scheme = $dokuUrl->getScheme(); 219c3437056SNickeau switch ($scheme) { 220c3437056SNickeau case DokuFs::SCHEME: 221c3437056SNickeau $id = $dokuUrl->getPath(); 222c3437056SNickeau // the id is always absolute, except in a link 223c3437056SNickeau // It may be relative, transform it as absolute 224c3437056SNickeau global $ID; 225c3437056SNickeau resolve_mediaid(getNS($ID), $id, $exists); 226c3437056SNickeau $path = DokuPath::createMediaPathFromId($id, $rev); 227c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 228c3437056SNickeau case InterWikiPath::scheme: 229c3437056SNickeau $path = InterWikiPath::create($dokuUrl->getPath()); 230c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 231c3437056SNickeau case InternetPath::scheme: 232c3437056SNickeau $path = InternetPath::create($dokuUrl->getPath()); 233c3437056SNickeau return self::createMediaLinkFromPath($path, $tagAttributes); 234c3437056SNickeau default: 235c3437056SNickeau LogUtility::msg("The media with the scheme ($scheme) are not yet supported. Media Source: $src"); 236c3437056SNickeau return null; 23737748cd8SNickeau 238c3437056SNickeau } 239c3437056SNickeau 24037748cd8SNickeau 24137748cd8SNickeau } 24237748cd8SNickeau 24337748cd8SNickeau /** 24437748cd8SNickeau * @param $match - the match of the renderer (just a shortcut) 24537748cd8SNickeau * @return MediaLink 24637748cd8SNickeau */ 24737748cd8SNickeau public static function createFromRenderMatch($match) 24837748cd8SNickeau { 24937748cd8SNickeau 25037748cd8SNickeau /** 25137748cd8SNickeau * The parsing function {@link Doku_Handler_Parse_Media} has some flow / problem 25237748cd8SNickeau * * It keeps the anchor only if there is no query string 25337748cd8SNickeau * * It takes the first digit as the width (ie media.pdf?page=31 would have a width of 31) 25437748cd8SNickeau * * `src` is not only the media path but may have a anchor 25537748cd8SNickeau * We parse it then 25637748cd8SNickeau */ 25737748cd8SNickeau 25837748cd8SNickeau 25937748cd8SNickeau /** 26037748cd8SNickeau * * Delete the opening and closing character 26137748cd8SNickeau * * create the url and description 26237748cd8SNickeau */ 26337748cd8SNickeau $match = preg_replace(array('/^\{\{/', '/\}\}$/u'), '', $match); 26437748cd8SNickeau $parts = explode('|', $match, 2); 26537748cd8SNickeau $description = null; 26637748cd8SNickeau $url = $parts[0]; 26737748cd8SNickeau if (isset($parts[1])) { 26837748cd8SNickeau $description = $parts[1]; 26937748cd8SNickeau } 27037748cd8SNickeau 27137748cd8SNickeau /** 27237748cd8SNickeau * Media Alignment 27337748cd8SNickeau */ 27437748cd8SNickeau $rightAlign = (bool)preg_match('/^ /', $url); 27537748cd8SNickeau $leftAlign = (bool)preg_match('/ $/', $url); 27637748cd8SNickeau $url = trim($url); 27737748cd8SNickeau 27837748cd8SNickeau // Logic = what's that ;)... 27937748cd8SNickeau if ($leftAlign & $rightAlign) { 28037748cd8SNickeau $align = 'center'; 28137748cd8SNickeau } else if ($rightAlign) { 28237748cd8SNickeau $align = 'right'; 28337748cd8SNickeau } else if ($leftAlign) { 28437748cd8SNickeau $align = 'left'; 28537748cd8SNickeau } else { 28637748cd8SNickeau $align = null; 28737748cd8SNickeau } 28837748cd8SNickeau 28937748cd8SNickeau /** 29037748cd8SNickeau * The combo attributes array 29137748cd8SNickeau */ 292c3437056SNickeau $dokuwikiUrl = DokuwikiUrl::createFromUrl($url); 293c3437056SNickeau $parsedAttributes = $dokuwikiUrl->toArray(); 294c3437056SNickeau $path = $dokuwikiUrl->getPath(); 295c3437056SNickeau $linkingKey = $dokuwikiUrl->getQueryParameter(MediaLink::LINKING_KEY); 296c3437056SNickeau if ($linkingKey === null) { 297c3437056SNickeau $linkingKey = PluginUtility::getConfValue(self::CONF_DEFAULT_LINKING, self::LINKING_DIRECT_VALUE); 29837748cd8SNickeau } 299c3437056SNickeau $parsedAttributes[MediaLink::LINKING_KEY] = $linkingKey; 30037748cd8SNickeau 30137748cd8SNickeau /** 30237748cd8SNickeau * Media Type 30337748cd8SNickeau */ 304c3437056SNickeau $scheme = $dokuwikiUrl->getScheme(); 305c3437056SNickeau if ($scheme === DokuFs::SCHEME) { 30637748cd8SNickeau $mediaType = MediaLink::INTERNAL_MEDIA_CALL_NAME; 307c3437056SNickeau } else { 308c3437056SNickeau $mediaType = MediaLink::EXTERNAL_MEDIA_CALL_NAME; 30937748cd8SNickeau } 31037748cd8SNickeau 31137748cd8SNickeau 31237748cd8SNickeau /** 31337748cd8SNickeau * src in dokuwiki is the path and the anchor if any 31437748cd8SNickeau */ 31537748cd8SNickeau $src = $path; 31637748cd8SNickeau if (isset($parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]) != null) { 31737748cd8SNickeau $src = $src . "#" . $parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]; 31837748cd8SNickeau } 31937748cd8SNickeau 32037748cd8SNickeau /** 32137748cd8SNickeau * To avoid clash with the combostrap component type 32237748cd8SNickeau * ie this is also a ComboStrap attribute where we set the type of a SVG (icon, illustration, background) 32337748cd8SNickeau * we store the media type (ie external/internal) in another key 32437748cd8SNickeau * 32537748cd8SNickeau * There is no need to repeat the attributes as the arrays are merged 32637748cd8SNickeau * into on but this is also an informal code to show which attributes 32737748cd8SNickeau * are only Dokuwiki Native 32837748cd8SNickeau * 32937748cd8SNickeau */ 33037748cd8SNickeau $dokuwikiAttributes = array( 33137748cd8SNickeau self::MEDIA_DOKUWIKI_TYPE => $mediaType, 33237748cd8SNickeau self::DOKUWIKI_SRC => $src, 33337748cd8SNickeau Dimension::WIDTH_KEY => $parsedAttributes[Dimension::WIDTH_KEY], 33437748cd8SNickeau Dimension::HEIGHT_KEY => $parsedAttributes[Dimension::HEIGHT_KEY], 33537748cd8SNickeau CacheMedia::CACHE_KEY => $parsedAttributes[CacheMedia::CACHE_KEY], 3361fa8c418SNickeau TagAttributes::TITLE_KEY => $description, 33737748cd8SNickeau MediaLink::ALIGN_KEY => $align, 33837748cd8SNickeau MediaLink::LINKING_KEY => $parsedAttributes[MediaLink::LINKING_KEY], 33937748cd8SNickeau ); 34037748cd8SNickeau 34137748cd8SNickeau /** 34237748cd8SNickeau * Merge standard dokuwiki attributes and 34337748cd8SNickeau * parsed attributes 34437748cd8SNickeau */ 34537748cd8SNickeau $mergedAttributes = PluginUtility::mergeAttributes($dokuwikiAttributes, $parsedAttributes); 34637748cd8SNickeau 34737748cd8SNickeau /** 34837748cd8SNickeau * If this is an internal media, 34937748cd8SNickeau * we are using our implementation 35037748cd8SNickeau * and we have a change on attribute specification 35137748cd8SNickeau */ 35237748cd8SNickeau if ($mediaType == MediaLink::INTERNAL_MEDIA_CALL_NAME) { 35337748cd8SNickeau 35437748cd8SNickeau /** 35537748cd8SNickeau * The align attribute on an image parse 35637748cd8SNickeau * is a float right 35737748cd8SNickeau * ComboStrap does a difference between a block right and a float right 35837748cd8SNickeau */ 35937748cd8SNickeau if ($mergedAttributes[self::ALIGN_KEY] === "right") { 36037748cd8SNickeau unset($mergedAttributes[self::ALIGN_KEY]); 36137748cd8SNickeau $mergedAttributes[FloatAttribute::FLOAT_KEY] = "right"; 36237748cd8SNickeau } 36337748cd8SNickeau 36437748cd8SNickeau 36537748cd8SNickeau } 36637748cd8SNickeau 36737748cd8SNickeau return self::createFromCallStackArray($mergedAttributes); 36837748cd8SNickeau 36937748cd8SNickeau } 37037748cd8SNickeau 37137748cd8SNickeau 37237748cd8SNickeau public 373c3437056SNickeau function setLazyLoad($false): MediaLink 37437748cd8SNickeau { 37537748cd8SNickeau $this->lazyLoad = $false; 376c3437056SNickeau return $this; 37737748cd8SNickeau } 37837748cd8SNickeau 37937748cd8SNickeau public 38037748cd8SNickeau function getLazyLoad() 38137748cd8SNickeau { 38237748cd8SNickeau return $this->lazyLoad; 38337748cd8SNickeau } 38437748cd8SNickeau 38537748cd8SNickeau 38637748cd8SNickeau /** 387c3437056SNickeau * Create a media link from a wiki id 38837748cd8SNickeau * 38937748cd8SNickeau * 390c3437056SNickeau * @param $wikiId - dokuwiki id 391c3437056SNickeau * @param TagAttributes|null $tagAttributes 392c3437056SNickeau * @param string|null $rev 39337748cd8SNickeau * @return MediaLink 39437748cd8SNickeau */ 39537748cd8SNickeau public 396c3437056SNickeau static function createMediaLinkFromId($wikiId, ?string $rev = '', TagAttributes $tagAttributes = null) 39737748cd8SNickeau { 39837748cd8SNickeau if (is_object($rev)) { 39937748cd8SNickeau LogUtility::msg("rev should not be an object", LogUtility::LVL_MSG_ERROR, "support"); 40037748cd8SNickeau } 40137748cd8SNickeau if ($tagAttributes == null) { 40237748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 40337748cd8SNickeau } else { 40437748cd8SNickeau if (!($tagAttributes instanceof TagAttributes)) { 40537748cd8SNickeau LogUtility::msg("TagAttributes is not an instance of Tag Attributes", LogUtility::LVL_MSG_ERROR, "support"); 40637748cd8SNickeau } 40737748cd8SNickeau } 40837748cd8SNickeau 409c3437056SNickeau $dokuPath = DokuPath::createMediaPathFromId($wikiId, $rev); 410c3437056SNickeau return self::createMediaLinkFromPath($dokuPath, $tagAttributes); 411c3437056SNickeau 412c3437056SNickeau } 413c3437056SNickeau 41437748cd8SNickeau /** 415c3437056SNickeau * @param Path $path 416*4cadd4f8SNickeau * @param TagAttributes|null $tagAttributes 417c3437056SNickeau * @return RasterImageLink|SvgImageLink|ThirdMediaLink 41837748cd8SNickeau */ 419*4cadd4f8SNickeau public static function createMediaLinkFromPath(Path $path, TagAttributes $tagAttributes = null) 4201fa8c418SNickeau { 421c3437056SNickeau 422*4cadd4f8SNickeau if ($tagAttributes === null) { 423*4cadd4f8SNickeau $tagAttributes = TagAttributes::createEmpty(); 424*4cadd4f8SNickeau } 425*4cadd4f8SNickeau 426*4cadd4f8SNickeau /** 427*4cadd4f8SNickeau * Get and delete the attribute for the link 428*4cadd4f8SNickeau * (The rest is for the image) 429*4cadd4f8SNickeau */ 430*4cadd4f8SNickeau $lazyLoadMethod = $tagAttributes->getValueAndRemoveIfPresent(self::LAZY_LOAD_METHOD, self::LAZY_LOAD_METHOD_LOZAD_VALUE); 431*4cadd4f8SNickeau $linking = $tagAttributes->getValueAndRemoveIfPresent(self::LINKING_KEY); 432*4cadd4f8SNickeau $linkingClass = $tagAttributes->getValueAndRemoveIfPresent(syntax_plugin_combo_media::LINK_CLASS_ATTRIBUTE); 433*4cadd4f8SNickeau 43437748cd8SNickeau /** 43537748cd8SNickeau * Processing 43637748cd8SNickeau */ 437c3437056SNickeau $mime = $path->getMime(); 438c3437056SNickeau if ($path->getExtension() === "svg") { 43937748cd8SNickeau /** 44037748cd8SNickeau * The mime type is set when uploading, not when 44137748cd8SNickeau * viewing. 44237748cd8SNickeau * Because they are internal image, the svg was already uploaded 44337748cd8SNickeau * Therefore, no authorization scheme here 44437748cd8SNickeau */ 445c3437056SNickeau $mime = Mime::create(Mime::SVG); 44637748cd8SNickeau } 44737748cd8SNickeau 448c3437056SNickeau if ($mime === null) { 449*4cadd4f8SNickeau $stringMime = self::UNKNOWN_MIME; 450*4cadd4f8SNickeau } else { 451*4cadd4f8SNickeau $stringMime = $mime->toString(); 45237748cd8SNickeau } 45337748cd8SNickeau 454*4cadd4f8SNickeau switch ($stringMime) { 455*4cadd4f8SNickeau case self::UNKNOWN_MIME: 456*4cadd4f8SNickeau 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); 457*4cadd4f8SNickeau $media = new ImageRaster($path, $tagAttributes); 458*4cadd4f8SNickeau $mediaLink = new RasterImageLink($media); 459*4cadd4f8SNickeau break; 460*4cadd4f8SNickeau case Mime::SVG: 461*4cadd4f8SNickeau $media = new ImageSvg($path, $tagAttributes); 462*4cadd4f8SNickeau $mediaLink = new SvgImageLink($media); 463*4cadd4f8SNickeau break; 464*4cadd4f8SNickeau default: 465c3437056SNickeau if (!$mime->isImage()) { 466c3437056SNickeau LogUtility::msg("The type ($mime) of media ($path) is not an image", LogUtility::LVL_MSG_DEBUG, "image"); 467c3437056SNickeau $media = new ThirdMedia($path, $tagAttributes); 468*4cadd4f8SNickeau $mediaLink = new ThirdMediaLink($media); 469*4cadd4f8SNickeau } else { 470c3437056SNickeau $media = new ImageRaster($path, $tagAttributes); 471*4cadd4f8SNickeau $mediaLink = new RasterImageLink($media); 472*4cadd4f8SNickeau } 473*4cadd4f8SNickeau break; 474*4cadd4f8SNickeau } 475c3437056SNickeau 476*4cadd4f8SNickeau $mediaLink 477*4cadd4f8SNickeau ->setLazyLoadMethod($lazyLoadMethod) 478*4cadd4f8SNickeau ->setLinking($linking) 479*4cadd4f8SNickeau ->setLinkingClass($linkingClass); 480*4cadd4f8SNickeau return $mediaLink; 481c3437056SNickeau 48237748cd8SNickeau } 48337748cd8SNickeau 484*4cadd4f8SNickeau public function setLazyLoadMethod(string $lazyLoadMethod): MediaLink 485*4cadd4f8SNickeau { 486*4cadd4f8SNickeau $this->lazyLoadMethod = $lazyLoadMethod; 487*4cadd4f8SNickeau return $this; 488*4cadd4f8SNickeau } 489*4cadd4f8SNickeau 49037748cd8SNickeau 49137748cd8SNickeau /** 49237748cd8SNickeau * A function to set explicitly which array format 49337748cd8SNickeau * is used in the returned data of a {@link SyntaxPlugin::handle()} 49437748cd8SNickeau * (which ultimately is stored in the {@link CallStack) 49537748cd8SNickeau * 49637748cd8SNickeau * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()} 49737748cd8SNickeau * that is indexed by number (ie without property name) 49837748cd8SNickeau * 49937748cd8SNickeau * 50037748cd8SNickeau * Return the same array than with the {@link self::parse()} method 50137748cd8SNickeau * that is used in the {@link CallStack} 50237748cd8SNickeau * 50337748cd8SNickeau * @return array of key string and value 50437748cd8SNickeau */ 505c3437056SNickeau public 506c3437056SNickeau function toCallStackArray(): array 50737748cd8SNickeau { 50837748cd8SNickeau /** 50937748cd8SNickeau * Trying to stay inline with the dokuwiki key 51037748cd8SNickeau * We use the 'src' attributes as id 51137748cd8SNickeau * 51237748cd8SNickeau * src is a path (not an id) 51337748cd8SNickeau */ 51437748cd8SNickeau $array = array( 515*4cadd4f8SNickeau PagePath::PROPERTY_NAME => $this->getMedia()->getPath()->toString(), 516*4cadd4f8SNickeau self::LINKING_KEY => $this->getLinking() 51737748cd8SNickeau ); 51837748cd8SNickeau 51937748cd8SNickeau 52037748cd8SNickeau // Add the extra attribute 5211fa8c418SNickeau return array_merge($this->getMedia()->getAttributes()->toCallStackArray(), $array); 52237748cd8SNickeau 52337748cd8SNickeau 52437748cd8SNickeau } 52537748cd8SNickeau 52637748cd8SNickeau 52737748cd8SNickeau public 52837748cd8SNickeau static function isInternalMediaSyntax($text) 52937748cd8SNickeau { 53037748cd8SNickeau return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text); 53137748cd8SNickeau } 53237748cd8SNickeau 53337748cd8SNickeau 53437748cd8SNickeau public 53537748cd8SNickeau function __toString() 53637748cd8SNickeau { 537c3437056SNickeau $media = $this->getMedia(); 538c3437056SNickeau $dokuPath = $media->getPath(); 539c3437056SNickeau if ($dokuPath !== null) { 540c3437056SNickeau return $dokuPath->getDokuwikiId(); 541c3437056SNickeau } else { 542c3437056SNickeau return $media->__toString(); 543c3437056SNickeau } 54437748cd8SNickeau } 54537748cd8SNickeau 54637748cd8SNickeau 54737748cd8SNickeau private 54837748cd8SNickeau function getLinking() 54937748cd8SNickeau { 550*4cadd4f8SNickeau return $this->linking; 55137748cd8SNickeau } 55237748cd8SNickeau 553*4cadd4f8SNickeau private 554*4cadd4f8SNickeau function setLinking($value): MediaLink 555*4cadd4f8SNickeau { 556*4cadd4f8SNickeau $this->linking = $value; 557*4cadd4f8SNickeau return $this; 558*4cadd4f8SNickeau } 559*4cadd4f8SNickeau 560*4cadd4f8SNickeau private 561*4cadd4f8SNickeau function getLinkingClass() 562*4cadd4f8SNickeau { 563*4cadd4f8SNickeau return $this->linkingClass; 564*4cadd4f8SNickeau } 565*4cadd4f8SNickeau 566*4cadd4f8SNickeau private 567*4cadd4f8SNickeau function setLinkingClass($value): MediaLink 568*4cadd4f8SNickeau { 569*4cadd4f8SNickeau $this->linkingClass = $value; 570*4cadd4f8SNickeau return $this; 571*4cadd4f8SNickeau } 57237748cd8SNickeau 57337748cd8SNickeau /** 57437748cd8SNickeau * @return string - the HTML of the image inside a link if asked 57537748cd8SNickeau */ 57637748cd8SNickeau public 5771fa8c418SNickeau function renderMediaTagWithLink(): string 57837748cd8SNickeau { 57937748cd8SNickeau 58037748cd8SNickeau /** 58137748cd8SNickeau * Link to the media 58237748cd8SNickeau * 58337748cd8SNickeau */ 5841fa8c418SNickeau $mediaLink = TagAttributes::createEmpty(); 58537748cd8SNickeau // https://www.dokuwiki.org/config:target 58637748cd8SNickeau global $conf; 58737748cd8SNickeau $target = $conf['target']['media']; 588*4cadd4f8SNickeau $mediaLink->addOutputAttributeValueIfNotEmpty("target", $target); 58937748cd8SNickeau if (!empty($target)) { 590*4cadd4f8SNickeau $mediaLink->addOutputAttributeValue("rel", 'noopener'); 59137748cd8SNickeau } 59237748cd8SNickeau 59337748cd8SNickeau /** 59437748cd8SNickeau * Do we add a link to the image ? 59537748cd8SNickeau */ 5961fa8c418SNickeau $media = $this->getMedia(); 597c3437056SNickeau $dokuPath = $media->getPath(); 598c3437056SNickeau if (!($dokuPath instanceof DokuPath)) { 599c3437056SNickeau LogUtility::msg("Media Link are only supported on media from the internal library ($media)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 600c3437056SNickeau return ""; 601c3437056SNickeau } 6021fa8c418SNickeau $linking = $this->getLinking(); 60337748cd8SNickeau switch ($linking) { 60437748cd8SNickeau case self::LINKING_LINKONLY_VALUE: // show only a url 60537748cd8SNickeau $src = ml( 606c3437056SNickeau $dokuPath->getDokuwikiId(), 60737748cd8SNickeau array( 608c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 6091fa8c418SNickeau 'cache' => $media->getCache(), 610c3437056SNickeau 'rev' => $dokuPath->getRevision() 61137748cd8SNickeau ) 61237748cd8SNickeau ); 613*4cadd4f8SNickeau $mediaLink->addOutputAttributeValue("href", $src); 6141fa8c418SNickeau $title = $media->getTitle(); 61537748cd8SNickeau if (empty($title)) { 616c3437056SNickeau $title = $media->getType(); 61737748cd8SNickeau } 6181fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . $title . "</a>"; 61937748cd8SNickeau case self::LINKING_NOLINK_VALUE: 62037748cd8SNickeau return $this->renderMediaTag(); 62137748cd8SNickeau default: 62237748cd8SNickeau case self::LINKING_DIRECT_VALUE: 62337748cd8SNickeau //directly to the image 62437748cd8SNickeau $src = ml( 625c3437056SNickeau $dokuPath->getDokuwikiId(), 62637748cd8SNickeau array( 627c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 6281fa8c418SNickeau 'cache' => $media->getCache(), 629c3437056SNickeau 'rev' => $dokuPath->getRevision() 63037748cd8SNickeau ), 63137748cd8SNickeau true 63237748cd8SNickeau ); 633*4cadd4f8SNickeau $mediaLink->addOutputAttributeValue("href", $src); 634*4cadd4f8SNickeau $snippetId = "lightbox"; 635*4cadd4f8SNickeau $mediaLink->addClassName("{$snippetId}-combo"); 636*4cadd4f8SNickeau $linkingClass = $this->getLinkingClass(); 637*4cadd4f8SNickeau if ($linkingClass !== null) { 638*4cadd4f8SNickeau $mediaLink->addClassName($linkingClass); 639*4cadd4f8SNickeau } 640*4cadd4f8SNickeau $snippetManager = PluginUtility::getSnippetManager(); 641*4cadd4f8SNickeau $snippetManager->attachJavascriptComboLibrary(); 642*4cadd4f8SNickeau $snippetManager->attachInternalJavascriptForSlot("lightbox"); 643*4cadd4f8SNickeau $snippetManager->attachCssInternalStyleSheetForSlot("lightbox"); 644c3437056SNickeau return $mediaLink->toHtmlEnterTag("a") . $this->renderMediaTag() . "</a>"; 64537748cd8SNickeau 64637748cd8SNickeau case self::LINKING_DETAILS_VALUE: 64737748cd8SNickeau //go to the details media viewer 64837748cd8SNickeau $src = ml( 649c3437056SNickeau $dokuPath->getDokuwikiId(), 65037748cd8SNickeau array( 651c3437056SNickeau 'id' => $dokuPath->getDokuwikiId(), 6521fa8c418SNickeau 'cache' => $media->getCache(), 653c3437056SNickeau 'rev' => $dokuPath->getRevision() 65437748cd8SNickeau ), 65537748cd8SNickeau false 65637748cd8SNickeau ); 657*4cadd4f8SNickeau $mediaLink->addOutputAttributeValue("href", $src); 6581fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . 65937748cd8SNickeau $this->renderMediaTag() . 66037748cd8SNickeau "</a>"; 66137748cd8SNickeau 66237748cd8SNickeau } 66337748cd8SNickeau 66437748cd8SNickeau 66537748cd8SNickeau } 66637748cd8SNickeau 66737748cd8SNickeau 66837748cd8SNickeau /** 66937748cd8SNickeau * @return string - the HTML of the image 67037748cd8SNickeau */ 671c3437056SNickeau public 672c3437056SNickeau 673c3437056SNickeau abstract function renderMediaTag(): string; 6741fa8c418SNickeau 67537748cd8SNickeau 67637748cd8SNickeau /** 6771fa8c418SNickeau * The file 6781fa8c418SNickeau * @return Media 67937748cd8SNickeau */ 6801fa8c418SNickeau public function getMedia(): Media 6811fa8c418SNickeau { 6821fa8c418SNickeau return $this->media; 6831fa8c418SNickeau } 68437748cd8SNickeau 685*4cadd4f8SNickeau protected function getLazyLoadMethod(): string 686*4cadd4f8SNickeau { 687*4cadd4f8SNickeau return $this->lazyLoadMethod; 688*4cadd4f8SNickeau } 68937748cd8SNickeau 69082a60d03SNickeau 69137748cd8SNickeau} 692