xref: /plugin/combo/ComboStrap/MediaMarkup.php (revision 70bbd7f1f72440223cc13f3495efdcb2b0a11514)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeau
404fd306cSNickeaunamespace ComboStrap;
504fd306cSNickeau
604fd306cSNickeau
704fd306cSNickeauuse ComboStrap\TagAttribute\Align;
804fd306cSNickeauuse ComboStrap\TagAttribute\Animation;
904fd306cSNickeauuse ComboStrap\TagAttribute\Shadow;
1004fd306cSNickeauuse ComboStrap\Web\Url;
1104fd306cSNickeauuse Doku_Renderer_metadata;
1204fd306cSNickeauuse Doku_Renderer_xhtml;
1304fd306cSNickeauuse renderer_plugin_combo_analytics;
1404fd306cSNickeauuse syntax_plugin_combo_media;
1504fd306cSNickeau
1604fd306cSNickeau/**
1704fd306cSNickeau * This class represents a media markup:
1804fd306cSNickeau *   - with a {@link MediaMarkup::getFetcher() fetcher}
1904fd306cSNickeau *   - and {@link MediaMarkup::getExtraMediaTagAttributes() tag/styling attributes}
2004fd306cSNickeau *
2104fd306cSNickeau * You can create it:
2204fd306cSNickeau *   * via a {@link MediaMarkup::createFromRef() Markup Ref} (The string ref in the document)
2304fd306cSNickeau *   * via a {@link MediaMarkup::createFromFetcher() Fetcher}
2404fd306cSNickeau *   * via a {@link MediaMarkup::createFromFetchUrl() Fetch Url}
2504fd306cSNickeau *   * via a {@link MediaMarkup::createFromCallStackArray() callstack array} of {@link syntax_plugin_combo_media::render()}
2604fd306cSNickeau *   * via a {@link MediaMarkup::createFromMarkup() string match} of {@link syntax_plugin_combo_media::handle()}
2704fd306cSNickeau *
2804fd306cSNickeau *
2904fd306cSNickeau */
3004fd306cSNickeauclass MediaMarkup
3104fd306cSNickeau{
3204fd306cSNickeau
3304fd306cSNickeau    /**
3404fd306cSNickeau     * No name as this is {{ --- }}
3504fd306cSNickeau     */
3604fd306cSNickeau    public const TAG = "media";
3704fd306cSNickeau
3804fd306cSNickeau    /**
3904fd306cSNickeau     * The dokuwiki type and mode name
4004fd306cSNickeau     * (ie call)
4104fd306cSNickeau     *  * ie {@link MediaMarkup::EXTERNAL_MEDIA_CALL_NAME}
4204fd306cSNickeau     *  or {@link MediaMarkup::INTERNAL_MEDIA_CALL_NAME}
4304fd306cSNickeau     *
4404fd306cSNickeau     * The dokuwiki type (internalmedia/externalmedia)
4504fd306cSNickeau     *
4604fd306cSNickeau     */
4704fd306cSNickeau    public const MEDIA_DOKUWIKI_TYPE = 'dokuwiki_media_type';
4804fd306cSNickeau    public const EXTERNAL_MEDIA_CALL_NAME = "externalmedia";
4904fd306cSNickeau    public const INTERNAL_MEDIA_CALL_NAME = "internalmedia";
5004fd306cSNickeau
5104fd306cSNickeau    /**
5204fd306cSNickeau     * Link value:
5304fd306cSNickeau     *   * 'nolink'
5404fd306cSNickeau     *   * 'direct': directly to the image
5504fd306cSNickeau     *   * 'linkonly': show only a url
5604fd306cSNickeau     *   * 'details': go to the details media viewer
5704fd306cSNickeau     *
5804fd306cSNickeau     * @var
5904fd306cSNickeau     */
6004fd306cSNickeau    public const LINKING_KEY = 'linking';
6104fd306cSNickeau    public const LINKING_DETAILS_VALUE = 'details';
6204fd306cSNickeau    public const LINKING_DIRECT_VALUE = 'direct';
6304fd306cSNickeau    /**
6404fd306cSNickeau     * Only used by Dokuwiki
6504fd306cSNickeau     * Contains the path and eventually an anchor
6604fd306cSNickeau     * never query parameters
6704fd306cSNickeau     */
6804fd306cSNickeau    public const DOKUWIKI_SRC = "src";
6904fd306cSNickeau    public const LINKING_LINKONLY_VALUE = "linkonly";
7004fd306cSNickeau    public const LINKING_NOLINK_VALUE = 'nolink';
7104fd306cSNickeau    /**
7204fd306cSNickeau     * Default image linking value
7304fd306cSNickeau     */
7404fd306cSNickeau    public const CONF_DEFAULT_LINKING = "defaultImageLinking";
7504fd306cSNickeau
7604fd306cSNickeau    const CANONICAL = "media";
7704fd306cSNickeau
7804fd306cSNickeau    /**
7904fd306cSNickeau     * This attributes does not apply
8004fd306cSNickeau     * to a fetch (URL)
8104fd306cSNickeau     * They are only for the tag (img, svg, ...)
8204fd306cSNickeau     * or internal
8304fd306cSNickeau     */
8404fd306cSNickeau    public const STYLE_ATTRIBUTES = [
8504fd306cSNickeau        TagAttributes::TITLE_KEY,
8604fd306cSNickeau        Hover::ON_HOVER_ATTRIBUTE,
8704fd306cSNickeau        Animation::ON_VIEW_ATTRIBUTE,
8804fd306cSNickeau        Shadow::SHADOW_ATT,
8904fd306cSNickeau        Opacity::OPACITY_ATTRIBUTE,
9004fd306cSNickeau        TagAttributes::CLASS_KEY,
9104fd306cSNickeau    ];
9204fd306cSNickeau
9304fd306cSNickeau    /**
9404fd306cSNickeau     * An attribute to set the class of the link if any
9504fd306cSNickeau     */
9604fd306cSNickeau    public const LINK_CLASS_ATTRIBUTE = "link-class";
97*70bbd7f1Sgerardnico    public static string $MEDIA_QUERY_PARAMETER = "media";
9804fd306cSNickeau
9904fd306cSNickeau
10004fd306cSNickeau    private ?string $align = null;
10104fd306cSNickeau    private ?string $label = null;
10204fd306cSNickeau    private ?MarkupRef $markupRef = null;
10304fd306cSNickeau    private ?string $linking = null;
10404fd306cSNickeau    private ?string $lazyLoadMethod = null;
10504fd306cSNickeau    private TagAttributes $extraMediaTagAttributes;
10604fd306cSNickeau    private ?string $linkingClass = null;
10704fd306cSNickeau    private IFetcher $fetcher;
10804fd306cSNickeau    private Url $fetchUrl;
10904fd306cSNickeau
11004fd306cSNickeau    private function __construct()
11104fd306cSNickeau    {
11204fd306cSNickeau        $this->extraMediaTagAttributes = TagAttributes::createEmpty();
11304fd306cSNickeau    }
11404fd306cSNickeau
11504fd306cSNickeau
11604fd306cSNickeau    /**
11704fd306cSNickeau     * Private method use {@link MediaMarkup::createFromRef()} to create a media markup via a ref
11804fd306cSNickeau     *
11904fd306cSNickeau     * Set and parse a media wiki ref that you can found in the first part of a media markup
12004fd306cSNickeau     *
12104fd306cSNickeau     * @param string $markupRef
12204fd306cSNickeau     * @return MediaMarkup
12304fd306cSNickeau     * @throws ExceptionBadArgument
12404fd306cSNickeau     * @throws ExceptionBadSyntax
12504fd306cSNickeau     * @throws ExceptionNotFound
12604fd306cSNickeau     */
12704fd306cSNickeau    private function setMarkupRef(string $markupRef): MediaMarkup
12804fd306cSNickeau    {
12904fd306cSNickeau
13004fd306cSNickeau        $markupRef = trim($markupRef);
13104fd306cSNickeau        $this->markupRef = MarkupRef::createMediaFromRef($markupRef);
13204fd306cSNickeau
13304fd306cSNickeau        $refUrl = $this->markupRef->getUrl();
13404fd306cSNickeau        $this->setUrl($refUrl);
13504fd306cSNickeau
13604fd306cSNickeau        return $this;
13704fd306cSNickeau    }
13804fd306cSNickeau
13904fd306cSNickeau    /**
14004fd306cSNickeau     * @param $callStackArray
14104fd306cSNickeau     * @return MediaMarkup
14204fd306cSNickeau     * @throws ExceptionBadArgument
14304fd306cSNickeau     * @throws ExceptionBadSyntax
14404fd306cSNickeau     * @throws ExceptionNotFound
14504fd306cSNickeau     * @throws ExceptionNotExists
14604fd306cSNickeau     */
14704fd306cSNickeau    public static function createFromCallStackArray($callStackArray): MediaMarkup
14804fd306cSNickeau    {
14904fd306cSNickeau
15004fd306cSNickeau        $tagAttributes = TagAttributes::createFromCallStackArray($callStackArray);
15104fd306cSNickeau        $ref = $tagAttributes->getValueAndRemoveIfPresent(MarkupRef::REF_ATTRIBUTE);
15204fd306cSNickeau        if ($ref === null) {
15304fd306cSNickeau            $ref = $tagAttributes->getValueAndRemoveIfPresent(MediaMarkup::DOKUWIKI_SRC);
15404fd306cSNickeau            if ($ref === null) {
15504fd306cSNickeau                throw new ExceptionBadArgument("The media reference was not found in the callstack array", self::CANONICAL);
15604fd306cSNickeau            }
15704fd306cSNickeau        }
15804fd306cSNickeau        return self::createFromRef($ref)
15904fd306cSNickeau            ->buildFromTagAttributes($tagAttributes);
16004fd306cSNickeau
16104fd306cSNickeau
16204fd306cSNickeau    }
16304fd306cSNickeau
16404fd306cSNickeau    /**
16504fd306cSNickeau     * @throws ExceptionBadArgument
16604fd306cSNickeau     * @throws ExceptionBadSyntax
16704fd306cSNickeau     * @throws ExceptionNotExists
16804fd306cSNickeau     * @throws ExceptionNotFound
16904fd306cSNickeau     * @throws ExceptionInternal
17004fd306cSNickeau     */
17104fd306cSNickeau    public static function createFromFetchUrl(Url $fetchUrl): MediaMarkup
17204fd306cSNickeau    {
17304fd306cSNickeau        return (new MediaMarkup())->setUrl($fetchUrl);
17404fd306cSNickeau    }
17504fd306cSNickeau
17604fd306cSNickeau    public static function createFromFetcher(IFetcher $fetcher): MediaMarkup
17704fd306cSNickeau    {
17804fd306cSNickeau        return (new MediaMarkup())
17904fd306cSNickeau            ->setFetcher($fetcher);
18004fd306cSNickeau    }
18104fd306cSNickeau
18204fd306cSNickeau    public static function renderSpecial(array $data, Doku_Renderer_xhtml $renderer)
18304fd306cSNickeau    {
18404fd306cSNickeau
18504fd306cSNickeau        $callStackArray = $data[PluginUtility::ATTRIBUTES];
186*70bbd7f1Sgerardnico        $display = $callStackArray[Display::DISPLAY] ?? null;
18704fd306cSNickeau        if ($display === Display::DISPLAY_NONE_VALUE) {
18804fd306cSNickeau            /**
18904fd306cSNickeau             * Used primarly to not show the featured images
19004fd306cSNickeau             * in the outline {@link Outline::toHtmlSectionOutlineCallsRecurse()}
19104fd306cSNickeau             * for item page
19204fd306cSNickeau             * But we keep the metadata to move them if any
19304fd306cSNickeau             */
19404fd306cSNickeau            return false;
19504fd306cSNickeau        }
19604fd306cSNickeau
19704fd306cSNickeau        /** @var Doku_Renderer_xhtml $renderer */
19804fd306cSNickeau        try {
19904fd306cSNickeau            $mediaMarkup = MediaMarkup::createFromCallStackArray($callStackArray);
20004fd306cSNickeau        } catch (ExceptionCompile $e) {
20104fd306cSNickeau            return $e->getMessage();
20204fd306cSNickeau        }
20304fd306cSNickeau
20404fd306cSNickeau
20504fd306cSNickeau        if (
20604fd306cSNickeau            $mediaMarkup->getInternalExternalType() === MediaMarkup::INTERNAL_MEDIA_CALL_NAME
20704fd306cSNickeau        ) {
20804fd306cSNickeau            try {
20904fd306cSNickeau                $isImage = $mediaMarkup->getFetcher()->getMime()->isImage();
21004fd306cSNickeau            } catch (\Exception $e) {
21104fd306cSNickeau                $isImage = false;
21204fd306cSNickeau            }
21304fd306cSNickeau            if ($isImage) {
21404fd306cSNickeau                try {
21504fd306cSNickeau                    return MediaLink::createFromMediaMarkup($mediaMarkup)->renderMediaTag();
21604fd306cSNickeau                } catch (ExceptionCompile $e) {
21704fd306cSNickeau                    if (PluginUtility::isDevOrTest()) {
21804fd306cSNickeau                        throw new ExceptionRuntime("Media Rendering Error. {$e->getMessage()}", MediaLink::CANONICAL, 0, $e);
21904fd306cSNickeau                    } else {
22004fd306cSNickeau                        $errorClass = syntax_plugin_combo_media::SVG_RENDERING_ERROR_CLASS;
22104fd306cSNickeau                        $message = "Media ({$mediaMarkup}). Error while rendering: {$e->getMessage()}";
22204fd306cSNickeau                        LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, MediaLink::CANONICAL);
22304fd306cSNickeau                        return "<span class=\"text-danger $errorClass\">" . hsc(trim($message)) . "</span>";
22404fd306cSNickeau
22504fd306cSNickeau                    }
22604fd306cSNickeau                }
22704fd306cSNickeau            }
22804fd306cSNickeau
22904fd306cSNickeau        }
23004fd306cSNickeau
23104fd306cSNickeau
23204fd306cSNickeau        /**
23304fd306cSNickeau         * This is not an local internal media image (a video or an url image)
23404fd306cSNickeau         * Dokuwiki takes over
23504fd306cSNickeau         */
23604fd306cSNickeau        $mediaType = $mediaMarkup->getInternalExternalType();
23704fd306cSNickeau        try {
23804fd306cSNickeau            $title = $mediaMarkup->getLabel();
23904fd306cSNickeau        } catch (ExceptionNotFound $e) {
24004fd306cSNickeau            $title = null;
24104fd306cSNickeau        }
24204fd306cSNickeau        try {
24304fd306cSNickeau            $linking = $mediaMarkup->getLinking();
24404fd306cSNickeau        } catch (ExceptionNotFound $e) {
24504fd306cSNickeau            $linking = null;
24604fd306cSNickeau        }
24704fd306cSNickeau        try {
24804fd306cSNickeau            $align = $mediaMarkup->getAlign();
24904fd306cSNickeau        } catch (ExceptionNotFound $e) {
25004fd306cSNickeau            $align = null;
25104fd306cSNickeau        }
25204fd306cSNickeau        try {
25304fd306cSNickeau            /**
25404fd306cSNickeau             * We use the markup ref url
25504fd306cSNickeau             * because we don't support http/https (external) url
25604fd306cSNickeau             * And there is therefore no fetcher available
25704fd306cSNickeau             */
25804fd306cSNickeau            $markupUrl = $mediaMarkup->getMarkupRef()->getUrl();
25904fd306cSNickeau
26004fd306cSNickeau        } catch (ExceptionNotFound $e) {
26104fd306cSNickeau            // the
26204fd306cSNickeau            LogUtility::internalError("As the media markup is created from a markup in the syntax component, it should be available");
26304fd306cSNickeau            return "";
26404fd306cSNickeau        }
26504fd306cSNickeau
26604fd306cSNickeau        try {
26704fd306cSNickeau            $src = $mediaMarkup->getSrc();
26804fd306cSNickeau        } catch (ExceptionNotFound $e) {
26904fd306cSNickeau            LogUtility::internalError("For an external markup, the src should not be empty", self::CANONICAL);
27004fd306cSNickeau            return "";
27104fd306cSNickeau        }
27204fd306cSNickeau        try {
27304fd306cSNickeau            $isImage = FileSystems::getMime($markupUrl)->isImage();
27404fd306cSNickeau        } catch (ExceptionNotFound $e) {
27504fd306cSNickeau            $isImage = false;
27604fd306cSNickeau        }
27704fd306cSNickeau        if ($isImage) {
27804fd306cSNickeau            /**
27904fd306cSNickeau             * We need to delete the
28004fd306cSNickeau             * wXh and other properties
28104fd306cSNickeau             * Dokuwiki does not accept it in its function
28204fd306cSNickeau             */
28304fd306cSNickeau            try {
28404fd306cSNickeau                $src = Url::createEmpty()
28504fd306cSNickeau                    ->setScheme($markupUrl->getScheme())
28604fd306cSNickeau                    ->setHost($markupUrl->getHost())
28704fd306cSNickeau                    ->setPath($markupUrl->getPath())
28804fd306cSNickeau                    ->toString();
28904fd306cSNickeau            } catch (ExceptionNotFound $e) {
29004fd306cSNickeau
29104fd306cSNickeau            }
29204fd306cSNickeau        }
29304fd306cSNickeau        try {
29404fd306cSNickeau            $width = $markupUrl->getQueryPropertyValue(Dimension::WIDTH_KEY);
29504fd306cSNickeau        } catch
29604fd306cSNickeau        (ExceptionNotFound $e) {
29704fd306cSNickeau            $width = null;
29804fd306cSNickeau        }
29904fd306cSNickeau        try {
30004fd306cSNickeau            $height = $markupUrl->getQueryPropertyValue(Dimension::HEIGHT_KEY);
30104fd306cSNickeau        } catch (ExceptionNotFound $e) {
30204fd306cSNickeau            $height = null;
30304fd306cSNickeau        }
30404fd306cSNickeau        try {
30504fd306cSNickeau            $cache = $markupUrl->getQueryPropertyValue(IFetcherAbs::CACHE_KEY);
30604fd306cSNickeau        } catch (ExceptionNotFound $e) {
30704fd306cSNickeau            // Dokuwiki needs a value
30804fd306cSNickeau            // If their is no value it will output it without any value
30904fd306cSNickeau            // in the query string.
31004fd306cSNickeau            $cache = IFetcherAbs::CACHE_DEFAULT_VALUE;
31104fd306cSNickeau        }
31204fd306cSNickeau        switch ($mediaType) {
31304fd306cSNickeau            case MediaMarkup::INTERNAL_MEDIA_CALL_NAME:
31404fd306cSNickeau                return $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
31504fd306cSNickeau            case MediaMarkup::EXTERNAL_MEDIA_CALL_NAME:
31604fd306cSNickeau                return $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
31704fd306cSNickeau            default:
31804fd306cSNickeau                LogUtility::msg("The dokuwiki media type ($mediaType) is unknown");
31904fd306cSNickeau                return "";
32004fd306cSNickeau        }
32104fd306cSNickeau    }
32204fd306cSNickeau
32304fd306cSNickeau
32404fd306cSNickeau    /**
32504fd306cSNickeau     * Compliance: src in dokuwiki is the id and the anchor if any
32604fd306cSNickeau     * Dokuwiki does not understand other property and the reference metadata
32704fd306cSNickeau     * may not work if we send back the `ref`
32804fd306cSNickeau     * @throws ExceptionNotFound
32904fd306cSNickeau     */
33004fd306cSNickeau    public function getSrc(): string
33104fd306cSNickeau    {
33204fd306cSNickeau        $internalExternalType = $this->getInternalExternalType();
33304fd306cSNickeau        switch ($internalExternalType) {
33404fd306cSNickeau            case MediaMarkup::INTERNAL_MEDIA_CALL_NAME:
33504fd306cSNickeau                /**
33604fd306cSNickeau                 * Absolute id because dokuwiki resolve a relatif id
33704fd306cSNickeau                 * to the actual namespace
33804fd306cSNickeau                 */
33904fd306cSNickeau                $src = $this->getPath()->toAbsoluteId();
34004fd306cSNickeau                try {
34104fd306cSNickeau                    $src = "$src#{$this->markupRef->getUrl()->getFragment()}";
34204fd306cSNickeau                } catch (ExceptionNotFound $e) {
34304fd306cSNickeau                    // ok
34404fd306cSNickeau                }
34504fd306cSNickeau                return $src;
34604fd306cSNickeau            case MediaMarkup::EXTERNAL_MEDIA_CALL_NAME:
34704fd306cSNickeau                return $this->getMarkupRef()->getRef();
34804fd306cSNickeau            default:
34904fd306cSNickeau                LogUtility::internalError("The internal/external type value ($internalExternalType) is unknown");
35004fd306cSNickeau                return $this->getMarkupRef()->getRef();
35104fd306cSNickeau        }
35204fd306cSNickeau
35304fd306cSNickeau    }
35404fd306cSNickeau
35504fd306cSNickeau    /**
35604fd306cSNickeau     * Media Type Needed by Dokuwiki
35704fd306cSNickeau     */
35804fd306cSNickeau    public function getInternalExternalType(): string
35904fd306cSNickeau    {
36004fd306cSNickeau        try {
36104fd306cSNickeau            // if there is a path, this is internal
36204fd306cSNickeau            // if interwiki this, wiki id, ...
36304fd306cSNickeau            $this->markupRef->getPath();
36404fd306cSNickeau            return self::INTERNAL_MEDIA_CALL_NAME;
36504fd306cSNickeau        } catch (ExceptionNotFound $e) {
36604fd306cSNickeau            return self::EXTERNAL_MEDIA_CALL_NAME;
36704fd306cSNickeau        }
36804fd306cSNickeau
36904fd306cSNickeau    }
37004fd306cSNickeau
37104fd306cSNickeau
37204fd306cSNickeau    /**
37304fd306cSNickeau     * @throws ExceptionBadSyntax
37404fd306cSNickeau     * @throws ExceptionBadArgument
37504fd306cSNickeau     * @throws ExceptionNotFound
37604fd306cSNickeau     */
37704fd306cSNickeau    public static function createFromRef(string $markupRef): MediaMarkup
37804fd306cSNickeau    {
37904fd306cSNickeau        return (new MediaMarkup())->setMarkupRef($markupRef);
38004fd306cSNickeau    }
38104fd306cSNickeau
38204fd306cSNickeau    /**
38304fd306cSNickeau     * Keep track of the metadata
38404fd306cSNickeau     * @param array $data
38504fd306cSNickeau     * @param Doku_Renderer_metadata $renderer
38604fd306cSNickeau     * @return void
38704fd306cSNickeau     */
38804fd306cSNickeau    public static function metadata(array $data, Doku_Renderer_metadata $renderer)
38904fd306cSNickeau    {
39004fd306cSNickeau
39104fd306cSNickeau        $tagAttributes = $data[PluginUtility::ATTRIBUTES];
39204fd306cSNickeau        if ($tagAttributes === null) {
39304fd306cSNickeau            // error on handle
39404fd306cSNickeau            return;
39504fd306cSNickeau        }
39604fd306cSNickeau        syntax_plugin_combo_media::registerImageMeta($tagAttributes, $renderer);
39704fd306cSNickeau
39804fd306cSNickeau    }
39904fd306cSNickeau
40004fd306cSNickeau    /**
40104fd306cSNickeau     * Special pattern call
40204fd306cSNickeau     * @param array $data
40304fd306cSNickeau     * @param renderer_plugin_combo_analytics $renderer
40404fd306cSNickeau     * @return void
40504fd306cSNickeau     * @deprecated - for metadata but yeah ...
40604fd306cSNickeau     */
40704fd306cSNickeau    public static function analytics(array $data, renderer_plugin_combo_analytics $renderer)
40804fd306cSNickeau    {
40904fd306cSNickeau
41004fd306cSNickeau        $tagAttributes = $data[PluginUtility::ATTRIBUTES];
41104fd306cSNickeau        syntax_plugin_combo_media::updateStatistics($tagAttributes, $renderer);
41204fd306cSNickeau
41304fd306cSNickeau    }
41404fd306cSNickeau
41504fd306cSNickeau
41604fd306cSNickeau    /**
41704fd306cSNickeau     * @return Url - an url that has query property as a fetch url
41804fd306cSNickeau     * It permits to select the fetch class
41904fd306cSNickeau     * @deprecated use {@link MediaMarkup::getFetcher()}->getUrl instead
42004fd306cSNickeau     */
42104fd306cSNickeau    public function getFetchUrl(): Url
42204fd306cSNickeau    {
42304fd306cSNickeau        return $this->getFetcher()->getFetchUrl();
42404fd306cSNickeau    }
42504fd306cSNickeau
42604fd306cSNickeau
42704fd306cSNickeau    /**
42804fd306cSNickeau     * @param string $match - the match of the renderer
42904fd306cSNickeau     * @throws ExceptionBadSyntax - if no ref was found
43004fd306cSNickeau     * @throws ExceptionBadArgument
43104fd306cSNickeau     * @throws ExceptionNotFound|ExceptionNotExists
43204fd306cSNickeau     * @throws ExceptionInternal
43304fd306cSNickeau     */
43404fd306cSNickeau    public static function createFromMarkup(string $match): MediaMarkup
43504fd306cSNickeau    {
43604fd306cSNickeau
43704fd306cSNickeau        $mediaMarkup = new MediaMarkup();
43804fd306cSNickeau
43904fd306cSNickeau        /**
44004fd306cSNickeau         *   * Delete the opening and closing character
44104fd306cSNickeau         *   * create the url and description
44204fd306cSNickeau         */
44304fd306cSNickeau        $match = preg_replace(array('/^{{/', '/}}$/u'), '', $match);
44404fd306cSNickeau        $parts = explode('|', $match, 2);
44504fd306cSNickeau
44604fd306cSNickeau        $ref = $parts[0];
44704fd306cSNickeau        if ($ref === null) {
44804fd306cSNickeau            throw new ExceptionBadSyntax("No ref was found");
44904fd306cSNickeau        }
45004fd306cSNickeau        $mediaMarkup->setMarkupRef($ref);
45104fd306cSNickeau        if (isset($parts[1])) {
45204fd306cSNickeau            $mediaMarkup->setLabel($parts[1]);
45304fd306cSNickeau        }
45404fd306cSNickeau
45504fd306cSNickeau
45604fd306cSNickeau        /**
45704fd306cSNickeau         * Media Alignment
45804fd306cSNickeau         */
45904fd306cSNickeau        $rightAlign = (bool)preg_match('/^ /', $ref);
46004fd306cSNickeau        $leftAlign = (bool)preg_match('/ $/', $ref);
46104fd306cSNickeau        $align = null;
46204fd306cSNickeau        // Logic = what's that ;)...
46304fd306cSNickeau        if ($leftAlign & $rightAlign) {
46404fd306cSNickeau            $align = 'center';
46504fd306cSNickeau        } else if ($rightAlign) {
46604fd306cSNickeau            $align = 'right';
46704fd306cSNickeau        } else if ($leftAlign) {
46804fd306cSNickeau            $align = 'left';
46904fd306cSNickeau        }
47004fd306cSNickeau        if ($align !== null) {
47104fd306cSNickeau            $mediaMarkup->setAlign($align);
47204fd306cSNickeau        }
47304fd306cSNickeau
47404fd306cSNickeau        return $mediaMarkup;
47504fd306cSNickeau
47604fd306cSNickeau
47704fd306cSNickeau    }
47804fd306cSNickeau
47904fd306cSNickeau    public function setAlign(string $align): MediaMarkup
48004fd306cSNickeau    {
48104fd306cSNickeau        $this->align = $align;
48204fd306cSNickeau        return $this;
48304fd306cSNickeau    }
48404fd306cSNickeau
48504fd306cSNickeau    public function setLabel(string $label): MediaMarkup
48604fd306cSNickeau    {
48704fd306cSNickeau        $this->label = $label;
48804fd306cSNickeau        return $this;
48904fd306cSNickeau    }
49004fd306cSNickeau
49104fd306cSNickeau    /**
49204fd306cSNickeau     * just FYI, not used
49304fd306cSNickeau     *
49404fd306cSNickeau     * Create an image from dokuwiki {@link Internallink internal call media attributes}
49504fd306cSNickeau     *
49604fd306cSNickeau     * Dokuwiki extracts already the width, height and align property
49704fd306cSNickeau     * @param array $callAttributes
49804fd306cSNickeau     * @return MediaMarkup
49904fd306cSNickeau     */
50004fd306cSNickeau    public static function createFromIndexAttributes(array $callAttributes)
50104fd306cSNickeau    {
50204fd306cSNickeau        $src = $callAttributes[0];
50304fd306cSNickeau        $title = $callAttributes[1];
50404fd306cSNickeau        $align = $callAttributes[2];
50504fd306cSNickeau        $width = $callAttributes[3];
50604fd306cSNickeau        $height = $callAttributes[4];
50704fd306cSNickeau        $cache = $callAttributes[5];
50804fd306cSNickeau        $linking = $callAttributes[6];
50904fd306cSNickeau
51004fd306cSNickeau        $ref = "$src?{$width}x$height&$cache";
51104fd306cSNickeau        return (new MediaMarkup())
51204fd306cSNickeau            ->setMarkupRef($ref)
51304fd306cSNickeau            ->setAlign($align)
51404fd306cSNickeau            ->setLabel($title)
51504fd306cSNickeau            ->setLinking($linking);
51604fd306cSNickeau
51704fd306cSNickeau    }
51804fd306cSNickeau
51904fd306cSNickeau    /**
52004fd306cSNickeau     * A function to set explicitly which array format
52104fd306cSNickeau     * is used in the returned data of a {@link SyntaxPlugin::handle()}
52204fd306cSNickeau     * (which ultimately is stored in the {@link CallStack)
52304fd306cSNickeau     *
52404fd306cSNickeau     * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()}
52504fd306cSNickeau     * that is indexed by number (ie without property name)
52604fd306cSNickeau     *
52704fd306cSNickeau     *
52804fd306cSNickeau     * Return the array that is used in the {@link CallStack}
52904fd306cSNickeau     *
53004fd306cSNickeau     * @return array of key string and value
53104fd306cSNickeau     */
53204fd306cSNickeau    public function toCallStackArray(): array
53304fd306cSNickeau    {
53404fd306cSNickeau        /**
53504fd306cSNickeau         * We store linking as attribute (to make it possible to change the linking by other plugin)
53604fd306cSNickeau         * (ie no linking in heading , ...)
53704fd306cSNickeau         */
53804fd306cSNickeau        $attributes[MediaMarkup::LINKING_KEY] = $this->linking;
53904fd306cSNickeau        $attributes[MarkupRef::REF_ATTRIBUTE] = $this->markupRef->getRef();
54004fd306cSNickeau        $attributes[Align::ALIGN_ATTRIBUTE] = $this->align;
54104fd306cSNickeau        $attributes[TagAttributes::TITLE_KEY] = $this->label;
54204fd306cSNickeau        return $attributes;
54304fd306cSNickeau
54404fd306cSNickeau    }
54504fd306cSNickeau
54604fd306cSNickeau    public function setLinking(string $linking): MediaMarkup
54704fd306cSNickeau    {
54804fd306cSNickeau        $this->linking = $linking;
54904fd306cSNickeau        return $this;
55004fd306cSNickeau    }
55104fd306cSNickeau
55204fd306cSNickeau    /**
55304fd306cSNickeau     * @throws ExceptionNotFound
55404fd306cSNickeau     */
55504fd306cSNickeau    public function getLinking(): string
55604fd306cSNickeau    {
55704fd306cSNickeau        /**
55804fd306cSNickeau         * Linking
55904fd306cSNickeau         */
56004fd306cSNickeau        $linking = $this->linking;
56104fd306cSNickeau        if ($linking !== null) {
56204fd306cSNickeau            return $linking;
56304fd306cSNickeau        }
56404fd306cSNickeau        throw new ExceptionNotFound("No linking set");
56504fd306cSNickeau
56604fd306cSNickeau
56704fd306cSNickeau    }
56804fd306cSNickeau
56904fd306cSNickeau    /**
57004fd306cSNickeau     * Align on the url has precedence
57104fd306cSNickeau     * if present
57204fd306cSNickeau     * @throws ExceptionNotFound
57304fd306cSNickeau     */
57404fd306cSNickeau    public function getAlign(): string
57504fd306cSNickeau    {
57604fd306cSNickeau
57704fd306cSNickeau        if ($this->align !== null) {
57804fd306cSNickeau            return $this->align;
57904fd306cSNickeau        }
58004fd306cSNickeau        throw new ExceptionNotFound("No align was specified");
58104fd306cSNickeau    }
58204fd306cSNickeau
58304fd306cSNickeau
58404fd306cSNickeau    public function toTagAttributes()
58504fd306cSNickeau    {
58604fd306cSNickeau
58704fd306cSNickeau
58804fd306cSNickeau        /**
58904fd306cSNickeau         * The align attribute on an image parse
59004fd306cSNickeau         * is a float right
59104fd306cSNickeau         * ComboStrap does a difference between a block right and a float right
59204fd306cSNickeau         */
59304fd306cSNickeau        try {
59404fd306cSNickeau            $align = $this->getAlign();
59504fd306cSNickeau            if ($align === "right") {
59604fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue(FloatAttribute::FLOAT_KEY, "right");
59704fd306cSNickeau            } else {
59804fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue(Align::ALIGN_ATTRIBUTE, $align);
59904fd306cSNickeau            }
60004fd306cSNickeau        } catch (ExceptionNotFound $e) {
60104fd306cSNickeau            // ok
60204fd306cSNickeau        }
60304fd306cSNickeau
60404fd306cSNickeau        return $this->extraMediaTagAttributes;
60504fd306cSNickeau
60604fd306cSNickeau    }
60704fd306cSNickeau
60804fd306cSNickeau    /**
60904fd306cSNickeau     * @throws ExceptionNotFound
61004fd306cSNickeau     */
61104fd306cSNickeau    public function getLabel(): string
61204fd306cSNickeau    {
61304fd306cSNickeau        if (empty($this->label)) {
61404fd306cSNickeau            throw new ExceptionNotFound("No label specified");
61504fd306cSNickeau        }
61604fd306cSNickeau        return $this->label;
61704fd306cSNickeau    }
61804fd306cSNickeau
61904fd306cSNickeau    public
62004fd306cSNickeau    function setLazyLoadMethod($false): MediaMarkup
62104fd306cSNickeau    {
62204fd306cSNickeau        $this->lazyLoadMethod = $false;
62304fd306cSNickeau        return $this;
62404fd306cSNickeau    }
62504fd306cSNickeau
62604fd306cSNickeau    /**
62704fd306cSNickeau     * @throws ExceptionNotFound
62804fd306cSNickeau     */
62904fd306cSNickeau    public
63004fd306cSNickeau    function getLazyLoadMethod(): string
63104fd306cSNickeau    {
63204fd306cSNickeau
63304fd306cSNickeau        if ($this->lazyLoadMethod !== null) {
63404fd306cSNickeau            return $this->lazyLoadMethod;
63504fd306cSNickeau        }
63604fd306cSNickeau        throw new ExceptionNotFound("Lazy method is not specified");
63704fd306cSNickeau
63804fd306cSNickeau    }
63904fd306cSNickeau
64004fd306cSNickeau    public
64104fd306cSNickeau    function getLazyLoadMethodOrDefault(): string
64204fd306cSNickeau    {
64304fd306cSNickeau        try {
64404fd306cSNickeau            return $this->getLazyLoadMethod();
64504fd306cSNickeau        } catch (ExceptionNotFound $e) {
64604fd306cSNickeau            return LazyLoad::getDefault();
64704fd306cSNickeau        }
64804fd306cSNickeau
64904fd306cSNickeau    }
65004fd306cSNickeau
65104fd306cSNickeau
65204fd306cSNickeau    public
65304fd306cSNickeau    static function isInternalMediaSyntax($text)
65404fd306cSNickeau    {
65504fd306cSNickeau        return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text);
65604fd306cSNickeau    }
65704fd306cSNickeau
65804fd306cSNickeau
65904fd306cSNickeau    public function isLazy(): bool
66004fd306cSNickeau    {
66104fd306cSNickeau
66204fd306cSNickeau        return $this->getLazyLoadMethodOrDefault() !== LazyLoad::LAZY_LOAD_METHOD_NONE_VALUE;
66304fd306cSNickeau
66404fd306cSNickeau    }
66504fd306cSNickeau
66604fd306cSNickeau    public function getExtraMediaTagAttributes(): TagAttributes
66704fd306cSNickeau    {
66804fd306cSNickeau        try {
66904fd306cSNickeau            $this->extraMediaTagAttributes->addComponentAttributeValue(Align::ALIGN_ATTRIBUTE, $this->getAlign());
67004fd306cSNickeau        } catch (ExceptionNotFound $e) {
67104fd306cSNickeau            // ok
67204fd306cSNickeau        }
67304fd306cSNickeau        return $this->extraMediaTagAttributes;
67404fd306cSNickeau    }
67504fd306cSNickeau
67604fd306cSNickeau
67704fd306cSNickeau    public function __toString()
67804fd306cSNickeau    {
67904fd306cSNickeau        return $this->toMarkupSyntax();
68004fd306cSNickeau    }
68104fd306cSNickeau
68204fd306cSNickeau    public function setLazyLoad(bool $true): MediaMarkup
68304fd306cSNickeau    {
68404fd306cSNickeau        if ($true) {
68504fd306cSNickeau            $this->lazyLoadMethod = LazyLoad::getDefault();
68604fd306cSNickeau        } else {
68704fd306cSNickeau            $this->lazyLoadMethod = LazyLoad::LAZY_LOAD_METHOD_NONE_VALUE;
68804fd306cSNickeau        }
68904fd306cSNickeau        return $this;
69004fd306cSNickeau    }
69104fd306cSNickeau
69204fd306cSNickeau    /**
69304fd306cSNickeau     * Get and delete the attribute for the link
69404fd306cSNickeau     * (The rest is for the image)
69504fd306cSNickeau     */
69604fd306cSNickeau    public
69704fd306cSNickeau    function getLinkingClass()
69804fd306cSNickeau    {
69904fd306cSNickeau        return $this->linkingClass;
70004fd306cSNickeau    }
70104fd306cSNickeau
70204fd306cSNickeau    /**
70304fd306cSNickeau     * @throws ExceptionNotFound
70404fd306cSNickeau     */
70504fd306cSNickeau    public function getMarkupRef(): MarkupRef
70604fd306cSNickeau    {
70704fd306cSNickeau        if ($this->markupRef === null) {
70804fd306cSNickeau            throw new ExceptionNotFound("No markup, this media markup was not created from a markup");
70904fd306cSNickeau        }
71004fd306cSNickeau        return $this->markupRef;
71104fd306cSNickeau    }
71204fd306cSNickeau
71304fd306cSNickeau
71404fd306cSNickeau    /**
71504fd306cSNickeau     * @param TagAttributes $tagAttributes - the attributes in a tag format
71604fd306cSNickeau     * @return $this
71704fd306cSNickeau     */
71804fd306cSNickeau    public function buildFromTagAttributes(TagAttributes $tagAttributes): MediaMarkup
71904fd306cSNickeau    {
72004fd306cSNickeau
72104fd306cSNickeau        $linking = $tagAttributes->getValueAndRemoveIfPresent(self::LINKING_KEY);
72204fd306cSNickeau        if ($linking !== null) {
72304fd306cSNickeau            $this->setLinking($linking);
72404fd306cSNickeau        }
72504fd306cSNickeau        $label = $tagAttributes->getValueAndRemoveIfPresent(TagAttributes::TITLE_KEY);
72604fd306cSNickeau        if ($label !== null) {
72704fd306cSNickeau            $this->setLabel($label);
72804fd306cSNickeau        }
72904fd306cSNickeau        $align = $tagAttributes->getValueAndRemoveIfPresent(Align::ALIGN_ATTRIBUTE);
73004fd306cSNickeau        if ($align !== null) {
73104fd306cSNickeau            $this->setAlign($align);
73204fd306cSNickeau        }
73304fd306cSNickeau        $lazy = $tagAttributes->getValueAndRemoveIfPresent(LazyLoad::LAZY_LOAD_METHOD);
73404fd306cSNickeau        if ($lazy !== null) {
73504fd306cSNickeau            $this->setLazyLoadMethod($lazy);
73604fd306cSNickeau        }
73704fd306cSNickeau
73804fd306cSNickeau        /**
73904fd306cSNickeau         * dokuwiki attribute
74004fd306cSNickeau         */
74104fd306cSNickeau        if (isset($this->fetchUrl)) {
74204fd306cSNickeau            $width = $tagAttributes->getValueAndRemoveIfPresent(Dimension::WIDTH_KEY);
74304fd306cSNickeau            if ($width !== null) {
74404fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::WIDTH_KEY, $width);
74504fd306cSNickeau            }
74604fd306cSNickeau            $height = $tagAttributes->getValueAndRemoveIfPresent(Dimension::HEIGHT_KEY);
74704fd306cSNickeau            if ($height !== null) {
74804fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::HEIGHT_KEY, $height);
74904fd306cSNickeau            }
75004fd306cSNickeau            $ratio = $tagAttributes->getValueAndRemoveIfPresent(Dimension::RATIO_ATTRIBUTE);
75104fd306cSNickeau            if ($ratio !== null) {
75204fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::RATIO_ATTRIBUTE, $ratio);
75304fd306cSNickeau            }
75404fd306cSNickeau        }
75504fd306cSNickeau
75604fd306cSNickeau        foreach ($tagAttributes->getComponentAttributes() as $key => $value) {
75704fd306cSNickeau            $this->extraMediaTagAttributes->addComponentAttributeValue($key, $value);
75804fd306cSNickeau        }
75904fd306cSNickeau
76004fd306cSNickeau        foreach ($tagAttributes->getStyleDeclarations() as $key => $value) {
76104fd306cSNickeau            $this->extraMediaTagAttributes->addStyleDeclarationIfNotSet($key, $value);
76204fd306cSNickeau        }
76304fd306cSNickeau
76404fd306cSNickeau        return $this;
76504fd306cSNickeau    }
76604fd306cSNickeau
76704fd306cSNickeau    /**
76804fd306cSNickeau     * @throws ExceptionBadArgument
76904fd306cSNickeau     * @throws ExceptionBadSyntax
77004fd306cSNickeau     * @throws ExceptionNotExists
77104fd306cSNickeau     * @throws ExceptionNotFound
77204fd306cSNickeau     */
77304fd306cSNickeau    public function toHtml(): string
77404fd306cSNickeau    {
77504fd306cSNickeau        return MediaLink::createFromMediaMarkup($this)
77604fd306cSNickeau            ->renderMediaTag();
77704fd306cSNickeau    }
77804fd306cSNickeau
77904fd306cSNickeau    /**
78004fd306cSNickeau     * @throws ExceptionBadSyntax
78104fd306cSNickeau     * @throws ExceptionBadArgument
78204fd306cSNickeau     * @throws ExceptionNotExists
78304fd306cSNickeau     * @throws ExceptionNotFound
78404fd306cSNickeau     */
78504fd306cSNickeau    public function getMediaLink()
78604fd306cSNickeau    {
78704fd306cSNickeau        return MediaLink::createFromMediaMarkup($this);
78804fd306cSNickeau    }
78904fd306cSNickeau
79004fd306cSNickeau    private
79104fd306cSNickeau    function setLinkingClass($value): MediaMarkup
79204fd306cSNickeau    {
79304fd306cSNickeau        $this->linkingClass = $value;
79404fd306cSNickeau        return $this;
79504fd306cSNickeau    }
79604fd306cSNickeau
79704fd306cSNickeau    /**
79804fd306cSNickeau     * @return string the wiki syntax
79904fd306cSNickeau     */
80004fd306cSNickeau    public function toMarkupSyntax(): string
80104fd306cSNickeau    {
80204fd306cSNickeau        $descriptionPart = "";
80304fd306cSNickeau        try {
80404fd306cSNickeau            $descriptionPart = "|" . $this->getLabel();
80504fd306cSNickeau        } catch (ExceptionNotFound $e) {
80604fd306cSNickeau            // ok
80704fd306cSNickeau        }
80804fd306cSNickeau        try {
80904fd306cSNickeau            $ref = $this->getRef();
81004fd306cSNickeau        } catch (ExceptionNotFound $e) {
81104fd306cSNickeau            $ref = $this->getFetchUrl()->toString();
81204fd306cSNickeau        }
81304fd306cSNickeau        return '{{' . $ref . $descriptionPart . '}}';
81404fd306cSNickeau    }
81504fd306cSNickeau
81604fd306cSNickeau    /**
81704fd306cSNickeau     *
81804fd306cSNickeau     * Private method use {@link MediaMarkup::createFromFetchUrl()} to create a media markup via a Url
81904fd306cSNickeau     *
82004fd306cSNickeau     * @throws ExceptionNotFound
82104fd306cSNickeau     */
82204fd306cSNickeau    private function setUrl(Url $fetchUrl): MediaMarkup
82304fd306cSNickeau    {
82404fd306cSNickeau
82504fd306cSNickeau        /**
82604fd306cSNickeau         * Tag Attributes
82704fd306cSNickeau         */
82804fd306cSNickeau        try {
82904fd306cSNickeau            $this->align = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(Align::ALIGN_ATTRIBUTE);
83004fd306cSNickeau        } catch (ExceptionNotFound $e) {
83104fd306cSNickeau            // ok
83204fd306cSNickeau        }
83304fd306cSNickeau        try {
83404fd306cSNickeau            $this->linking = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(self::LINKING_KEY);
83504fd306cSNickeau        } catch (ExceptionNotFound $e) {
83604fd306cSNickeau            // ok
83704fd306cSNickeau        }
83804fd306cSNickeau        try {
83904fd306cSNickeau            $this->lazyLoadMethod = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(LazyLoad::LAZY_LOAD_METHOD);
84004fd306cSNickeau        } catch (ExceptionNotFound $e) {
84104fd306cSNickeau            // ok
84204fd306cSNickeau        }
84304fd306cSNickeau        try {
84404fd306cSNickeau            $this->linkingClass = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(self::LINK_CLASS_ATTRIBUTE);
84504fd306cSNickeau        } catch (ExceptionNotFound $e) {
84604fd306cSNickeau            // ok
84704fd306cSNickeau        }
84804fd306cSNickeau
84904fd306cSNickeau        foreach (self::STYLE_ATTRIBUTES as $nonUrlAttribute) {
85004fd306cSNickeau            try {
85104fd306cSNickeau                $value = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent($nonUrlAttribute);
85204fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue($nonUrlAttribute, $value);
85304fd306cSNickeau            } catch (ExceptionNotFound $e) {
85404fd306cSNickeau                // ok
85504fd306cSNickeau            }
85604fd306cSNickeau        }
85704fd306cSNickeau
85804fd306cSNickeau        $this->fetchUrl = $fetchUrl;
85904fd306cSNickeau        return $this;
86004fd306cSNickeau    }
86104fd306cSNickeau
86204fd306cSNickeau    /**
86304fd306cSNickeau     * @throws ExceptionNotFound
86404fd306cSNickeau     */
86504fd306cSNickeau    private function getRef(): string
86604fd306cSNickeau    {
86704fd306cSNickeau        if ($this->markupRef === null) {
86804fd306cSNickeau            throw new ExceptionNotFound("No ref was specified");
86904fd306cSNickeau        }
87004fd306cSNickeau        return $this->markupRef->getRef();
87104fd306cSNickeau    }
87204fd306cSNickeau
87304fd306cSNickeau    /**
87404fd306cSNickeau     * @throws ExceptionNotFound - if this markup does not have a path origin
87504fd306cSNickeau     * @deprecated use the {@link self::getFetcher()} instead
87604fd306cSNickeau     * A media may be generated (ie {@link FetcherVignette}
87704fd306cSNickeau     * therefore the path may be not present
87804fd306cSNickeau     *
87904fd306cSNickeau     * If you want to known the mime use {@link self::getFetcher()} then {@link IFetcher::getMime()}
88004fd306cSNickeau     */
88104fd306cSNickeau    public function getPath(): WikiPath
88204fd306cSNickeau    {
88304fd306cSNickeau        try {
88404fd306cSNickeau
88504fd306cSNickeau            return $this->getMarkupRef()->getPath();
88604fd306cSNickeau
88704fd306cSNickeau        } catch (ExceptionNotFound $e) {
88804fd306cSNickeau
88904fd306cSNickeau            if ($this->fetcher instanceof IFetcherSource) {
89004fd306cSNickeau                return $this->fetcher->getSourcePath();
89104fd306cSNickeau            }
89204fd306cSNickeau            throw $e;
89304fd306cSNickeau
89404fd306cSNickeau        }
89504fd306cSNickeau    }
89604fd306cSNickeau
89704fd306cSNickeau    /**
89804fd306cSNickeau     * Private method use {@link MediaMarkup::createFromFetcher()} to create a media markup via a Fetcher
89904fd306cSNickeau     * @param IFetcher $fetcher
90004fd306cSNickeau     * @return MediaMarkup
90104fd306cSNickeau     */
90204fd306cSNickeau    private function setFetcher(IFetcher $fetcher): MediaMarkup
90304fd306cSNickeau    {
90404fd306cSNickeau        $this->fetcher = $fetcher;
90504fd306cSNickeau        return $this;
90604fd306cSNickeau    }
90704fd306cSNickeau
90804fd306cSNickeau
90904fd306cSNickeau    /**
91004fd306cSNickeau     * @return IFetcher
91104fd306cSNickeau     */
91204fd306cSNickeau    public function getFetcher(): IFetcher
91304fd306cSNickeau    {
91404fd306cSNickeau        if (!isset($this->fetcher)) {
91504fd306cSNickeau            if (!isset($this->fetchUrl)) {
91604fd306cSNickeau                throw new ExceptionRuntimeInternal("No fetcher or url was set");
91704fd306cSNickeau            }
91804fd306cSNickeau            /**
91904fd306cSNickeau             * Fetcher is build later
92004fd306cSNickeau             * because for a raster image
92104fd306cSNickeau             * actually, we can't built it
92204fd306cSNickeau             * if the file does not exists.
92304fd306cSNickeau             * It will throw an error immediatly and we may want not.
92404fd306cSNickeau             * For resources, we want to build the url even if the image does not exists.
92504fd306cSNickeau             */
92604fd306cSNickeau            try {
92704fd306cSNickeau                $this->fetcher = FetcherSystem::createPathFetcherFromUrl($this->fetchUrl);
92804fd306cSNickeau            } catch (ExceptionBadArgument|ExceptionInternal|ExceptionNotFound $e) {
92904fd306cSNickeau                try {
93004fd306cSNickeau                    // we don't support http fetch
93104fd306cSNickeau                    if (!($this->getMarkupRef()->getSchemeType() === MarkupRef::WEB_URI)) {
93204fd306cSNickeau                        throw ExceptionRuntimeInternal::withMessageAndError("we don't support http fetch", $e);
93304fd306cSNickeau                    }
93404fd306cSNickeau                } catch (ExceptionNotFound $e) {
93504fd306cSNickeau                    // ok no markup ref
93604fd306cSNickeau                }
93704fd306cSNickeau            }
93804fd306cSNickeau        }
93904fd306cSNickeau        return $this->fetcher;
94004fd306cSNickeau    }
94104fd306cSNickeau
94204fd306cSNickeau
94304fd306cSNickeau}
944