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; 1637748cd8SNickeauuse syntax_plugin_combo_media; 1737748cd8SNickeau 18*1fa8c418SNickeaurequire_once(__DIR__ . '/PluginUtility.php'); 1937748cd8SNickeau 2037748cd8SNickeau/** 2137748cd8SNickeau * Class InternalMedia 2237748cd8SNickeau * Represent a media link 2337748cd8SNickeau * 2437748cd8SNickeau * 2537748cd8SNickeau * @package ComboStrap 2637748cd8SNickeau * 2737748cd8SNickeau * Wrapper around {@link Doku_Handler_Parse_Media} 2837748cd8SNickeau * 2937748cd8SNickeau * Not that for dokuwiki the `type` key of the attributes is the `call` 3037748cd8SNickeau * and therefore determine the function in an render 3137748cd8SNickeau * (ie {@link \Doku_Renderer::internalmedialink()} or {@link \Doku_Renderer::externalmedialink()} 3237748cd8SNickeau * 33*1fa8c418SNickeau * This is a link to a media (pdf, image, ...). 34*1fa8c418SNickeau * It's used to check the media type and to 35*1fa8c418SNickeau * take over if the media type is an image 3637748cd8SNickeau */ 37*1fa8c418SNickeauabstract class MediaLink 3837748cd8SNickeau{ 3937748cd8SNickeau 4037748cd8SNickeau 4137748cd8SNickeau /** 4237748cd8SNickeau * The dokuwiki type and mode name 4337748cd8SNickeau * (ie call) 4437748cd8SNickeau * * ie {@link MediaLink::EXTERNAL_MEDIA_CALL_NAME} 4537748cd8SNickeau * or {@link MediaLink::INTERNAL_MEDIA_CALL_NAME} 4637748cd8SNickeau * 4737748cd8SNickeau * The dokuwiki type (internalmedia/externalmedia) 4837748cd8SNickeau * is saved in a `type` key that clash with the 4937748cd8SNickeau * combostrap type. To avoid the clash, we renamed it 5037748cd8SNickeau */ 5137748cd8SNickeau const MEDIA_DOKUWIKI_TYPE = 'dokuwiki_type'; 5237748cd8SNickeau const INTERNAL_MEDIA_CALL_NAME = "internalmedia"; 5337748cd8SNickeau const EXTERNAL_MEDIA_CALL_NAME = "externalmedia"; 5437748cd8SNickeau 5537748cd8SNickeau const CANONICAL = "image"; 5637748cd8SNickeau 5737748cd8SNickeau /** 5837748cd8SNickeau * This attributes does not apply 5937748cd8SNickeau * to a URL 6037748cd8SNickeau * They are only for the tag (img, svg, ...) 6137748cd8SNickeau * or internal 6237748cd8SNickeau */ 6337748cd8SNickeau const NON_URL_ATTRIBUTES = [ 64*1fa8c418SNickeau MediaLink::ALIGN_KEY, 65*1fa8c418SNickeau MediaLink::LINKING_KEY, 6637748cd8SNickeau TagAttributes::TITLE_KEY, 6737748cd8SNickeau Hover::ON_HOVER_ATTRIBUTE, 6837748cd8SNickeau Animation::ON_VIEW_ATTRIBUTE, 6937748cd8SNickeau MediaLink::MEDIA_DOKUWIKI_TYPE, 7037748cd8SNickeau MediaLink::DOKUWIKI_SRC 7137748cd8SNickeau ]; 7237748cd8SNickeau 7337748cd8SNickeau /** 7437748cd8SNickeau * This attribute applies 7537748cd8SNickeau * to a image url (img, svg, ...) 7637748cd8SNickeau */ 7737748cd8SNickeau const URL_ATTRIBUTES = [ 7837748cd8SNickeau Dimension::WIDTH_KEY, 7937748cd8SNickeau Dimension::HEIGHT_KEY, 8037748cd8SNickeau CacheMedia::CACHE_KEY, 8137748cd8SNickeau ]; 8237748cd8SNickeau 8337748cd8SNickeau /** 8437748cd8SNickeau * Default image linking value 8537748cd8SNickeau */ 8637748cd8SNickeau const CONF_DEFAULT_LINKING = "defaultImageLinking"; 8737748cd8SNickeau const LINKING_LINKONLY_VALUE = "linkonly"; 8837748cd8SNickeau const LINKING_DETAILS_VALUE = 'details'; 8937748cd8SNickeau const LINKING_NOLINK_VALUE = 'nolink'; 9037748cd8SNickeau 9137748cd8SNickeau /** 9237748cd8SNickeau * @deprecated 2021-06-12 9337748cd8SNickeau */ 9437748cd8SNickeau const LINK_PATTERN = "{{\s*([^|\s]*)\s*\|?.*}}"; 9537748cd8SNickeau 9637748cd8SNickeau const LINKING_DIRECT_VALUE = 'direct'; 9737748cd8SNickeau 9837748cd8SNickeau /** 9937748cd8SNickeau * Only used by Dokuwiki 10037748cd8SNickeau * Contains the path and eventually an anchor 10137748cd8SNickeau * never query parameters 10237748cd8SNickeau */ 10337748cd8SNickeau const DOKUWIKI_SRC = "src"; 10437748cd8SNickeau /** 10537748cd8SNickeau * Link value: 10637748cd8SNickeau * * 'nolink' 10737748cd8SNickeau * * 'direct': directly to the image 10837748cd8SNickeau * * 'linkonly': show only a url 10937748cd8SNickeau * * 'details': go to the details media viewer 11037748cd8SNickeau * 11137748cd8SNickeau * @var 11237748cd8SNickeau */ 11337748cd8SNickeau const LINKING_KEY = 'linking'; 11437748cd8SNickeau const ALIGN_KEY = 'align'; 11537748cd8SNickeau 11637748cd8SNickeau 11737748cd8SNickeau private $lazyLoad = null; 11837748cd8SNickeau 11937748cd8SNickeau 12037748cd8SNickeau /** 121*1fa8c418SNickeau * The path of the media 122*1fa8c418SNickeau * @var Media[] 12337748cd8SNickeau */ 124*1fa8c418SNickeau private $media; 12537748cd8SNickeau 12637748cd8SNickeau 12737748cd8SNickeau /** 12837748cd8SNickeau * Image constructor. 129*1fa8c418SNickeau * @param Image $media 13037748cd8SNickeau * 13137748cd8SNickeau * Protected and not private 13237748cd8SNickeau * to allow cascading init 13337748cd8SNickeau * If private, the parent attributes are null 13437748cd8SNickeau */ 135*1fa8c418SNickeau protected function __construct(Media $media) 13637748cd8SNickeau { 137*1fa8c418SNickeau $this->media = $media; 13837748cd8SNickeau } 13937748cd8SNickeau 14037748cd8SNickeau 14137748cd8SNickeau 14237748cd8SNickeau /** 14337748cd8SNickeau * Create an image from dokuwiki internal call media attributes 14437748cd8SNickeau * @param array $callAttributes 14537748cd8SNickeau * @return MediaLink 14637748cd8SNickeau */ 14737748cd8SNickeau public static function createFromIndexAttributes(array $callAttributes) 14837748cd8SNickeau { 14937748cd8SNickeau $id = $callAttributes[0]; // path 15037748cd8SNickeau $title = $callAttributes[1]; 15137748cd8SNickeau $align = $callAttributes[2]; 15237748cd8SNickeau $width = $callAttributes[3]; 15337748cd8SNickeau $height = $callAttributes[4]; 15437748cd8SNickeau $cache = $callAttributes[5]; 15537748cd8SNickeau $linking = $callAttributes[6]; 15637748cd8SNickeau 15737748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 15837748cd8SNickeau $tagAttributes->addComponentAttributeValue(TagAttributes::TITLE_KEY, $title); 15937748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::ALIGN_KEY, $align); 16037748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::WIDTH_KEY, $width); 16137748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::HEIGHT_KEY, $height); 16237748cd8SNickeau $tagAttributes->addComponentAttributeValue(CacheMedia::CACHE_KEY, $cache); 16337748cd8SNickeau $tagAttributes->addComponentAttributeValue(self::LINKING_KEY, $linking); 16437748cd8SNickeau 16537748cd8SNickeau return self::createMediaLinkFromNonQualifiedPath($id, $tagAttributes); 16637748cd8SNickeau 16737748cd8SNickeau } 16837748cd8SNickeau 16937748cd8SNickeau /** 17037748cd8SNickeau * A function to explicitly create an internal media from 17137748cd8SNickeau * a call stack array (ie key string and value) that we get in the {@link SyntaxPlugin::render()} 17237748cd8SNickeau * from the {@link MediaLink::toCallStackArray()} 17337748cd8SNickeau * 17437748cd8SNickeau * @param $attributes - the attributes created by the function {@link MediaLink::getParseAttributes()} 17537748cd8SNickeau * @param $rev - the mtime 17637748cd8SNickeau * @return MediaLink|RasterImageLink|SvgImageLink 17737748cd8SNickeau */ 17837748cd8SNickeau public static function createFromCallStackArray($attributes, $rev = null) 17937748cd8SNickeau { 18037748cd8SNickeau 18137748cd8SNickeau if (!is_array($attributes)) { 18237748cd8SNickeau // Debug for the key_exist below because of the following message: 18337748cd8SNickeau // `PHP Warning: key_exists() expects parameter 2 to be array, array given` 18437748cd8SNickeau LogUtility::msg("The `attributes` parameter is not an array. Value ($attributes)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 18537748cd8SNickeau } 18637748cd8SNickeau 18737748cd8SNickeau /** 18837748cd8SNickeau * Media id are not cleaned 18937748cd8SNickeau * They are always absolute ? 19037748cd8SNickeau */ 19137748cd8SNickeau if (!isset($attributes[DokuPath::PATH_ATTRIBUTE])) { 19237748cd8SNickeau $path = "notfound"; 19337748cd8SNickeau LogUtility::msg("A path attribute is mandatory when creating a media link and was not found in the attributes " . print_r($attributes, true), LogUtility::LVL_MSG_ERROR, self::CANONICAL); 19437748cd8SNickeau } else { 19537748cd8SNickeau $path = $attributes[DokuPath::PATH_ATTRIBUTE]; 19637748cd8SNickeau unset($attributes[DokuPath::PATH_ATTRIBUTE]); 19737748cd8SNickeau } 19837748cd8SNickeau 19937748cd8SNickeau 20037748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 20137748cd8SNickeau 20237748cd8SNickeau 20337748cd8SNickeau return self::createMediaLinkFromNonQualifiedPath($path, $rev, $tagAttributes); 20437748cd8SNickeau 20537748cd8SNickeau } 20637748cd8SNickeau 20737748cd8SNickeau /** 20837748cd8SNickeau * @param $match - the match of the renderer (just a shortcut) 20937748cd8SNickeau * @return MediaLink 21037748cd8SNickeau */ 21137748cd8SNickeau public static function createFromRenderMatch($match) 21237748cd8SNickeau { 21337748cd8SNickeau 21437748cd8SNickeau /** 21537748cd8SNickeau * The parsing function {@link Doku_Handler_Parse_Media} has some flow / problem 21637748cd8SNickeau * * It keeps the anchor only if there is no query string 21737748cd8SNickeau * * It takes the first digit as the width (ie media.pdf?page=31 would have a width of 31) 21837748cd8SNickeau * * `src` is not only the media path but may have a anchor 21937748cd8SNickeau * We parse it then 22037748cd8SNickeau */ 22137748cd8SNickeau 22237748cd8SNickeau 22337748cd8SNickeau /** 22437748cd8SNickeau * * Delete the opening and closing character 22537748cd8SNickeau * * create the url and description 22637748cd8SNickeau */ 22737748cd8SNickeau $match = preg_replace(array('/^\{\{/', '/\}\}$/u'), '', $match); 22837748cd8SNickeau $parts = explode('|', $match, 2); 22937748cd8SNickeau $description = null; 23037748cd8SNickeau $url = $parts[0]; 23137748cd8SNickeau if (isset($parts[1])) { 23237748cd8SNickeau $description = $parts[1]; 23337748cd8SNickeau } 23437748cd8SNickeau 23537748cd8SNickeau /** 23637748cd8SNickeau * Media Alignment 23737748cd8SNickeau */ 23837748cd8SNickeau $rightAlign = (bool)preg_match('/^ /', $url); 23937748cd8SNickeau $leftAlign = (bool)preg_match('/ $/', $url); 24037748cd8SNickeau $url = trim($url); 24137748cd8SNickeau 24237748cd8SNickeau // Logic = what's that ;)... 24337748cd8SNickeau if ($leftAlign & $rightAlign) { 24437748cd8SNickeau $align = 'center'; 24537748cd8SNickeau } else if ($rightAlign) { 24637748cd8SNickeau $align = 'right'; 24737748cd8SNickeau } else if ($leftAlign) { 24837748cd8SNickeau $align = 'left'; 24937748cd8SNickeau } else { 25037748cd8SNickeau $align = null; 25137748cd8SNickeau } 25237748cd8SNickeau 25337748cd8SNickeau /** 25437748cd8SNickeau * The combo attributes array 25537748cd8SNickeau */ 25637748cd8SNickeau $parsedAttributes = DokuwikiUrl::createFromUrl($url)->toArray(); 25737748cd8SNickeau $path = $parsedAttributes[DokuPath::PATH_ATTRIBUTE]; 25837748cd8SNickeau if (!isset($parsedAttributes[MediaLink::LINKING_KEY])) { 25937748cd8SNickeau $parsedAttributes[MediaLink::LINKING_KEY] = PluginUtility::getConfValue(self::CONF_DEFAULT_LINKING, self::LINKING_DIRECT_VALUE); 26037748cd8SNickeau } 26137748cd8SNickeau 26237748cd8SNickeau /** 26337748cd8SNickeau * Media Type 26437748cd8SNickeau */ 26537748cd8SNickeau if (media_isexternal($path) || link_isinterwiki($path)) { 26637748cd8SNickeau $mediaType = MediaLink::EXTERNAL_MEDIA_CALL_NAME; 26737748cd8SNickeau } else { 26837748cd8SNickeau $mediaType = MediaLink::INTERNAL_MEDIA_CALL_NAME; 26937748cd8SNickeau } 27037748cd8SNickeau 27137748cd8SNickeau 27237748cd8SNickeau /** 27337748cd8SNickeau * src in dokuwiki is the path and the anchor if any 27437748cd8SNickeau */ 27537748cd8SNickeau $src = $path; 27637748cd8SNickeau if (isset($parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]) != null) { 27737748cd8SNickeau $src = $src . "#" . $parsedAttributes[DokuwikiUrl::ANCHOR_ATTRIBUTES]; 27837748cd8SNickeau } 27937748cd8SNickeau 28037748cd8SNickeau /** 28137748cd8SNickeau * To avoid clash with the combostrap component type 28237748cd8SNickeau * ie this is also a ComboStrap attribute where we set the type of a SVG (icon, illustration, background) 28337748cd8SNickeau * we store the media type (ie external/internal) in another key 28437748cd8SNickeau * 28537748cd8SNickeau * There is no need to repeat the attributes as the arrays are merged 28637748cd8SNickeau * into on but this is also an informal code to show which attributes 28737748cd8SNickeau * are only Dokuwiki Native 28837748cd8SNickeau * 28937748cd8SNickeau */ 29037748cd8SNickeau $dokuwikiAttributes = array( 29137748cd8SNickeau self::MEDIA_DOKUWIKI_TYPE => $mediaType, 29237748cd8SNickeau self::DOKUWIKI_SRC => $src, 29337748cd8SNickeau Dimension::WIDTH_KEY => $parsedAttributes[Dimension::WIDTH_KEY], 29437748cd8SNickeau Dimension::HEIGHT_KEY => $parsedAttributes[Dimension::HEIGHT_KEY], 29537748cd8SNickeau CacheMedia::CACHE_KEY => $parsedAttributes[CacheMedia::CACHE_KEY], 296*1fa8c418SNickeau TagAttributes::TITLE_KEY => $description, 29737748cd8SNickeau MediaLink::ALIGN_KEY => $align, 29837748cd8SNickeau MediaLink::LINKING_KEY => $parsedAttributes[MediaLink::LINKING_KEY], 29937748cd8SNickeau ); 30037748cd8SNickeau 30137748cd8SNickeau /** 30237748cd8SNickeau * Merge standard dokuwiki attributes and 30337748cd8SNickeau * parsed attributes 30437748cd8SNickeau */ 30537748cd8SNickeau $mergedAttributes = PluginUtility::mergeAttributes($dokuwikiAttributes, $parsedAttributes); 30637748cd8SNickeau 30737748cd8SNickeau /** 30837748cd8SNickeau * If this is an internal media, 30937748cd8SNickeau * we are using our implementation 31037748cd8SNickeau * and we have a change on attribute specification 31137748cd8SNickeau */ 31237748cd8SNickeau if ($mediaType == MediaLink::INTERNAL_MEDIA_CALL_NAME) { 31337748cd8SNickeau 31437748cd8SNickeau /** 31537748cd8SNickeau * The align attribute on an image parse 31637748cd8SNickeau * is a float right 31737748cd8SNickeau * ComboStrap does a difference between a block right and a float right 31837748cd8SNickeau */ 31937748cd8SNickeau if ($mergedAttributes[self::ALIGN_KEY] === "right") { 32037748cd8SNickeau unset($mergedAttributes[self::ALIGN_KEY]); 32137748cd8SNickeau $mergedAttributes[FloatAttribute::FLOAT_KEY] = "right"; 32237748cd8SNickeau } 32337748cd8SNickeau 32437748cd8SNickeau 32537748cd8SNickeau } 32637748cd8SNickeau 32737748cd8SNickeau return self::createFromCallStackArray($mergedAttributes); 32837748cd8SNickeau 32937748cd8SNickeau } 33037748cd8SNickeau 33137748cd8SNickeau 33237748cd8SNickeau public 33337748cd8SNickeau function setLazyLoad($false) 33437748cd8SNickeau { 33537748cd8SNickeau $this->lazyLoad = $false; 33637748cd8SNickeau } 33737748cd8SNickeau 33837748cd8SNickeau public 33937748cd8SNickeau function getLazyLoad() 34037748cd8SNickeau { 34137748cd8SNickeau return $this->lazyLoad; 34237748cd8SNickeau } 34337748cd8SNickeau 34437748cd8SNickeau 34537748cd8SNickeau /** 34637748cd8SNickeau * Create a media link from a unknown type path (ie relative or absolute) 34737748cd8SNickeau * 34837748cd8SNickeau * This function transforms the path to absolute against the actual namespace of the requested page ID if the 34937748cd8SNickeau * path is relative. 35037748cd8SNickeau * 35137748cd8SNickeau * @param $nonQualifiedPath 35237748cd8SNickeau * @param TagAttributes $tagAttributes 35337748cd8SNickeau * @param string $rev 35437748cd8SNickeau * @return MediaLink 35537748cd8SNickeau */ 35637748cd8SNickeau public 35737748cd8SNickeau static function createMediaLinkFromNonQualifiedPath($nonQualifiedPath, $rev = null, $tagAttributes = null) 35837748cd8SNickeau { 35937748cd8SNickeau if (is_object($rev)) { 36037748cd8SNickeau LogUtility::msg("rev should not be an object", LogUtility::LVL_MSG_ERROR, "support"); 36137748cd8SNickeau } 36237748cd8SNickeau if ($tagAttributes == null) { 36337748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(); 36437748cd8SNickeau } else { 36537748cd8SNickeau if (!($tagAttributes instanceof TagAttributes)) { 36637748cd8SNickeau LogUtility::msg("TagAttributes is not an instance of Tag Attributes", LogUtility::LVL_MSG_ERROR, "support"); 36737748cd8SNickeau } 36837748cd8SNickeau } 36937748cd8SNickeau 37037748cd8SNickeau /** 37137748cd8SNickeau * Resolution 37237748cd8SNickeau */ 37337748cd8SNickeau $qualifiedPath = $nonQualifiedPath; 37437748cd8SNickeau if (!media_isexternal($qualifiedPath)) { 37537748cd8SNickeau global $ID; 37637748cd8SNickeau $qualifiedId = $nonQualifiedPath; 37737748cd8SNickeau resolve_mediaid(getNS($ID), $qualifiedId, $exists); 37837748cd8SNickeau $qualifiedPath = DokuPath::PATH_SEPARATOR . $qualifiedId; 37937748cd8SNickeau } 38037748cd8SNickeau 381*1fa8c418SNickeau 382*1fa8c418SNickeau return self::createMediaLinkFromAbsolutePath($qualifiedPath,$rev,$tagAttributes); 383*1fa8c418SNickeau } 384*1fa8c418SNickeau 385*1fa8c418SNickeau public static function createMediaLinkFromAbsolutePath($qualifiedPath, $rev = null, $tagAttributes = null) 386*1fa8c418SNickeau { 38737748cd8SNickeau /** 38837748cd8SNickeau * Processing 38937748cd8SNickeau */ 39037748cd8SNickeau $dokuPath = DokuPath::createMediaPathFromAbsolutePath($qualifiedPath, $rev); 39137748cd8SNickeau if ($dokuPath->getExtension() == "svg") { 39237748cd8SNickeau /** 39337748cd8SNickeau * The mime type is set when uploading, not when 39437748cd8SNickeau * viewing. 39537748cd8SNickeau * Because they are internal image, the svg was already uploaded 39637748cd8SNickeau * Therefore, no authorization scheme here 39737748cd8SNickeau */ 39837748cd8SNickeau $mime = "image/svg+xml"; 39937748cd8SNickeau } else { 40037748cd8SNickeau $mime = $dokuPath->getKnownMime(); 40137748cd8SNickeau } 40237748cd8SNickeau 40337748cd8SNickeau if (substr($mime, 0, 5) == 'image') { 40437748cd8SNickeau if (substr($mime, 6) == "svg+xml") { 405*1fa8c418SNickeau 406*1fa8c418SNickeau $svgImage = new ImageSvg($qualifiedPath, $rev, $tagAttributes); 407*1fa8c418SNickeau $internalMedia = new SvgImageLink($svgImage); 40837748cd8SNickeau } else { 409*1fa8c418SNickeau $rasterImage = new ImageRaster($qualifiedPath, $rev, $tagAttributes); 410*1fa8c418SNickeau $internalMedia = new RasterImageLink($rasterImage ); 41137748cd8SNickeau } 41237748cd8SNickeau } else { 41337748cd8SNickeau if ($mime == false) { 414*1fa8c418SNickeau LogUtility::msg("The mime type of the media ($qualifiedPath) is <a href=\"https://www.dokuwiki.org/mime\">unknown (not in the configuration file)</a>", LogUtility::LVL_MSG_ERROR); 415*1fa8c418SNickeau $media = new ImageRaster($qualifiedPath, $rev, $tagAttributes); 416*1fa8c418SNickeau $internalMedia = new RasterImageLink($media); 41737748cd8SNickeau } else { 418*1fa8c418SNickeau LogUtility::msg("The type ($mime) of media ($qualifiedPath) is not an image", LogUtility::LVL_MSG_DEBUG, "image"); 419*1fa8c418SNickeau $media = Media::create($qualifiedPath, $rev, $tagAttributes); 420*1fa8c418SNickeau $internalMedia = new ThirdMediaLink($media); 42137748cd8SNickeau } 42237748cd8SNickeau } 42337748cd8SNickeau 42437748cd8SNickeau return $internalMedia; 42537748cd8SNickeau } 42637748cd8SNickeau 42737748cd8SNickeau 42837748cd8SNickeau /** 42937748cd8SNickeau * A function to set explicitly which array format 43037748cd8SNickeau * is used in the returned data of a {@link SyntaxPlugin::handle()} 43137748cd8SNickeau * (which ultimately is stored in the {@link CallStack) 43237748cd8SNickeau * 43337748cd8SNickeau * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()} 43437748cd8SNickeau * that is indexed by number (ie without property name) 43537748cd8SNickeau * 43637748cd8SNickeau * 43737748cd8SNickeau * Return the same array than with the {@link self::parse()} method 43837748cd8SNickeau * that is used in the {@link CallStack} 43937748cd8SNickeau * 44037748cd8SNickeau * @return array of key string and value 44137748cd8SNickeau */ 442*1fa8c418SNickeau public function toCallStackArray(): array 44337748cd8SNickeau { 44437748cd8SNickeau /** 44537748cd8SNickeau * Trying to stay inline with the dokuwiki key 44637748cd8SNickeau * We use the 'src' attributes as id 44737748cd8SNickeau * 44837748cd8SNickeau * src is a path (not an id) 44937748cd8SNickeau */ 45037748cd8SNickeau $array = array( 451*1fa8c418SNickeau DokuPath::PATH_ATTRIBUTE => $this->getMedia()->getPath() 45237748cd8SNickeau ); 45337748cd8SNickeau 45437748cd8SNickeau 45537748cd8SNickeau // Add the extra attribute 456*1fa8c418SNickeau return array_merge($this->getMedia()->getAttributes()->toCallStackArray(), $array); 45737748cd8SNickeau 45837748cd8SNickeau 45937748cd8SNickeau } 46037748cd8SNickeau 46137748cd8SNickeau 462*1fa8c418SNickeau 46337748cd8SNickeau 46437748cd8SNickeau 46537748cd8SNickeau public 46637748cd8SNickeau static function isInternalMediaSyntax($text) 46737748cd8SNickeau { 46837748cd8SNickeau return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text); 46937748cd8SNickeau } 47037748cd8SNickeau 47137748cd8SNickeau 47237748cd8SNickeau 47337748cd8SNickeau public 47437748cd8SNickeau function __toString() 47537748cd8SNickeau { 476*1fa8c418SNickeau return $this->getMedia()->getId(); 47737748cd8SNickeau } 47837748cd8SNickeau 47937748cd8SNickeau private 48037748cd8SNickeau function getAlign() 48137748cd8SNickeau { 482*1fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::ALIGN_KEY); 48337748cd8SNickeau } 48437748cd8SNickeau 48537748cd8SNickeau private 48637748cd8SNickeau function getLinking() 48737748cd8SNickeau { 488*1fa8c418SNickeau return $this->getMedia()->getAttributes()->getComponentAttributeValue(self::LINKING_KEY); 48937748cd8SNickeau } 49037748cd8SNickeau 49137748cd8SNickeau 49237748cd8SNickeau 49337748cd8SNickeau /** 49437748cd8SNickeau * @return string - the HTML of the image inside a link if asked 49537748cd8SNickeau */ 49637748cd8SNickeau public 497*1fa8c418SNickeau function renderMediaTagWithLink(): string 49837748cd8SNickeau { 49937748cd8SNickeau 50037748cd8SNickeau /** 50137748cd8SNickeau * Link to the media 50237748cd8SNickeau * 50337748cd8SNickeau */ 504*1fa8c418SNickeau $mediaLink = TagAttributes::createEmpty(); 50537748cd8SNickeau // https://www.dokuwiki.org/config:target 50637748cd8SNickeau global $conf; 50737748cd8SNickeau $target = $conf['target']['media']; 508*1fa8c418SNickeau $mediaLink->addHtmlAttributeValueIfNotEmpty("target", $target); 50937748cd8SNickeau if (!empty($target)) { 510*1fa8c418SNickeau $mediaLink->addHtmlAttributeValue("rel", 'noopener'); 51137748cd8SNickeau } 51237748cd8SNickeau 51337748cd8SNickeau /** 51437748cd8SNickeau * Do we add a link to the image ? 51537748cd8SNickeau */ 516*1fa8c418SNickeau $media = $this->getMedia(); 517*1fa8c418SNickeau $linking = $this->getLinking(); 51837748cd8SNickeau switch ($linking) { 51937748cd8SNickeau case self::LINKING_LINKONLY_VALUE: // show only a url 52037748cd8SNickeau $src = ml( 521*1fa8c418SNickeau $media->getId(), 52237748cd8SNickeau array( 523*1fa8c418SNickeau 'id' => $media->getId(), 524*1fa8c418SNickeau 'cache' => $media->getCache(), 525*1fa8c418SNickeau 'rev' => $media->getRevision() 52637748cd8SNickeau ) 52737748cd8SNickeau ); 528*1fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 529*1fa8c418SNickeau $title = $media->getTitle(); 53037748cd8SNickeau if (empty($title)) { 531*1fa8c418SNickeau $title = $media->getBaseName(); 53237748cd8SNickeau } 533*1fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . $title . "</a>"; 53437748cd8SNickeau case self::LINKING_NOLINK_VALUE: 53537748cd8SNickeau return $this->renderMediaTag(); 53637748cd8SNickeau default: 53737748cd8SNickeau case self::LINKING_DIRECT_VALUE: 53837748cd8SNickeau //directly to the image 53937748cd8SNickeau $src = ml( 540*1fa8c418SNickeau $media->getId(), 54137748cd8SNickeau array( 542*1fa8c418SNickeau 'id' => $media->getId(), 543*1fa8c418SNickeau 'cache' => $media->getCache(), 544*1fa8c418SNickeau 'rev' => $media->getRevision() 54537748cd8SNickeau ), 54637748cd8SNickeau true 54737748cd8SNickeau ); 548*1fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 549*1fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . 55037748cd8SNickeau $this->renderMediaTag() . 55137748cd8SNickeau "</a>"; 55237748cd8SNickeau 55337748cd8SNickeau case self::LINKING_DETAILS_VALUE: 55437748cd8SNickeau //go to the details media viewer 55537748cd8SNickeau $src = ml( 556*1fa8c418SNickeau $media->getId(), 55737748cd8SNickeau array( 558*1fa8c418SNickeau 'id' => $media->getId(), 559*1fa8c418SNickeau 'cache' => $media->getCache(), 560*1fa8c418SNickeau 'rev' => $media->getRevision() 56137748cd8SNickeau ), 56237748cd8SNickeau false 56337748cd8SNickeau ); 564*1fa8c418SNickeau $mediaLink->addHtmlAttributeValue("href", $src); 565*1fa8c418SNickeau return $mediaLink->toHtmlEnterTag("a") . 56637748cd8SNickeau $this->renderMediaTag() . 56737748cd8SNickeau "</a>"; 56837748cd8SNickeau 56937748cd8SNickeau } 57037748cd8SNickeau 57137748cd8SNickeau 57237748cd8SNickeau } 57337748cd8SNickeau 57437748cd8SNickeau 57537748cd8SNickeau 57637748cd8SNickeau 57737748cd8SNickeau 57837748cd8SNickeau /** 57937748cd8SNickeau * @return string - the HTML of the image 58037748cd8SNickeau */ 581*1fa8c418SNickeau public abstract function renderMediaTag(): string; 582*1fa8c418SNickeau 58337748cd8SNickeau 58437748cd8SNickeau /** 585*1fa8c418SNickeau * The file 586*1fa8c418SNickeau * @return Media 58737748cd8SNickeau */ 588*1fa8c418SNickeau public function getMedia(): Media 589*1fa8c418SNickeau { 590*1fa8c418SNickeau return $this->media; 591*1fa8c418SNickeau } 59237748cd8SNickeau 59337748cd8SNickeau 59437748cd8SNickeau} 595