1c176b8b3SJohann Duscher<?php 2c176b8b3SJohann Duscher/** 3c176b8b3SJohann Duscher * Test Adapter for Delete Page Guard Plugin 4c176b8b3SJohann Duscher * 5c176b8b3SJohann Duscher * This file provides a testable version of the plugin by extending the 6c176b8b3SJohann Duscher * actual plugin class and making protected methods accessible for testing. 7c176b8b3SJohann Duscher * 8c176b8b3SJohann Duscher * @license GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html) - see LICENSE.md 9c176b8b3SJohann Duscher * @author Johann Duscher <jonny.dee@posteo.net> 10c176b8b3SJohann Duscher * @copyright 2025 Johann Duscher 11c176b8b3SJohann Duscher */ 12c176b8b3SJohann Duscher 13c176b8b3SJohann Duscher// Mock the DokuWiki ActionPlugin class for testing 14c176b8b3SJohann Duscherif (!class_exists('dokuwiki\Extension\ActionPlugin')) { 15c176b8b3SJohann Duscher class ActionPlugin { 16c176b8b3SJohann Duscher protected $config = [ 17c176b8b3SJohann Duscher 'patterns' => "^start$\n^sidebar$\n^users:[^:]+:start$", 18c176b8b3SJohann Duscher 'match_target' => 'id', 19c176b8b3SJohann Duscher 'exempt_groups' => 'editors,moderators', 20c176b8b3SJohann Duscher 'trim_mode' => true 21c176b8b3SJohann Duscher ]; 22c176b8b3SJohann Duscher 23c176b8b3SJohann Duscher protected $lang = [ 24c176b8b3SJohann Duscher 'pattern_redos_warning' => 'Pattern "%s" may cause performance issues', 25c176b8b3SJohann Duscher 'pattern_too_long' => 'Pattern "%s" is too long (max 1000 chars)', 26c176b8b3SJohann Duscher 'pattern_invalid_syntax' => 'Pattern "%s" has invalid syntax: %s', 27c176b8b3SJohann Duscher 'deny_msg' => 'Deleting this page is not allowed.', 28c176b8b3SJohann Duscher 'config_validation_errors' => 'Some regex patterns have validation errors.' 29c176b8b3SJohann Duscher ]; 30c176b8b3SJohann Duscher 31c176b8b3SJohann Duscher public function getConf($key) { 32c176b8b3SJohann Duscher return isset($this->config[$key]) ? $this->config[$key] : null; 33c176b8b3SJohann Duscher } 34c176b8b3SJohann Duscher 35c176b8b3SJohann Duscher public function getLang($key) { 36c176b8b3SJohann Duscher return isset($this->lang[$key]) ? $this->lang[$key] : "[$key]"; 37c176b8b3SJohann Duscher } 38c176b8b3SJohann Duscher } 39c176b8b3SJohann Duscher 40c176b8b3SJohann Duscher // Create the namespace alias 41c176b8b3SJohann Duscher class_alias('ActionPlugin', 'dokuwiki\Extension\ActionPlugin'); 42c176b8b3SJohann Duscher} 43c176b8b3SJohann Duscher 44c176b8b3SJohann Duscher// Mock DokuWiki Event classes 45c176b8b3SJohann Duscherif (!class_exists('dokuwiki\Extension\Event')) { 46c176b8b3SJohann Duscher class Event { 47c176b8b3SJohann Duscher public $data = []; 48c176b8b3SJohann Duscher public $canPreventDefault = true; 49c176b8b3SJohann Duscher } 50c176b8b3SJohann Duscher class_alias('Event', 'dokuwiki\Extension\Event'); 51c176b8b3SJohann Duscher} 52c176b8b3SJohann Duscher 53c176b8b3SJohann Duscherif (!class_exists('dokuwiki\Extension\EventHandler')) { 54c176b8b3SJohann Duscher class EventHandler { 55c176b8b3SJohann Duscher public function register_hook($event, $when, $obj, $method) { 56c176b8b3SJohann Duscher // Mock implementation 57c176b8b3SJohann Duscher } 58c176b8b3SJohann Duscher } 59c176b8b3SJohann Duscher class_alias('EventHandler', 'dokuwiki\Extension\EventHandler'); 60c176b8b3SJohann Duscher} 61c176b8b3SJohann Duscher 62c176b8b3SJohann Duscher// Mock DokuWiki constants and functions 63c176b8b3SJohann Duscherif (!defined('DOKU_INC')) define('DOKU_INC', dirname(__DIR__) . '/'); 64c176b8b3SJohann Duscher 65*bacaf983SJohann Duscher// Mock wikiFN function for file path testing 66*bacaf983SJohann Duscherif (!function_exists('wikiFN')) { 67*bacaf983SJohann Duscher function wikiFN($id) { 68*bacaf983SJohann Duscher global $conf; 69*bacaf983SJohann Duscher $datadir = isset($conf['datadir']) ? $conf['datadir'] : '/var/data'; 70*bacaf983SJohann Duscher return $datadir . '/pages/' . str_replace(':', '/', $id) . '.txt'; 71*bacaf983SJohann Duscher } 72*bacaf983SJohann Duscher} 73*bacaf983SJohann Duscher 74*bacaf983SJohann Duscher// Mock global $conf 75*bacaf983SJohann Duscher$GLOBALS['conf'] = [ 76*bacaf983SJohann Duscher 'datadir' => '/var/data' 77*bacaf983SJohann Duscher]; 78*bacaf983SJohann Duscher 79c176b8b3SJohann Duscher// Include the actual plugin file 80c176b8b3SJohann Duscherrequire_once dirname(__DIR__) . '/action.php'; 81c176b8b3SJohann Duscher 82c176b8b3SJohann Duscher/** 83c176b8b3SJohann Duscher * Testable version of the Delete Page Guard plugin 84c176b8b3SJohann Duscher * 85c176b8b3SJohann Duscher * Extends the actual plugin class and exposes protected methods for testing. 86c176b8b3SJohann Duscher */ 87c176b8b3SJohann Duscherclass TestableDeletePageGuard extends action_plugin_deletepageguard { 88c176b8b3SJohann Duscher 89c176b8b3SJohann Duscher /** 90*bacaf983SJohann Duscher * Mock configuration storage 91c176b8b3SJohann Duscher */ 92*bacaf983SJohann Duscher private $testConfig = [ 93c176b8b3SJohann Duscher 'patterns' => "^start$\n^sidebar$\n^users:[^:]+:start$", 94c176b8b3SJohann Duscher 'match_target' => 'id', 95c176b8b3SJohann Duscher 'exempt_groups' => 'editors,moderators', 96c176b8b3SJohann Duscher 'trim_mode' => true 97c176b8b3SJohann Duscher ]; 98*bacaf983SJohann Duscher 99*bacaf983SJohann Duscher /** 100*bacaf983SJohann Duscher * Override getConf to use mock configuration 101*bacaf983SJohann Duscher */ 102*bacaf983SJohann Duscher public function getConf($key) { 103*bacaf983SJohann Duscher return isset($this->testConfig[$key]) ? $this->testConfig[$key] : null; 104*bacaf983SJohann Duscher } 105*bacaf983SJohann Duscher 106*bacaf983SJohann Duscher /** 107*bacaf983SJohann Duscher * Set test configuration (for testing different modes) 108*bacaf983SJohann Duscher */ 109*bacaf983SJohann Duscher public function setTestConfig($key, $value) { 110*bacaf983SJohann Duscher $this->testConfig[$key] = $value; 111c176b8b3SJohann Duscher } 112c176b8b3SJohann Duscher 113c176b8b3SJohann Duscher /** 114c176b8b3SJohann Duscher * Override getLang to use mock language strings 115c176b8b3SJohann Duscher */ 116c176b8b3SJohann Duscher public function getLang($key) { 117c176b8b3SJohann Duscher $lang = [ 118c176b8b3SJohann Duscher 'pattern_redos_warning' => 'Pattern "%s" may cause performance issues', 119c176b8b3SJohann Duscher 'pattern_too_long' => 'Pattern "%s" is too long (max 1000 chars)', 120c176b8b3SJohann Duscher 'pattern_invalid_syntax' => 'Pattern "%s" has invalid syntax: %s', 121c176b8b3SJohann Duscher 'deny_msg' => 'Deleting this page is not allowed.', 122c176b8b3SJohann Duscher 'config_validation_errors' => 'Some regex patterns have validation errors.' 123c176b8b3SJohann Duscher ]; 124c176b8b3SJohann Duscher return isset($lang[$key]) ? $lang[$key] : "[$key]"; 125c176b8b3SJohann Duscher } 126c176b8b3SJohann Duscher 127c176b8b3SJohann Duscher /** 128c176b8b3SJohann Duscher * Expose protected validateRegexPattern method for testing 129c176b8b3SJohann Duscher */ 130c176b8b3SJohann Duscher public function validateRegexPattern($pattern, $lineNumber = 0) { 131c176b8b3SJohann Duscher return parent::validateRegexPattern($pattern, $lineNumber); 132c176b8b3SJohann Duscher } 133c176b8b3SJohann Duscher 134c176b8b3SJohann Duscher /** 135c176b8b3SJohann Duscher * Expose protected matchesPattern method for testing 136c176b8b3SJohann Duscher */ 137c176b8b3SJohann Duscher public function matchesPattern($pattern, $target) { 138c176b8b3SJohann Duscher return parent::matchesPattern($pattern, $target); 139c176b8b3SJohann Duscher } 140c176b8b3SJohann Duscher 141c176b8b3SJohann Duscher /** 142c176b8b3SJohann Duscher * Expose protected getRelativeFilePath method for testing 143c176b8b3SJohann Duscher */ 144c176b8b3SJohann Duscher public function getRelativeFilePath($fullPath, $dataDir) { 145c176b8b3SJohann Duscher return parent::getRelativeFilePath($fullPath, $dataDir); 146c176b8b3SJohann Duscher } 147c176b8b3SJohann Duscher}