15cc1319aSAndreas Gohr<?php 25cc1319aSAndreas Gohr 35cc1319aSAndreas Gohrnamespace dokuwiki\plugin\statistics\test; 45cc1319aSAndreas Gohr 55cc1319aSAndreas Gohruse DokuWikiTest; 6696a1b1bSAndreas Gohruse dokuwiki\plugin\statistics\Logger; 7696a1b1bSAndreas Gohruse helper_plugin_statistics; 85cc1319aSAndreas Gohr 95cc1319aSAndreas Gohr/** 10696a1b1bSAndreas Gohr * Tests for the statistics plugin Logger class 115cc1319aSAndreas Gohr * 125cc1319aSAndreas Gohr * @group plugin_statistics 135cc1319aSAndreas Gohr * @group plugins 145cc1319aSAndreas Gohr */ 155cc1319aSAndreas Gohrclass LoggerTest extends DokuWikiTest 165cc1319aSAndreas Gohr{ 17de1daf8cSAndreas Gohr protected $pluginsEnabled = ['statistics', 'sqlite']; 18de1daf8cSAndreas Gohr 19696a1b1bSAndreas Gohr /** @var helper_plugin_statistics */ 20696a1b1bSAndreas Gohr protected $helper; 215cc1319aSAndreas Gohr 22696a1b1bSAndreas Gohr /** @var Logger */ 23696a1b1bSAndreas Gohr protected $logger; 24696a1b1bSAndreas Gohr 25696a1b1bSAndreas Gohr public function setUp(): void 26696a1b1bSAndreas Gohr { 27696a1b1bSAndreas Gohr parent::setUp(); 28696a1b1bSAndreas Gohr 29696a1b1bSAndreas Gohr // Load the helper plugin 30696a1b1bSAndreas Gohr $this->helper = plugin_load('helper', 'statistics'); 31696a1b1bSAndreas Gohr 32696a1b1bSAndreas Gohr // Mock user agent to avoid bot detection 33696a1b1bSAndreas Gohr $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'; 34696a1b1bSAndreas Gohr 35696a1b1bSAndreas Gohr // Initialize logger 36696a1b1bSAndreas Gohr $this->logger = new Logger($this->helper); 37696a1b1bSAndreas Gohr } 38696a1b1bSAndreas Gohr 39696a1b1bSAndreas Gohr public function tearDown(): void 40696a1b1bSAndreas Gohr { 41696a1b1bSAndreas Gohr unset($_SERVER['HTTP_USER_AGENT']); 42696a1b1bSAndreas Gohr parent::tearDown(); 43696a1b1bSAndreas Gohr } 44696a1b1bSAndreas Gohr 45696a1b1bSAndreas Gohr /** 46696a1b1bSAndreas Gohr * Test constructor initializes properties correctly 47696a1b1bSAndreas Gohr */ 48696a1b1bSAndreas Gohr public function testConstructor() 49696a1b1bSAndreas Gohr { 50696a1b1bSAndreas Gohr $this->assertInstanceOf(Logger::class, $this->logger); 51696a1b1bSAndreas Gohr 52696a1b1bSAndreas Gohr // Test that bot user agents throw exception 53696a1b1bSAndreas Gohr $_SERVER['HTTP_USER_AGENT'] = 'Googlebot/2.1 (+http://www.google.com/bot.html)'; 54696a1b1bSAndreas Gohr 55696a1b1bSAndreas Gohr $this->expectException(\RuntimeException::class); 56696a1b1bSAndreas Gohr $this->expectExceptionMessage('Bot detected, not logging'); 57696a1b1bSAndreas Gohr new Logger($this->helper); 58696a1b1bSAndreas Gohr } 59696a1b1bSAndreas Gohr 60696a1b1bSAndreas Gohr /** 61696a1b1bSAndreas Gohr * Test begin and end transaction methods 62696a1b1bSAndreas Gohr */ 63696a1b1bSAndreas Gohr public function testBeginEnd() 64696a1b1bSAndreas Gohr { 65696a1b1bSAndreas Gohr $this->logger->begin(); 66696a1b1bSAndreas Gohr 67696a1b1bSAndreas Gohr // Verify transaction is active by checking PDO 68696a1b1bSAndreas Gohr $pdo = $this->helper->getDB()->getPdo(); 69696a1b1bSAndreas Gohr $this->assertTrue($pdo->inTransaction()); 70696a1b1bSAndreas Gohr 71696a1b1bSAndreas Gohr $this->logger->end(); 72696a1b1bSAndreas Gohr 73696a1b1bSAndreas Gohr // Verify transaction is committed 74696a1b1bSAndreas Gohr $this->assertFalse($pdo->inTransaction()); 75696a1b1bSAndreas Gohr } 76696a1b1bSAndreas Gohr 77696a1b1bSAndreas Gohr /** 78696a1b1bSAndreas Gohr * Test logLastseen method 79696a1b1bSAndreas Gohr */ 80696a1b1bSAndreas Gohr public function testLogLastseen() 81696a1b1bSAndreas Gohr { 82696a1b1bSAndreas Gohr global $INPUT; 83696a1b1bSAndreas Gohr 84696a1b1bSAndreas Gohr // Test with no user (should not log) 85696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', ''); 86696a1b1bSAndreas Gohr $this->logger->logLastseen(); 87696a1b1bSAndreas Gohr 88696a1b1bSAndreas Gohr $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM lastseen'); 89696a1b1bSAndreas Gohr $this->assertEquals(0, $count); 90696a1b1bSAndreas Gohr 91696a1b1bSAndreas Gohr // Test with user 92696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', 'testuser'); 93696a1b1bSAndreas Gohr $this->logger->logLastseen(); 94696a1b1bSAndreas Gohr 95696a1b1bSAndreas Gohr $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM lastseen'); 96696a1b1bSAndreas Gohr $this->assertEquals(1, $count); 97696a1b1bSAndreas Gohr 98696a1b1bSAndreas Gohr $user = $this->helper->getDB()->queryValue('SELECT user FROM lastseen WHERE user = ?', ['testuser']); 99696a1b1bSAndreas Gohr $this->assertEquals('testuser', $user); 100696a1b1bSAndreas Gohr } 101696a1b1bSAndreas Gohr 102696a1b1bSAndreas Gohr /** 103696a1b1bSAndreas Gohr * Data provider for logGroups test 104696a1b1bSAndreas Gohr */ 105696a1b1bSAndreas Gohr public function logGroupsProvider() 106696a1b1bSAndreas Gohr { 107696a1b1bSAndreas Gohr return [ 108696a1b1bSAndreas Gohr 'empty groups' => [[], 'view', 0], 109696a1b1bSAndreas Gohr 'single group' => [['admin'], 'view', 1], 110696a1b1bSAndreas Gohr 'multiple groups' => [['admin', 'user'], 'edit', 2], 111696a1b1bSAndreas Gohr 'filtered groups' => [['admin', 'nonexistent'], 'view', 1], // assuming only 'admin' is configured 112696a1b1bSAndreas Gohr ]; 113696a1b1bSAndreas Gohr } 114696a1b1bSAndreas Gohr 115696a1b1bSAndreas Gohr /** 116696a1b1bSAndreas Gohr * Test logGroups method 117696a1b1bSAndreas Gohr * @dataProvider logGroupsProvider 118696a1b1bSAndreas Gohr */ 119696a1b1bSAndreas Gohr public function testLogGroups($groups, $type, $expectedCount) 120696a1b1bSAndreas Gohr { 121de1daf8cSAndreas Gohr global $conf; 122de1daf8cSAndreas Gohr $conf['plugin']['statistics']['loggroups'] = ['admin', 'user']; 123696a1b1bSAndreas Gohr 12423e0cc03SAndreas Gohr // Clear any existing data for this test 12523e0cc03SAndreas Gohr $this->helper->getDB()->exec('DELETE FROM groups WHERE type = ?', [$type]); 12623e0cc03SAndreas Gohr 127696a1b1bSAndreas Gohr $this->logger->logGroups($type, $groups); 128696a1b1bSAndreas Gohr 129696a1b1bSAndreas Gohr $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM groups WHERE type = ?', [$type]); 130696a1b1bSAndreas Gohr $this->assertEquals($expectedCount, $count); 131696a1b1bSAndreas Gohr 132696a1b1bSAndreas Gohr if ($expectedCount > 0) { 133696a1b1bSAndreas Gohr $loggedGroups = $this->helper->getDB()->queryAll('SELECT `group` FROM groups WHERE type = ?', [$type]); 134696a1b1bSAndreas Gohr $this->assertCount($expectedCount, $loggedGroups); 135696a1b1bSAndreas Gohr } 136696a1b1bSAndreas Gohr } 137696a1b1bSAndreas Gohr 138696a1b1bSAndreas Gohr /** 139696a1b1bSAndreas Gohr * Data provider for logExternalSearch test 140696a1b1bSAndreas Gohr */ 141696a1b1bSAndreas Gohr public function logExternalSearchProvider() 142696a1b1bSAndreas Gohr { 143696a1b1bSAndreas Gohr return [ 144696a1b1bSAndreas Gohr 'google search' => [ 145696a1b1bSAndreas Gohr 'https://www.google.com/search?q=dokuwiki+test', 146696a1b1bSAndreas Gohr 'search', 147696a1b1bSAndreas Gohr 'dokuwiki test', 148de1daf8cSAndreas Gohr 'google' 149696a1b1bSAndreas Gohr ], 150696a1b1bSAndreas Gohr 'non-search referer' => [ 151696a1b1bSAndreas Gohr 'https://example.com/page', 152696a1b1bSAndreas Gohr '', 153696a1b1bSAndreas Gohr null, 154696a1b1bSAndreas Gohr null 155696a1b1bSAndreas Gohr ], 156696a1b1bSAndreas Gohr ]; 157696a1b1bSAndreas Gohr } 158696a1b1bSAndreas Gohr 159696a1b1bSAndreas Gohr /** 160696a1b1bSAndreas Gohr * Test logExternalSearch method 161696a1b1bSAndreas Gohr * @dataProvider logExternalSearchProvider 162696a1b1bSAndreas Gohr */ 163696a1b1bSAndreas Gohr public function testLogExternalSearch($referer, $expectedType, $expectedQuery, $expectedEngine) 164696a1b1bSAndreas Gohr { 165696a1b1bSAndreas Gohr global $INPUT; 166696a1b1bSAndreas Gohr $INPUT->set('p', 'test:page'); 167696a1b1bSAndreas Gohr 168696a1b1bSAndreas Gohr $type = ''; 169696a1b1bSAndreas Gohr $this->logger->logExternalSearch($referer, $type); 170696a1b1bSAndreas Gohr 171696a1b1bSAndreas Gohr $this->assertEquals($expectedType, $type); 172696a1b1bSAndreas Gohr 173696a1b1bSAndreas Gohr if ($expectedType === 'search') { 174696a1b1bSAndreas Gohr $searchCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM search'); 175696a1b1bSAndreas Gohr $this->assertEquals(1, $searchCount); 176696a1b1bSAndreas Gohr 177696a1b1bSAndreas Gohr $search = $this->helper->getDB()->queryRecord('SELECT * FROM search ORDER BY dt DESC LIMIT 1'); 178696a1b1bSAndreas Gohr $this->assertEquals($expectedQuery, $search['query']); 179696a1b1bSAndreas Gohr $this->assertEquals($expectedEngine, $search['engine']); 180696a1b1bSAndreas Gohr } 181696a1b1bSAndreas Gohr } 182696a1b1bSAndreas Gohr 183696a1b1bSAndreas Gohr /** 184696a1b1bSAndreas Gohr * Test logSearch method 185696a1b1bSAndreas Gohr */ 186696a1b1bSAndreas Gohr public function testLogSearch() 187696a1b1bSAndreas Gohr { 188696a1b1bSAndreas Gohr $page = 'test:page'; 189696a1b1bSAndreas Gohr $query = 'test search query'; 190696a1b1bSAndreas Gohr $words = ['test', 'search', 'query']; 191696a1b1bSAndreas Gohr $engine = 'Google'; 192696a1b1bSAndreas Gohr 193696a1b1bSAndreas Gohr $this->logger->logSearch($page, $query, $words, $engine); 194696a1b1bSAndreas Gohr 195696a1b1bSAndreas Gohr // Check search table 196696a1b1bSAndreas Gohr $search = $this->helper->getDB()->queryRecord('SELECT * FROM search ORDER BY dt DESC LIMIT 1'); 197696a1b1bSAndreas Gohr $this->assertEquals($page, $search['page']); 198696a1b1bSAndreas Gohr $this->assertEquals($query, $search['query']); 199696a1b1bSAndreas Gohr $this->assertEquals($engine, $search['engine']); 200696a1b1bSAndreas Gohr 201696a1b1bSAndreas Gohr // Check searchwords table 202de1daf8cSAndreas Gohr $wordCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM searchwords WHERE sid = ?', [$search['id']]); 203696a1b1bSAndreas Gohr $this->assertEquals(3, $wordCount); 204696a1b1bSAndreas Gohr 205de1daf8cSAndreas Gohr $loggedWords = $this->helper->getDB()->queryAll('SELECT word FROM searchwords WHERE sid = ? ORDER BY word', [$search['id']]); 206696a1b1bSAndreas Gohr $this->assertEquals(['query', 'search', 'test'], array_column($loggedWords, 'word')); 207696a1b1bSAndreas Gohr } 208696a1b1bSAndreas Gohr 209696a1b1bSAndreas Gohr /** 210696a1b1bSAndreas Gohr * Test logSession method 211696a1b1bSAndreas Gohr */ 212696a1b1bSAndreas Gohr public function testLogSession() 213696a1b1bSAndreas Gohr { 214696a1b1bSAndreas Gohr // Test without adding view 215696a1b1bSAndreas Gohr $this->logger->logSession(0); 216696a1b1bSAndreas Gohr 217696a1b1bSAndreas Gohr $sessionCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM session'); 218696a1b1bSAndreas Gohr $this->assertEquals(1, $sessionCount); 219696a1b1bSAndreas Gohr 220696a1b1bSAndreas Gohr $session = $this->helper->getDB()->queryRecord('SELECT * FROM session ORDER BY dt DESC LIMIT 1'); 221696a1b1bSAndreas Gohr $this->assertEquals(0, $session['views']); 222696a1b1bSAndreas Gohr 223696a1b1bSAndreas Gohr // Test adding view 224696a1b1bSAndreas Gohr $this->logger->logSession(1); 225696a1b1bSAndreas Gohr 226696a1b1bSAndreas Gohr $session = $this->helper->getDB()->queryRecord('SELECT * FROM session ORDER BY dt DESC LIMIT 1'); 227696a1b1bSAndreas Gohr $this->assertEquals(1, $session['views']); 228696a1b1bSAndreas Gohr 229696a1b1bSAndreas Gohr // Test incrementing views 230696a1b1bSAndreas Gohr $this->logger->logSession(1); 231696a1b1bSAndreas Gohr 232696a1b1bSAndreas Gohr $session = $this->helper->getDB()->queryRecord('SELECT * FROM session ORDER BY dt DESC LIMIT 1'); 233696a1b1bSAndreas Gohr $this->assertEquals(2, $session['views']); 234696a1b1bSAndreas Gohr } 235696a1b1bSAndreas Gohr 236696a1b1bSAndreas Gohr /** 237696a1b1bSAndreas Gohr * Test logIp method 238696a1b1bSAndreas Gohr */ 239696a1b1bSAndreas Gohr public function testLogIp() 240696a1b1bSAndreas Gohr { 241696a1b1bSAndreas Gohr $ip = '8.8.8.8'; 242696a1b1bSAndreas Gohr 243c7cad24dSAndreas Gohr // Create a mock HTTP client 244c7cad24dSAndreas Gohr $mockHttpClient = $this->createMock(\dokuwiki\HTTP\DokuHTTPClient::class); 2456c24c4b8SAndreas Gohr 246c7cad24dSAndreas Gohr // Mock the API response 247c7cad24dSAndreas Gohr $mockResponse = json_encode([ 248c7cad24dSAndreas Gohr 'status' => 'success', 249c7cad24dSAndreas Gohr 'country' => 'United States', 250c7cad24dSAndreas Gohr 'countryCode' => 'US', 251c7cad24dSAndreas Gohr 'city' => 'Ashburn', 252c7cad24dSAndreas Gohr 'query' => $ip 253c7cad24dSAndreas Gohr ]); 2546c24c4b8SAndreas Gohr 255c7cad24dSAndreas Gohr $mockHttpClient->expects($this->once()) 256c7cad24dSAndreas Gohr ->method('get') 257c7cad24dSAndreas Gohr ->with('http://ip-api.com/json/' . $ip) 258c7cad24dSAndreas Gohr ->willReturn($mockResponse); 259696a1b1bSAndreas Gohr 260c7cad24dSAndreas Gohr // Set timeout property 261c7cad24dSAndreas Gohr $mockHttpClient->timeout = 10; 262c7cad24dSAndreas Gohr 263c7cad24dSAndreas Gohr // Create logger with mock HTTP client 264c7cad24dSAndreas Gohr $logger = new Logger($this->helper, $mockHttpClient); 265c7cad24dSAndreas Gohr 266c7cad24dSAndreas Gohr // Test with IP that doesn't exist in database 267c7cad24dSAndreas Gohr $logger->logIp($ip); 268c7cad24dSAndreas Gohr 269c7cad24dSAndreas Gohr // Verify the IP was logged 270c7cad24dSAndreas Gohr $ipRecord = $this->helper->getDB()->queryRecord('SELECT * FROM iplocation WHERE ip = ?', [$ip]); 271c7cad24dSAndreas Gohr $this->assertNotNull($ipRecord); 272c7cad24dSAndreas Gohr $this->assertEquals($ip, $ipRecord['ip']); 273c7cad24dSAndreas Gohr $this->assertEquals('United States', $ipRecord['country']); 274c7cad24dSAndreas Gohr $this->assertEquals('US', $ipRecord['code']); 275c7cad24dSAndreas Gohr $this->assertEquals('Ashburn', $ipRecord['city']); 276c7cad24dSAndreas Gohr $this->assertNotEmpty($ipRecord['host']); // gethostbyaddr result 277c7cad24dSAndreas Gohr 278c7cad24dSAndreas Gohr // Test with IP that already exists and is recent (should not make HTTP call) 279c7cad24dSAndreas Gohr $mockHttpClient2 = $this->createMock(\dokuwiki\HTTP\DokuHTTPClient::class); 280c7cad24dSAndreas Gohr $mockHttpClient2->expects($this->never())->method('get'); 281c7cad24dSAndreas Gohr 282c7cad24dSAndreas Gohr $logger2 = new Logger($this->helper, $mockHttpClient2); 283c7cad24dSAndreas Gohr $logger2->logIp($ip); // Should not trigger HTTP call 284696a1b1bSAndreas Gohr } 285696a1b1bSAndreas Gohr 286696a1b1bSAndreas Gohr /** 287696a1b1bSAndreas Gohr * Test logOutgoing method 288696a1b1bSAndreas Gohr */ 289696a1b1bSAndreas Gohr public function testLogOutgoing() 290696a1b1bSAndreas Gohr { 291696a1b1bSAndreas Gohr global $INPUT; 292696a1b1bSAndreas Gohr 293696a1b1bSAndreas Gohr // Test without outgoing link 294696a1b1bSAndreas Gohr $INPUT->set('ol', ''); 295696a1b1bSAndreas Gohr $this->logger->logOutgoing(); 296696a1b1bSAndreas Gohr 297696a1b1bSAndreas Gohr $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM outlinks'); 298696a1b1bSAndreas Gohr $this->assertEquals(0, $count); 299696a1b1bSAndreas Gohr 300696a1b1bSAndreas Gohr // Test with outgoing link 301696a1b1bSAndreas Gohr $link = 'https://example.com'; 302696a1b1bSAndreas Gohr $page = 'test:page'; 303696a1b1bSAndreas Gohr $INPUT->set('ol', $link); 304696a1b1bSAndreas Gohr $INPUT->set('p', $page); 305696a1b1bSAndreas Gohr 306696a1b1bSAndreas Gohr $this->logger->logOutgoing(); 307696a1b1bSAndreas Gohr 308696a1b1bSAndreas Gohr $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM outlinks'); 309696a1b1bSAndreas Gohr $this->assertEquals(1, $count); 310696a1b1bSAndreas Gohr 311696a1b1bSAndreas Gohr $outlink = $this->helper->getDB()->queryRecord('SELECT * FROM outlinks ORDER BY dt DESC LIMIT 1'); 312696a1b1bSAndreas Gohr $this->assertEquals($link, $outlink['link']); 313696a1b1bSAndreas Gohr $this->assertEquals(md5($link), $outlink['link_md5']); 314696a1b1bSAndreas Gohr $this->assertEquals($page, $outlink['page']); 315696a1b1bSAndreas Gohr } 316696a1b1bSAndreas Gohr 317696a1b1bSAndreas Gohr /** 318696a1b1bSAndreas Gohr * Test logAccess method 319696a1b1bSAndreas Gohr */ 320696a1b1bSAndreas Gohr public function testLogAccess() 321696a1b1bSAndreas Gohr { 322de1daf8cSAndreas Gohr global $INPUT, $USERINFO, $conf; 323de1daf8cSAndreas Gohr 324de1daf8cSAndreas Gohr $conf['plugin']['statistics']['loggroups'] = ['admin', 'user']; 325696a1b1bSAndreas Gohr 32623e0cc03SAndreas Gohr // Clear any existing data for this test 32723e0cc03SAndreas Gohr $this->helper->getDB()->exec('DELETE FROM groups WHERE type = ?', ['view']); 32823e0cc03SAndreas Gohr 329696a1b1bSAndreas Gohr $page = 'test:page'; 330696a1b1bSAndreas Gohr $referer = 'https://example.com'; 331696a1b1bSAndreas Gohr $user = 'testuser'; 332696a1b1bSAndreas Gohr 333696a1b1bSAndreas Gohr $INPUT->set('p', $page); 334696a1b1bSAndreas Gohr $INPUT->set('r', $referer); 335696a1b1bSAndreas Gohr $INPUT->set('sx', 1920); 336696a1b1bSAndreas Gohr $INPUT->set('sy', 1080); 337696a1b1bSAndreas Gohr $INPUT->set('vx', 1200); 338696a1b1bSAndreas Gohr $INPUT->set('vy', 800); 339696a1b1bSAndreas Gohr $INPUT->set('js', 1); 340696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', $user); 341696a1b1bSAndreas Gohr 342696a1b1bSAndreas Gohr $USERINFO = ['grps' => ['admin', 'user']]; 343696a1b1bSAndreas Gohr 344696a1b1bSAndreas Gohr $this->logger->logAccess(); 345696a1b1bSAndreas Gohr 346696a1b1bSAndreas Gohr // Check access table 347696a1b1bSAndreas Gohr $access = $this->helper->getDB()->queryRecord('SELECT * FROM access ORDER BY dt DESC LIMIT 1'); 348696a1b1bSAndreas Gohr $this->assertEquals($page, $access['page']); 349696a1b1bSAndreas Gohr $this->assertEquals($user, $access['user']); 350696a1b1bSAndreas Gohr $this->assertEquals(1920, $access['screen_x']); 351696a1b1bSAndreas Gohr $this->assertEquals(1080, $access['screen_y']); 352696a1b1bSAndreas Gohr $this->assertEquals(1200, $access['view_x']); 353696a1b1bSAndreas Gohr $this->assertEquals(800, $access['view_y']); 354696a1b1bSAndreas Gohr $this->assertEquals(1, $access['js']); 355696a1b1bSAndreas Gohr $this->assertEquals('external', $access['ref_type']); 356696a1b1bSAndreas Gohr 357696a1b1bSAndreas Gohr // Check refseen table 358696a1b1bSAndreas Gohr $refCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM refseen WHERE ref_md5 = ?', [md5($referer)]); 359696a1b1bSAndreas Gohr $this->assertEquals(1, $refCount); 360696a1b1bSAndreas Gohr 361696a1b1bSAndreas Gohr // Check groups table 362696a1b1bSAndreas Gohr $groupCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM groups WHERE type = ?', ['view']); 363696a1b1bSAndreas Gohr $this->assertEquals(2, $groupCount); 364696a1b1bSAndreas Gohr } 365696a1b1bSAndreas Gohr 366696a1b1bSAndreas Gohr /** 367696a1b1bSAndreas Gohr * Data provider for logMedia test 368696a1b1bSAndreas Gohr */ 369696a1b1bSAndreas Gohr public function logMediaProvider() 370696a1b1bSAndreas Gohr { 371696a1b1bSAndreas Gohr return [ 372696a1b1bSAndreas Gohr 'image inline' => ['test.jpg', 'image/jpeg', true, 1024], 373696a1b1bSAndreas Gohr 'video not inline' => ['test.mp4', 'video/mp4', false, 2048], 374696a1b1bSAndreas Gohr 'document' => ['test.pdf', 'application/pdf', false, 512], 375696a1b1bSAndreas Gohr ]; 376696a1b1bSAndreas Gohr } 377696a1b1bSAndreas Gohr 378696a1b1bSAndreas Gohr /** 379696a1b1bSAndreas Gohr * Test logMedia method 380696a1b1bSAndreas Gohr * @dataProvider logMediaProvider 381696a1b1bSAndreas Gohr */ 382696a1b1bSAndreas Gohr public function testLogMedia($media, $mime, $inline, $size) 383696a1b1bSAndreas Gohr { 384696a1b1bSAndreas Gohr global $INPUT; 385696a1b1bSAndreas Gohr 386696a1b1bSAndreas Gohr $user = 'testuser'; 387696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', $user); 388696a1b1bSAndreas Gohr 389696a1b1bSAndreas Gohr $this->logger->logMedia($media, $mime, $inline, $size); 390696a1b1bSAndreas Gohr 391696a1b1bSAndreas Gohr $mediaLog = $this->helper->getDB()->queryRecord('SELECT * FROM media ORDER BY dt DESC LIMIT 1'); 392696a1b1bSAndreas Gohr $this->assertEquals($media, $mediaLog['media']); 393696a1b1bSAndreas Gohr $this->assertEquals($user, $mediaLog['user']); 394696a1b1bSAndreas Gohr $this->assertEquals($size, $mediaLog['size']); 395696a1b1bSAndreas Gohr $this->assertEquals($inline ? 1 : 0, $mediaLog['inline']); 396696a1b1bSAndreas Gohr 397696a1b1bSAndreas Gohr [$mime1, $mime2] = explode('/', strtolower($mime)); 398696a1b1bSAndreas Gohr $this->assertEquals($mime1, $mediaLog['mime1']); 399696a1b1bSAndreas Gohr $this->assertEquals($mime2, $mediaLog['mime2']); 400696a1b1bSAndreas Gohr } 401696a1b1bSAndreas Gohr 402696a1b1bSAndreas Gohr /** 403696a1b1bSAndreas Gohr * Data provider for logEdit test 404696a1b1bSAndreas Gohr */ 405696a1b1bSAndreas Gohr public function logEditProvider() 406696a1b1bSAndreas Gohr { 407696a1b1bSAndreas Gohr return [ 408696a1b1bSAndreas Gohr 'create page' => ['new:page', 'create'], 409696a1b1bSAndreas Gohr 'edit page' => ['existing:page', 'edit'], 410696a1b1bSAndreas Gohr 'delete page' => ['old:page', 'delete'], 411696a1b1bSAndreas Gohr ]; 412696a1b1bSAndreas Gohr } 413696a1b1bSAndreas Gohr 414696a1b1bSAndreas Gohr /** 415696a1b1bSAndreas Gohr * Test logEdit method 416696a1b1bSAndreas Gohr * @dataProvider logEditProvider 417696a1b1bSAndreas Gohr */ 418696a1b1bSAndreas Gohr public function testLogEdit($page, $type) 419696a1b1bSAndreas Gohr { 420de1daf8cSAndreas Gohr global $INPUT, $USERINFO, $conf; 421de1daf8cSAndreas Gohr 422de1daf8cSAndreas Gohr $conf['plugin']['statistics']['loggroups'] = ['admin']; 423696a1b1bSAndreas Gohr 42423e0cc03SAndreas Gohr // Clear any existing data for this test 42523e0cc03SAndreas Gohr $this->helper->getDB()->exec('DELETE FROM groups WHERE type = ?', ['edit']); 42623e0cc03SAndreas Gohr 427696a1b1bSAndreas Gohr $user = 'testuser'; 428696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', $user); 429696a1b1bSAndreas Gohr $USERINFO = ['grps' => ['admin']]; 430696a1b1bSAndreas Gohr 431696a1b1bSAndreas Gohr $this->logger->logEdit($page, $type); 432696a1b1bSAndreas Gohr 433696a1b1bSAndreas Gohr // Check edits table 434696a1b1bSAndreas Gohr $edit = $this->helper->getDB()->queryRecord('SELECT * FROM edits ORDER BY dt DESC LIMIT 1'); 435696a1b1bSAndreas Gohr $this->assertEquals($page, $edit['page']); 436696a1b1bSAndreas Gohr $this->assertEquals($type, $edit['type']); 437696a1b1bSAndreas Gohr $this->assertEquals($user, $edit['user']); 438696a1b1bSAndreas Gohr 439696a1b1bSAndreas Gohr // Check groups table 440696a1b1bSAndreas Gohr $groupCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM groups WHERE type = ?', ['edit']); 441696a1b1bSAndreas Gohr $this->assertEquals(1, $groupCount); 442696a1b1bSAndreas Gohr } 443696a1b1bSAndreas Gohr 444696a1b1bSAndreas Gohr /** 445696a1b1bSAndreas Gohr * Data provider for logLogin test 446696a1b1bSAndreas Gohr */ 447696a1b1bSAndreas Gohr public function logLoginProvider() 448696a1b1bSAndreas Gohr { 449696a1b1bSAndreas Gohr return [ 450696a1b1bSAndreas Gohr 'login' => ['login', 'testuser'], 451696a1b1bSAndreas Gohr 'logout' => ['logout', 'testuser'], 452696a1b1bSAndreas Gohr 'create' => ['create', 'newuser'], 453696a1b1bSAndreas Gohr ]; 454696a1b1bSAndreas Gohr } 455696a1b1bSAndreas Gohr 456696a1b1bSAndreas Gohr /** 457696a1b1bSAndreas Gohr * Test logLogin method 458696a1b1bSAndreas Gohr * @dataProvider logLoginProvider 459696a1b1bSAndreas Gohr */ 460696a1b1bSAndreas Gohr public function testLogLogin($type, $user) 461696a1b1bSAndreas Gohr { 462696a1b1bSAndreas Gohr global $INPUT; 463696a1b1bSAndreas Gohr 464696a1b1bSAndreas Gohr if ($user === 'testuser') { 465696a1b1bSAndreas Gohr $INPUT->server->set('REMOTE_USER', $user); 466696a1b1bSAndreas Gohr $this->logger->logLogin($type); 467696a1b1bSAndreas Gohr } else { 468696a1b1bSAndreas Gohr $this->logger->logLogin($type, $user); 469696a1b1bSAndreas Gohr } 470696a1b1bSAndreas Gohr 471696a1b1bSAndreas Gohr $login = $this->helper->getDB()->queryRecord('SELECT * FROM logins ORDER BY dt DESC LIMIT 1'); 472696a1b1bSAndreas Gohr $this->assertEquals($type, $login['type']); 473696a1b1bSAndreas Gohr $this->assertEquals($user, $login['user']); 474696a1b1bSAndreas Gohr } 475696a1b1bSAndreas Gohr 476696a1b1bSAndreas Gohr /** 477696a1b1bSAndreas Gohr * Test logHistoryPages method 478696a1b1bSAndreas Gohr */ 479696a1b1bSAndreas Gohr public function testLogHistoryPages() 480696a1b1bSAndreas Gohr { 481696a1b1bSAndreas Gohr $this->logger->logHistoryPages(); 482696a1b1bSAndreas Gohr 483696a1b1bSAndreas Gohr // Check that both page_count and page_size entries were created 484696a1b1bSAndreas Gohr $pageCount = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['page_count']); 485696a1b1bSAndreas Gohr $pageSize = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['page_size']); 486696a1b1bSAndreas Gohr 487696a1b1bSAndreas Gohr $this->assertIsNumeric($pageCount); 488696a1b1bSAndreas Gohr $this->assertIsNumeric($pageSize); 489696a1b1bSAndreas Gohr $this->assertGreaterThanOrEqual(0, $pageCount); 490696a1b1bSAndreas Gohr $this->assertGreaterThanOrEqual(0, $pageSize); 491696a1b1bSAndreas Gohr } 492696a1b1bSAndreas Gohr 493696a1b1bSAndreas Gohr /** 494696a1b1bSAndreas Gohr * Test logHistoryMedia method 495696a1b1bSAndreas Gohr */ 496696a1b1bSAndreas Gohr public function testLogHistoryMedia() 497696a1b1bSAndreas Gohr { 498696a1b1bSAndreas Gohr $this->logger->logHistoryMedia(); 499696a1b1bSAndreas Gohr 500696a1b1bSAndreas Gohr // Check that both media_count and media_size entries were created 501696a1b1bSAndreas Gohr $mediaCount = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['media_count']); 502696a1b1bSAndreas Gohr $mediaSize = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['media_size']); 503696a1b1bSAndreas Gohr 504696a1b1bSAndreas Gohr $this->assertIsNumeric($mediaCount); 505696a1b1bSAndreas Gohr $this->assertIsNumeric($mediaSize); 506696a1b1bSAndreas Gohr $this->assertGreaterThanOrEqual(0, $mediaCount); 507696a1b1bSAndreas Gohr $this->assertGreaterThanOrEqual(0, $mediaSize); 508696a1b1bSAndreas Gohr } 509696a1b1bSAndreas Gohr 510696a1b1bSAndreas Gohr /** 511696a1b1bSAndreas Gohr * Test that feedreader user agents are handled correctly 512696a1b1bSAndreas Gohr */ 513696a1b1bSAndreas Gohr public function testFeedReaderUserAgent() 514696a1b1bSAndreas Gohr { 515*00f786d8SAndreas Gohr // Use a user agent that DeviceDetector recognizes as a feedreader 516*00f786d8SAndreas Gohr $_SERVER['HTTP_USER_AGENT'] = 'BashPodder/1.0 (http://bashpodder.sourceforge.net/)'; 517696a1b1bSAndreas Gohr 518696a1b1bSAndreas Gohr $logger = new Logger($this->helper); 519696a1b1bSAndreas Gohr 520696a1b1bSAndreas Gohr // Use reflection to access protected property 521696a1b1bSAndreas Gohr $reflection = new \ReflectionClass($logger); 522696a1b1bSAndreas Gohr $uaTypeProperty = $reflection->getProperty('uaType'); 523696a1b1bSAndreas Gohr $uaTypeProperty->setAccessible(true); 524696a1b1bSAndreas Gohr 525696a1b1bSAndreas Gohr $this->assertEquals('feedreader', $uaTypeProperty->getValue($logger)); 526696a1b1bSAndreas Gohr } 527696a1b1bSAndreas Gohr 528696a1b1bSAndreas Gohr /** 529696a1b1bSAndreas Gohr * Test session logging only works for browser type 530696a1b1bSAndreas Gohr */ 531696a1b1bSAndreas Gohr public function testLogSessionOnlyForBrowser() 532696a1b1bSAndreas Gohr { 53323e0cc03SAndreas Gohr // Clear any existing session data 53423e0cc03SAndreas Gohr $this->helper->getDB()->exec('DELETE FROM session'); 53523e0cc03SAndreas Gohr 536696a1b1bSAndreas Gohr // Change user agent type to feedreader using reflection 537696a1b1bSAndreas Gohr $reflection = new \ReflectionClass($this->logger); 538696a1b1bSAndreas Gohr $uaTypeProperty = $reflection->getProperty('uaType'); 539696a1b1bSAndreas Gohr $uaTypeProperty->setAccessible(true); 540696a1b1bSAndreas Gohr $uaTypeProperty->setValue($this->logger, 'feedreader'); 541696a1b1bSAndreas Gohr 542696a1b1bSAndreas Gohr $this->logger->logSession(1); 543696a1b1bSAndreas Gohr 544696a1b1bSAndreas Gohr $sessionCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM session'); 545696a1b1bSAndreas Gohr $this->assertEquals(0, $sessionCount); 5465cc1319aSAndreas Gohr } 5475cc1319aSAndreas Gohr} 548