1<?php 2/** 3 * Admin interface for Delete Page Guard pattern validation 4 * 5 * @license GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html) - see LICENSE.md 6 * @author Johann Duscher <jonny.dee@posteo.net> 7 * @copyright 2025 Johann Duscher 8 */ 9 10use dokuwiki\Extension\AdminPlugin; 11 12// Protect against direct call 13if (!defined('DOKU_INC')) die(); 14 15/** 16 * Class admin_plugin_deletepageguard 17 * 18 * Provides an admin interface for validating Delete Page Guard patterns 19 * and offering configuration guidance to administrators. 20 */ 21class admin_plugin_deletepageguard extends AdminPlugin { 22 23 /** 24 * Return sort order for position in admin menu 25 * @return int 26 */ 27 public function getMenuSort() { 28 return 200; 29 } 30 31 /** 32 * Return the text to display in the admin menu 33 * @return string 34 */ 35 public function getMenuText($language) { 36 return $this->getLang('menu'); 37 } 38 39 /** 40 * Return true if access to this admin plugin is allowed 41 * @return bool 42 */ 43 public function forAdminOnly() { 44 return true; 45 } 46 47 /** 48 * Handle user request 49 * @return void 50 */ 51 public function handle() { 52 // Nothing to handle - validation is done in html() method 53 } 54 55 /** 56 * Render HTML output 57 * @return void 58 */ 59 public function html() { 60 echo '<h1>' . $this->getLang('admin_title') . '</h1>'; 61 echo '<div class="level1">'; 62 63 // Determine which patterns to show - use POST data if available, otherwise config 64 $patterns = $_POST['test_patterns'] ?? $this->getConf('patterns'); 65 66 // Show validation results if form was submitted 67 if (isset($_POST['validate_patterns'])) { 68 echo '<h2>' . $this->getLang('validation_results_title') . '</h2>'; 69 $this->showPatternValidation($patterns); 70 } else { 71 // Show current config patterns on initial load 72 $this->showPatternValidation($patterns); 73 } 74 75 // Add validation form 76 echo '<h2>' . $this->getLang('test_patterns_title') . '</h2>'; 77 echo '<form method="post" accept-charset="utf-8">'; 78 echo '<p>' . $this->getLang('test_patterns_help') . '</p>'; 79 echo '<textarea name="test_patterns" rows="10" cols="80" class="edit">' . hsc($patterns) . '</textarea><br>'; 80 echo '<input type="submit" name="validate_patterns" value="' . $this->getLang('validate_button') . '" class="button">'; 81 echo '</form>'; 82 83 echo '</div>'; 84 } 85 86 /** 87 * Display pattern validation results 88 * @param string $patterns The patterns to validate 89 * @return void 90 */ 91 private function showPatternValidation($patterns) { 92 if (empty(trim($patterns))) { 93 echo '<div class="info">' . $this->getLang('no_patterns') . '</div>'; 94 return; 95 } 96 97 $lines = preg_split('/\R+/', $patterns, -1, PREG_SPLIT_NO_EMPTY); 98 $hasErrors = false; 99 $validCount = 0; 100 101 echo '<div class="level2">'; 102 echo '<h3>' . $this->getLang('validation_results') . '</h3>'; 103 echo '<ul>'; 104 105 foreach ($lines as $i => $line) { 106 $pattern = trim($line); 107 if ($pattern === '') continue; 108 109 $lineNum = $i + 1; 110 $status = $this->validateSinglePattern($pattern); 111 112 if ($status === true) { 113 echo '<li><span style="color: green; font-weight: bold;">✓</span> '; 114 echo '<strong>Line ' . $lineNum . ':</strong> <code>' . hsc($pattern) . '</code></li>'; 115 $validCount++; 116 } else { 117 echo '<li><span style="color: red; font-weight: bold;">✗</span> '; 118 echo '<strong>Line ' . $lineNum . ':</strong> <code>' . hsc($pattern) . '</code><br>'; 119 echo ' <em style="color: red;">' . hsc($status) . '</em></li>'; 120 $hasErrors = true; 121 } 122 } 123 124 echo '</ul>'; 125 126 if (!$hasErrors && $validCount > 0) { 127 echo '<div class="success">' . sprintf($this->getLang('all_patterns_valid'), $validCount) . '</div>'; 128 } elseif ($hasErrors) { 129 echo '<div class="error">' . $this->getLang('some_patterns_invalid') . '</div>'; 130 } 131 132 echo '</div>'; 133 } 134 135 /** 136 * Validate a single pattern by delegating to the action plugin's validator. 137 * This ensures consistent validation logic between admin UI and runtime checks. 138 * 139 * @param string $pattern The pattern to validate 140 * @return string|true True if valid, error message if invalid 141 */ 142 private function validateSinglePattern($pattern) { 143 // Load the action plugin to use its centralized validation logic 144 $actionPlugin = plugin_load('action', 'deletepageguard'); 145 if (!$actionPlugin) { 146 return 'Error: Could not load validation service'; 147 } 148 149 // Use the action plugin's validateRegexPattern method (without line number) 150 $result = $actionPlugin->validateRegexPattern($pattern, 0); 151 152 // The action plugin returns true for valid, string for invalid 153 // We need to strip the "Line 0: " prefix if present 154 if (is_string($result)) { 155 $result = preg_replace('/^Line 0: /', '', $result); 156 } 157 158 return $result; 159 } 160}