xref: /webtrees/app/MediaFile.php (revision 9b93b7c342a543e7bd55b5a09d97ba0c39fc32b0)
18f5f5da8SGreg Roach<?php
28f5f5da8SGreg Roach/**
38f5f5da8SGreg Roach * webtrees: online genealogy
48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
58f5f5da8SGreg Roach * This program is free software: you can redistribute it and/or modify
68f5f5da8SGreg Roach * it under the terms of the GNU General Public License as published by
78f5f5da8SGreg Roach * the Free Software Foundation, either version 3 of the License, or
88f5f5da8SGreg Roach * (at your option) any later version.
98f5f5da8SGreg Roach * This program is distributed in the hope that it will be useful,
108f5f5da8SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
118f5f5da8SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128f5f5da8SGreg Roach * GNU General Public License for more details.
138f5f5da8SGreg Roach * You should have received a copy of the GNU General Public License
148f5f5da8SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
158f5f5da8SGreg Roach */
16e7f56f2aSGreg Roachdeclare(strict_types=1);
17e7f56f2aSGreg Roach
188f5f5da8SGreg Roachnamespace Fisharebest\Webtrees;
198f5f5da8SGreg Roach
208f5f5da8SGreg Roachuse League\Glide\Urls\UrlBuilderFactory;
21*9b93b7c3SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
222361dfe8SGreg Roachuse Throwable;
23*9b93b7c3SGreg Roachuse function app;
248f5f5da8SGreg Roach
258f5f5da8SGreg Roach/**
268f5f5da8SGreg Roach * A GEDCOM media file.  A media object can contain many media files,
278f5f5da8SGreg Roach * such as scans of both sides of a document, the transcript of an audio
288f5f5da8SGreg Roach * recording, etc.
298f5f5da8SGreg Roach */
30c1010edaSGreg Roachclass MediaFile
31c1010edaSGreg Roach{
3216d6367aSGreg Roach    private const MIME_TYPES = [
335225fdfcSGreg Roach        'bmp'  => 'image/bmp',
345225fdfcSGreg Roach        'doc'  => 'application/msword',
355225fdfcSGreg Roach        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
365225fdfcSGreg Roach        'ged'  => 'text/x-gedcom',
375225fdfcSGreg Roach        'gif'  => 'image/gif',
385225fdfcSGreg Roach        'html' => 'text/html',
395225fdfcSGreg Roach        'htm'  => 'text/html',
405225fdfcSGreg Roach        'jpeg' => 'image/jpeg',
415225fdfcSGreg Roach        'jpg'  => 'image/jpeg',
425225fdfcSGreg Roach        'mov'  => 'video/quicktime',
435225fdfcSGreg Roach        'mp3'  => 'audio/mpeg',
445225fdfcSGreg Roach        'mp4'  => 'video/mp4',
455225fdfcSGreg Roach        'ogv'  => 'video/ogg',
465225fdfcSGreg Roach        'pdf'  => 'application/pdf',
475225fdfcSGreg Roach        'png'  => 'image/png',
485225fdfcSGreg Roach        'rar'  => 'application/x-rar-compressed',
495225fdfcSGreg Roach        'swf'  => 'application/x-shockwave-flash',
505225fdfcSGreg Roach        'svg'  => 'image/svg',
515225fdfcSGreg Roach        'tiff' => 'image/tiff',
525225fdfcSGreg Roach        'tif'  => 'image/tiff',
535225fdfcSGreg Roach        'xls'  => 'application/vnd-ms-excel',
545225fdfcSGreg Roach        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
555225fdfcSGreg Roach        'wmv'  => 'video/x-ms-wmv',
565225fdfcSGreg Roach        'zip'  => 'application/zip',
575225fdfcSGreg Roach    ];
585225fdfcSGreg Roach
598f5f5da8SGreg Roach    /** @var string The filename */
608f5f5da8SGreg Roach    private $multimedia_file_refn = '';
618f5f5da8SGreg Roach
628f5f5da8SGreg Roach    /** @var string The file extension; jpeg, txt, mp4, etc. */
638f5f5da8SGreg Roach    private $multimedia_format = '';
648f5f5da8SGreg Roach
658f5f5da8SGreg Roach    /** @var string The type of document; newspaper, microfiche, etc. */
668f5f5da8SGreg Roach    private $source_media_type = '';
678f5f5da8SGreg Roach    /** @var string The filename */
688f5f5da8SGreg Roach
698f5f5da8SGreg Roach    /** @var string The name of the document */
708f5f5da8SGreg Roach    private $descriptive_title = '';
718f5f5da8SGreg Roach
728f5f5da8SGreg Roach    /** @var Media $media The media object to which this file belongs */
738f5f5da8SGreg Roach    private $media;
748f5f5da8SGreg Roach
7564b90bf1SGreg Roach    /** @var string */
7664b90bf1SGreg Roach    private $fact_id;
7764b90bf1SGreg Roach
788f5f5da8SGreg Roach    /**
798f5f5da8SGreg Roach     * Create a MediaFile from raw GEDCOM data.
808f5f5da8SGreg Roach     *
818f5f5da8SGreg Roach     * @param string $gedcom
828f5f5da8SGreg Roach     * @param Media  $media
838f5f5da8SGreg Roach     */
84c1010edaSGreg Roach    public function __construct($gedcom, Media $media)
85c1010edaSGreg Roach    {
868f5f5da8SGreg Roach        $this->media   = $media;
8764b90bf1SGreg Roach        $this->fact_id = md5($gedcom);
888f5f5da8SGreg Roach
898f5f5da8SGreg Roach        if (preg_match('/^\d FILE (.+)/m', $gedcom, $match)) {
908f5f5da8SGreg Roach            $this->multimedia_file_refn = $match[1];
91423c6ccdSGreg Roach            $this->multimedia_format    = pathinfo($match[1], PATHINFO_EXTENSION);
928f5f5da8SGreg Roach        }
938f5f5da8SGreg Roach
948f5f5da8SGreg Roach        if (preg_match('/^\d FORM (.+)/m', $gedcom, $match)) {
958f5f5da8SGreg Roach            $this->multimedia_format = $match[1];
968f5f5da8SGreg Roach        }
978f5f5da8SGreg Roach
988f5f5da8SGreg Roach        if (preg_match('/^\d TYPE (.+)/m', $gedcom, $match)) {
998f5f5da8SGreg Roach            $this->source_media_type = $match[1];
1008f5f5da8SGreg Roach        }
1018f5f5da8SGreg Roach
1028f5f5da8SGreg Roach        if (preg_match('/^\d TITL (.+)/m', $gedcom, $match)) {
1038f5f5da8SGreg Roach            $this->descriptive_title = $match[1];
1048f5f5da8SGreg Roach        }
1058f5f5da8SGreg Roach    }
1068f5f5da8SGreg Roach
1078f5f5da8SGreg Roach    /**
10864b90bf1SGreg Roach     * Get the filename.
1098f5f5da8SGreg Roach     *
1108f5f5da8SGreg Roach     * @return string
1118f5f5da8SGreg Roach     */
112c1010edaSGreg Roach    public function filename(): string
113c1010edaSGreg Roach    {
1146e6a9947SGreg Roach        return $this->multimedia_file_refn;
1158f5f5da8SGreg Roach    }
1168f5f5da8SGreg Roach
1178f5f5da8SGreg Roach    /**
118d6641c58SGreg Roach     * Get the base part of the filename.
119d6641c58SGreg Roach     *
120d6641c58SGreg Roach     * @return string
121d6641c58SGreg Roach     */
122c1010edaSGreg Roach    public function basename(): string
123c1010edaSGreg Roach    {
124d6641c58SGreg Roach        return basename($this->multimedia_file_refn);
125d6641c58SGreg Roach    }
126d6641c58SGreg Roach
127d6641c58SGreg Roach    /**
128d6641c58SGreg Roach     * Get the folder part of the filename.
129d6641c58SGreg Roach     *
130d6641c58SGreg Roach     * @return string
131d6641c58SGreg Roach     */
132c1010edaSGreg Roach    public function dirname(): string
133c1010edaSGreg Roach    {
134d6641c58SGreg Roach        $dirname = dirname($this->multimedia_file_refn);
135d6641c58SGreg Roach
136d6641c58SGreg Roach        if ($dirname === '.') {
137d6641c58SGreg Roach            return '';
138d6641c58SGreg Roach        }
139b2ce94c6SRico Sonntag
140b2ce94c6SRico Sonntag        return $dirname;
141d6641c58SGreg Roach    }
142d6641c58SGreg Roach
143d6641c58SGreg Roach    /**
14464b90bf1SGreg Roach     * Get the format.
1458f5f5da8SGreg Roach     *
1468f5f5da8SGreg Roach     * @return string
1478f5f5da8SGreg Roach     */
148c1010edaSGreg Roach    public function format(): string
149c1010edaSGreg Roach    {
1508f5f5da8SGreg Roach        return $this->multimedia_format;
1518f5f5da8SGreg Roach    }
1528f5f5da8SGreg Roach
1538f5f5da8SGreg Roach    /**
15464b90bf1SGreg Roach     * Get the type.
1558f5f5da8SGreg Roach     *
1568f5f5da8SGreg Roach     * @return string
1578f5f5da8SGreg Roach     */
158c1010edaSGreg Roach    public function type(): string
159c1010edaSGreg Roach    {
1608f5f5da8SGreg Roach        return $this->source_media_type;
1618f5f5da8SGreg Roach    }
1628f5f5da8SGreg Roach
1638f5f5da8SGreg Roach    /**
16464b90bf1SGreg Roach     * Get the title.
1658f5f5da8SGreg Roach     *
1668f5f5da8SGreg Roach     * @return string
1678f5f5da8SGreg Roach     */
168c1010edaSGreg Roach    public function title(): string
169c1010edaSGreg Roach    {
1708f5f5da8SGreg Roach        return $this->descriptive_title;
1718f5f5da8SGreg Roach    }
1728f5f5da8SGreg Roach
1738f5f5da8SGreg Roach    /**
17464b90bf1SGreg Roach     * Get the fact ID.
17564b90bf1SGreg Roach     *
17664b90bf1SGreg Roach     * @return string
17764b90bf1SGreg Roach     */
178c1010edaSGreg Roach    public function factId(): string
179c1010edaSGreg Roach    {
18064b90bf1SGreg Roach        return $this->fact_id;
18164b90bf1SGreg Roach    }
18264b90bf1SGreg Roach
18364b90bf1SGreg Roach    /**
184d6641c58SGreg Roach     * @return bool
185d6641c58SGreg Roach     */
1868f53f488SRico Sonntag    public function isPendingAddition(): bool
187c1010edaSGreg Roach    {
18830158ae7SGreg Roach        foreach ($this->media->facts() as $fact) {
189905ab80aSGreg Roach            if ($fact->id() === $this->fact_id) {
190d6641c58SGreg Roach                return $fact->isPendingAddition();
191d6641c58SGreg Roach            }
192d6641c58SGreg Roach        }
193d6641c58SGreg Roach
194d6641c58SGreg Roach        return false;
195d6641c58SGreg Roach    }
196d6641c58SGreg Roach
197d6641c58SGreg Roach    /**
198d6641c58SGreg Roach     * @return bool
199d6641c58SGreg Roach     */
2008f53f488SRico Sonntag    public function isPendingDeletion(): bool
201c1010edaSGreg Roach    {
20230158ae7SGreg Roach        foreach ($this->media->facts() as $fact) {
203905ab80aSGreg Roach            if ($fact->id() === $this->fact_id) {
204d6641c58SGreg Roach                return $fact->isPendingDeletion();
205d6641c58SGreg Roach            }
206d6641c58SGreg Roach        }
207d6641c58SGreg Roach
208d6641c58SGreg Roach        return false;
209d6641c58SGreg Roach    }
210d6641c58SGreg Roach
211d6641c58SGreg Roach    /**
21264b90bf1SGreg Roach     * Display an image-thumbnail or a media-icon, and add markup for image viewers such as colorbox.
21364b90bf1SGreg Roach     *
21464b90bf1SGreg Roach     * @param int      $width      Pixels
21564b90bf1SGreg Roach     * @param int      $height     Pixels
21664b90bf1SGreg Roach     * @param string   $fit        "crop" or "contain"
217e364afe4SGreg Roach     * @param string[] $image_attributes Additional HTML attributes
21864b90bf1SGreg Roach     *
21964b90bf1SGreg Roach     * @return string
22064b90bf1SGreg Roach     */
221e364afe4SGreg Roach    public function displayImage($width, $height, $fit, $image_attributes = []): string
222c1010edaSGreg Roach    {
22364b90bf1SGreg Roach        if ($this->isExternal()) {
22464b90bf1SGreg Roach            $src    = $this->multimedia_file_refn;
22564b90bf1SGreg Roach            $srcset = [];
22664b90bf1SGreg Roach        } else {
22764b90bf1SGreg Roach            // Generate multiple images for displays with higher pixel densities.
22864b90bf1SGreg Roach            $src    = $this->imageUrl($width, $height, $fit);
22964b90bf1SGreg Roach            $srcset = [];
230bb308685SGreg Roach            foreach ([2, 3, 4] as $x) {
23164b90bf1SGreg Roach                $srcset[] = $this->imageUrl($width * $x, $height * $x, $fit) . ' ' . $x . 'x';
23264b90bf1SGreg Roach            }
23364b90bf1SGreg Roach        }
23464b90bf1SGreg Roach
23548b53306SGreg Roach        if ($this->isImage()) {
236e364afe4SGreg Roach            $image = '<img ' . Html::attributes($image_attributes + [
23764b90bf1SGreg Roach                        'dir'    => 'auto',
23864b90bf1SGreg Roach                        'src'    => $src,
23964b90bf1SGreg Roach                        'srcset' => implode(',', $srcset),
24039ca88baSGreg Roach                        'alt'    => htmlspecialchars_decode(strip_tags($this->media->fullName())),
24164b90bf1SGreg Roach                    ]) . '>';
24264b90bf1SGreg Roach
243e364afe4SGreg Roach            $link_attributes = Html::attributes([
24464b90bf1SGreg Roach                'class'      => 'gallery',
24564b90bf1SGreg Roach                'type'       => $this->mimeType(),
24660e3c46aSGreg Roach                'href'       => $this->imageUrl(0, 0, 'contain'),
24739ca88baSGreg Roach                'data-title' => htmlspecialchars_decode(strip_tags($this->media->fullName())),
24864b90bf1SGreg Roach            ]);
249e1d1700bSGreg Roach        } else {
25048b53306SGreg Roach            $image = view('icons/mime', ['type' => $this->mimeType()]);
251e364afe4SGreg Roach
252e364afe4SGreg Roach            $link_attributes = Html::attributes([
253e1d1700bSGreg Roach                'type' => $this->mimeType(),
254e1d1700bSGreg Roach                'href' => $this->downloadUrl(),
255e1d1700bSGreg Roach            ]);
256e1d1700bSGreg Roach        }
25764b90bf1SGreg Roach
258e364afe4SGreg Roach        return '<a ' . $link_attributes . '>' . $image . '</a>';
25964b90bf1SGreg Roach    }
26064b90bf1SGreg Roach
2614a9f750fSGreg Roach    /**
2624a9f750fSGreg Roach     * A list of image attributes
2634a9f750fSGreg Roach     *
2644a9f750fSGreg Roach     * @return string[]
2654a9f750fSGreg Roach     */
266c1010edaSGreg Roach    public function attributes(): array
267c1010edaSGreg Roach    {
2684a9f750fSGreg Roach        $attributes = [];
26964b90bf1SGreg Roach
2704a9f750fSGreg Roach        if (!$this->isExternal() || $this->fileExists()) {
2714a9f750fSGreg Roach            $file = $this->folder() . $this->multimedia_file_refn;
2724a9f750fSGreg Roach
2734a9f750fSGreg Roach            $attributes['__FILE_SIZE__'] = $this->fileSizeKB();
2744a9f750fSGreg Roach
2754a9f750fSGreg Roach            $imgsize = getimagesize($file);
2764a9f750fSGreg Roach            if (is_array($imgsize) && !empty($imgsize['0'])) {
2774a9f750fSGreg Roach                $attributes['__IMAGE_SIZE__'] = I18N::translate('%1$s × %2$s pixels', I18N::number($imgsize['0']), I18N::number($imgsize['1']));
2784a9f750fSGreg Roach            }
2794a9f750fSGreg Roach        }
2804a9f750fSGreg Roach
2814a9f750fSGreg Roach        return $attributes;
2824a9f750fSGreg Roach    }
2834a9f750fSGreg Roach
2844a9f750fSGreg Roach    /**
2854a9f750fSGreg Roach     * check if the file exists on this server
2864a9f750fSGreg Roach     *
2874a9f750fSGreg Roach     * @return bool
2884a9f750fSGreg Roach     */
2898f53f488SRico Sonntag    public function fileExists(): bool
290c1010edaSGreg Roach    {
291d6641c58SGreg Roach        return !$this->isExternal() && file_exists($this->folder() . $this->multimedia_file_refn);
2924a9f750fSGreg Roach    }
2934a9f750fSGreg Roach
2944a9f750fSGreg Roach    /**
2954a9f750fSGreg Roach     * Is the media file actually a URL?
2964a9f750fSGreg Roach     */
297c1010edaSGreg Roach    public function isExternal(): bool
298c1010edaSGreg Roach    {
2994a9f750fSGreg Roach        return strpos($this->multimedia_file_refn, '://') !== false;
3004a9f750fSGreg Roach    }
3014a9f750fSGreg Roach
3024a9f750fSGreg Roach    /**
3034a9f750fSGreg Roach     * Is the media file an image?
3044a9f750fSGreg Roach     */
305c1010edaSGreg Roach    public function isImage(): bool
306c1010edaSGreg Roach    {
307c1010edaSGreg Roach        return in_array($this->extension(), [
308c1010edaSGreg Roach            'jpeg',
309c1010edaSGreg Roach            'jpg',
310c1010edaSGreg Roach            'gif',
311c1010edaSGreg Roach            'png',
312c1010edaSGreg Roach        ]);
3134a9f750fSGreg Roach    }
3144a9f750fSGreg Roach
3154a9f750fSGreg Roach    /**
31644379edcSGreg Roach     * Where is the file stored on disk?
31744379edcSGreg Roach     */
318c1010edaSGreg Roach    public function folder(): string
319c1010edaSGreg Roach    {
320f4afa648SGreg Roach        return WT_DATA_DIR . $this->media->tree()->getPreference('MEDIA_DIRECTORY');
32144379edcSGreg Roach    }
32244379edcSGreg Roach
32344379edcSGreg Roach    /**
3244a9f750fSGreg Roach     * A user-friendly view of the file size
3254a9f750fSGreg Roach     *
3264a9f750fSGreg Roach     * @return int
3274a9f750fSGreg Roach     */
328c1010edaSGreg Roach    private function fileSizeBytes(): int
329c1010edaSGreg Roach    {
3304a9f750fSGreg Roach        try {
3314a9f750fSGreg Roach            return filesize($this->folder() . $this->multimedia_file_refn);
3322361dfe8SGreg Roach        } catch (Throwable $ex) {
3334a9f750fSGreg Roach            return 0;
3344a9f750fSGreg Roach        }
3354a9f750fSGreg Roach    }
3364a9f750fSGreg Roach
3374a9f750fSGreg Roach    /**
3384a9f750fSGreg Roach     * get the media file size in KB
3394a9f750fSGreg Roach     *
3404a9f750fSGreg Roach     * @return string
3414a9f750fSGreg Roach     */
3428f53f488SRico Sonntag    public function fileSizeKB(): string
343c1010edaSGreg Roach    {
344b0b72ea4SGreg Roach        $size = $this->fileSizeBytes();
345cdaafeeeSGreg Roach        $size = intdiv($size + 1023, 1024);
3464a9f750fSGreg Roach
347bbb76c12SGreg Roach        /* I18N: size of file in KB */
348bbb76c12SGreg Roach        return I18N::translate('%s KB', I18N::number($size));
3494a9f750fSGreg Roach    }
35064b90bf1SGreg Roach
35164b90bf1SGreg Roach    /**
3528f5f5da8SGreg Roach     * Get the filename on the server - for those (very few!) functions which actually
353bf7c4bf8SGreg Roach     * need the filename, such as the PDF reports.
3548f5f5da8SGreg Roach     *
3558f5f5da8SGreg Roach     * @return string
3568f5f5da8SGreg Roach     */
357e364afe4SGreg Roach    public function getServerFilename(): string
358c1010edaSGreg Roach    {
359f4afa648SGreg Roach        $MEDIA_DIRECTORY = $this->media->tree()->getPreference('MEDIA_DIRECTORY');
3608f5f5da8SGreg Roach
361bb308685SGreg Roach        if ($this->multimedia_file_refn === '' || $this->isExternal()) {
3628f5f5da8SGreg Roach            // External image, or (in the case of corrupt GEDCOM data) no image at all
36364b90bf1SGreg Roach            return $this->multimedia_file_refn;
364b2ce94c6SRico Sonntag        }
365b2ce94c6SRico Sonntag
3668f5f5da8SGreg Roach        // Main image
36764b90bf1SGreg Roach        return WT_DATA_DIR . $MEDIA_DIRECTORY . $this->multimedia_file_refn;
3688f5f5da8SGreg Roach    }
3698f5f5da8SGreg Roach
3708f5f5da8SGreg Roach    /**
371e1d1700bSGreg Roach     * Generate a URL to download a non-image media file.
372e1d1700bSGreg Roach     *
373e1d1700bSGreg Roach     * @return string
374e1d1700bSGreg Roach     */
3758f53f488SRico Sonntag    public function downloadUrl(): string
376c1010edaSGreg Roach    {
377e1d1700bSGreg Roach        return route('media-download', [
378c0935879SGreg Roach            'xref'    => $this->media->xref(),
379f4afa648SGreg Roach            'ged'     => $this->media->tree()->name(),
380e1d1700bSGreg Roach            'fact_id' => $this->fact_id,
381e1d1700bSGreg Roach        ]);
382e1d1700bSGreg Roach    }
383e1d1700bSGreg Roach
384e1d1700bSGreg Roach    /**
3858f5f5da8SGreg Roach     * Generate a URL for an image.
3868f5f5da8SGreg Roach     *
3878f5f5da8SGreg Roach     * @param int    $width  Maximum width in pixels
3888f5f5da8SGreg Roach     * @param int    $height Maximum height in pixels
3898f5f5da8SGreg Roach     * @param string $fit    "crop" or "contain"
3908f5f5da8SGreg Roach     *
3918f5f5da8SGreg Roach     * @return string
3928f5f5da8SGreg Roach     */
3938f53f488SRico Sonntag    public function imageUrl($width, $height, $fit): string
394c1010edaSGreg Roach    {
3958f5f5da8SGreg Roach        // Sign the URL, to protect against mass-resize attacks.
3968f5f5da8SGreg Roach        $glide_key = Site::getPreference('glide-key');
3978f5f5da8SGreg Roach        if (empty($glide_key)) {
3988f5f5da8SGreg Roach            $glide_key = bin2hex(random_bytes(128));
3998f5f5da8SGreg Roach            Site::setPreference('glide-key', $glide_key);
4008f5f5da8SGreg Roach        }
4018f5f5da8SGreg Roach
402f4afa648SGreg Roach        if (Auth::accessLevel($this->media->tree()) > $this->media->tree()->getPreference('SHOW_NO_WATERMARK')) {
4038f5f5da8SGreg Roach            $mark = 'watermark.png';
4048f5f5da8SGreg Roach        } else {
4058f5f5da8SGreg Roach            $mark = '';
4068f5f5da8SGreg Roach        }
4078f5f5da8SGreg Roach
408*9b93b7c3SGreg Roach        $base_url = app(ServerRequestInterface::class)->getAttribute('base_url');
409*9b93b7c3SGreg Roach
410*9b93b7c3SGreg Roach        $url_builder = UrlBuilderFactory::create($base_url, $glide_key);
4114a9f750fSGreg Roach
4124a9f750fSGreg Roach        $url = $url_builder->getUrl('index.php', [
4134a9f750fSGreg Roach            'route'     => 'media-thumbnail',
414c0935879SGreg Roach            'xref'      => $this->media->xref(),
415f4afa648SGreg Roach            'ged'       => $this->media->tree()->name(),
4164a9f750fSGreg Roach            'fact_id'   => $this->fact_id,
4178f5f5da8SGreg Roach            'w'         => $width,
4188f5f5da8SGreg Roach            'h'         => $height,
4198f5f5da8SGreg Roach            'fit'       => $fit,
4208f5f5da8SGreg Roach            'mark'      => $mark,
4218f5f5da8SGreg Roach            'markh'     => '100h',
4228f5f5da8SGreg Roach            'markw'     => '100w',
4238f5f5da8SGreg Roach            'markalpha' => 25,
424c1010edaSGreg Roach            'or'        => 0,
425c1010edaSGreg Roach            // Intervention uses exif_read_data() which is very buggy.
4268f5f5da8SGreg Roach        ]);
4278f5f5da8SGreg Roach
4288f5f5da8SGreg Roach        return $url;
4298f5f5da8SGreg Roach    }
4308f5f5da8SGreg Roach
4318f5f5da8SGreg Roach    /**
4328f5f5da8SGreg Roach     * What file extension is used by this file?
4338f5f5da8SGreg Roach     *
4348f5f5da8SGreg Roach     * @return string
4358f5f5da8SGreg Roach     */
436e364afe4SGreg Roach    public function extension(): string
437c1010edaSGreg Roach    {
438a99c6938SGreg Roach        if (preg_match('/\.([a-zA-Z0-9]+)$/', $this->multimedia_file_refn, $match)) {
4398f5f5da8SGreg Roach            return strtolower($match[1]);
4408f5f5da8SGreg Roach        }
441b2ce94c6SRico Sonntag
442b2ce94c6SRico Sonntag        return '';
4438f5f5da8SGreg Roach    }
4448f5f5da8SGreg Roach
4458f5f5da8SGreg Roach    /**
4468f5f5da8SGreg Roach     * What is the mime-type of this object?
4478f5f5da8SGreg Roach     * For simplicity and efficiency, use the extension, rather than the contents.
4488f5f5da8SGreg Roach     *
4498f5f5da8SGreg Roach     * @return string
4508f5f5da8SGreg Roach     */
4518f53f488SRico Sonntag    public function mimeType(): string
452c1010edaSGreg Roach    {
4535225fdfcSGreg Roach        return self::MIME_TYPES[$this->extension()] ?? 'application/octet-stream';
4548f5f5da8SGreg Roach    }
4558f5f5da8SGreg Roach}
456