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