xref: /dokuwiki/inc/File/MediaFile.php (revision dd9e8e5ea54469964faab99223a61bd48146ac42)
10603f506SAndreas Gohr<?php
20603f506SAndreas Gohr
30603f506SAndreas Gohrnamespace dokuwiki\File;
40603f506SAndreas Gohr
5*dd9e8e5eSAndreas Gohruse Exception;
679a2d784SGerrit Uitslaguse JpegMeta;
7*dd9e8e5eSAndreas Gohruse splitbrain\slika\ImageInfo;
80603f506SAndreas Gohr
90603f506SAndreas Gohrclass MediaFile
100603f506SAndreas Gohr{
110603f506SAndreas Gohr    protected $id;
12fe9d054bSAndreas Gohr    protected $rev;
130603f506SAndreas Gohr    protected $path;
140603f506SAndreas Gohr
150603f506SAndreas Gohr    protected $mime;
160603f506SAndreas Gohr    protected $ext;
170603f506SAndreas Gohr    protected $downloadable;
180603f506SAndreas Gohr
190603f506SAndreas Gohr    protected $width;
200603f506SAndreas Gohr    protected $height;
210603f506SAndreas Gohr    protected $meta;
220603f506SAndreas Gohr
230603f506SAndreas Gohr    /**
240603f506SAndreas Gohr     * MediaFile constructor.
250603f506SAndreas Gohr     * @param string $id
260603f506SAndreas Gohr     * @param string|int $rev optional revision
270603f506SAndreas Gohr     */
280603f506SAndreas Gohr    public function __construct($id, $rev = '')
290603f506SAndreas Gohr    {
300603f506SAndreas Gohr        $this->id = $id; //FIXME should it be cleaned?
310603f506SAndreas Gohr        $this->path = mediaFN($id, $rev);
32fe9d054bSAndreas Gohr        $this->rev = $rev;
330603f506SAndreas Gohr
34445164b2SAndreas Gohr        [$this->ext, $this->mime, $this->downloadable] = mimetype($this->path, false);
350603f506SAndreas Gohr    }
360603f506SAndreas Gohr
370603f506SAndreas Gohr    /** @return string */
380603f506SAndreas Gohr    public function getId()
390603f506SAndreas Gohr    {
400603f506SAndreas Gohr        return $this->id;
410603f506SAndreas Gohr    }
420603f506SAndreas Gohr
43fe9d054bSAndreas Gohr    /** @return string|int Empty string for current version */
44fe9d054bSAndreas Gohr    public function getRev()
45fe9d054bSAndreas Gohr    {
46fe9d054bSAndreas Gohr        return $this->rev;
47fe9d054bSAndreas Gohr    }
48fe9d054bSAndreas Gohr
490603f506SAndreas Gohr    /** @return string */
500603f506SAndreas Gohr    public function getPath()
510603f506SAndreas Gohr    {
520603f506SAndreas Gohr        return $this->path;
530603f506SAndreas Gohr    }
540603f506SAndreas Gohr
550603f506SAndreas Gohr    /**
560603f506SAndreas Gohr     * The ID without namespace, used for display purposes
570603f506SAndreas Gohr     *
580603f506SAndreas Gohr     * @return string
590603f506SAndreas Gohr     */
600603f506SAndreas Gohr    public function getDisplayName()
610603f506SAndreas Gohr    {
620603f506SAndreas Gohr        return noNS($this->id);
630603f506SAndreas Gohr    }
640603f506SAndreas Gohr
650603f506SAndreas Gohr    /** @return string */
660603f506SAndreas Gohr    public function getMime()
670603f506SAndreas Gohr    {
680603f506SAndreas Gohr        if (!$this->mime) return 'application/octet-stream';
690603f506SAndreas Gohr        return $this->mime;
700603f506SAndreas Gohr    }
710603f506SAndreas Gohr
720603f506SAndreas Gohr    /** @return string */
730603f506SAndreas Gohr    public function getExtension()
740603f506SAndreas Gohr    {
750603f506SAndreas Gohr        return (string)$this->ext;
760603f506SAndreas Gohr    }
770603f506SAndreas Gohr
780603f506SAndreas Gohr    /**
790603f506SAndreas Gohr     * Similar to the extesion but does some clean up
800603f506SAndreas Gohr     *
810603f506SAndreas Gohr     * @return string
820603f506SAndreas Gohr     */
830603f506SAndreas Gohr    public function getIcoClass()
840603f506SAndreas Gohr    {
850603f506SAndreas Gohr        $ext = $this->getExtension();
860603f506SAndreas Gohr        if ($ext === '') $ext = 'file';
870603f506SAndreas Gohr        return preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
880603f506SAndreas Gohr    }
890603f506SAndreas Gohr
900603f506SAndreas Gohr    /**
910603f506SAndreas Gohr     * Should this file be downloaded instead being displayed inline?
920603f506SAndreas Gohr     *
930603f506SAndreas Gohr     * @return bool
940603f506SAndreas Gohr     */
950603f506SAndreas Gohr    public function isDownloadable()
960603f506SAndreas Gohr    {
970603f506SAndreas Gohr        return $this->downloadable;
980603f506SAndreas Gohr    }
990603f506SAndreas Gohr
1000603f506SAndreas Gohr    /** @return int */
1010603f506SAndreas Gohr    public function getFileSize()
1020603f506SAndreas Gohr    {
1030603f506SAndreas Gohr        return filesize($this->path);
1040603f506SAndreas Gohr    }
1050603f506SAndreas Gohr
1060603f506SAndreas Gohr    /** @return int */
1070603f506SAndreas Gohr    public function getLastModified()
1080603f506SAndreas Gohr    {
1090603f506SAndreas Gohr        return filemtime($this->path);
1100603f506SAndreas Gohr    }
1110603f506SAndreas Gohr
1120603f506SAndreas Gohr    /** @return bool */
1130603f506SAndreas Gohr    public function isWritable()
1140603f506SAndreas Gohr    {
1150603f506SAndreas Gohr        return is_writable($this->path);
1160603f506SAndreas Gohr    }
1170603f506SAndreas Gohr
1180603f506SAndreas Gohr    /** @return bool */
1190603f506SAndreas Gohr    public function isImage()
1200603f506SAndreas Gohr    {
1216c16a3a9Sfiwswe        return (str_starts_with($this->mime, 'image/'));
1220603f506SAndreas Gohr    }
1230603f506SAndreas Gohr
1240603f506SAndreas Gohr    /**
1250603f506SAndreas Gohr     * initializes width and height for images when requested
1260603f506SAndreas Gohr     */
1270603f506SAndreas Gohr    protected function initSizes()
1280603f506SAndreas Gohr    {
1290603f506SAndreas Gohr        $this->width = 0;
1300603f506SAndreas Gohr        $this->height = 0;
1310603f506SAndreas Gohr        if (!$this->isImage()) return;
1320603f506SAndreas Gohr        $info = getimagesize($this->path);
1330603f506SAndreas Gohr        if ($info === false) return;
134445164b2SAndreas Gohr        [$this->width, $this->height] = $info;
1350603f506SAndreas Gohr    }
1360603f506SAndreas Gohr
1370603f506SAndreas Gohr    /**
1380603f506SAndreas Gohr     * Returns the width if this is a supported image, 0 otherwise
1390603f506SAndreas Gohr     *
1400603f506SAndreas Gohr     * @return int
1410603f506SAndreas Gohr     */
1420603f506SAndreas Gohr    public function getWidth()
1430603f506SAndreas Gohr    {
1440603f506SAndreas Gohr        if ($this->width === null) $this->initSizes();
1450603f506SAndreas Gohr        return $this->width;
1460603f506SAndreas Gohr    }
1470603f506SAndreas Gohr
1480603f506SAndreas Gohr    /**
1490603f506SAndreas Gohr     * Returns the height if this is a supported image, 0 otherwise
1500603f506SAndreas Gohr     *
1510603f506SAndreas Gohr     * @return int
1520603f506SAndreas Gohr     */
1530603f506SAndreas Gohr    public function getHeight()
1540603f506SAndreas Gohr    {
1550603f506SAndreas Gohr        if ($this->height === null) $this->initSizes();
1560603f506SAndreas Gohr        return $this->height;
1570603f506SAndreas Gohr    }
1580603f506SAndreas Gohr
1590603f506SAndreas Gohr    /**
160*dd9e8e5eSAndreas Gohr     * Returns the final display dimensions a fetch.php URL with the given
161*dd9e8e5eSAndreas Gohr     * parameters would produce, including EXIF auto-rotation
162*dd9e8e5eSAndreas Gohr     *
163*dd9e8e5eSAndreas Gohr     * @param int $w requested width (0 = no constraint)
164*dd9e8e5eSAndreas Gohr     * @param int $h requested height (0 = no constraint)
165*dd9e8e5eSAndreas Gohr     * @param bool $crop true for center-crop, false for bounding-box fit
166*dd9e8e5eSAndreas Gohr     * @return array [width, height]; [0, 0] for non-images/unreadable files
167*dd9e8e5eSAndreas Gohr     */
168*dd9e8e5eSAndreas Gohr    public function getDisplayDimensions($w = 0, $h = 0, $crop = false)
169*dd9e8e5eSAndreas Gohr    {
170*dd9e8e5eSAndreas Gohr        try {
171*dd9e8e5eSAndreas Gohr            $info = (new ImageInfo($this->path))->autorotate();
172*dd9e8e5eSAndreas Gohr        } catch (Exception $e) {
173*dd9e8e5eSAndreas Gohr            return [0, 0];
174*dd9e8e5eSAndreas Gohr        }
175*dd9e8e5eSAndreas Gohr        if ($w === 0 && $h === 0) return $info->getDimensions();
176*dd9e8e5eSAndreas Gohr        if ($crop) return $info->crop($w, $h)->getDimensions();
177*dd9e8e5eSAndreas Gohr        return $info->resize($w, $h)->getDimensions();
178*dd9e8e5eSAndreas Gohr    }
179*dd9e8e5eSAndreas Gohr
180*dd9e8e5eSAndreas Gohr    /**
1810603f506SAndreas Gohr     * Returns the permissions the current user has on the file
1820603f506SAndreas Gohr     *
1830603f506SAndreas Gohr     * @todo doing this for each file within a namespace is a waste, we need to cache this somehow
1840603f506SAndreas Gohr     * @return int
1850603f506SAndreas Gohr     */
1860603f506SAndreas Gohr    public function userPermission()
1870603f506SAndreas Gohr    {
1880603f506SAndreas Gohr        return auth_quickaclcheck(getNS($this->id) . ':*');
1890603f506SAndreas Gohr    }
1900603f506SAndreas Gohr
19179a2d784SGerrit Uitslag    /** @return JpegMeta */
1920603f506SAndreas Gohr    public function getMeta()
1930603f506SAndreas Gohr    {
19479a2d784SGerrit Uitslag        if ($this->meta === null) $this->meta = new JpegMeta($this->path);
1950603f506SAndreas Gohr        return $this->meta;
1960603f506SAndreas Gohr    }
1970603f506SAndreas Gohr}
198