xref: /plugin/statistics/_test/LoggerTest.php (revision 6c24c4b8dd25d3ef57de662c18fb744bbc6078b2)
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
243*6c24c4b8SAndreas Gohr        // Mock HTTP client response using this result:
244*6c24c4b8SAndreas Gohr        // {"status":"success","country":"United States","countryCode":"US","region":"VA","regionName":"Virginia","city":"Ashburn","zip":"20149","lat":39.03,"lon":-77.5,"timezone":"America/New_York","isp":"Google LLC","org":"Google Public DNS","as":"AS15169 Google LLC","query":"8.8.8.8"}
245*6c24c4b8SAndreas Gohr
246*6c24c4b8SAndreas Gohr
247696a1b1bSAndreas Gohr        $this->markTestSkipped('Requires mocking HTTP client for external API call');
248696a1b1bSAndreas Gohr
249696a1b1bSAndreas Gohr        // This test would need to mock the DokuHTTPClient to avoid actual API calls
250696a1b1bSAndreas Gohr        // For now, we'll skip it as the requirement was not to mock anything
251696a1b1bSAndreas Gohr    }
252696a1b1bSAndreas Gohr
253696a1b1bSAndreas Gohr    /**
254696a1b1bSAndreas Gohr     * Test logOutgoing method
255696a1b1bSAndreas Gohr     */
256696a1b1bSAndreas Gohr    public function testLogOutgoing()
257696a1b1bSAndreas Gohr    {
258696a1b1bSAndreas Gohr        global $INPUT;
259696a1b1bSAndreas Gohr
260696a1b1bSAndreas Gohr        // Test without outgoing link
261696a1b1bSAndreas Gohr        $INPUT->set('ol', '');
262696a1b1bSAndreas Gohr        $this->logger->logOutgoing();
263696a1b1bSAndreas Gohr
264696a1b1bSAndreas Gohr        $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM outlinks');
265696a1b1bSAndreas Gohr        $this->assertEquals(0, $count);
266696a1b1bSAndreas Gohr
267696a1b1bSAndreas Gohr        // Test with outgoing link
268696a1b1bSAndreas Gohr        $link = 'https://example.com';
269696a1b1bSAndreas Gohr        $page = 'test:page';
270696a1b1bSAndreas Gohr        $INPUT->set('ol', $link);
271696a1b1bSAndreas Gohr        $INPUT->set('p', $page);
272696a1b1bSAndreas Gohr
273696a1b1bSAndreas Gohr        $this->logger->logOutgoing();
274696a1b1bSAndreas Gohr
275696a1b1bSAndreas Gohr        $count = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM outlinks');
276696a1b1bSAndreas Gohr        $this->assertEquals(1, $count);
277696a1b1bSAndreas Gohr
278696a1b1bSAndreas Gohr        $outlink = $this->helper->getDB()->queryRecord('SELECT * FROM outlinks ORDER BY dt DESC LIMIT 1');
279696a1b1bSAndreas Gohr        $this->assertEquals($link, $outlink['link']);
280696a1b1bSAndreas Gohr        $this->assertEquals(md5($link), $outlink['link_md5']);
281696a1b1bSAndreas Gohr        $this->assertEquals($page, $outlink['page']);
282696a1b1bSAndreas Gohr    }
283696a1b1bSAndreas Gohr
284696a1b1bSAndreas Gohr    /**
285696a1b1bSAndreas Gohr     * Test logAccess method
286696a1b1bSAndreas Gohr     */
287696a1b1bSAndreas Gohr    public function testLogAccess()
288696a1b1bSAndreas Gohr    {
289de1daf8cSAndreas Gohr        global $INPUT, $USERINFO, $conf;
290de1daf8cSAndreas Gohr
291de1daf8cSAndreas Gohr        $conf['plugin']['statistics']['loggroups'] = ['admin', 'user'];
292696a1b1bSAndreas Gohr
29323e0cc03SAndreas Gohr        // Clear any existing data for this test
29423e0cc03SAndreas Gohr        $this->helper->getDB()->exec('DELETE FROM groups WHERE type = ?', ['view']);
29523e0cc03SAndreas Gohr
296696a1b1bSAndreas Gohr        $page = 'test:page';
297696a1b1bSAndreas Gohr        $referer = 'https://example.com';
298696a1b1bSAndreas Gohr        $user = 'testuser';
299696a1b1bSAndreas Gohr
300696a1b1bSAndreas Gohr        $INPUT->set('p', $page);
301696a1b1bSAndreas Gohr        $INPUT->set('r', $referer);
302696a1b1bSAndreas Gohr        $INPUT->set('sx', 1920);
303696a1b1bSAndreas Gohr        $INPUT->set('sy', 1080);
304696a1b1bSAndreas Gohr        $INPUT->set('vx', 1200);
305696a1b1bSAndreas Gohr        $INPUT->set('vy', 800);
306696a1b1bSAndreas Gohr        $INPUT->set('js', 1);
307696a1b1bSAndreas Gohr        $INPUT->server->set('REMOTE_USER', $user);
308696a1b1bSAndreas Gohr
309696a1b1bSAndreas Gohr        $USERINFO = ['grps' => ['admin', 'user']];
310696a1b1bSAndreas Gohr
311696a1b1bSAndreas Gohr        $this->logger->logAccess();
312696a1b1bSAndreas Gohr
313696a1b1bSAndreas Gohr        // Check access table
314696a1b1bSAndreas Gohr        $access = $this->helper->getDB()->queryRecord('SELECT * FROM access ORDER BY dt DESC LIMIT 1');
315696a1b1bSAndreas Gohr        $this->assertEquals($page, $access['page']);
316696a1b1bSAndreas Gohr        $this->assertEquals($user, $access['user']);
317696a1b1bSAndreas Gohr        $this->assertEquals(1920, $access['screen_x']);
318696a1b1bSAndreas Gohr        $this->assertEquals(1080, $access['screen_y']);
319696a1b1bSAndreas Gohr        $this->assertEquals(1200, $access['view_x']);
320696a1b1bSAndreas Gohr        $this->assertEquals(800, $access['view_y']);
321696a1b1bSAndreas Gohr        $this->assertEquals(1, $access['js']);
322696a1b1bSAndreas Gohr        $this->assertEquals('external', $access['ref_type']);
323696a1b1bSAndreas Gohr
324696a1b1bSAndreas Gohr        // Check refseen table
325696a1b1bSAndreas Gohr        $refCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM refseen WHERE ref_md5 = ?', [md5($referer)]);
326696a1b1bSAndreas Gohr        $this->assertEquals(1, $refCount);
327696a1b1bSAndreas Gohr
328696a1b1bSAndreas Gohr        // Check groups table
329696a1b1bSAndreas Gohr        $groupCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM groups WHERE type = ?', ['view']);
330696a1b1bSAndreas Gohr        $this->assertEquals(2, $groupCount);
331696a1b1bSAndreas Gohr    }
332696a1b1bSAndreas Gohr
333696a1b1bSAndreas Gohr    /**
334696a1b1bSAndreas Gohr     * Data provider for logMedia test
335696a1b1bSAndreas Gohr     */
336696a1b1bSAndreas Gohr    public function logMediaProvider()
337696a1b1bSAndreas Gohr    {
338696a1b1bSAndreas Gohr        return [
339696a1b1bSAndreas Gohr            'image inline' => ['test.jpg', 'image/jpeg', true, 1024],
340696a1b1bSAndreas Gohr            'video not inline' => ['test.mp4', 'video/mp4', false, 2048],
341696a1b1bSAndreas Gohr            'document' => ['test.pdf', 'application/pdf', false, 512],
342696a1b1bSAndreas Gohr        ];
343696a1b1bSAndreas Gohr    }
344696a1b1bSAndreas Gohr
345696a1b1bSAndreas Gohr    /**
346696a1b1bSAndreas Gohr     * Test logMedia method
347696a1b1bSAndreas Gohr     * @dataProvider logMediaProvider
348696a1b1bSAndreas Gohr     */
349696a1b1bSAndreas Gohr    public function testLogMedia($media, $mime, $inline, $size)
350696a1b1bSAndreas Gohr    {
351696a1b1bSAndreas Gohr        global $INPUT;
352696a1b1bSAndreas Gohr
353696a1b1bSAndreas Gohr        $user = 'testuser';
354696a1b1bSAndreas Gohr        $INPUT->server->set('REMOTE_USER', $user);
355696a1b1bSAndreas Gohr
356696a1b1bSAndreas Gohr        $this->logger->logMedia($media, $mime, $inline, $size);
357696a1b1bSAndreas Gohr
358696a1b1bSAndreas Gohr        $mediaLog = $this->helper->getDB()->queryRecord('SELECT * FROM media ORDER BY dt DESC LIMIT 1');
359696a1b1bSAndreas Gohr        $this->assertEquals($media, $mediaLog['media']);
360696a1b1bSAndreas Gohr        $this->assertEquals($user, $mediaLog['user']);
361696a1b1bSAndreas Gohr        $this->assertEquals($size, $mediaLog['size']);
362696a1b1bSAndreas Gohr        $this->assertEquals($inline ? 1 : 0, $mediaLog['inline']);
363696a1b1bSAndreas Gohr
364696a1b1bSAndreas Gohr        [$mime1, $mime2] = explode('/', strtolower($mime));
365696a1b1bSAndreas Gohr        $this->assertEquals($mime1, $mediaLog['mime1']);
366696a1b1bSAndreas Gohr        $this->assertEquals($mime2, $mediaLog['mime2']);
367696a1b1bSAndreas Gohr    }
368696a1b1bSAndreas Gohr
369696a1b1bSAndreas Gohr    /**
370696a1b1bSAndreas Gohr     * Data provider for logEdit test
371696a1b1bSAndreas Gohr     */
372696a1b1bSAndreas Gohr    public function logEditProvider()
373696a1b1bSAndreas Gohr    {
374696a1b1bSAndreas Gohr        return [
375696a1b1bSAndreas Gohr            'create page' => ['new:page', 'create'],
376696a1b1bSAndreas Gohr            'edit page' => ['existing:page', 'edit'],
377696a1b1bSAndreas Gohr            'delete page' => ['old:page', 'delete'],
378696a1b1bSAndreas Gohr        ];
379696a1b1bSAndreas Gohr    }
380696a1b1bSAndreas Gohr
381696a1b1bSAndreas Gohr    /**
382696a1b1bSAndreas Gohr     * Test logEdit method
383696a1b1bSAndreas Gohr     * @dataProvider logEditProvider
384696a1b1bSAndreas Gohr     */
385696a1b1bSAndreas Gohr    public function testLogEdit($page, $type)
386696a1b1bSAndreas Gohr    {
387de1daf8cSAndreas Gohr        global $INPUT, $USERINFO, $conf;
388de1daf8cSAndreas Gohr
389de1daf8cSAndreas Gohr        $conf['plugin']['statistics']['loggroups'] = ['admin'];
390696a1b1bSAndreas Gohr
39123e0cc03SAndreas Gohr        // Clear any existing data for this test
39223e0cc03SAndreas Gohr        $this->helper->getDB()->exec('DELETE FROM groups WHERE type = ?', ['edit']);
39323e0cc03SAndreas Gohr
394696a1b1bSAndreas Gohr        $user = 'testuser';
395696a1b1bSAndreas Gohr        $INPUT->server->set('REMOTE_USER', $user);
396696a1b1bSAndreas Gohr        $USERINFO = ['grps' => ['admin']];
397696a1b1bSAndreas Gohr
398696a1b1bSAndreas Gohr        $this->logger->logEdit($page, $type);
399696a1b1bSAndreas Gohr
400696a1b1bSAndreas Gohr        // Check edits table
401696a1b1bSAndreas Gohr        $edit = $this->helper->getDB()->queryRecord('SELECT * FROM edits ORDER BY dt DESC LIMIT 1');
402696a1b1bSAndreas Gohr        $this->assertEquals($page, $edit['page']);
403696a1b1bSAndreas Gohr        $this->assertEquals($type, $edit['type']);
404696a1b1bSAndreas Gohr        $this->assertEquals($user, $edit['user']);
405696a1b1bSAndreas Gohr
406696a1b1bSAndreas Gohr        // Check groups table
407696a1b1bSAndreas Gohr        $groupCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM groups WHERE type = ?', ['edit']);
408696a1b1bSAndreas Gohr        $this->assertEquals(1, $groupCount);
409696a1b1bSAndreas Gohr    }
410696a1b1bSAndreas Gohr
411696a1b1bSAndreas Gohr    /**
412696a1b1bSAndreas Gohr     * Data provider for logLogin test
413696a1b1bSAndreas Gohr     */
414696a1b1bSAndreas Gohr    public function logLoginProvider()
415696a1b1bSAndreas Gohr    {
416696a1b1bSAndreas Gohr        return [
417696a1b1bSAndreas Gohr            'login' => ['login', 'testuser'],
418696a1b1bSAndreas Gohr            'logout' => ['logout', 'testuser'],
419696a1b1bSAndreas Gohr            'create' => ['create', 'newuser'],
420696a1b1bSAndreas Gohr        ];
421696a1b1bSAndreas Gohr    }
422696a1b1bSAndreas Gohr
423696a1b1bSAndreas Gohr    /**
424696a1b1bSAndreas Gohr     * Test logLogin method
425696a1b1bSAndreas Gohr     * @dataProvider logLoginProvider
426696a1b1bSAndreas Gohr     */
427696a1b1bSAndreas Gohr    public function testLogLogin($type, $user)
428696a1b1bSAndreas Gohr    {
429696a1b1bSAndreas Gohr        global $INPUT;
430696a1b1bSAndreas Gohr
431696a1b1bSAndreas Gohr        if ($user === 'testuser') {
432696a1b1bSAndreas Gohr            $INPUT->server->set('REMOTE_USER', $user);
433696a1b1bSAndreas Gohr            $this->logger->logLogin($type);
434696a1b1bSAndreas Gohr        } else {
435696a1b1bSAndreas Gohr            $this->logger->logLogin($type, $user);
436696a1b1bSAndreas Gohr        }
437696a1b1bSAndreas Gohr
438696a1b1bSAndreas Gohr        $login = $this->helper->getDB()->queryRecord('SELECT * FROM logins ORDER BY dt DESC LIMIT 1');
439696a1b1bSAndreas Gohr        $this->assertEquals($type, $login['type']);
440696a1b1bSAndreas Gohr        $this->assertEquals($user, $login['user']);
441696a1b1bSAndreas Gohr    }
442696a1b1bSAndreas Gohr
443696a1b1bSAndreas Gohr    /**
444696a1b1bSAndreas Gohr     * Test logHistoryPages method
445696a1b1bSAndreas Gohr     */
446696a1b1bSAndreas Gohr    public function testLogHistoryPages()
447696a1b1bSAndreas Gohr    {
448696a1b1bSAndreas Gohr        $this->logger->logHistoryPages();
449696a1b1bSAndreas Gohr
450696a1b1bSAndreas Gohr        // Check that both page_count and page_size entries were created
451696a1b1bSAndreas Gohr        $pageCount = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['page_count']);
452696a1b1bSAndreas Gohr        $pageSize = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['page_size']);
453696a1b1bSAndreas Gohr
454696a1b1bSAndreas Gohr        $this->assertIsNumeric($pageCount);
455696a1b1bSAndreas Gohr        $this->assertIsNumeric($pageSize);
456696a1b1bSAndreas Gohr        $this->assertGreaterThanOrEqual(0, $pageCount);
457696a1b1bSAndreas Gohr        $this->assertGreaterThanOrEqual(0, $pageSize);
458696a1b1bSAndreas Gohr    }
459696a1b1bSAndreas Gohr
460696a1b1bSAndreas Gohr    /**
461696a1b1bSAndreas Gohr     * Test logHistoryMedia method
462696a1b1bSAndreas Gohr     */
463696a1b1bSAndreas Gohr    public function testLogHistoryMedia()
464696a1b1bSAndreas Gohr    {
465696a1b1bSAndreas Gohr        $this->logger->logHistoryMedia();
466696a1b1bSAndreas Gohr
467696a1b1bSAndreas Gohr        // Check that both media_count and media_size entries were created
468696a1b1bSAndreas Gohr        $mediaCount = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['media_count']);
469696a1b1bSAndreas Gohr        $mediaSize = $this->helper->getDB()->queryValue('SELECT value FROM history WHERE info = ?', ['media_size']);
470696a1b1bSAndreas Gohr
471696a1b1bSAndreas Gohr        $this->assertIsNumeric($mediaCount);
472696a1b1bSAndreas Gohr        $this->assertIsNumeric($mediaSize);
473696a1b1bSAndreas Gohr        $this->assertGreaterThanOrEqual(0, $mediaCount);
474696a1b1bSAndreas Gohr        $this->assertGreaterThanOrEqual(0, $mediaSize);
475696a1b1bSAndreas Gohr    }
476696a1b1bSAndreas Gohr
477696a1b1bSAndreas Gohr    /**
478696a1b1bSAndreas Gohr     * Test that feedreader user agents are handled correctly
479696a1b1bSAndreas Gohr     */
480696a1b1bSAndreas Gohr    public function testFeedReaderUserAgent()
481696a1b1bSAndreas Gohr    {
48223e0cc03SAndreas Gohr        // Use a user agent that DeviceDetector recognizes as a feedreader, not a bot
48323e0cc03SAndreas Gohr        $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; FeedReader)';
484696a1b1bSAndreas Gohr
485696a1b1bSAndreas Gohr        $logger = new Logger($this->helper);
486696a1b1bSAndreas Gohr
487696a1b1bSAndreas Gohr        // Use reflection to access protected property
488696a1b1bSAndreas Gohr        $reflection = new \ReflectionClass($logger);
489696a1b1bSAndreas Gohr        $uaTypeProperty = $reflection->getProperty('uaType');
490696a1b1bSAndreas Gohr        $uaTypeProperty->setAccessible(true);
491696a1b1bSAndreas Gohr
492696a1b1bSAndreas Gohr        $this->assertEquals('feedreader', $uaTypeProperty->getValue($logger));
493696a1b1bSAndreas Gohr    }
494696a1b1bSAndreas Gohr
495696a1b1bSAndreas Gohr    /**
496696a1b1bSAndreas Gohr     * Test session logging only works for browser type
497696a1b1bSAndreas Gohr     */
498696a1b1bSAndreas Gohr    public function testLogSessionOnlyForBrowser()
499696a1b1bSAndreas Gohr    {
50023e0cc03SAndreas Gohr        // Clear any existing session data
50123e0cc03SAndreas Gohr        $this->helper->getDB()->exec('DELETE FROM session');
50223e0cc03SAndreas Gohr
503696a1b1bSAndreas Gohr        // Change user agent type to feedreader using reflection
504696a1b1bSAndreas Gohr        $reflection = new \ReflectionClass($this->logger);
505696a1b1bSAndreas Gohr        $uaTypeProperty = $reflection->getProperty('uaType');
506696a1b1bSAndreas Gohr        $uaTypeProperty->setAccessible(true);
507696a1b1bSAndreas Gohr        $uaTypeProperty->setValue($this->logger, 'feedreader');
508696a1b1bSAndreas Gohr
509696a1b1bSAndreas Gohr        $this->logger->logSession(1);
510696a1b1bSAndreas Gohr
511696a1b1bSAndreas Gohr        $sessionCount = $this->helper->getDB()->queryValue('SELECT COUNT(*) FROM session');
512696a1b1bSAndreas Gohr        $this->assertEquals(0, $sessionCount);
5135cc1319aSAndreas Gohr    }
5145cc1319aSAndreas Gohr}
515