xref: /dokuwiki/inc/ChangeLog/MediaChangeLog.php (revision 5a285deb52b56fa567c6d217b5c396330c58f297)
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    /**
53*5a285debSAndreas Gohr     * Media deliberately does not keep an archive of its current revision — only the previous
54*5a285debSAndreas Gohr     * content is copied to the attic when a file is replaced or deleted (to save space). A
55*5a285debSAndreas Gohr     * detected external edit is the new current revision, so it is not snapshotted either: it
56*5a285debSAndreas Gohr     * will be archived like any other revision if and when it is later replaced. The changelog
57*5a285debSAndreas Gohr     * entry is still recorded by the caller, and the file-mtime repair for an unreliable date
58*5a285debSAndreas Gohr     * is handled by the base class.
59c7192766SSatoshi Sahara     *
60*5a285debSAndreas Gohr     * @param array $revInfo synthesized revision info (unused: nothing is archived)
61*5a285debSAndreas Gohr     * @return bool always true
62c7192766SSatoshi Sahara     */
6301e8d739SAndreas Gohr    protected function saveExternalAttic(array $revInfo)
64c7192766SSatoshi Sahara    {
6501e8d739SAndreas Gohr        return true;
66c7192766SSatoshi Sahara    }
670a245329SAndreas Gohr
680a245329SAndreas Gohr    /**
69*5a285debSAndreas Gohr     * Byte size of the last recorded revision.
700a245329SAndreas Gohr     *
71*5a285debSAndreas Gohr     * Media never archives its current revision (only the previous content is copied to the
72*5a285debSAndreas Gohr     * attic on replace or delete), so the last revision has no attic copy and its size cannot
73*5a285debSAndreas Gohr     * be read from disk. It is reconstructed instead as the previous revision's archived size
74*5a285debSAndreas Gohr     * plus the size change logged for the last revision. The first revision has no previous
75*5a285debSAndreas Gohr     * one, so its logged change is already its full size.
760a245329SAndreas Gohr     *
77*5a285debSAndreas Gohr     * @param int $clogRev timestamp of the last recorded revision
78*5a285debSAndreas Gohr     * @return int size in bytes (0 when it cannot be determined)
79*5a285debSAndreas Gohr     */
80*5a285debSAndreas Gohr    protected function lastRevisionSize($clogRev)
81*5a285debSAndreas Gohr    {
82*5a285debSAndreas Gohr        $revInfo = $this->getRevisionInfo($clogRev, false);
83*5a285debSAndreas Gohr        $sizechange = is_array($revInfo) ? (int) $revInfo['sizechange'] : 0;
84*5a285debSAndreas Gohr
85*5a285debSAndreas Gohr        $prev = $this->getRelativeRevision($clogRev, -1);
86*5a285debSAndreas Gohr        $prevSize = ($prev === false) ? 0 : io_getSizeFile($this->getFilename($prev));
87*5a285debSAndreas Gohr
88*5a285debSAndreas Gohr        return max($prevSize + $sizechange, 0);
89*5a285debSAndreas Gohr    }
90*5a285debSAndreas Gohr
91*5a285debSAndreas Gohr    /**
92*5a285debSAndreas Gohr     * Tell a real external edit from a mere mtime bump (touch, rsync --times, unzip of
93*5a285debSAndreas Gohr     * identical bytes, ...).
94*5a285debSAndreas Gohr     *
95*5a285debSAndreas Gohr     * The current media revision is never archived, so there is no stored copy to compare the
96*5a285debSAndreas Gohr     * current file against byte for byte. Its expected size is reconstructed instead (see
97*5a285debSAndreas Gohr     * lastRevisionSize()) and compared to the current file's size: a pure mtime bump leaves the
98*5a285debSAndreas Gohr     * size unchanged, so an equal size means the content did not change. A same-size external
99*5a285debSAndreas Gohr     * replacement cannot be told apart this way and is (rarely) treated as unchanged.
100*5a285debSAndreas Gohr     *
101*5a285debSAndreas Gohr     * @param int $rev revision timestamp to compare the current file against (the last revision)
102*5a285debSAndreas Gohr     * @return bool true if the content is considered unchanged
1030a245329SAndreas Gohr     */
1040a245329SAndreas Gohr    protected function currentContentMatchesRevision($rev)
1050a245329SAndreas Gohr    {
1060a245329SAndreas Gohr        $current = $this->getFilename();
107*5a285debSAndreas Gohr        if (!file_exists($current)) return false;
1080a245329SAndreas Gohr
109*5a285debSAndreas Gohr        return filesize($current) === $this->lastRevisionSize($rev);
1100a245329SAndreas Gohr    }
1110c3a5702SAndreas Gohr}
112