* @copyright 2025 Johann Duscher
*/
use dokuwiki\Extension\AdminPlugin;
// Protect against direct call
if (!defined('DOKU_INC')) die();
/**
* Class admin_plugin_deletepageguard
*
* Provides an admin interface for validating Delete Page Guard patterns
* and offering configuration guidance to administrators.
*/
class admin_plugin_deletepageguard extends AdminPlugin {
/**
* Return sort order for position in admin menu
* @return int
*/
public function getMenuSort() {
return 200;
}
/**
* Return true if access to this admin plugin is allowed
* @return bool
*/
public function forAdminOnly() {
return true;
}
/**
* Handle user request
* @return void
*/
public function handle() {
if (isset($_POST['validate_patterns'])) {
$this->validatePatternsFromPost();
}
}
/**
* Render HTML output
* @return void
*/
public function html() {
echo '
' . $this->getLang('admin_title') . '
';
echo '';
// Show current patterns and validation results
$patterns = $this->getConf('patterns');
$this->showPatternValidation($patterns);
// Add validation form
echo '
' . $this->getLang('test_patterns_title') . '
';
echo '
';
echo '
';
}
/**
* Validate patterns from POST data
* @return void
*/
private function validatePatternsFromPost() {
$patterns = $_POST['test_patterns'] ?? '';
echo '' . $this->getLang('validation_results_title') . '
';
$this->showPatternValidation($patterns);
}
/**
* Display pattern validation results
* @param string $patterns The patterns to validate
* @return void
*/
private function showPatternValidation($patterns) {
if (empty(trim($patterns))) {
echo '' . $this->getLang('no_patterns') . '
';
return;
}
$lines = preg_split('/\R+/', $patterns, -1, PREG_SPLIT_NO_EMPTY);
$hasErrors = false;
$validCount = 0;
echo '';
echo '
' . $this->getLang('validation_results') . '
';
echo '
';
foreach ($lines as $i => $line) {
$pattern = trim($line);
if ($pattern === '') continue;
$lineNum = $i + 1;
$status = $this->validateSinglePattern($pattern);
if ($status === true) {
echo '- ✓ ';
echo 'Line ' . $lineNum . ':
' . hsc($pattern) . ' ';
$validCount++;
} else {
echo '- ✗ ';
echo 'Line ' . $lineNum . ':
' . hsc($pattern) . '
';
echo ' ' . hsc($status) . ' ';
$hasErrors = true;
}
}
echo '
';
if (!$hasErrors && $validCount > 0) {
echo '
' . sprintf($this->getLang('all_patterns_valid'), $validCount) . '
';
} elseif ($hasErrors) {
echo '
' . $this->getLang('some_patterns_invalid') . '
';
}
echo '
';
}
/**
* Validate a single pattern and return detailed error message
* @param string $pattern The pattern to validate
* @return string|true True if valid, error message if invalid
*/
private function validateSinglePattern($pattern) {
// Same validation logic as in action.php but with more detailed messages
if (strlen($pattern) > 1000) {
return $this->getLang('error_pattern_too_long');
}
if (preg_match('/(\(.*\).*\+.*\(.*\).*\+)|(\(.*\).*\*.*\(.*\).*\*)/', $pattern)) {
return $this->getLang('error_pattern_redos');
}
$escapedPattern = '/' . str_replace('/', '\/', $pattern) . '/u';
$test = @preg_match($escapedPattern, '');
if ($test === false) {
$error = error_get_last();
$errorMsg = $error && isset($error['message']) ? $error['message'] : 'Unknown error';
return $this->getLang('error_pattern_syntax') . ': ' . $errorMsg;
}
return true;
}
}