xref: /dokuwiki/inc/Ui/Media/Display.php (revision dd9e8e5ea54469964faab99223a61bd48146ac42)
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 = '&#160;')
145bf9684bcSAndreas Gohr    {
146bf9684bcSAndreas Gohr        $w = $this->mediaFile->getWidth();
147bf9684bcSAndreas Gohr        $h = $this->mediaFile->getHeight();
148bf9684bcSAndreas Gohr        if ($w && $h) {
149bf9684bcSAndreas Gohr            return $w . '&#215;' . $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