18f5f5da8SGreg Roach<?php 28f5f5da8SGreg Roach/** 38f5f5da8SGreg Roach * webtrees: online genealogy 41062a142SGreg Roach * Copyright (C) 2018 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 */ 168f5f5da8SGreg Roachnamespace Fisharebest\Webtrees; 178f5f5da8SGreg Roach 188f5f5da8SGreg Roachuse League\Glide\Urls\UrlBuilderFactory; 192361dfe8SGreg Roachuse Throwable; 208f5f5da8SGreg Roach 218f5f5da8SGreg Roach/** 228f5f5da8SGreg Roach * A GEDCOM media file. A media object can contain many media files, 238f5f5da8SGreg Roach * such as scans of both sides of a document, the transcript of an audio 248f5f5da8SGreg Roach * recording, etc. 258f5f5da8SGreg Roach */ 268f5f5da8SGreg Roachclass MediaFile { 27*5225fdfcSGreg Roach const MIME_TYPES = [ 28*5225fdfcSGreg Roach 'bmp' => 'image/bmp', 29*5225fdfcSGreg Roach 'doc' => 'application/msword', 30*5225fdfcSGreg Roach 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 31*5225fdfcSGreg Roach 'ged' => 'text/x-gedcom', 32*5225fdfcSGreg Roach 'gif' => 'image/gif', 33*5225fdfcSGreg Roach 'html' => 'text/html', 34*5225fdfcSGreg Roach 'htm' => 'text/html', 35*5225fdfcSGreg Roach 'jpeg' => 'image/jpeg', 36*5225fdfcSGreg Roach 'jpg' => 'image/jpeg', 37*5225fdfcSGreg Roach 'mov' => 'video/quicktime', 38*5225fdfcSGreg Roach 'mp3' => 'audio/mpeg', 39*5225fdfcSGreg Roach 'mp4' => 'video/mp4', 40*5225fdfcSGreg Roach 'ogv' => 'video/ogg', 41*5225fdfcSGreg Roach 'pdf' => 'application/pdf', 42*5225fdfcSGreg Roach 'png' => 'image/png', 43*5225fdfcSGreg Roach 'rar' => 'application/x-rar-compressed', 44*5225fdfcSGreg Roach 'swf' => 'application/x-shockwave-flash', 45*5225fdfcSGreg Roach 'svg' => 'image/svg', 46*5225fdfcSGreg Roach 'tiff' => 'image/tiff', 47*5225fdfcSGreg Roach 'tif' => 'image/tiff', 48*5225fdfcSGreg Roach 'xls' => 'application/vnd-ms-excel', 49*5225fdfcSGreg Roach 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 50*5225fdfcSGreg Roach 'wmv' => 'video/x-ms-wmv', 51*5225fdfcSGreg Roach 'zip' => 'application/zip', 52*5225fdfcSGreg Roach ]; 53*5225fdfcSGreg Roach 548f5f5da8SGreg Roach /** @var string The filename */ 558f5f5da8SGreg Roach private $multimedia_file_refn = ''; 568f5f5da8SGreg Roach 578f5f5da8SGreg Roach /** @var string The file extension; jpeg, txt, mp4, etc. */ 588f5f5da8SGreg Roach private $multimedia_format = ''; 598f5f5da8SGreg Roach 608f5f5da8SGreg Roach /** @var string The type of document; newspaper, microfiche, etc. */ 618f5f5da8SGreg Roach private $source_media_type = ''; 628f5f5da8SGreg Roach /** @var string The filename */ 638f5f5da8SGreg Roach 648f5f5da8SGreg Roach /** @var string The name of the document */ 658f5f5da8SGreg Roach private $descriptive_title = ''; 668f5f5da8SGreg Roach 678f5f5da8SGreg Roach /** @var Media $media The media object to which this file belongs */ 688f5f5da8SGreg Roach private $media; 698f5f5da8SGreg Roach 7064b90bf1SGreg Roach /** @var string */ 7164b90bf1SGreg Roach private $fact_id; 7264b90bf1SGreg Roach 738f5f5da8SGreg Roach /** 748f5f5da8SGreg Roach * Create a MediaFile from raw GEDCOM data. 758f5f5da8SGreg Roach * 768f5f5da8SGreg Roach * @param string $gedcom 778f5f5da8SGreg Roach * @param Media $media 788f5f5da8SGreg Roach */ 798f5f5da8SGreg Roach public function __construct($gedcom, Media $media) { 808f5f5da8SGreg Roach $this->media = $media; 8164b90bf1SGreg Roach $this->fact_id = md5($gedcom); 828f5f5da8SGreg Roach 838f5f5da8SGreg Roach if (preg_match('/^\d FILE (.+)/m', $gedcom, $match)) { 848f5f5da8SGreg Roach $this->multimedia_file_refn = $match[1]; 858f5f5da8SGreg Roach } 868f5f5da8SGreg Roach 878f5f5da8SGreg Roach if (preg_match('/^\d FORM (.+)/m', $gedcom, $match)) { 888f5f5da8SGreg Roach $this->multimedia_format = $match[1]; 898f5f5da8SGreg Roach } 908f5f5da8SGreg Roach 918f5f5da8SGreg Roach if (preg_match('/^\d TYPE (.+)/m', $gedcom, $match)) { 928f5f5da8SGreg Roach $this->source_media_type = $match[1]; 938f5f5da8SGreg Roach } 948f5f5da8SGreg Roach 958f5f5da8SGreg Roach if (preg_match('/^\d TITL (.+)/m', $gedcom, $match)) { 968f5f5da8SGreg Roach $this->descriptive_title = $match[1]; 978f5f5da8SGreg Roach } 988f5f5da8SGreg Roach } 998f5f5da8SGreg Roach 1008f5f5da8SGreg Roach /** 10164b90bf1SGreg Roach * Get the filename. 1028f5f5da8SGreg Roach * 1038f5f5da8SGreg Roach * @return string 1048f5f5da8SGreg Roach */ 1056e6a9947SGreg Roach public function filename(): string { 1066e6a9947SGreg Roach return $this->multimedia_file_refn; 1078f5f5da8SGreg Roach } 1088f5f5da8SGreg Roach 1098f5f5da8SGreg Roach /** 110d6641c58SGreg Roach * Get the base part of the filename. 111d6641c58SGreg Roach * 112d6641c58SGreg Roach * @return string 113d6641c58SGreg Roach */ 114d6641c58SGreg Roach public function basename(): string { 115d6641c58SGreg Roach return basename($this->multimedia_file_refn); 116d6641c58SGreg Roach } 117d6641c58SGreg Roach 118d6641c58SGreg Roach /** 119d6641c58SGreg Roach * Get the folder part of the filename. 120d6641c58SGreg Roach * 121d6641c58SGreg Roach * @return string 122d6641c58SGreg Roach */ 123d6641c58SGreg Roach public function dirname(): string { 124d6641c58SGreg Roach $dirname = dirname($this->multimedia_file_refn); 125d6641c58SGreg Roach 126d6641c58SGreg Roach if ($dirname === '.') { 127d6641c58SGreg Roach return ''; 128d6641c58SGreg Roach } else { 129d6641c58SGreg Roach return $dirname; 130d6641c58SGreg Roach } 131d6641c58SGreg Roach } 132d6641c58SGreg Roach 133d6641c58SGreg Roach /** 13464b90bf1SGreg Roach * Get the format. 1358f5f5da8SGreg Roach * 1368f5f5da8SGreg Roach * @return string 1378f5f5da8SGreg Roach */ 1386e6a9947SGreg Roach public function format(): string { 1398f5f5da8SGreg Roach return $this->multimedia_format; 1408f5f5da8SGreg Roach } 1418f5f5da8SGreg Roach 1428f5f5da8SGreg Roach /** 14364b90bf1SGreg Roach * Get the type. 1448f5f5da8SGreg Roach * 1458f5f5da8SGreg Roach * @return string 1468f5f5da8SGreg Roach */ 1476e6a9947SGreg Roach public function type(): string { 1488f5f5da8SGreg Roach return $this->source_media_type; 1498f5f5da8SGreg Roach } 1508f5f5da8SGreg Roach 1518f5f5da8SGreg Roach /** 15264b90bf1SGreg Roach * Get the title. 1538f5f5da8SGreg Roach * 1548f5f5da8SGreg Roach * @return string 1558f5f5da8SGreg Roach */ 1566e6a9947SGreg Roach public function title(): string { 1578f5f5da8SGreg Roach return $this->descriptive_title; 1588f5f5da8SGreg Roach } 1598f5f5da8SGreg Roach 1608f5f5da8SGreg Roach /** 16164b90bf1SGreg Roach * Get the fact ID. 16264b90bf1SGreg Roach * 16364b90bf1SGreg Roach * @return string 16464b90bf1SGreg Roach */ 16564b90bf1SGreg Roach public function factId(): string { 16664b90bf1SGreg Roach return $this->fact_id; 16764b90bf1SGreg Roach } 16864b90bf1SGreg Roach 16964b90bf1SGreg Roach /** 170d6641c58SGreg Roach * @return bool 171d6641c58SGreg Roach */ 172ccf1c580SGreg Roach public function isPendingAddition() { 173d6641c58SGreg Roach foreach ($this->media->getFacts() as $fact) { 174d6641c58SGreg Roach if ($fact->getFactId() === $this->fact_id) { 175d6641c58SGreg Roach return $fact->isPendingAddition(); 176d6641c58SGreg Roach } 177d6641c58SGreg Roach } 178d6641c58SGreg Roach 179d6641c58SGreg Roach return false; 180d6641c58SGreg Roach } 181d6641c58SGreg Roach 182d6641c58SGreg Roach /** 183d6641c58SGreg Roach * @return bool 184d6641c58SGreg Roach */ 185d6641c58SGreg Roach public function isPendingDeletion() { 186d6641c58SGreg Roach foreach ($this->media->getFacts() as $fact) { 187d6641c58SGreg Roach if ($fact->getFactId() === $this->fact_id) { 188d6641c58SGreg Roach return $fact->isPendingDeletion(); 189d6641c58SGreg Roach } 190d6641c58SGreg Roach } 191d6641c58SGreg Roach 192d6641c58SGreg Roach return false; 193d6641c58SGreg Roach } 194d6641c58SGreg Roach 195d6641c58SGreg Roach /** 19664b90bf1SGreg Roach * Display an image-thumbnail or a media-icon, and add markup for image viewers such as colorbox. 19764b90bf1SGreg Roach * 19864b90bf1SGreg Roach * @param int $width Pixels 19964b90bf1SGreg Roach * @param int $height Pixels 20064b90bf1SGreg Roach * @param string $fit "crop" or "contain" 20164b90bf1SGreg Roach * @param string[] $attributes Additional HTML attributes 20264b90bf1SGreg Roach * 20364b90bf1SGreg Roach * @return string 20464b90bf1SGreg Roach */ 20564b90bf1SGreg Roach public function displayImage($width, $height, $fit, $attributes = []) { 20664b90bf1SGreg Roach if ($this->isExternal()) { 20764b90bf1SGreg Roach $src = $this->multimedia_file_refn; 20864b90bf1SGreg Roach $srcset = []; 20964b90bf1SGreg Roach } else { 21064b90bf1SGreg Roach // Generate multiple images for displays with higher pixel densities. 21164b90bf1SGreg Roach $src = $this->imageUrl($width, $height, $fit); 21264b90bf1SGreg Roach $srcset = []; 21364b90bf1SGreg Roach foreach ([2, 3, 4] as $x) { 21464b90bf1SGreg Roach $srcset[] = $this->imageUrl($width * $x, $height * $x, $fit) . ' ' . $x . 'x'; 21564b90bf1SGreg Roach } 21664b90bf1SGreg Roach } 21764b90bf1SGreg Roach 21864b90bf1SGreg Roach $image = '<img ' . Html::attributes($attributes + [ 21964b90bf1SGreg Roach 'dir' => 'auto', 22064b90bf1SGreg Roach 'src' => $src, 22164b90bf1SGreg Roach 'srcset' => implode(',', $srcset), 2225be0d03dSGreg Roach 'alt' => htmlspecialchars_decode(strip_tags($this->media->getFullName())), 22364b90bf1SGreg Roach ]) . '>'; 22464b90bf1SGreg Roach 225e1d1700bSGreg Roach if ($this->isImage()) { 22664b90bf1SGreg Roach $attributes = Html::attributes([ 22764b90bf1SGreg Roach 'class' => 'gallery', 22864b90bf1SGreg Roach 'type' => $this->mimeType(), 22960e3c46aSGreg Roach 'href' => $this->imageUrl(0, 0, 'contain'), 2305be0d03dSGreg Roach 'data-title' => htmlspecialchars_decode(strip_tags($this->media->getFullName())), 23164b90bf1SGreg Roach ]); 232e1d1700bSGreg Roach } else { 233e1d1700bSGreg Roach $attributes = Html::attributes([ 234e1d1700bSGreg Roach 'type' => $this->mimeType(), 235e1d1700bSGreg Roach 'href' => $this->downloadUrl(), 236e1d1700bSGreg Roach ]); 237e1d1700bSGreg Roach } 23864b90bf1SGreg Roach 23964b90bf1SGreg Roach return '<a ' . $attributes . '>' . $image . '</a>'; 24064b90bf1SGreg Roach } 24164b90bf1SGreg Roach 2424a9f750fSGreg Roach /** 2434a9f750fSGreg Roach * A list of image attributes 2444a9f750fSGreg Roach * 2454a9f750fSGreg Roach * @return string[] 2464a9f750fSGreg Roach */ 2474a9f750fSGreg Roach public function attributes(): array { 2484a9f750fSGreg Roach $attributes = []; 24964b90bf1SGreg Roach 2504a9f750fSGreg Roach if (!$this->isExternal() || $this->fileExists()) { 2514a9f750fSGreg Roach $file = $this->folder() . $this->multimedia_file_refn; 2524a9f750fSGreg Roach 2534a9f750fSGreg Roach $attributes['__FILE_SIZE__'] = $this->fileSizeKB(); 2544a9f750fSGreg Roach 2554a9f750fSGreg Roach $imgsize = getimagesize($file); 2564a9f750fSGreg Roach if (is_array($imgsize) && !empty($imgsize['0'])) { 2574a9f750fSGreg Roach $attributes['__IMAGE_SIZE__'] = I18N::translate('%1$s × %2$s pixels', I18N::number($imgsize['0']), I18N::number($imgsize['1'])); 2584a9f750fSGreg Roach } 2594a9f750fSGreg Roach } 2604a9f750fSGreg Roach 2614a9f750fSGreg Roach return $attributes; 2624a9f750fSGreg Roach } 2634a9f750fSGreg Roach 2644a9f750fSGreg Roach /** 2654a9f750fSGreg Roach * check if the file exists on this server 2664a9f750fSGreg Roach * 2674a9f750fSGreg Roach * @return bool 2684a9f750fSGreg Roach */ 2694a9f750fSGreg Roach public function fileExists() { 270d6641c58SGreg Roach return !$this->isExternal() && file_exists($this->folder() . $this->multimedia_file_refn); 2714a9f750fSGreg Roach } 2724a9f750fSGreg Roach 2734a9f750fSGreg Roach /** 2744a9f750fSGreg Roach * Is the media file actually a URL? 2754a9f750fSGreg Roach */ 2764a9f750fSGreg Roach public function isExternal(): bool { 2774a9f750fSGreg Roach return strpos($this->multimedia_file_refn, '://') !== false; 2784a9f750fSGreg Roach } 2794a9f750fSGreg Roach 2804a9f750fSGreg Roach /** 2814a9f750fSGreg Roach * Is the media file an image? 2824a9f750fSGreg Roach */ 2834a9f750fSGreg Roach public function isImage(): bool { 2844a9f750fSGreg Roach return in_array($this->extension(), ['jpeg', 'jpg', 'gif', 'png']); 2854a9f750fSGreg Roach } 2864a9f750fSGreg Roach 2874a9f750fSGreg Roach /** 28844379edcSGreg Roach * Where is the file stored on disk? 28944379edcSGreg Roach */ 29044379edcSGreg Roach public function folder(): string { 29144379edcSGreg Roach return WT_DATA_DIR . $this->media->getTree()->getPreference('MEDIA_DIRECTORY'); 29244379edcSGreg Roach } 29344379edcSGreg Roach 29444379edcSGreg Roach /** 2954a9f750fSGreg Roach * A user-friendly view of the file size 2964a9f750fSGreg Roach * 2974a9f750fSGreg Roach * @return int 2984a9f750fSGreg Roach */ 2994a9f750fSGreg Roach private function fileSizeBytes(): int { 3004a9f750fSGreg Roach try { 3014a9f750fSGreg Roach return filesize($this->folder() . $this->multimedia_file_refn); 3022361dfe8SGreg Roach } catch (Throwable $ex) { 3034a9f750fSGreg Roach DebugBar::addThrowable($ex); 3044a9f750fSGreg Roach 3054a9f750fSGreg Roach return 0; 3064a9f750fSGreg Roach } 3074a9f750fSGreg Roach } 3084a9f750fSGreg Roach 3094a9f750fSGreg Roach /** 3104a9f750fSGreg Roach * get the media file size in KB 3114a9f750fSGreg Roach * 3124a9f750fSGreg Roach * @return string 3134a9f750fSGreg Roach */ 3144a9f750fSGreg Roach public function fileSizeKB() { 3154a9f750fSGreg Roach $size = $this->filesizeBytes(); 3164a9f750fSGreg Roach $size = (int) (($size + 1023) / 1024); 3174a9f750fSGreg Roach 3184a9f750fSGreg Roach return /* I18N: size of file in KB */ I18N::translate('%s KB', I18N::number($size)); 3194a9f750fSGreg Roach } 32064b90bf1SGreg Roach 32164b90bf1SGreg Roach /** 3228f5f5da8SGreg Roach * Get the filename on the server - for those (very few!) functions which actually 323bf7c4bf8SGreg Roach * need the filename, such as the PDF reports. 3248f5f5da8SGreg Roach * 3258f5f5da8SGreg Roach * @return string 3268f5f5da8SGreg Roach */ 3278f5f5da8SGreg Roach public function getServerFilename() { 3288f5f5da8SGreg Roach $MEDIA_DIRECTORY = $this->media->getTree()->getPreference('MEDIA_DIRECTORY'); 3298f5f5da8SGreg Roach 33064b90bf1SGreg Roach if ($this->isExternal() || !$this->multimedia_file_refn) { 3318f5f5da8SGreg Roach // External image, or (in the case of corrupt GEDCOM data) no image at all 33264b90bf1SGreg Roach return $this->multimedia_file_refn; 3338f5f5da8SGreg Roach } else { 3348f5f5da8SGreg Roach // Main image 33564b90bf1SGreg Roach return WT_DATA_DIR . $MEDIA_DIRECTORY . $this->multimedia_file_refn; 3368f5f5da8SGreg Roach } 3378f5f5da8SGreg Roach } 3388f5f5da8SGreg Roach 3398f5f5da8SGreg Roach /** 3408f5f5da8SGreg Roach * get image properties 3418f5f5da8SGreg Roach * 3428f5f5da8SGreg Roach * @return array 3438f5f5da8SGreg Roach */ 3448f5f5da8SGreg Roach public function getImageAttributes() { 3458f5f5da8SGreg Roach $imgsize = []; 3468f5f5da8SGreg Roach if ($this->fileExists()) { 3478f5f5da8SGreg Roach try { 3488f5f5da8SGreg Roach $imgsize = getimagesize($this->getServerFilename()); 3498f5f5da8SGreg Roach if (is_array($imgsize) && !empty($imgsize['0'])) { 3508f5f5da8SGreg Roach // this is an image 3518f5f5da8SGreg Roach $imageTypes = ['', 'GIF', 'JPG', 'PNG', 'SWF', 'PSD', 'BMP', 'TIFF', 'TIFF', 'JPC', 'JP2', 'JPX', 'JB2', 'SWC', 'IFF', 'WBMP', 'XBM']; 3528f5f5da8SGreg Roach $imgsize['ext'] = $imageTypes[0 + $imgsize[2]]; 3538f5f5da8SGreg Roach // this is for display purposes, always show non-adjusted info 3548f5f5da8SGreg Roach $imgsize['WxH'] = /* I18N: image dimensions, width × height */ 3558f5f5da8SGreg Roach I18N::translate('%1$s × %2$s pixels', I18N::number($imgsize['0']), I18N::number($imgsize['1'])); 3568f5f5da8SGreg Roach } 3572361dfe8SGreg Roach } catch (Throwable $ex) { 3588f5f5da8SGreg Roach DebugBar::addThrowable($ex); 3598f5f5da8SGreg Roach 3608f5f5da8SGreg Roach // Not an image, or not a valid image? 3618f5f5da8SGreg Roach $imgsize = false; 3628f5f5da8SGreg Roach } 3638f5f5da8SGreg Roach } 3648f5f5da8SGreg Roach 3658f5f5da8SGreg Roach if (!is_array($imgsize) || empty($imgsize['0'])) { 3668f5f5da8SGreg Roach // this is not an image, OR the file doesn’t exist OR it is a url 3678f5f5da8SGreg Roach $imgsize[0] = 0; 3688f5f5da8SGreg Roach $imgsize[1] = 0; 3698f5f5da8SGreg Roach $imgsize['ext'] = ''; 3708f5f5da8SGreg Roach $imgsize['mime'] = ''; 3718f5f5da8SGreg Roach $imgsize['WxH'] = ''; 3728f5f5da8SGreg Roach } 3738f5f5da8SGreg Roach 3748f5f5da8SGreg Roach if (empty($imgsize['mime'])) { 3758f5f5da8SGreg Roach // this is not an image, OR the file doesn’t exist OR it is a url 3768f5f5da8SGreg Roach // set file type equal to the file extension - can’t use parse_url because this may not be a full url 3774a9f750fSGreg Roach $exp = explode('?', $this->multimedia_file_refn); 3788f5f5da8SGreg Roach $imgsize['ext'] = strtoupper(pathinfo($exp[0], PATHINFO_EXTENSION)); 3798f5f5da8SGreg Roach // all mimetypes we wish to serve with the media firewall must be added to this array. 3808f5f5da8SGreg Roach $mime = [ 3818f5f5da8SGreg Roach 'DOC' => 'application/msword', 3828f5f5da8SGreg Roach 'MOV' => 'video/quicktime', 3838f5f5da8SGreg Roach 'MP3' => 'audio/mpeg', 3848f5f5da8SGreg Roach 'PDF' => 'application/pdf', 3858f5f5da8SGreg Roach 'PPT' => 'application/vnd.ms-powerpoint', 3868f5f5da8SGreg Roach 'RTF' => 'text/rtf', 3878f5f5da8SGreg Roach 'SID' => 'image/x-mrsid', 3888f5f5da8SGreg Roach 'TXT' => 'text/plain', 3898f5f5da8SGreg Roach 'XLS' => 'application/vnd.ms-excel', 3908f5f5da8SGreg Roach 'WMV' => 'video/x-ms-wmv', 3918f5f5da8SGreg Roach ]; 3928f5f5da8SGreg Roach if (empty($mime[$imgsize['ext']])) { 3938f5f5da8SGreg Roach // if we don’t know what the mimetype is, use something ambiguous 3948f5f5da8SGreg Roach $imgsize['mime'] = 'application/octet-stream'; 3958f5f5da8SGreg Roach if ($this->fileExists()) { 3968f5f5da8SGreg Roach // alert the admin if we cannot determine the mime type of an existing file 3978f5f5da8SGreg Roach // as the media firewall will be unable to serve this file properly 3984a9f750fSGreg Roach Log::addMediaLog('Media Firewall error: >Unknown Mimetype< for file >' . $this->multimedia_file_refn . '<'); 3998f5f5da8SGreg Roach } 4008f5f5da8SGreg Roach } else { 4018f5f5da8SGreg Roach $imgsize['mime'] = $mime[$imgsize['ext']]; 4028f5f5da8SGreg Roach } 4038f5f5da8SGreg Roach } 4048f5f5da8SGreg Roach 4058f5f5da8SGreg Roach return $imgsize; 4068f5f5da8SGreg Roach } 4078f5f5da8SGreg Roach 4088f5f5da8SGreg Roach /** 409e1d1700bSGreg Roach * Generate a URL to download a non-image media file. 410e1d1700bSGreg Roach * 411e1d1700bSGreg Roach * @return string 412e1d1700bSGreg Roach */ 413e1d1700bSGreg Roach public function downloadUrl() { 414e1d1700bSGreg Roach return route('media-download', [ 415e1d1700bSGreg Roach 'xref' => $this->media->getXref(), 416e1d1700bSGreg Roach 'ged' => $this->media->getTree()->getName(), 417e1d1700bSGreg Roach 'fact_id' => $this->fact_id, 418e1d1700bSGreg Roach ]); 419e1d1700bSGreg Roach } 420e1d1700bSGreg Roach 421e1d1700bSGreg Roach /** 4228f5f5da8SGreg Roach * Generate a URL for an image. 4238f5f5da8SGreg Roach * 4248f5f5da8SGreg Roach * @param int $width Maximum width in pixels 4258f5f5da8SGreg Roach * @param int $height Maximum height in pixels 4268f5f5da8SGreg Roach * @param string $fit "crop" or "contain" 4278f5f5da8SGreg Roach * 4288f5f5da8SGreg Roach * @return string 4298f5f5da8SGreg Roach */ 4308f5f5da8SGreg Roach public function imageUrl($width, $height, $fit) { 4318f5f5da8SGreg Roach // Sign the URL, to protect against mass-resize attacks. 4328f5f5da8SGreg Roach $glide_key = Site::getPreference('glide-key'); 4338f5f5da8SGreg Roach if (empty($glide_key)) { 4348f5f5da8SGreg Roach $glide_key = bin2hex(random_bytes(128)); 4358f5f5da8SGreg Roach Site::setPreference('glide-key', $glide_key); 4368f5f5da8SGreg Roach } 4378f5f5da8SGreg Roach 43864b90bf1SGreg Roach if (Auth::accessLevel($this->media->getTree()) > $this->media->getTree()->getPreference('SHOW_NO_WATERMARK')) { 4398f5f5da8SGreg Roach $mark = 'watermark.png'; 4408f5f5da8SGreg Roach } else { 4418f5f5da8SGreg Roach $mark = ''; 4428f5f5da8SGreg Roach } 4438f5f5da8SGreg Roach 4444a9f750fSGreg Roach $url_builder = UrlBuilderFactory::create(WT_BASE_URL, $glide_key); 4454a9f750fSGreg Roach 4464a9f750fSGreg Roach $url = $url_builder->getUrl('index.php', [ 4474a9f750fSGreg Roach 'route' => 'media-thumbnail', 4484a9f750fSGreg Roach 'xref' => $this->media->getXref(), 44964b90bf1SGreg Roach 'ged' => $this->media->getTree()->getName(), 4504a9f750fSGreg Roach 'fact_id' => $this->fact_id, 4518f5f5da8SGreg Roach 'w' => $width, 4528f5f5da8SGreg Roach 'h' => $height, 4538f5f5da8SGreg Roach 'fit' => $fit, 4548f5f5da8SGreg Roach 'mark' => $mark, 4558f5f5da8SGreg Roach 'markh' => '100h', 4568f5f5da8SGreg Roach 'markw' => '100w', 4578f5f5da8SGreg Roach 'markalpha' => 25, 4588f5f5da8SGreg Roach 'or' => 0, // Intervention uses exif_read_data() which is very buggy. 4598f5f5da8SGreg Roach ]); 4608f5f5da8SGreg Roach 4618f5f5da8SGreg Roach return $url; 4628f5f5da8SGreg Roach } 4638f5f5da8SGreg Roach 4648f5f5da8SGreg Roach /** 4658f5f5da8SGreg Roach * What file extension is used by this file? 4668f5f5da8SGreg Roach * 4678f5f5da8SGreg Roach * @return string 4688f5f5da8SGreg Roach */ 4698f5f5da8SGreg Roach public function extension() { 470a99c6938SGreg Roach if (preg_match('/\.([a-zA-Z0-9]+)$/', $this->multimedia_file_refn, $match)) { 4718f5f5da8SGreg Roach return strtolower($match[1]); 4728f5f5da8SGreg Roach } else { 4738f5f5da8SGreg Roach return ''; 4748f5f5da8SGreg Roach } 4758f5f5da8SGreg Roach } 4768f5f5da8SGreg Roach 4778f5f5da8SGreg Roach /** 4788f5f5da8SGreg Roach * What is the mime-type of this object? 4798f5f5da8SGreg Roach * For simplicity and efficiency, use the extension, rather than the contents. 4808f5f5da8SGreg Roach * 4818f5f5da8SGreg Roach * @return string 4828f5f5da8SGreg Roach */ 4838f5f5da8SGreg Roach public function mimeType() { 484*5225fdfcSGreg Roach return self::MIME_TYPES[$this->extension()] ?? 'application/octet-stream'; 4858f5f5da8SGreg Roach } 4868f5f5da8SGreg Roach} 487