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