1*40a07da2SAndreas Gohr<?php 2*40a07da2SAndreas Gohr 3*40a07da2SAndreas Gohrnamespace dokuwiki\plugin\dw2pdf\test; 4*40a07da2SAndreas Gohr 5*40a07da2SAndreas Gohruse dokuwiki\plugin\dw2pdf\src\BookCreatorLiveSelectionCollector; 6*40a07da2SAndreas Gohruse dokuwiki\plugin\dw2pdf\src\Cache; 7*40a07da2SAndreas Gohruse dokuwiki\plugin\dw2pdf\src\Config; 8*40a07da2SAndreas Gohruse dokuwiki\plugin\dw2pdf\src\ExportException; 9*40a07da2SAndreas Gohruse dokuwiki\plugin\dw2pdf\src\PdfExportService; 10*40a07da2SAndreas Gohruse dokuwiki\test\mock\AuthPlugin; 11*40a07da2SAndreas Gohruse DokuWikiTest; 12*40a07da2SAndreas Gohr 13*40a07da2SAndreas Gohr/** 14*40a07da2SAndreas Gohr * Tests the feedback given when an export yields no usable pages 15*40a07da2SAndreas Gohr * 16*40a07da2SAndreas Gohr * @group plugin_dw2pdf 17*40a07da2SAndreas Gohr * @group plugins 18*40a07da2SAndreas Gohr */ 19*40a07da2SAndreas Gohrclass ExportFeedbackTest extends DokuWikiTest 20*40a07da2SAndreas Gohr{ 21*40a07da2SAndreas Gohr /** @var string[] Plugins to enable for these tests */ 22*40a07da2SAndreas Gohr protected $pluginsEnabled = ['dw2pdf']; 23*40a07da2SAndreas Gohr 24*40a07da2SAndreas Gohr /** @var array|null Saved ACL rules to restore after each test */ 25*40a07da2SAndreas Gohr protected $oldAuthAcl; 26*40a07da2SAndreas Gohr 27*40a07da2SAndreas Gohr public function setUp(): void 28*40a07da2SAndreas Gohr { 29*40a07da2SAndreas Gohr parent::setUp(); 30*40a07da2SAndreas Gohr $_REQUEST = []; 31*40a07da2SAndreas Gohr 32*40a07da2SAndreas Gohr global $AUTH_ACL, $auth; 33*40a07da2SAndreas Gohr $this->oldAuthAcl = $AUTH_ACL; 34*40a07da2SAndreas Gohr $auth = new AuthPlugin(); 35*40a07da2SAndreas Gohr } 36*40a07da2SAndreas Gohr 37*40a07da2SAndreas Gohr public function tearDown(): void 38*40a07da2SAndreas Gohr { 39*40a07da2SAndreas Gohr global $AUTH_ACL; 40*40a07da2SAndreas Gohr $AUTH_ACL = $this->oldAuthAcl; 41*40a07da2SAndreas Gohr parent::tearDown(); 42*40a07da2SAndreas Gohr } 43*40a07da2SAndreas Gohr 44*40a07da2SAndreas Gohr /** 45*40a07da2SAndreas Gohr * Deny read access to everybody 46*40a07da2SAndreas Gohr */ 47*40a07da2SAndreas Gohr protected function denyAll(): void 48*40a07da2SAndreas Gohr { 49*40a07da2SAndreas Gohr global $conf, $AUTH_ACL; 50*40a07da2SAndreas Gohr $conf['useacl'] = 1; 51*40a07da2SAndreas Gohr $AUTH_ACL = ['* @ALL 0']; 52*40a07da2SAndreas Gohr } 53*40a07da2SAndreas Gohr 54*40a07da2SAndreas Gohr /** 55*40a07da2SAndreas Gohr * When every selected page is unreadable, they are dropped from the export but remembered. 56*40a07da2SAndreas Gohr */ 57*40a07da2SAndreas Gohr public function testForbiddenPagesArePartitioned(): void 58*40a07da2SAndreas Gohr { 59*40a07da2SAndreas Gohr global $INPUT; 60*40a07da2SAndreas Gohr $pageA = 'playground:secret:a'; 61*40a07da2SAndreas Gohr $pageB = 'playground:secret:b'; 62*40a07da2SAndreas Gohr saveWikiText($pageA, 'A', 'create'); 63*40a07da2SAndreas Gohr saveWikiText($pageB, 'B', 'create'); 64*40a07da2SAndreas Gohr 65*40a07da2SAndreas Gohr $this->denyAll(); 66*40a07da2SAndreas Gohr $INPUT->set('selection', json_encode([$pageA, $pageB])); 67*40a07da2SAndreas Gohr 68*40a07da2SAndreas Gohr $collector = new BookCreatorLiveSelectionCollector(new Config()); 69*40a07da2SAndreas Gohr $this->assertSame([], $collector->getPages()); 70*40a07da2SAndreas Gohr $this->assertSame([$pageA, $pageB], $collector->getSkippedPages()); 71*40a07da2SAndreas Gohr } 72*40a07da2SAndreas Gohr 73*40a07da2SAndreas Gohr /** 74*40a07da2SAndreas Gohr * Readable pages are kept while forbidden ones are skipped (always-skip behavior). 75*40a07da2SAndreas Gohr */ 76*40a07da2SAndreas Gohr public function testMixedAccessKeepsReadablePages(): void 77*40a07da2SAndreas Gohr { 78*40a07da2SAndreas Gohr global $INPUT, $conf, $AUTH_ACL; 79*40a07da2SAndreas Gohr $readable = 'playground:public:a'; 80*40a07da2SAndreas Gohr $secret = 'playground:secret:b'; 81*40a07da2SAndreas Gohr saveWikiText($readable, 'A', 'create'); 82*40a07da2SAndreas Gohr saveWikiText($secret, 'B', 'create'); 83*40a07da2SAndreas Gohr 84*40a07da2SAndreas Gohr $conf['useacl'] = 1; 85*40a07da2SAndreas Gohr $AUTH_ACL = [ 86*40a07da2SAndreas Gohr '* @ALL 8', 87*40a07da2SAndreas Gohr 'playground:secret:* @ALL 0', 88*40a07da2SAndreas Gohr ]; 89*40a07da2SAndreas Gohr $INPUT->set('selection', json_encode([$readable, $secret])); 90*40a07da2SAndreas Gohr 91*40a07da2SAndreas Gohr $collector = new BookCreatorLiveSelectionCollector(new Config()); 92*40a07da2SAndreas Gohr $this->assertSame([$readable], $collector->getPages()); 93*40a07da2SAndreas Gohr $this->assertSame([$secret], $collector->getSkippedPages()); 94*40a07da2SAndreas Gohr } 95*40a07da2SAndreas Gohr 96*40a07da2SAndreas Gohr /** 97*40a07da2SAndreas Gohr * An export where every page is forbidden reports only how many pages were skipped. 98*40a07da2SAndreas Gohr */ 99*40a07da2SAndreas Gohr public function testServiceThrowsForbiddenWhenAllSkipped(): void 100*40a07da2SAndreas Gohr { 101*40a07da2SAndreas Gohr $pageA = 'playground:secret:a'; 102*40a07da2SAndreas Gohr saveWikiText($pageA, 'A', 'create'); 103*40a07da2SAndreas Gohr $this->denyAll(); 104*40a07da2SAndreas Gohr 105*40a07da2SAndreas Gohr $service = $this->makeService([$pageA]); 106*40a07da2SAndreas Gohr 107*40a07da2SAndreas Gohr try { 108*40a07da2SAndreas Gohr $service->getDebugHtml(); 109*40a07da2SAndreas Gohr $this->fail('Expected ExportException was not thrown'); 110*40a07da2SAndreas Gohr } catch (ExportException $e) { 111*40a07da2SAndreas Gohr $this->assertSame('forbidden', $e->getMessage()); 112*40a07da2SAndreas Gohr $this->assertSame([], $e->getArgs(), 'No details about the skipped pages should be exposed'); 113*40a07da2SAndreas Gohr } 114*40a07da2SAndreas Gohr } 115*40a07da2SAndreas Gohr 116*40a07da2SAndreas Gohr /** 117*40a07da2SAndreas Gohr * An export with no selection at all reports an empty selection. 118*40a07da2SAndreas Gohr */ 119*40a07da2SAndreas Gohr public function testServiceThrowsEmptyWhenNothingSelected(): void 120*40a07da2SAndreas Gohr { 121*40a07da2SAndreas Gohr $service = $this->makeService([]); 122*40a07da2SAndreas Gohr 123*40a07da2SAndreas Gohr $this->expectException(ExportException::class); 124*40a07da2SAndreas Gohr $this->expectExceptionMessage('empty'); 125*40a07da2SAndreas Gohr $service->getDebugHtml(); 126*40a07da2SAndreas Gohr } 127*40a07da2SAndreas Gohr 128*40a07da2SAndreas Gohr /** 129*40a07da2SAndreas Gohr * Build a debug PdfExportService for a live book selection. 130*40a07da2SAndreas Gohr * 131*40a07da2SAndreas Gohr * @param string[] $selection Page ids to export 132*40a07da2SAndreas Gohr * @return PdfExportService 133*40a07da2SAndreas Gohr */ 134*40a07da2SAndreas Gohr protected function makeService(array $selection): PdfExportService 135*40a07da2SAndreas Gohr { 136*40a07da2SAndreas Gohr $config = new Config(['debug' => 1, 'liveselection' => json_encode($selection)]); 137*40a07da2SAndreas Gohr $collector = new BookCreatorLiveSelectionCollector($config); 138*40a07da2SAndreas Gohr $cache = new Cache($config, $collector); 139*40a07da2SAndreas Gohr return new PdfExportService($config, $collector, $cache, 'Contents', 'tester'); 140*40a07da2SAndreas Gohr } 141*40a07da2SAndreas Gohr} 142