xref: /dokuwiki/inc/ChangeLog/MediaChangeLog.php (revision 6f10c544ba4dccbc9874cebc522bd31c9ae71432)
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    /**
535a285debSAndreas Gohr     * Media deliberately does not keep an archive of its current revision — only the previous
545a285debSAndreas Gohr     * content is copied to the attic when a file is replaced or deleted (to save space). A
555a285debSAndreas Gohr     * detected external edit is the new current revision, so it is not snapshotted either: it
565a285debSAndreas Gohr     * will be archived like any other revision if and when it is later replaced. The changelog
575a285debSAndreas Gohr     * entry is still recorded by the caller, and the file-mtime repair for an unreliable date
585a285debSAndreas Gohr     * is handled by the base class.
59c7192766SSatoshi Sahara     *
605a285debSAndreas Gohr     * @param array $revInfo synthesized revision info (unused: nothing is archived)
615a285debSAndreas 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    /**
695a285debSAndreas Gohr     * Byte size of the last recorded revision.
700a245329SAndreas Gohr     *
715a285debSAndreas Gohr     * Media never archives its current revision (only the previous content is copied to the
725a285debSAndreas Gohr     * attic on replace or delete), so the last revision has no attic copy and its size cannot
735a285debSAndreas Gohr     * be read from disk. It is reconstructed instead as the previous revision's archived size
745a285debSAndreas Gohr     * plus the size change logged for the last revision. The first revision has no previous
755a285debSAndreas Gohr     * one, so its logged change is already its full size.
760a245329SAndreas Gohr     *
77*6f10c544SAndreas Gohr     * @param int $recordedRev timestamp of the last recorded revision
785a285debSAndreas Gohr     * @return int size in bytes (0 when it cannot be determined)
795a285debSAndreas Gohr     */
80*6f10c544SAndreas Gohr    protected function lastRevisionSize($recordedRev)
815a285debSAndreas Gohr    {
82*6f10c544SAndreas Gohr        $revInfo = $this->getRevisionInfo($recordedRev, false);
835a285debSAndreas Gohr        $sizechange = is_array($revInfo) ? (int) $revInfo['sizechange'] : 0;
845a285debSAndreas Gohr
85*6f10c544SAndreas Gohr        $prev = $this->getRelativeRevision($recordedRev, -1);
865a285debSAndreas Gohr        $prevSize = ($prev === false) ? 0 : io_getSizeFile($this->getFilename($prev));
875a285debSAndreas Gohr
885a285debSAndreas Gohr        return max($prevSize + $sizechange, 0);
895a285debSAndreas Gohr    }
905a285debSAndreas Gohr
915a285debSAndreas Gohr    /**
925a285debSAndreas Gohr     * Tell a real external edit from a mere mtime bump (touch, rsync --times, unzip of
935a285debSAndreas Gohr     * identical bytes, ...).
945a285debSAndreas Gohr     *
955a285debSAndreas Gohr     * The current media revision is never archived, so there is no stored copy to compare the
965a285debSAndreas Gohr     * current file against byte for byte. Its expected size is reconstructed instead (see
975a285debSAndreas Gohr     * lastRevisionSize()) and compared to the current file's size: a pure mtime bump leaves the
985a285debSAndreas Gohr     * size unchanged, so an equal size means the content did not change. A same-size external
995a285debSAndreas Gohr     * replacement cannot be told apart this way and is (rarely) treated as unchanged.
1005a285debSAndreas Gohr     *
1015a285debSAndreas Gohr     * @param int $rev revision timestamp to compare the current file against (the last revision)
1025a285debSAndreas 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();
1075a285debSAndreas Gohr        if (!file_exists($current)) return false;
1080a245329SAndreas Gohr
1095a285debSAndreas Gohr        return filesize($current) === $this->lastRevisionSize($rev);
1100a245329SAndreas Gohr    }
1110c3a5702SAndreas Gohr}
112