xref: /template/strap/ComboStrap/MediaMarkup.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeau
4*04fd306cSNickeaunamespace ComboStrap;
5*04fd306cSNickeau
6*04fd306cSNickeau
7*04fd306cSNickeauuse ComboStrap\TagAttribute\Align;
8*04fd306cSNickeauuse ComboStrap\TagAttribute\Animation;
9*04fd306cSNickeauuse ComboStrap\TagAttribute\Shadow;
10*04fd306cSNickeauuse ComboStrap\Web\Url;
11*04fd306cSNickeauuse Doku_Renderer_metadata;
12*04fd306cSNickeauuse Doku_Renderer_xhtml;
13*04fd306cSNickeauuse renderer_plugin_combo_analytics;
14*04fd306cSNickeauuse syntax_plugin_combo_media;
15*04fd306cSNickeau
16*04fd306cSNickeau/**
17*04fd306cSNickeau * This class represents a media markup:
18*04fd306cSNickeau *   - with a {@link MediaMarkup::getFetcher() fetcher}
19*04fd306cSNickeau *   - and {@link MediaMarkup::getExtraMediaTagAttributes() tag/styling attributes}
20*04fd306cSNickeau *
21*04fd306cSNickeau * You can create it:
22*04fd306cSNickeau *   * via a {@link MediaMarkup::createFromRef() Markup Ref} (The string ref in the document)
23*04fd306cSNickeau *   * via a {@link MediaMarkup::createFromFetcher() Fetcher}
24*04fd306cSNickeau *   * via a {@link MediaMarkup::createFromFetchUrl() Fetch Url}
25*04fd306cSNickeau *   * via a {@link MediaMarkup::createFromCallStackArray() callstack array} of {@link syntax_plugin_combo_media::render()}
26*04fd306cSNickeau *   * via a {@link MediaMarkup::createFromMarkup() string match} of {@link syntax_plugin_combo_media::handle()}
27*04fd306cSNickeau *
28*04fd306cSNickeau *
29*04fd306cSNickeau */
30*04fd306cSNickeauclass MediaMarkup
31*04fd306cSNickeau{
32*04fd306cSNickeau
33*04fd306cSNickeau    /**
34*04fd306cSNickeau     * No name as this is {{ --- }}
35*04fd306cSNickeau     */
36*04fd306cSNickeau    public const TAG = "media";
37*04fd306cSNickeau
38*04fd306cSNickeau    /**
39*04fd306cSNickeau     * The dokuwiki type and mode name
40*04fd306cSNickeau     * (ie call)
41*04fd306cSNickeau     *  * ie {@link MediaMarkup::EXTERNAL_MEDIA_CALL_NAME}
42*04fd306cSNickeau     *  or {@link MediaMarkup::INTERNAL_MEDIA_CALL_NAME}
43*04fd306cSNickeau     *
44*04fd306cSNickeau     * The dokuwiki type (internalmedia/externalmedia)
45*04fd306cSNickeau     *
46*04fd306cSNickeau     */
47*04fd306cSNickeau    public const MEDIA_DOKUWIKI_TYPE = 'dokuwiki_media_type';
48*04fd306cSNickeau    public const EXTERNAL_MEDIA_CALL_NAME = "externalmedia";
49*04fd306cSNickeau    public const INTERNAL_MEDIA_CALL_NAME = "internalmedia";
50*04fd306cSNickeau
51*04fd306cSNickeau    /**
52*04fd306cSNickeau     * Link value:
53*04fd306cSNickeau     *   * 'nolink'
54*04fd306cSNickeau     *   * 'direct': directly to the image
55*04fd306cSNickeau     *   * 'linkonly': show only a url
56*04fd306cSNickeau     *   * 'details': go to the details media viewer
57*04fd306cSNickeau     *
58*04fd306cSNickeau     * @var
59*04fd306cSNickeau     */
60*04fd306cSNickeau    public const LINKING_KEY = 'linking';
61*04fd306cSNickeau    public const LINKING_DETAILS_VALUE = 'details';
62*04fd306cSNickeau    public const LINKING_DIRECT_VALUE = 'direct';
63*04fd306cSNickeau    /**
64*04fd306cSNickeau     * Only used by Dokuwiki
65*04fd306cSNickeau     * Contains the path and eventually an anchor
66*04fd306cSNickeau     * never query parameters
67*04fd306cSNickeau     */
68*04fd306cSNickeau    public const DOKUWIKI_SRC = "src";
69*04fd306cSNickeau    public const LINKING_LINKONLY_VALUE = "linkonly";
70*04fd306cSNickeau    public const LINKING_NOLINK_VALUE = 'nolink';
71*04fd306cSNickeau    /**
72*04fd306cSNickeau     * Default image linking value
73*04fd306cSNickeau     */
74*04fd306cSNickeau    public const CONF_DEFAULT_LINKING = "defaultImageLinking";
75*04fd306cSNickeau
76*04fd306cSNickeau    const CANONICAL = "media";
77*04fd306cSNickeau
78*04fd306cSNickeau    /**
79*04fd306cSNickeau     * This attributes does not apply
80*04fd306cSNickeau     * to a fetch (URL)
81*04fd306cSNickeau     * They are only for the tag (img, svg, ...)
82*04fd306cSNickeau     * or internal
83*04fd306cSNickeau     */
84*04fd306cSNickeau    public const STYLE_ATTRIBUTES = [
85*04fd306cSNickeau        TagAttributes::TITLE_KEY,
86*04fd306cSNickeau        Hover::ON_HOVER_ATTRIBUTE,
87*04fd306cSNickeau        Animation::ON_VIEW_ATTRIBUTE,
88*04fd306cSNickeau        Shadow::SHADOW_ATT,
89*04fd306cSNickeau        Opacity::OPACITY_ATTRIBUTE,
90*04fd306cSNickeau        TagAttributes::CLASS_KEY,
91*04fd306cSNickeau    ];
92*04fd306cSNickeau
93*04fd306cSNickeau    /**
94*04fd306cSNickeau     * An attribute to set the class of the link if any
95*04fd306cSNickeau     */
96*04fd306cSNickeau    public const LINK_CLASS_ATTRIBUTE = "link-class";
97*04fd306cSNickeau
98*04fd306cSNickeau
99*04fd306cSNickeau    private ?string $align = null;
100*04fd306cSNickeau    private ?string $label = null;
101*04fd306cSNickeau    private ?MarkupRef $markupRef = null;
102*04fd306cSNickeau    private ?string $linking = null;
103*04fd306cSNickeau    private ?string $lazyLoadMethod = null;
104*04fd306cSNickeau    private TagAttributes $extraMediaTagAttributes;
105*04fd306cSNickeau    private ?string $linkingClass = null;
106*04fd306cSNickeau    private IFetcher $fetcher;
107*04fd306cSNickeau    private Url $fetchUrl;
108*04fd306cSNickeau
109*04fd306cSNickeau    private function __construct()
110*04fd306cSNickeau    {
111*04fd306cSNickeau        $this->extraMediaTagAttributes = TagAttributes::createEmpty();
112*04fd306cSNickeau    }
113*04fd306cSNickeau
114*04fd306cSNickeau
115*04fd306cSNickeau    /**
116*04fd306cSNickeau     * Private method use {@link MediaMarkup::createFromRef()} to create a media markup via a ref
117*04fd306cSNickeau     *
118*04fd306cSNickeau     * Set and parse a media wiki ref that you can found in the first part of a media markup
119*04fd306cSNickeau     *
120*04fd306cSNickeau     * @param string $markupRef
121*04fd306cSNickeau     * @return MediaMarkup
122*04fd306cSNickeau     * @throws ExceptionBadArgument
123*04fd306cSNickeau     * @throws ExceptionBadSyntax
124*04fd306cSNickeau     * @throws ExceptionNotFound
125*04fd306cSNickeau     */
126*04fd306cSNickeau    private function setMarkupRef(string $markupRef): MediaMarkup
127*04fd306cSNickeau    {
128*04fd306cSNickeau
129*04fd306cSNickeau        $markupRef = trim($markupRef);
130*04fd306cSNickeau        $this->markupRef = MarkupRef::createMediaFromRef($markupRef);
131*04fd306cSNickeau
132*04fd306cSNickeau        $refUrl = $this->markupRef->getUrl();
133*04fd306cSNickeau        $this->setUrl($refUrl);
134*04fd306cSNickeau
135*04fd306cSNickeau        return $this;
136*04fd306cSNickeau    }
137*04fd306cSNickeau
138*04fd306cSNickeau    /**
139*04fd306cSNickeau     * @param $callStackArray
140*04fd306cSNickeau     * @return MediaMarkup
141*04fd306cSNickeau     * @throws ExceptionBadArgument
142*04fd306cSNickeau     * @throws ExceptionBadSyntax
143*04fd306cSNickeau     * @throws ExceptionNotFound
144*04fd306cSNickeau     * @throws ExceptionNotExists
145*04fd306cSNickeau     */
146*04fd306cSNickeau    public static function createFromCallStackArray($callStackArray): MediaMarkup
147*04fd306cSNickeau    {
148*04fd306cSNickeau
149*04fd306cSNickeau        $tagAttributes = TagAttributes::createFromCallStackArray($callStackArray);
150*04fd306cSNickeau        $ref = $tagAttributes->getValueAndRemoveIfPresent(MarkupRef::REF_ATTRIBUTE);
151*04fd306cSNickeau        if ($ref === null) {
152*04fd306cSNickeau            $ref = $tagAttributes->getValueAndRemoveIfPresent(MediaMarkup::DOKUWIKI_SRC);
153*04fd306cSNickeau            if ($ref === null) {
154*04fd306cSNickeau                throw new ExceptionBadArgument("The media reference was not found in the callstack array", self::CANONICAL);
155*04fd306cSNickeau            }
156*04fd306cSNickeau        }
157*04fd306cSNickeau        return self::createFromRef($ref)
158*04fd306cSNickeau            ->buildFromTagAttributes($tagAttributes);
159*04fd306cSNickeau
160*04fd306cSNickeau
161*04fd306cSNickeau    }
162*04fd306cSNickeau
163*04fd306cSNickeau    /**
164*04fd306cSNickeau     * @throws ExceptionBadArgument
165*04fd306cSNickeau     * @throws ExceptionBadSyntax
166*04fd306cSNickeau     * @throws ExceptionNotExists
167*04fd306cSNickeau     * @throws ExceptionNotFound
168*04fd306cSNickeau     * @throws ExceptionInternal
169*04fd306cSNickeau     */
170*04fd306cSNickeau    public static function createFromFetchUrl(Url $fetchUrl): MediaMarkup
171*04fd306cSNickeau    {
172*04fd306cSNickeau        return (new MediaMarkup())->setUrl($fetchUrl);
173*04fd306cSNickeau    }
174*04fd306cSNickeau
175*04fd306cSNickeau    public static function createFromFetcher(IFetcher $fetcher): MediaMarkup
176*04fd306cSNickeau    {
177*04fd306cSNickeau        return (new MediaMarkup())
178*04fd306cSNickeau            ->setFetcher($fetcher);
179*04fd306cSNickeau    }
180*04fd306cSNickeau
181*04fd306cSNickeau    public static function renderSpecial(array $data, Doku_Renderer_xhtml $renderer)
182*04fd306cSNickeau    {
183*04fd306cSNickeau
184*04fd306cSNickeau        $callStackArray = $data[PluginUtility::ATTRIBUTES];
185*04fd306cSNickeau        $display = $callStackArray[Display::DISPLAY];
186*04fd306cSNickeau        if ($display === Display::DISPLAY_NONE_VALUE) {
187*04fd306cSNickeau            /**
188*04fd306cSNickeau             * Used primarly to not show the featured images
189*04fd306cSNickeau             * in the outline {@link Outline::toHtmlSectionOutlineCallsRecurse()}
190*04fd306cSNickeau             * for item page
191*04fd306cSNickeau             * But we keep the metadata to move them if any
192*04fd306cSNickeau             */
193*04fd306cSNickeau            return false;
194*04fd306cSNickeau        }
195*04fd306cSNickeau
196*04fd306cSNickeau        /** @var Doku_Renderer_xhtml $renderer */
197*04fd306cSNickeau        try {
198*04fd306cSNickeau            $mediaMarkup = MediaMarkup::createFromCallStackArray($callStackArray);
199*04fd306cSNickeau        } catch (ExceptionCompile $e) {
200*04fd306cSNickeau            return $e->getMessage();
201*04fd306cSNickeau        }
202*04fd306cSNickeau
203*04fd306cSNickeau
204*04fd306cSNickeau        if (
205*04fd306cSNickeau            $mediaMarkup->getInternalExternalType() === MediaMarkup::INTERNAL_MEDIA_CALL_NAME
206*04fd306cSNickeau        ) {
207*04fd306cSNickeau            try {
208*04fd306cSNickeau                $isImage = $mediaMarkup->getFetcher()->getMime()->isImage();
209*04fd306cSNickeau            } catch (\Exception $e) {
210*04fd306cSNickeau                $isImage = false;
211*04fd306cSNickeau            }
212*04fd306cSNickeau            if ($isImage) {
213*04fd306cSNickeau                try {
214*04fd306cSNickeau                    return MediaLink::createFromMediaMarkup($mediaMarkup)->renderMediaTag();
215*04fd306cSNickeau                } catch (ExceptionCompile $e) {
216*04fd306cSNickeau                    if (PluginUtility::isDevOrTest()) {
217*04fd306cSNickeau                        throw new ExceptionRuntime("Media Rendering Error. {$e->getMessage()}", MediaLink::CANONICAL, 0, $e);
218*04fd306cSNickeau                    } else {
219*04fd306cSNickeau                        $errorClass = syntax_plugin_combo_media::SVG_RENDERING_ERROR_CLASS;
220*04fd306cSNickeau                        $message = "Media ({$mediaMarkup}). Error while rendering: {$e->getMessage()}";
221*04fd306cSNickeau                        LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, MediaLink::CANONICAL);
222*04fd306cSNickeau                        return "<span class=\"text-danger $errorClass\">" . hsc(trim($message)) . "</span>";
223*04fd306cSNickeau
224*04fd306cSNickeau                    }
225*04fd306cSNickeau                }
226*04fd306cSNickeau            }
227*04fd306cSNickeau
228*04fd306cSNickeau        }
229*04fd306cSNickeau
230*04fd306cSNickeau
231*04fd306cSNickeau        /**
232*04fd306cSNickeau         * This is not an local internal media image (a video or an url image)
233*04fd306cSNickeau         * Dokuwiki takes over
234*04fd306cSNickeau         */
235*04fd306cSNickeau        $mediaType = $mediaMarkup->getInternalExternalType();
236*04fd306cSNickeau        try {
237*04fd306cSNickeau            $title = $mediaMarkup->getLabel();
238*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
239*04fd306cSNickeau            $title = null;
240*04fd306cSNickeau        }
241*04fd306cSNickeau        try {
242*04fd306cSNickeau            $linking = $mediaMarkup->getLinking();
243*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
244*04fd306cSNickeau            $linking = null;
245*04fd306cSNickeau        }
246*04fd306cSNickeau        try {
247*04fd306cSNickeau            $align = $mediaMarkup->getAlign();
248*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
249*04fd306cSNickeau            $align = null;
250*04fd306cSNickeau        }
251*04fd306cSNickeau        try {
252*04fd306cSNickeau            /**
253*04fd306cSNickeau             * We use the markup ref url
254*04fd306cSNickeau             * because we don't support http/https (external) url
255*04fd306cSNickeau             * And there is therefore no fetcher available
256*04fd306cSNickeau             */
257*04fd306cSNickeau            $markupUrl = $mediaMarkup->getMarkupRef()->getUrl();
258*04fd306cSNickeau
259*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
260*04fd306cSNickeau            // the
261*04fd306cSNickeau            LogUtility::internalError("As the media markup is created from a markup in the syntax component, it should be available");
262*04fd306cSNickeau            return "";
263*04fd306cSNickeau        }
264*04fd306cSNickeau
265*04fd306cSNickeau        try {
266*04fd306cSNickeau            $src = $mediaMarkup->getSrc();
267*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
268*04fd306cSNickeau            LogUtility::internalError("For an external markup, the src should not be empty", self::CANONICAL);
269*04fd306cSNickeau            return "";
270*04fd306cSNickeau        }
271*04fd306cSNickeau        try {
272*04fd306cSNickeau            $isImage = FileSystems::getMime($markupUrl)->isImage();
273*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
274*04fd306cSNickeau            $isImage = false;
275*04fd306cSNickeau        }
276*04fd306cSNickeau        if ($isImage) {
277*04fd306cSNickeau            /**
278*04fd306cSNickeau             * We need to delete the
279*04fd306cSNickeau             * wXh and other properties
280*04fd306cSNickeau             * Dokuwiki does not accept it in its function
281*04fd306cSNickeau             */
282*04fd306cSNickeau            try {
283*04fd306cSNickeau                $src = Url::createEmpty()
284*04fd306cSNickeau                    ->setScheme($markupUrl->getScheme())
285*04fd306cSNickeau                    ->setHost($markupUrl->getHost())
286*04fd306cSNickeau                    ->setPath($markupUrl->getPath())
287*04fd306cSNickeau                    ->toString();
288*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
289*04fd306cSNickeau
290*04fd306cSNickeau            }
291*04fd306cSNickeau        }
292*04fd306cSNickeau        try {
293*04fd306cSNickeau            $width = $markupUrl->getQueryPropertyValue(Dimension::WIDTH_KEY);
294*04fd306cSNickeau        } catch
295*04fd306cSNickeau        (ExceptionNotFound $e) {
296*04fd306cSNickeau            $width = null;
297*04fd306cSNickeau        }
298*04fd306cSNickeau        try {
299*04fd306cSNickeau            $height = $markupUrl->getQueryPropertyValue(Dimension::HEIGHT_KEY);
300*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
301*04fd306cSNickeau            $height = null;
302*04fd306cSNickeau        }
303*04fd306cSNickeau        try {
304*04fd306cSNickeau            $cache = $markupUrl->getQueryPropertyValue(IFetcherAbs::CACHE_KEY);
305*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
306*04fd306cSNickeau            // Dokuwiki needs a value
307*04fd306cSNickeau            // If their is no value it will output it without any value
308*04fd306cSNickeau            // in the query string.
309*04fd306cSNickeau            $cache = IFetcherAbs::CACHE_DEFAULT_VALUE;
310*04fd306cSNickeau        }
311*04fd306cSNickeau        switch ($mediaType) {
312*04fd306cSNickeau            case MediaMarkup::INTERNAL_MEDIA_CALL_NAME:
313*04fd306cSNickeau                return $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
314*04fd306cSNickeau            case MediaMarkup::EXTERNAL_MEDIA_CALL_NAME:
315*04fd306cSNickeau                return $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
316*04fd306cSNickeau            default:
317*04fd306cSNickeau                LogUtility::msg("The dokuwiki media type ($mediaType) is unknown");
318*04fd306cSNickeau                return "";
319*04fd306cSNickeau        }
320*04fd306cSNickeau    }
321*04fd306cSNickeau
322*04fd306cSNickeau
323*04fd306cSNickeau    /**
324*04fd306cSNickeau     * Compliance: src in dokuwiki is the id and the anchor if any
325*04fd306cSNickeau     * Dokuwiki does not understand other property and the reference metadata
326*04fd306cSNickeau     * may not work if we send back the `ref`
327*04fd306cSNickeau     * @throws ExceptionNotFound
328*04fd306cSNickeau     */
329*04fd306cSNickeau    public function getSrc(): string
330*04fd306cSNickeau    {
331*04fd306cSNickeau        $internalExternalType = $this->getInternalExternalType();
332*04fd306cSNickeau        switch ($internalExternalType) {
333*04fd306cSNickeau            case MediaMarkup::INTERNAL_MEDIA_CALL_NAME:
334*04fd306cSNickeau                /**
335*04fd306cSNickeau                 * Absolute id because dokuwiki resolve a relatif id
336*04fd306cSNickeau                 * to the actual namespace
337*04fd306cSNickeau                 */
338*04fd306cSNickeau                $src = $this->getPath()->toAbsoluteId();
339*04fd306cSNickeau                try {
340*04fd306cSNickeau                    $src = "$src#{$this->markupRef->getUrl()->getFragment()}";
341*04fd306cSNickeau                } catch (ExceptionNotFound $e) {
342*04fd306cSNickeau                    // ok
343*04fd306cSNickeau                }
344*04fd306cSNickeau                return $src;
345*04fd306cSNickeau            case MediaMarkup::EXTERNAL_MEDIA_CALL_NAME:
346*04fd306cSNickeau                return $this->getMarkupRef()->getRef();
347*04fd306cSNickeau            default:
348*04fd306cSNickeau                LogUtility::internalError("The internal/external type value ($internalExternalType) is unknown");
349*04fd306cSNickeau                return $this->getMarkupRef()->getRef();
350*04fd306cSNickeau        }
351*04fd306cSNickeau
352*04fd306cSNickeau    }
353*04fd306cSNickeau
354*04fd306cSNickeau    /**
355*04fd306cSNickeau     * Media Type Needed by Dokuwiki
356*04fd306cSNickeau     */
357*04fd306cSNickeau    public function getInternalExternalType(): string
358*04fd306cSNickeau    {
359*04fd306cSNickeau        try {
360*04fd306cSNickeau            // if there is a path, this is internal
361*04fd306cSNickeau            // if interwiki this, wiki id, ...
362*04fd306cSNickeau            $this->markupRef->getPath();
363*04fd306cSNickeau            return self::INTERNAL_MEDIA_CALL_NAME;
364*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
365*04fd306cSNickeau            return self::EXTERNAL_MEDIA_CALL_NAME;
366*04fd306cSNickeau        }
367*04fd306cSNickeau
368*04fd306cSNickeau    }
369*04fd306cSNickeau
370*04fd306cSNickeau
371*04fd306cSNickeau    /**
372*04fd306cSNickeau     * @throws ExceptionBadSyntax
373*04fd306cSNickeau     * @throws ExceptionBadArgument
374*04fd306cSNickeau     * @throws ExceptionNotFound
375*04fd306cSNickeau     */
376*04fd306cSNickeau    public static function createFromRef(string $markupRef): MediaMarkup
377*04fd306cSNickeau    {
378*04fd306cSNickeau        return (new MediaMarkup())->setMarkupRef($markupRef);
379*04fd306cSNickeau    }
380*04fd306cSNickeau
381*04fd306cSNickeau    /**
382*04fd306cSNickeau     * Keep track of the metadata
383*04fd306cSNickeau     * @param array $data
384*04fd306cSNickeau     * @param Doku_Renderer_metadata $renderer
385*04fd306cSNickeau     * @return void
386*04fd306cSNickeau     */
387*04fd306cSNickeau    public static function metadata(array $data, Doku_Renderer_metadata $renderer)
388*04fd306cSNickeau    {
389*04fd306cSNickeau
390*04fd306cSNickeau        $tagAttributes = $data[PluginUtility::ATTRIBUTES];
391*04fd306cSNickeau        if ($tagAttributes === null) {
392*04fd306cSNickeau            // error on handle
393*04fd306cSNickeau            return;
394*04fd306cSNickeau        }
395*04fd306cSNickeau        syntax_plugin_combo_media::registerImageMeta($tagAttributes, $renderer);
396*04fd306cSNickeau
397*04fd306cSNickeau    }
398*04fd306cSNickeau
399*04fd306cSNickeau    /**
400*04fd306cSNickeau     * Special pattern call
401*04fd306cSNickeau     * @param array $data
402*04fd306cSNickeau     * @param renderer_plugin_combo_analytics $renderer
403*04fd306cSNickeau     * @return void
404*04fd306cSNickeau     * @deprecated - for metadata but yeah ...
405*04fd306cSNickeau     */
406*04fd306cSNickeau    public static function analytics(array $data, renderer_plugin_combo_analytics $renderer)
407*04fd306cSNickeau    {
408*04fd306cSNickeau
409*04fd306cSNickeau        $tagAttributes = $data[PluginUtility::ATTRIBUTES];
410*04fd306cSNickeau        syntax_plugin_combo_media::updateStatistics($tagAttributes, $renderer);
411*04fd306cSNickeau
412*04fd306cSNickeau    }
413*04fd306cSNickeau
414*04fd306cSNickeau
415*04fd306cSNickeau    /**
416*04fd306cSNickeau     * @return Url - an url that has query property as a fetch url
417*04fd306cSNickeau     * It permits to select the fetch class
418*04fd306cSNickeau     * @deprecated use {@link MediaMarkup::getFetcher()}->getUrl instead
419*04fd306cSNickeau     */
420*04fd306cSNickeau    public function getFetchUrl(): Url
421*04fd306cSNickeau    {
422*04fd306cSNickeau        return $this->getFetcher()->getFetchUrl();
423*04fd306cSNickeau    }
424*04fd306cSNickeau
425*04fd306cSNickeau
426*04fd306cSNickeau    /**
427*04fd306cSNickeau     * @param string $match - the match of the renderer
428*04fd306cSNickeau     * @throws ExceptionBadSyntax - if no ref was found
429*04fd306cSNickeau     * @throws ExceptionBadArgument
430*04fd306cSNickeau     * @throws ExceptionNotFound|ExceptionNotExists
431*04fd306cSNickeau     * @throws ExceptionInternal
432*04fd306cSNickeau     */
433*04fd306cSNickeau    public static function createFromMarkup(string $match): MediaMarkup
434*04fd306cSNickeau    {
435*04fd306cSNickeau
436*04fd306cSNickeau        $mediaMarkup = new MediaMarkup();
437*04fd306cSNickeau
438*04fd306cSNickeau        /**
439*04fd306cSNickeau         *   * Delete the opening and closing character
440*04fd306cSNickeau         *   * create the url and description
441*04fd306cSNickeau         */
442*04fd306cSNickeau        $match = preg_replace(array('/^{{/', '/}}$/u'), '', $match);
443*04fd306cSNickeau        $parts = explode('|', $match, 2);
444*04fd306cSNickeau
445*04fd306cSNickeau        $ref = $parts[0];
446*04fd306cSNickeau        if ($ref === null) {
447*04fd306cSNickeau            throw new ExceptionBadSyntax("No ref was found");
448*04fd306cSNickeau        }
449*04fd306cSNickeau        $mediaMarkup->setMarkupRef($ref);
450*04fd306cSNickeau        if (isset($parts[1])) {
451*04fd306cSNickeau            $mediaMarkup->setLabel($parts[1]);
452*04fd306cSNickeau        }
453*04fd306cSNickeau
454*04fd306cSNickeau
455*04fd306cSNickeau        /**
456*04fd306cSNickeau         * Media Alignment
457*04fd306cSNickeau         */
458*04fd306cSNickeau        $rightAlign = (bool)preg_match('/^ /', $ref);
459*04fd306cSNickeau        $leftAlign = (bool)preg_match('/ $/', $ref);
460*04fd306cSNickeau        $align = null;
461*04fd306cSNickeau        // Logic = what's that ;)...
462*04fd306cSNickeau        if ($leftAlign & $rightAlign) {
463*04fd306cSNickeau            $align = 'center';
464*04fd306cSNickeau        } else if ($rightAlign) {
465*04fd306cSNickeau            $align = 'right';
466*04fd306cSNickeau        } else if ($leftAlign) {
467*04fd306cSNickeau            $align = 'left';
468*04fd306cSNickeau        }
469*04fd306cSNickeau        if ($align !== null) {
470*04fd306cSNickeau            $mediaMarkup->setAlign($align);
471*04fd306cSNickeau        }
472*04fd306cSNickeau
473*04fd306cSNickeau        return $mediaMarkup;
474*04fd306cSNickeau
475*04fd306cSNickeau
476*04fd306cSNickeau    }
477*04fd306cSNickeau
478*04fd306cSNickeau    public function setAlign(string $align): MediaMarkup
479*04fd306cSNickeau    {
480*04fd306cSNickeau        $this->align = $align;
481*04fd306cSNickeau        return $this;
482*04fd306cSNickeau    }
483*04fd306cSNickeau
484*04fd306cSNickeau    public function setLabel(string $label): MediaMarkup
485*04fd306cSNickeau    {
486*04fd306cSNickeau        $this->label = $label;
487*04fd306cSNickeau        return $this;
488*04fd306cSNickeau    }
489*04fd306cSNickeau
490*04fd306cSNickeau    /**
491*04fd306cSNickeau     * just FYI, not used
492*04fd306cSNickeau     *
493*04fd306cSNickeau     * Create an image from dokuwiki {@link Internallink internal call media attributes}
494*04fd306cSNickeau     *
495*04fd306cSNickeau     * Dokuwiki extracts already the width, height and align property
496*04fd306cSNickeau     * @param array $callAttributes
497*04fd306cSNickeau     * @return MediaMarkup
498*04fd306cSNickeau     */
499*04fd306cSNickeau    public static function createFromIndexAttributes(array $callAttributes)
500*04fd306cSNickeau    {
501*04fd306cSNickeau        $src = $callAttributes[0];
502*04fd306cSNickeau        $title = $callAttributes[1];
503*04fd306cSNickeau        $align = $callAttributes[2];
504*04fd306cSNickeau        $width = $callAttributes[3];
505*04fd306cSNickeau        $height = $callAttributes[4];
506*04fd306cSNickeau        $cache = $callAttributes[5];
507*04fd306cSNickeau        $linking = $callAttributes[6];
508*04fd306cSNickeau
509*04fd306cSNickeau        $ref = "$src?{$width}x$height&$cache";
510*04fd306cSNickeau        return (new MediaMarkup())
511*04fd306cSNickeau            ->setMarkupRef($ref)
512*04fd306cSNickeau            ->setAlign($align)
513*04fd306cSNickeau            ->setLabel($title)
514*04fd306cSNickeau            ->setLinking($linking);
515*04fd306cSNickeau
516*04fd306cSNickeau    }
517*04fd306cSNickeau
518*04fd306cSNickeau    /**
519*04fd306cSNickeau     * A function to set explicitly which array format
520*04fd306cSNickeau     * is used in the returned data of a {@link SyntaxPlugin::handle()}
521*04fd306cSNickeau     * (which ultimately is stored in the {@link CallStack)
522*04fd306cSNickeau     *
523*04fd306cSNickeau     * This is to make the difference with the {@link MediaLink::createFromIndexAttributes()}
524*04fd306cSNickeau     * that is indexed by number (ie without property name)
525*04fd306cSNickeau     *
526*04fd306cSNickeau     *
527*04fd306cSNickeau     * Return the array that is used in the {@link CallStack}
528*04fd306cSNickeau     *
529*04fd306cSNickeau     * @return array of key string and value
530*04fd306cSNickeau     */
531*04fd306cSNickeau    public function toCallStackArray(): array
532*04fd306cSNickeau    {
533*04fd306cSNickeau        /**
534*04fd306cSNickeau         * We store linking as attribute (to make it possible to change the linking by other plugin)
535*04fd306cSNickeau         * (ie no linking in heading , ...)
536*04fd306cSNickeau         */
537*04fd306cSNickeau        $attributes[MediaMarkup::LINKING_KEY] = $this->linking;
538*04fd306cSNickeau        $attributes[MarkupRef::REF_ATTRIBUTE] = $this->markupRef->getRef();
539*04fd306cSNickeau        $attributes[Align::ALIGN_ATTRIBUTE] = $this->align;
540*04fd306cSNickeau        $attributes[TagAttributes::TITLE_KEY] = $this->label;
541*04fd306cSNickeau        return $attributes;
542*04fd306cSNickeau
543*04fd306cSNickeau    }
544*04fd306cSNickeau
545*04fd306cSNickeau    public function setLinking(string $linking): MediaMarkup
546*04fd306cSNickeau    {
547*04fd306cSNickeau        $this->linking = $linking;
548*04fd306cSNickeau        return $this;
549*04fd306cSNickeau    }
550*04fd306cSNickeau
551*04fd306cSNickeau    /**
552*04fd306cSNickeau     * @throws ExceptionNotFound
553*04fd306cSNickeau     */
554*04fd306cSNickeau    public function getLinking(): string
555*04fd306cSNickeau    {
556*04fd306cSNickeau        /**
557*04fd306cSNickeau         * Linking
558*04fd306cSNickeau         */
559*04fd306cSNickeau        $linking = $this->linking;
560*04fd306cSNickeau        if ($linking !== null) {
561*04fd306cSNickeau            return $linking;
562*04fd306cSNickeau        }
563*04fd306cSNickeau        throw new ExceptionNotFound("No linking set");
564*04fd306cSNickeau
565*04fd306cSNickeau
566*04fd306cSNickeau    }
567*04fd306cSNickeau
568*04fd306cSNickeau    /**
569*04fd306cSNickeau     * Align on the url has precedence
570*04fd306cSNickeau     * if present
571*04fd306cSNickeau     * @throws ExceptionNotFound
572*04fd306cSNickeau     */
573*04fd306cSNickeau    public function getAlign(): string
574*04fd306cSNickeau    {
575*04fd306cSNickeau
576*04fd306cSNickeau        if ($this->align !== null) {
577*04fd306cSNickeau            return $this->align;
578*04fd306cSNickeau        }
579*04fd306cSNickeau        throw new ExceptionNotFound("No align was specified");
580*04fd306cSNickeau    }
581*04fd306cSNickeau
582*04fd306cSNickeau
583*04fd306cSNickeau    public function toTagAttributes()
584*04fd306cSNickeau    {
585*04fd306cSNickeau
586*04fd306cSNickeau
587*04fd306cSNickeau        /**
588*04fd306cSNickeau         * The align attribute on an image parse
589*04fd306cSNickeau         * is a float right
590*04fd306cSNickeau         * ComboStrap does a difference between a block right and a float right
591*04fd306cSNickeau         */
592*04fd306cSNickeau        try {
593*04fd306cSNickeau            $align = $this->getAlign();
594*04fd306cSNickeau            if ($align === "right") {
595*04fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue(FloatAttribute::FLOAT_KEY, "right");
596*04fd306cSNickeau            } else {
597*04fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue(Align::ALIGN_ATTRIBUTE, $align);
598*04fd306cSNickeau            }
599*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
600*04fd306cSNickeau            // ok
601*04fd306cSNickeau        }
602*04fd306cSNickeau
603*04fd306cSNickeau        return $this->extraMediaTagAttributes;
604*04fd306cSNickeau
605*04fd306cSNickeau    }
606*04fd306cSNickeau
607*04fd306cSNickeau    /**
608*04fd306cSNickeau     * @throws ExceptionNotFound
609*04fd306cSNickeau     */
610*04fd306cSNickeau    public function getLabel(): string
611*04fd306cSNickeau    {
612*04fd306cSNickeau        if (empty($this->label)) {
613*04fd306cSNickeau            throw new ExceptionNotFound("No label specified");
614*04fd306cSNickeau        }
615*04fd306cSNickeau        return $this->label;
616*04fd306cSNickeau    }
617*04fd306cSNickeau
618*04fd306cSNickeau    public
619*04fd306cSNickeau    function setLazyLoadMethod($false): MediaMarkup
620*04fd306cSNickeau    {
621*04fd306cSNickeau        $this->lazyLoadMethod = $false;
622*04fd306cSNickeau        return $this;
623*04fd306cSNickeau    }
624*04fd306cSNickeau
625*04fd306cSNickeau    /**
626*04fd306cSNickeau     * @throws ExceptionNotFound
627*04fd306cSNickeau     */
628*04fd306cSNickeau    public
629*04fd306cSNickeau    function getLazyLoadMethod(): string
630*04fd306cSNickeau    {
631*04fd306cSNickeau
632*04fd306cSNickeau        if ($this->lazyLoadMethod !== null) {
633*04fd306cSNickeau            return $this->lazyLoadMethod;
634*04fd306cSNickeau        }
635*04fd306cSNickeau        throw new ExceptionNotFound("Lazy method is not specified");
636*04fd306cSNickeau
637*04fd306cSNickeau    }
638*04fd306cSNickeau
639*04fd306cSNickeau    public
640*04fd306cSNickeau    function getLazyLoadMethodOrDefault(): string
641*04fd306cSNickeau    {
642*04fd306cSNickeau        try {
643*04fd306cSNickeau            return $this->getLazyLoadMethod();
644*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
645*04fd306cSNickeau            return LazyLoad::getDefault();
646*04fd306cSNickeau        }
647*04fd306cSNickeau
648*04fd306cSNickeau    }
649*04fd306cSNickeau
650*04fd306cSNickeau
651*04fd306cSNickeau    public
652*04fd306cSNickeau    static function isInternalMediaSyntax($text)
653*04fd306cSNickeau    {
654*04fd306cSNickeau        return preg_match(' / ' . syntax_plugin_combo_media::MEDIA_PATTERN . ' / msSi', $text);
655*04fd306cSNickeau    }
656*04fd306cSNickeau
657*04fd306cSNickeau
658*04fd306cSNickeau    public function isLazy(): bool
659*04fd306cSNickeau    {
660*04fd306cSNickeau
661*04fd306cSNickeau        return $this->getLazyLoadMethodOrDefault() !== LazyLoad::LAZY_LOAD_METHOD_NONE_VALUE;
662*04fd306cSNickeau
663*04fd306cSNickeau    }
664*04fd306cSNickeau
665*04fd306cSNickeau    public function getExtraMediaTagAttributes(): TagAttributes
666*04fd306cSNickeau    {
667*04fd306cSNickeau        try {
668*04fd306cSNickeau            $this->extraMediaTagAttributes->addComponentAttributeValue(Align::ALIGN_ATTRIBUTE, $this->getAlign());
669*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
670*04fd306cSNickeau            // ok
671*04fd306cSNickeau        }
672*04fd306cSNickeau        return $this->extraMediaTagAttributes;
673*04fd306cSNickeau    }
674*04fd306cSNickeau
675*04fd306cSNickeau
676*04fd306cSNickeau    public function __toString()
677*04fd306cSNickeau    {
678*04fd306cSNickeau        return $this->toMarkupSyntax();
679*04fd306cSNickeau    }
680*04fd306cSNickeau
681*04fd306cSNickeau    public function setLazyLoad(bool $true): MediaMarkup
682*04fd306cSNickeau    {
683*04fd306cSNickeau        if ($true) {
684*04fd306cSNickeau            $this->lazyLoadMethod = LazyLoad::getDefault();
685*04fd306cSNickeau        } else {
686*04fd306cSNickeau            $this->lazyLoadMethod = LazyLoad::LAZY_LOAD_METHOD_NONE_VALUE;
687*04fd306cSNickeau        }
688*04fd306cSNickeau        return $this;
689*04fd306cSNickeau    }
690*04fd306cSNickeau
691*04fd306cSNickeau    /**
692*04fd306cSNickeau     * Get and delete the attribute for the link
693*04fd306cSNickeau     * (The rest is for the image)
694*04fd306cSNickeau     */
695*04fd306cSNickeau    public
696*04fd306cSNickeau    function getLinkingClass()
697*04fd306cSNickeau    {
698*04fd306cSNickeau        return $this->linkingClass;
699*04fd306cSNickeau    }
700*04fd306cSNickeau
701*04fd306cSNickeau    /**
702*04fd306cSNickeau     * @throws ExceptionNotFound
703*04fd306cSNickeau     */
704*04fd306cSNickeau    public function getMarkupRef(): MarkupRef
705*04fd306cSNickeau    {
706*04fd306cSNickeau        if ($this->markupRef === null) {
707*04fd306cSNickeau            throw new ExceptionNotFound("No markup, this media markup was not created from a markup");
708*04fd306cSNickeau        }
709*04fd306cSNickeau        return $this->markupRef;
710*04fd306cSNickeau    }
711*04fd306cSNickeau
712*04fd306cSNickeau
713*04fd306cSNickeau    /**
714*04fd306cSNickeau     * @param TagAttributes $tagAttributes - the attributes in a tag format
715*04fd306cSNickeau     * @return $this
716*04fd306cSNickeau     */
717*04fd306cSNickeau    public function buildFromTagAttributes(TagAttributes $tagAttributes): MediaMarkup
718*04fd306cSNickeau    {
719*04fd306cSNickeau
720*04fd306cSNickeau        $linking = $tagAttributes->getValueAndRemoveIfPresent(self::LINKING_KEY);
721*04fd306cSNickeau        if ($linking !== null) {
722*04fd306cSNickeau            $this->setLinking($linking);
723*04fd306cSNickeau        }
724*04fd306cSNickeau        $label = $tagAttributes->getValueAndRemoveIfPresent(TagAttributes::TITLE_KEY);
725*04fd306cSNickeau        if ($label !== null) {
726*04fd306cSNickeau            $this->setLabel($label);
727*04fd306cSNickeau        }
728*04fd306cSNickeau        $align = $tagAttributes->getValueAndRemoveIfPresent(Align::ALIGN_ATTRIBUTE);
729*04fd306cSNickeau        if ($align !== null) {
730*04fd306cSNickeau            $this->setAlign($align);
731*04fd306cSNickeau        }
732*04fd306cSNickeau        $lazy = $tagAttributes->getValueAndRemoveIfPresent(LazyLoad::LAZY_LOAD_METHOD);
733*04fd306cSNickeau        if ($lazy !== null) {
734*04fd306cSNickeau            $this->setLazyLoadMethod($lazy);
735*04fd306cSNickeau        }
736*04fd306cSNickeau
737*04fd306cSNickeau        /**
738*04fd306cSNickeau         * dokuwiki attribute
739*04fd306cSNickeau         */
740*04fd306cSNickeau        if (isset($this->fetchUrl)) {
741*04fd306cSNickeau            $width = $tagAttributes->getValueAndRemoveIfPresent(Dimension::WIDTH_KEY);
742*04fd306cSNickeau            if ($width !== null) {
743*04fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::WIDTH_KEY, $width);
744*04fd306cSNickeau            }
745*04fd306cSNickeau            $height = $tagAttributes->getValueAndRemoveIfPresent(Dimension::HEIGHT_KEY);
746*04fd306cSNickeau            if ($height !== null) {
747*04fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::HEIGHT_KEY, $height);
748*04fd306cSNickeau            }
749*04fd306cSNickeau            $ratio = $tagAttributes->getValueAndRemoveIfPresent(Dimension::RATIO_ATTRIBUTE);
750*04fd306cSNickeau            if ($ratio !== null) {
751*04fd306cSNickeau                $this->fetchUrl->addQueryParameterIfNotPresent(Dimension::RATIO_ATTRIBUTE, $ratio);
752*04fd306cSNickeau            }
753*04fd306cSNickeau        }
754*04fd306cSNickeau
755*04fd306cSNickeau        foreach ($tagAttributes->getComponentAttributes() as $key => $value) {
756*04fd306cSNickeau            $this->extraMediaTagAttributes->addComponentAttributeValue($key, $value);
757*04fd306cSNickeau        }
758*04fd306cSNickeau
759*04fd306cSNickeau        foreach ($tagAttributes->getStyleDeclarations() as $key => $value) {
760*04fd306cSNickeau            $this->extraMediaTagAttributes->addStyleDeclarationIfNotSet($key, $value);
761*04fd306cSNickeau        }
762*04fd306cSNickeau
763*04fd306cSNickeau        return $this;
764*04fd306cSNickeau    }
765*04fd306cSNickeau
766*04fd306cSNickeau    /**
767*04fd306cSNickeau     * @throws ExceptionBadArgument
768*04fd306cSNickeau     * @throws ExceptionBadSyntax
769*04fd306cSNickeau     * @throws ExceptionNotExists
770*04fd306cSNickeau     * @throws ExceptionNotFound
771*04fd306cSNickeau     */
772*04fd306cSNickeau    public function toHtml(): string
773*04fd306cSNickeau    {
774*04fd306cSNickeau        return MediaLink::createFromMediaMarkup($this)
775*04fd306cSNickeau            ->renderMediaTag();
776*04fd306cSNickeau    }
777*04fd306cSNickeau
778*04fd306cSNickeau    /**
779*04fd306cSNickeau     * @throws ExceptionBadSyntax
780*04fd306cSNickeau     * @throws ExceptionBadArgument
781*04fd306cSNickeau     * @throws ExceptionNotExists
782*04fd306cSNickeau     * @throws ExceptionNotFound
783*04fd306cSNickeau     */
784*04fd306cSNickeau    public function getMediaLink()
785*04fd306cSNickeau    {
786*04fd306cSNickeau        return MediaLink::createFromMediaMarkup($this);
787*04fd306cSNickeau    }
788*04fd306cSNickeau
789*04fd306cSNickeau    private
790*04fd306cSNickeau    function setLinkingClass($value): MediaMarkup
791*04fd306cSNickeau    {
792*04fd306cSNickeau        $this->linkingClass = $value;
793*04fd306cSNickeau        return $this;
794*04fd306cSNickeau    }
795*04fd306cSNickeau
796*04fd306cSNickeau    /**
797*04fd306cSNickeau     * @return string the wiki syntax
798*04fd306cSNickeau     */
799*04fd306cSNickeau    public function toMarkupSyntax(): string
800*04fd306cSNickeau    {
801*04fd306cSNickeau        $descriptionPart = "";
802*04fd306cSNickeau        try {
803*04fd306cSNickeau            $descriptionPart = "|" . $this->getLabel();
804*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
805*04fd306cSNickeau            // ok
806*04fd306cSNickeau        }
807*04fd306cSNickeau        try {
808*04fd306cSNickeau            $ref = $this->getRef();
809*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
810*04fd306cSNickeau            $ref = $this->getFetchUrl()->toString();
811*04fd306cSNickeau        }
812*04fd306cSNickeau        return '{{' . $ref . $descriptionPart . '}}';
813*04fd306cSNickeau    }
814*04fd306cSNickeau
815*04fd306cSNickeau    /**
816*04fd306cSNickeau     *
817*04fd306cSNickeau     * Private method use {@link MediaMarkup::createFromFetchUrl()} to create a media markup via a Url
818*04fd306cSNickeau     *
819*04fd306cSNickeau     * @throws ExceptionNotFound
820*04fd306cSNickeau     */
821*04fd306cSNickeau    private function setUrl(Url $fetchUrl): MediaMarkup
822*04fd306cSNickeau    {
823*04fd306cSNickeau
824*04fd306cSNickeau        /**
825*04fd306cSNickeau         * Tag Attributes
826*04fd306cSNickeau         */
827*04fd306cSNickeau        try {
828*04fd306cSNickeau            $this->align = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(Align::ALIGN_ATTRIBUTE);
829*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
830*04fd306cSNickeau            // ok
831*04fd306cSNickeau        }
832*04fd306cSNickeau        try {
833*04fd306cSNickeau            $this->linking = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(self::LINKING_KEY);
834*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
835*04fd306cSNickeau            // ok
836*04fd306cSNickeau        }
837*04fd306cSNickeau        try {
838*04fd306cSNickeau            $this->lazyLoadMethod = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(LazyLoad::LAZY_LOAD_METHOD);
839*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
840*04fd306cSNickeau            // ok
841*04fd306cSNickeau        }
842*04fd306cSNickeau        try {
843*04fd306cSNickeau            $this->linkingClass = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent(self::LINK_CLASS_ATTRIBUTE);
844*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
845*04fd306cSNickeau            // ok
846*04fd306cSNickeau        }
847*04fd306cSNickeau
848*04fd306cSNickeau        foreach (self::STYLE_ATTRIBUTES as $nonUrlAttribute) {
849*04fd306cSNickeau            try {
850*04fd306cSNickeau                $value = $fetchUrl->getQueryPropertyValueAndRemoveIfPresent($nonUrlAttribute);
851*04fd306cSNickeau                $this->extraMediaTagAttributes->addComponentAttributeValue($nonUrlAttribute, $value);
852*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
853*04fd306cSNickeau                // ok
854*04fd306cSNickeau            }
855*04fd306cSNickeau        }
856*04fd306cSNickeau
857*04fd306cSNickeau        $this->fetchUrl = $fetchUrl;
858*04fd306cSNickeau        return $this;
859*04fd306cSNickeau    }
860*04fd306cSNickeau
861*04fd306cSNickeau    /**
862*04fd306cSNickeau     * @throws ExceptionNotFound
863*04fd306cSNickeau     */
864*04fd306cSNickeau    private function getRef(): string
865*04fd306cSNickeau    {
866*04fd306cSNickeau        if ($this->markupRef === null) {
867*04fd306cSNickeau            throw new ExceptionNotFound("No ref was specified");
868*04fd306cSNickeau        }
869*04fd306cSNickeau        return $this->markupRef->getRef();
870*04fd306cSNickeau    }
871*04fd306cSNickeau
872*04fd306cSNickeau    /**
873*04fd306cSNickeau     * @throws ExceptionNotFound - if this markup does not have a path origin
874*04fd306cSNickeau     * @deprecated use the {@link self::getFetcher()} instead
875*04fd306cSNickeau     * A media may be generated (ie {@link FetcherVignette}
876*04fd306cSNickeau     * therefore the path may be not present
877*04fd306cSNickeau     *
878*04fd306cSNickeau     * If you want to known the mime use {@link self::getFetcher()} then {@link IFetcher::getMime()}
879*04fd306cSNickeau     */
880*04fd306cSNickeau    public function getPath(): WikiPath
881*04fd306cSNickeau    {
882*04fd306cSNickeau        try {
883*04fd306cSNickeau
884*04fd306cSNickeau            return $this->getMarkupRef()->getPath();
885*04fd306cSNickeau
886*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
887*04fd306cSNickeau
888*04fd306cSNickeau            if ($this->fetcher instanceof IFetcherSource) {
889*04fd306cSNickeau                return $this->fetcher->getSourcePath();
890*04fd306cSNickeau            }
891*04fd306cSNickeau            throw $e;
892*04fd306cSNickeau
893*04fd306cSNickeau        }
894*04fd306cSNickeau    }
895*04fd306cSNickeau
896*04fd306cSNickeau    /**
897*04fd306cSNickeau     * Private method use {@link MediaMarkup::createFromFetcher()} to create a media markup via a Fetcher
898*04fd306cSNickeau     * @param IFetcher $fetcher
899*04fd306cSNickeau     * @return MediaMarkup
900*04fd306cSNickeau     */
901*04fd306cSNickeau    private function setFetcher(IFetcher $fetcher): MediaMarkup
902*04fd306cSNickeau    {
903*04fd306cSNickeau        $this->fetcher = $fetcher;
904*04fd306cSNickeau        return $this;
905*04fd306cSNickeau    }
906*04fd306cSNickeau
907*04fd306cSNickeau
908*04fd306cSNickeau    /**
909*04fd306cSNickeau     * @return IFetcher
910*04fd306cSNickeau     */
911*04fd306cSNickeau    public function getFetcher(): IFetcher
912*04fd306cSNickeau    {
913*04fd306cSNickeau        if (!isset($this->fetcher)) {
914*04fd306cSNickeau            if (!isset($this->fetchUrl)) {
915*04fd306cSNickeau                throw new ExceptionRuntimeInternal("No fetcher or url was set");
916*04fd306cSNickeau            }
917*04fd306cSNickeau            /**
918*04fd306cSNickeau             * Fetcher is build later
919*04fd306cSNickeau             * because for a raster image
920*04fd306cSNickeau             * actually, we can't built it
921*04fd306cSNickeau             * if the file does not exists.
922*04fd306cSNickeau             * It will throw an error immediatly and we may want not.
923*04fd306cSNickeau             * For resources, we want to build the url even if the image does not exists.
924*04fd306cSNickeau             */
925*04fd306cSNickeau            try {
926*04fd306cSNickeau                $this->fetcher = FetcherSystem::createPathFetcherFromUrl($this->fetchUrl);
927*04fd306cSNickeau            } catch (ExceptionBadArgument|ExceptionInternal|ExceptionNotFound $e) {
928*04fd306cSNickeau                try {
929*04fd306cSNickeau                    // we don't support http fetch
930*04fd306cSNickeau                    if (!($this->getMarkupRef()->getSchemeType() === MarkupRef::WEB_URI)) {
931*04fd306cSNickeau                        throw ExceptionRuntimeInternal::withMessageAndError("we don't support http fetch", $e);
932*04fd306cSNickeau                    }
933*04fd306cSNickeau                } catch (ExceptionNotFound $e) {
934*04fd306cSNickeau                    // ok no markup ref
935*04fd306cSNickeau                }
936*04fd306cSNickeau            }
937*04fd306cSNickeau        }
938*04fd306cSNickeau        return $this->fetcher;
939*04fd306cSNickeau    }
940*04fd306cSNickeau
941*04fd306cSNickeau
942*04fd306cSNickeau}
943