1bf9684bcSAndreas Gohr<?php 2bf9684bcSAndreas Gohr 3bf9684bcSAndreas Gohrnamespace dokuwiki\Ui\Media; 4bf9684bcSAndreas Gohr 50603f506SAndreas Gohruse dokuwiki\File\MediaFile; 6bf9684bcSAndreas Gohr 7bf9684bcSAndreas Gohrclass Display 8bf9684bcSAndreas Gohr{ 979b00823SAndreas Gohr /** @var MediaFile */ 10bf9684bcSAndreas Gohr protected $mediaFile; 11bf9684bcSAndreas Gohr 1279b00823SAndreas Gohr /** @var string should IDs be shown relative to this namespace? Used in search results */ 13e2d055f5SAndreas Gohr protected $relativeDisplay; 1479b00823SAndreas Gohr 159453716dSAndreas Gohr /** @var bool scroll to this file on display? */ 169453716dSAndreas Gohr protected $scrollIntoView = false; 179453716dSAndreas Gohr 18bf9684bcSAndreas Gohr /** 19bf9684bcSAndreas Gohr * Display constructor. 20bf9684bcSAndreas Gohr * @param MediaFile $mediaFile 21bf9684bcSAndreas Gohr */ 22bf9684bcSAndreas Gohr public function __construct(MediaFile $mediaFile) 23bf9684bcSAndreas Gohr { 24bf9684bcSAndreas Gohr $this->mediaFile = $mediaFile; 25bf9684bcSAndreas Gohr } 26bf9684bcSAndreas Gohr 27bf9684bcSAndreas Gohr /** 28bf9684bcSAndreas Gohr * Get the HTML to display a preview image if possible, otherwise show an icon 29bf9684bcSAndreas Gohr * 30bf9684bcSAndreas Gohr * @param int $w bounding box width to resize pixel based images to 31bf9684bcSAndreas Gohr * @param int $h bounding box height to resize pixel based images to 32bf9684bcSAndreas Gohr * @return string 33bf9684bcSAndreas Gohr */ 34bf9684bcSAndreas Gohr public function getPreviewHtml($w, $h) 35bf9684bcSAndreas Gohr { 36bf9684bcSAndreas Gohr if ($this->mediaFile->isImage()) { 374f33babfSAndreas Gohr $src = ml($this->mediaFile->getId(), ['w' => $w, 'h' => $h]); 38bf9684bcSAndreas Gohr } else { 39bf9684bcSAndreas Gohr $src = $this->getIconUrl(); 40bf9684bcSAndreas Gohr } 41bf9684bcSAndreas Gohr 428e9d8d55SAndreas Gohr $attr = [ 438e9d8d55SAndreas Gohr 'alt' => $this->mediaFile->getDisplayName(), 448e9d8d55SAndreas Gohr 'loading' => 'lazy', 458e9d8d55SAndreas Gohr 'width' => $w, 468e9d8d55SAndreas Gohr 'height' => $h, 478e9d8d55SAndreas Gohr ]; 488e9d8d55SAndreas Gohr 498e9d8d55SAndreas Gohr return '<img src="' . $src . '" ' . buildAttributes($attr) . ' />'; 50bf9684bcSAndreas Gohr } 51bf9684bcSAndreas Gohr 52bf9684bcSAndreas Gohr /** 53*dd9e8e5eSAndreas Gohr * Get the HTML for the large detail-view preview 54*dd9e8e5eSAndreas Gohr * 55*dd9e8e5eSAndreas Gohr * Produces the <div class="image"><a><img/></a></div> block shown on the 56*dd9e8e5eSAndreas Gohr * mediamanager "View" tab and in the media diff view. Unlike the thumbnail 57*dd9e8e5eSAndreas Gohr * in {@see getPreviewHtml()}, this uses bounding-box fit so the full image 58*dd9e8e5eSAndreas Gohr * is visible with correct aspect ratio, including EXIF-rotated JPEGs. 59*dd9e8e5eSAndreas Gohr * 60*dd9e8e5eSAndreas Gohr * @param int $w bounding box width 61*dd9e8e5eSAndreas Gohr * @param int $h bounding box height 62*dd9e8e5eSAndreas Gohr * @return string empty string for non-images or unreadable files 63*dd9e8e5eSAndreas Gohr */ 64*dd9e8e5eSAndreas Gohr public function getDetailHtml($w = 500, $h = 500) 65*dd9e8e5eSAndreas Gohr { 66*dd9e8e5eSAndreas Gohr global $lang; 67*dd9e8e5eSAndreas Gohr 68*dd9e8e5eSAndreas Gohr if (!$this->mediaFile->isImage()) return ''; 69*dd9e8e5eSAndreas Gohr 70*dd9e8e5eSAndreas Gohr [$dw, $dh] = $this->mediaFile->getDisplayDimensions($w, $h, false); 71*dd9e8e5eSAndreas Gohr if ($dw <= 0) return ''; 72*dd9e8e5eSAndreas Gohr 73*dd9e8e5eSAndreas Gohr $id = $this->mediaFile->getId(); 74*dd9e8e5eSAndreas Gohr $rev = $this->mediaFile->getRev(); 75*dd9e8e5eSAndreas Gohr $cacheBust = $rev 76*dd9e8e5eSAndreas Gohr ? ['rev' => $rev] 77*dd9e8e5eSAndreas Gohr : ['t' => filemtime($this->mediaFile->getPath())]; 78*dd9e8e5eSAndreas Gohr 79*dd9e8e5eSAndreas Gohr // pass raw '&' separator so buildAttributes' hsc() encodes exactly once 80*dd9e8e5eSAndreas Gohr $imgAttr = [ 81*dd9e8e5eSAndreas Gohr 'src' => ml($id, ['w' => $w, 'h' => $h, 'fit' => 1, ...$cacheBust], true, '&'), 82*dd9e8e5eSAndreas Gohr 'alt' => $this->mediaFile->getDisplayName(), 83*dd9e8e5eSAndreas Gohr 'width' => $dw, 84*dd9e8e5eSAndreas Gohr 'height' => $dh, 85*dd9e8e5eSAndreas Gohr 'style' => 'max-width: ' . $dw . 'px;', 86*dd9e8e5eSAndreas Gohr ]; 87*dd9e8e5eSAndreas Gohr $linkAttr = [ 88*dd9e8e5eSAndreas Gohr 'href' => ml($id, $cacheBust, true, '&'), 89*dd9e8e5eSAndreas Gohr 'target' => '_blank', 90*dd9e8e5eSAndreas Gohr 'title' => $lang['mediaview'], 91*dd9e8e5eSAndreas Gohr ]; 92*dd9e8e5eSAndreas Gohr 93*dd9e8e5eSAndreas Gohr return '<div class="image">' 94*dd9e8e5eSAndreas Gohr . '<a ' . buildAttributes($linkAttr) . '>' 95*dd9e8e5eSAndreas Gohr . '<img ' . buildAttributes($imgAttr) . ' />' 96*dd9e8e5eSAndreas Gohr . '</a>' 97*dd9e8e5eSAndreas Gohr . '</div>'; 98*dd9e8e5eSAndreas Gohr } 99*dd9e8e5eSAndreas Gohr 100*dd9e8e5eSAndreas Gohr /** 101bf9684bcSAndreas Gohr * Return the URL to the icon for this file 102bf9684bcSAndreas Gohr * 103bf9684bcSAndreas Gohr * @return string 104bf9684bcSAndreas Gohr */ 105bf9684bcSAndreas Gohr public function getIconUrl() 106bf9684bcSAndreas Gohr { 107bf9684bcSAndreas Gohr $link = 'lib/images/fileicons/svg/' . $this->mediaFile->getIcoClass() . '.svg'; 108bf9684bcSAndreas Gohr if (!file_exists(DOKU_INC . $link)) $link = 'lib/images/fileicons/svg/file.svg'; 109bf9684bcSAndreas Gohr return DOKU_BASE . $link; 110bf9684bcSAndreas Gohr } 111bf9684bcSAndreas Gohr 11279b00823SAndreas Gohr /** 11379b00823SAndreas Gohr * Show IDs relative to this namespace 11479b00823SAndreas Gohr * 11579b00823SAndreas Gohr * @param string|null $ns Use null to disable 11679b00823SAndreas Gohr */ 11779b00823SAndreas Gohr public function relativeDisplay($ns) 11879b00823SAndreas Gohr { 11979b00823SAndreas Gohr $this->relativeDisplay = $ns; 12079b00823SAndreas Gohr } 12179b00823SAndreas Gohr 1229453716dSAndreas Gohr /** 1239453716dSAndreas Gohr * Scroll to this file on display? 1249453716dSAndreas Gohr * 1259453716dSAndreas Gohr * @param bool $set 1269453716dSAndreas Gohr */ 1279453716dSAndreas Gohr public function scrollIntoView($set = true) 1289453716dSAndreas Gohr { 1299453716dSAndreas Gohr $this->scrollIntoView = $set; 1309453716dSAndreas Gohr } 1319453716dSAndreas Gohr 132bf9684bcSAndreas Gohr /** @return string */ 133bf9684bcSAndreas Gohr protected function formatDate() 134bf9684bcSAndreas Gohr { 135bf9684bcSAndreas Gohr return dformat($this->mediaFile->getLastModified()); 136bf9684bcSAndreas Gohr } 137bf9684bcSAndreas Gohr 138bf9684bcSAndreas Gohr /** 139bf9684bcSAndreas Gohr * Output the image dimension if any 140bf9684bcSAndreas Gohr * 141bf9684bcSAndreas Gohr * @param string $empty what to show when no dimensions are available 142bf9684bcSAndreas Gohr * @return string 143bf9684bcSAndreas Gohr */ 1449a1a86fbSAndreas Gohr protected function formatDimensions($empty = ' ') 145bf9684bcSAndreas Gohr { 146bf9684bcSAndreas Gohr $w = $this->mediaFile->getWidth(); 147bf9684bcSAndreas Gohr $h = $this->mediaFile->getHeight(); 148bf9684bcSAndreas Gohr if ($w && $h) { 149bf9684bcSAndreas Gohr return $w . '×' . $h; 150bf9684bcSAndreas Gohr } else { 151bf9684bcSAndreas Gohr return $empty; 152bf9684bcSAndreas Gohr } 153bf9684bcSAndreas Gohr } 154bf9684bcSAndreas Gohr 155bf9684bcSAndreas Gohr /** @return string */ 156bf9684bcSAndreas Gohr protected function formatFileSize() 157bf9684bcSAndreas Gohr { 158bf9684bcSAndreas Gohr return filesize_h($this->mediaFile->getFileSize()); 159bf9684bcSAndreas Gohr } 16079b00823SAndreas Gohr 16179b00823SAndreas Gohr /** @return string */ 16279b00823SAndreas Gohr protected function formatDisplayName() 16379b00823SAndreas Gohr { 16479b00823SAndreas Gohr if ($this->relativeDisplay !== null) { 16579b00823SAndreas Gohr $id = $this->mediaFile->getId(); 1666c16a3a9Sfiwswe if (str_starts_with($id, $this->relativeDisplay)) { 16779b00823SAndreas Gohr $id = substr($id, strlen($this->relativeDisplay)); 16879b00823SAndreas Gohr } 16979b00823SAndreas Gohr return ltrim($id, ':'); 17079b00823SAndreas Gohr } else { 17179b00823SAndreas Gohr return $this->mediaFile->getDisplayName(); 17279b00823SAndreas Gohr } 17379b00823SAndreas Gohr } 174bf9684bcSAndreas Gohr} 175