xref: /template/strap/ComboStrap/MediaLink.php (revision 1fa8c418ed5809db58049141be41b7738471dd32)
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