12bde879aSAndreas Gohr<?php 22bde879aSAndreas Gohr 32bde879aSAndreas Gohrnamespace dokuwiki\test\ChangeLog; 42bde879aSAndreas Gohr 52bde879aSAndreas Gohruse dokuwiki\ChangeLog\PageChangeLog; 62bde879aSAndreas Gohr 72bde879aSAndreas Gohr/** 82bde879aSAndreas Gohr * Tests for dokuwiki\ChangeLog\PageChangeLog. 92bde879aSAndreas Gohr */ 102bde879aSAndreas Gohrclass PageChangeLogTest extends \DokuWikiTest 112bde879aSAndreas Gohr{ 122bde879aSAndreas Gohr /** 132bde879aSAndreas Gohr * A page deleted through DokuWiki is recorded as its own revision, newer than the 142bde879aSAndreas Gohr * last revision that still had content. getRelativeRevision() must walk back from 152bde879aSAndreas Gohr * that deletion entry to the last content revision (issue #4635). 162bde879aSAndreas Gohr */ 172bde879aSAndreas Gohr public function testRevisionBeforeNormalDeletion() 182bde879aSAndreas Gohr { 192bde879aSAndreas Gohr $page = 'changelog_deleted'; 202bde879aSAndreas Gohr saveWikiText($page, 'first content', 'create', false); 212bde879aSAndreas Gohr $this->waitForTick(true); 222bde879aSAndreas Gohr saveWikiText($page, 'second content longer', 'edit', false); 232bde879aSAndreas Gohr $this->waitForTick(true); 242bde879aSAndreas Gohr 252bde879aSAndreas Gohr $editRev = (new PageChangeLog($page))->currentRevision(); 262bde879aSAndreas Gohr 272bde879aSAndreas Gohr saveWikiText($page, '', 'delete', false); 282bde879aSAndreas Gohr clearstatcache(); 292bde879aSAndreas Gohr 302bde879aSAndreas Gohr $changelog = new PageChangeLog($page); 312bde879aSAndreas Gohr $delRev = $changelog->currentRevision(); 322bde879aSAndreas Gohr 332bde879aSAndreas Gohr $this->assertNotEquals($editRev, $delRev, 'deletion should get its own revision'); 342bde879aSAndreas Gohr $this->assertEquals( 352bde879aSAndreas Gohr DOKU_CHANGE_TYPE_DELETE, 362bde879aSAndreas Gohr $changelog->getRevisionInfo($delRev)['type'], 372bde879aSAndreas Gohr 'current revision should be the deletion' 382bde879aSAndreas Gohr ); 392bde879aSAndreas Gohr $this->assertEquals( 402bde879aSAndreas Gohr $editRev, 412bde879aSAndreas Gohr $changelog->getRelativeRevision($delRev, -1), 422bde879aSAndreas Gohr 'the revision before the deletion should be the last edit' 432bde879aSAndreas Gohr ); 442bde879aSAndreas Gohr } 452bde879aSAndreas Gohr 462bde879aSAndreas Gohr /** 472bde879aSAndreas Gohr * An external deletion is detected and persisted on first read as its own revision 482bde879aSAndreas Gohr * with an unknown exact date, newer than the last content revision. 492bde879aSAndreas Gohr * getRelativeRevision() must walk back from it to that last content revision 502bde879aSAndreas Gohr * (issue #4635). 512bde879aSAndreas Gohr */ 522bde879aSAndreas Gohr public function testRevisionBeforeExternalDeletion() 532bde879aSAndreas Gohr { 542bde879aSAndreas Gohr $page = 'changelog_extdeleted'; 552bde879aSAndreas Gohr saveWikiText($page, 'first content', 'create', false); 562bde879aSAndreas Gohr $this->waitForTick(true); 572bde879aSAndreas Gohr saveWikiText($page, 'second content longer', 'edit', false); 582bde879aSAndreas Gohr $this->waitForTick(true); 592bde879aSAndreas Gohr 602bde879aSAndreas Gohr $editRev = (new PageChangeLog($page))->currentRevision(); 612bde879aSAndreas Gohr 622bde879aSAndreas Gohr // delete the page file externally, bypassing DokuWiki 632bde879aSAndreas Gohr unlink(wikiFN($page)); 642bde879aSAndreas Gohr clearstatcache(); 652bde879aSAndreas Gohr 662bde879aSAndreas Gohr // first read detects and persists the external deletion 672bde879aSAndreas Gohr $changelog = new PageChangeLog($page); 682bde879aSAndreas Gohr $delRev = $changelog->currentRevision(); 692bde879aSAndreas Gohr $delInfo = $changelog->getRevisionInfo($delRev); 702bde879aSAndreas Gohr 712bde879aSAndreas Gohr $this->assertNotEquals($editRev, $delRev, 'external deletion should get its own revision'); 722bde879aSAndreas Gohr $this->assertEquals(DOKU_CHANGE_TYPE_DELETE, $delInfo['type'], 'current revision should be the deletion'); 732bde879aSAndreas Gohr $this->assertFalse($delInfo['timestamp'], 'external deletion has an unknown exact date'); 742bde879aSAndreas Gohr $this->assertEquals( 752bde879aSAndreas Gohr $editRev, 762bde879aSAndreas Gohr $changelog->getRelativeRevision($delRev, -1), 772bde879aSAndreas Gohr 'the revision before the external deletion should be the last edit' 782bde879aSAndreas Gohr ); 792bde879aSAndreas Gohr } 80*0a245329SAndreas Gohr 81*0a245329SAndreas Gohr /** 82*0a245329SAndreas Gohr * A current revision's file can have its modification time bumped without any content 83*0a245329SAndreas Gohr * change (a backup restore, a git checkout, ...). That must not be recorded as an 84*0a245329SAndreas Gohr * external edit: the content is compared against the last revision and, when identical, 85*0a245329SAndreas Gohr * the file mtime is reset to the recorded revision date instead (issue #4634). 86*0a245329SAndreas Gohr */ 87*0a245329SAndreas Gohr public function testTouchedFileWithUnchangedContentIsNotExternalEdit() 88*0a245329SAndreas Gohr { 89*0a245329SAndreas Gohr $page = 'changelog_touched'; 90*0a245329SAndreas Gohr saveWikiText($page, 'first content', 'create', false); 91*0a245329SAndreas Gohr 92*0a245329SAndreas Gohr $changelog = new PageChangeLog($page); 93*0a245329SAndreas Gohr $lastRev = $changelog->currentRevision(); 94*0a245329SAndreas Gohr 95*0a245329SAndreas Gohr // bump the file mtime forward without changing the content 96*0a245329SAndreas Gohr touch(wikiFN($page), $lastRev + 1000); 97*0a245329SAndreas Gohr clearstatcache(); 98*0a245329SAndreas Gohr 99*0a245329SAndreas Gohr $changelog = new PageChangeLog($page); 100*0a245329SAndreas Gohr $currentRev = $changelog->currentRevision(); 101*0a245329SAndreas Gohr $currentInfo = $changelog->getRevisionInfo($currentRev); 102*0a245329SAndreas Gohr 103*0a245329SAndreas Gohr $this->assertEquals($lastRev, $currentRev, 'unchanged content must not create an external revision'); 104*0a245329SAndreas Gohr $this->assertArrayNotHasKey('timestamp', $currentInfo, 'should not be a synthesized external edit'); 105*0a245329SAndreas Gohr $this->assertCount(1, $changelog->getRevisions(-1, 200), 'no external edit entry should be added'); 106*0a245329SAndreas Gohr 107*0a245329SAndreas Gohr clearstatcache(); 108*0a245329SAndreas Gohr $this->assertEquals($lastRev, filemtime(wikiFN($page)), 'file mtime should be reset to the changelog date'); 109*0a245329SAndreas Gohr } 1102bde879aSAndreas Gohr} 111