xref: /dokuwiki/inc/ChangeLog/MediaChangeLog.php (revision 0a245329500f3be55c2a4eb03710ad926803aac6)
10c3a5702SAndreas Gohr<?php
20c3a5702SAndreas Gohr
30c3a5702SAndreas Gohrnamespace dokuwiki\ChangeLog;
40c3a5702SAndreas Gohr
50c3a5702SAndreas Gohr/**
607869ee7SSatoshi Sahara * Class MediaChangeLog; handles changelog of a media file
70c3a5702SAndreas Gohr */
80c3a5702SAndreas Gohrclass MediaChangeLog extends ChangeLog
90c3a5702SAndreas Gohr{
100c3a5702SAndreas Gohr    /**
110c3a5702SAndreas Gohr     * Returns path to changelog
120c3a5702SAndreas Gohr     *
130c3a5702SAndreas Gohr     * @return string path to file
140c3a5702SAndreas Gohr     */
150c3a5702SAndreas Gohr    protected function getChangelogFilename()
160c3a5702SAndreas Gohr    {
170c3a5702SAndreas Gohr        return mediaMetaFN($this->id, '.changes');
180c3a5702SAndreas Gohr    }
190c3a5702SAndreas Gohr
200c3a5702SAndreas Gohr    /**
210c3a5702SAndreas Gohr     * Returns path to current page/media
220c3a5702SAndreas Gohr     *
23e49fa56bSSatoshi Sahara     * @param string|int $rev empty string or revision timestamp
240c3a5702SAndreas Gohr     * @return string path to file
250c3a5702SAndreas Gohr     */
26e49fa56bSSatoshi Sahara    protected function getFilename($rev = '')
270c3a5702SAndreas Gohr    {
28e49fa56bSSatoshi Sahara        return mediaFN($this->id, $rev);
290c3a5702SAndreas Gohr    }
30c7192766SSatoshi Sahara
31a835c93aSGerrit Uitslag    /**
32a835c93aSGerrit Uitslag     * Returns mode
33a835c93aSGerrit Uitslag     *
34a835c93aSGerrit Uitslag     * @return string RevisionInfo::MODE_PAGE
35a835c93aSGerrit Uitslag     */
36a835c93aSGerrit Uitslag    protected function getMode()
37a835c93aSGerrit Uitslag    {
38a835c93aSGerrit Uitslag        return RevisionInfo::MODE_MEDIA;
39a835c93aSGerrit Uitslag    }
40c7192766SSatoshi Sahara
4101e8d739SAndreas Gohr    /**
4201e8d739SAndreas Gohr     * Returns path to the global media-changelog file
4301e8d739SAndreas Gohr     *
4401e8d739SAndreas Gohr     * @return string path to file
4501e8d739SAndreas Gohr     */
4601e8d739SAndreas Gohr    protected function getGlobalChangelogFilename()
4701e8d739SAndreas Gohr    {
4801e8d739SAndreas Gohr        global $conf;
4901e8d739SAndreas Gohr        return $conf['media_changelog'];
5001e8d739SAndreas Gohr    }
51c7192766SSatoshi Sahara
52c7192766SSatoshi Sahara    /**
5301e8d739SAndreas Gohr     * Copy the externally-modified media file to the attic at the synthesized revision date.
5401e8d739SAndreas Gohr     * If the file mtime is older than the last known revision (broken chronology),
5501e8d739SAndreas Gohr     * touch the file forward so future reads see a consistent state.
56c7192766SSatoshi Sahara     *
5701e8d739SAndreas Gohr     * @param array $revInfo synthesized revision info
5801e8d739SAndreas Gohr     * @return bool true on success (or nothing to copy), false if the attic copy failed
59c7192766SSatoshi Sahara     */
6001e8d739SAndreas Gohr    protected function saveExternalAttic(array $revInfo)
61c7192766SSatoshi Sahara    {
62c7192766SSatoshi Sahara        global $conf;
63c7192766SSatoshi Sahara
6401e8d739SAndreas Gohr        $file = $this->getFilename();
6501e8d739SAndreas Gohr        if (!file_exists($file)) return true;
66c7192766SSatoshi Sahara
6701e8d739SAndreas Gohr        // rescue: file mtime older than last revision — touch forward to the synthesized date
6801e8d739SAndreas Gohr        if (empty($revInfo['timestamp'])) {
6901e8d739SAndreas Gohr            if (!@touch($file, $revInfo['date'])) return false;
7001e8d739SAndreas Gohr            clearstatcache(false, $file);
7101e8d739SAndreas Gohr        }
72c7192766SSatoshi Sahara
7301e8d739SAndreas Gohr        $atticfile = $this->getFilename($revInfo['date']);
7401e8d739SAndreas Gohr        io_makeFileDir($atticfile);
7501e8d739SAndreas Gohr        if (!@copy($file, $atticfile)) return false;
7601e8d739SAndreas Gohr        if (!empty($conf['fmode'])) @chmod($atticfile, $conf['fmode']);
7701e8d739SAndreas Gohr        return true;
78c7192766SSatoshi Sahara    }
79*0a245329SAndreas Gohr
80*0a245329SAndreas Gohr    /**
81*0a245329SAndreas Gohr     * Compare the current media file against the attic copy of a revision.
82*0a245329SAndreas Gohr     *
83*0a245329SAndreas Gohr     * Media revisions are stored as raw copies. The (potentially large, binary) files are
84*0a245329SAndreas Gohr     * not loaded into memory: a differing size rules out a match immediately, otherwise the
85*0a245329SAndreas Gohr     * contents are hashed in a streaming fashion via md5_file().
86*0a245329SAndreas Gohr     *
87*0a245329SAndreas Gohr     * @param int $rev revision timestamp to compare the current file against
88*0a245329SAndreas Gohr     * @return bool true if the content is identical
89*0a245329SAndreas Gohr     */
90*0a245329SAndreas Gohr    protected function currentContentMatchesRevision($rev)
91*0a245329SAndreas Gohr    {
92*0a245329SAndreas Gohr        $current = $this->getFilename();
93*0a245329SAndreas Gohr        $attic = $this->getFilename($rev);
94*0a245329SAndreas Gohr        if (!file_exists($current) || !file_exists($attic)) return false;
95*0a245329SAndreas Gohr        if (filesize($current) !== filesize($attic)) return false;
96*0a245329SAndreas Gohr
97*0a245329SAndreas Gohr        return md5_file($current) === md5_file($attic);
98*0a245329SAndreas Gohr    }
990c3a5702SAndreas Gohr}
100