xref: /plugin/deletepageguard/admin.php (revision 9a383d51b90310842e2a3f0f9d693178d0875b32)
11a97af9eSJohann Duscher<?php
21a97af9eSJohann Duscher/**
31a97af9eSJohann Duscher * Admin interface for Delete Page Guard pattern validation
41a97af9eSJohann Duscher *
51a97af9eSJohann Duscher * @license GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html) - see LICENSE.md
61a97af9eSJohann Duscher * @author  Johann Duscher <jonny.dee@posteo.net>
71a97af9eSJohann Duscher * @copyright 2025 Johann Duscher
81a97af9eSJohann Duscher */
91a97af9eSJohann Duscher
101a97af9eSJohann Duscheruse dokuwiki\Extension\AdminPlugin;
111a97af9eSJohann Duscher
121a97af9eSJohann Duscher// Protect against direct call
131a97af9eSJohann Duscherif (!defined('DOKU_INC')) die();
141a97af9eSJohann Duscher
151a97af9eSJohann Duscher/**
161a97af9eSJohann Duscher * Class admin_plugin_deletepageguard
171a97af9eSJohann Duscher *
181a97af9eSJohann Duscher * Provides an admin interface for validating Delete Page Guard patterns
191a97af9eSJohann Duscher * and offering configuration guidance to administrators.
201a97af9eSJohann Duscher */
211a97af9eSJohann Duscherclass admin_plugin_deletepageguard extends AdminPlugin {
221a97af9eSJohann Duscher
231a97af9eSJohann Duscher    /**
241a97af9eSJohann Duscher     * Return sort order for position in admin menu
251a97af9eSJohann Duscher     * @return int
261a97af9eSJohann Duscher     */
271a97af9eSJohann Duscher    public function getMenuSort() {
281a97af9eSJohann Duscher        return 200;
291a97af9eSJohann Duscher    }
301a97af9eSJohann Duscher
311a97af9eSJohann Duscher    /**
32*9a383d51SJohann Duscher     * Return the text to display in the admin menu
33*9a383d51SJohann Duscher     * @return string
34*9a383d51SJohann Duscher     */
35*9a383d51SJohann Duscher    public function getMenuText($language) {
36*9a383d51SJohann Duscher        return $this->getLang('menu');
37*9a383d51SJohann Duscher    }
38*9a383d51SJohann Duscher
39*9a383d51SJohann Duscher    /**
401a97af9eSJohann Duscher     * Return true if access to this admin plugin is allowed
411a97af9eSJohann Duscher     * @return bool
421a97af9eSJohann Duscher     */
431a97af9eSJohann Duscher    public function forAdminOnly() {
441a97af9eSJohann Duscher        return true;
451a97af9eSJohann Duscher    }
461a97af9eSJohann Duscher
471a97af9eSJohann Duscher    /**
481a97af9eSJohann Duscher     * Handle user request
491a97af9eSJohann Duscher     * @return void
501a97af9eSJohann Duscher     */
511a97af9eSJohann Duscher    public function handle() {
52*9a383d51SJohann Duscher        // Nothing to handle - validation is done in html() method
531a97af9eSJohann Duscher    }
541a97af9eSJohann Duscher
551a97af9eSJohann Duscher    /**
561a97af9eSJohann Duscher     * Render HTML output
571a97af9eSJohann Duscher     * @return void
581a97af9eSJohann Duscher     */
591a97af9eSJohann Duscher    public function html() {
601a97af9eSJohann Duscher        echo '<h1>' . $this->getLang('admin_title') . '</h1>';
611a97af9eSJohann Duscher        echo '<div class="level1">';
621a97af9eSJohann Duscher
63*9a383d51SJohann Duscher        // Determine which patterns to show - use POST data if available, otherwise config
64*9a383d51SJohann Duscher        $patterns = $_POST['test_patterns'] ?? $this->getConf('patterns');
65*9a383d51SJohann Duscher
66*9a383d51SJohann Duscher        // Show validation results if form was submitted
67*9a383d51SJohann Duscher        if (isset($_POST['validate_patterns'])) {
68*9a383d51SJohann Duscher            echo '<h2>' . $this->getLang('validation_results_title') . '</h2>';
691a97af9eSJohann Duscher            $this->showPatternValidation($patterns);
70*9a383d51SJohann Duscher        } else {
71*9a383d51SJohann Duscher            // Show current config patterns on initial load
72*9a383d51SJohann Duscher            $this->showPatternValidation($patterns);
73*9a383d51SJohann Duscher        }
741a97af9eSJohann Duscher
751a97af9eSJohann Duscher        // Add validation form
761a97af9eSJohann Duscher        echo '<h2>' . $this->getLang('test_patterns_title') . '</h2>';
771a97af9eSJohann Duscher        echo '<form method="post" accept-charset="utf-8">';
781a97af9eSJohann Duscher        echo '<p>' . $this->getLang('test_patterns_help') . '</p>';
791a97af9eSJohann Duscher        echo '<textarea name="test_patterns" rows="10" cols="80" class="edit">' . hsc($patterns) . '</textarea><br>';
801a97af9eSJohann Duscher        echo '<input type="submit" name="validate_patterns" value="' . $this->getLang('validate_button') . '" class="button">';
811a97af9eSJohann Duscher        echo '</form>';
821a97af9eSJohann Duscher
831a97af9eSJohann Duscher        echo '</div>';
841a97af9eSJohann Duscher    }
851a97af9eSJohann Duscher
861a97af9eSJohann Duscher    /**
871a97af9eSJohann Duscher     * Display pattern validation results
881a97af9eSJohann Duscher     * @param string $patterns The patterns to validate
891a97af9eSJohann Duscher     * @return void
901a97af9eSJohann Duscher     */
911a97af9eSJohann Duscher    private function showPatternValidation($patterns) {
921a97af9eSJohann Duscher        if (empty(trim($patterns))) {
931a97af9eSJohann Duscher            echo '<div class="info">' . $this->getLang('no_patterns') . '</div>';
941a97af9eSJohann Duscher            return;
951a97af9eSJohann Duscher        }
961a97af9eSJohann Duscher
971a97af9eSJohann Duscher        $lines = preg_split('/\R+/', $patterns, -1, PREG_SPLIT_NO_EMPTY);
981a97af9eSJohann Duscher        $hasErrors = false;
991a97af9eSJohann Duscher        $validCount = 0;
1001a97af9eSJohann Duscher
1011a97af9eSJohann Duscher        echo '<div class="level2">';
1021a97af9eSJohann Duscher        echo '<h3>' . $this->getLang('validation_results') . '</h3>';
1031a97af9eSJohann Duscher        echo '<ul>';
1041a97af9eSJohann Duscher
1051a97af9eSJohann Duscher        foreach ($lines as $i => $line) {
1061a97af9eSJohann Duscher            $pattern = trim($line);
1071a97af9eSJohann Duscher            if ($pattern === '') continue;
1081a97af9eSJohann Duscher
1091a97af9eSJohann Duscher            $lineNum = $i + 1;
1101a97af9eSJohann Duscher            $status = $this->validateSinglePattern($pattern);
1111a97af9eSJohann Duscher
1121a97af9eSJohann Duscher            if ($status === true) {
1131a97af9eSJohann Duscher                echo '<li><span style="color: green; font-weight: bold;">✓</span> ';
1141a97af9eSJohann Duscher                echo '<strong>Line ' . $lineNum . ':</strong> <code>' . hsc($pattern) . '</code></li>';
1151a97af9eSJohann Duscher                $validCount++;
1161a97af9eSJohann Duscher            } else {
1171a97af9eSJohann Duscher                echo '<li><span style="color: red; font-weight: bold;">✗</span> ';
1181a97af9eSJohann Duscher                echo '<strong>Line ' . $lineNum . ':</strong> <code>' . hsc($pattern) . '</code><br>';
1191a97af9eSJohann Duscher                echo '&nbsp;&nbsp;&nbsp;<em style="color: red;">' . hsc($status) . '</em></li>';
1201a97af9eSJohann Duscher                $hasErrors = true;
1211a97af9eSJohann Duscher            }
1221a97af9eSJohann Duscher        }
1231a97af9eSJohann Duscher
1241a97af9eSJohann Duscher        echo '</ul>';
1251a97af9eSJohann Duscher
1261a97af9eSJohann Duscher        if (!$hasErrors && $validCount > 0) {
1271a97af9eSJohann Duscher            echo '<div class="success">' . sprintf($this->getLang('all_patterns_valid'), $validCount) . '</div>';
1281a97af9eSJohann Duscher        } elseif ($hasErrors) {
1291a97af9eSJohann Duscher            echo '<div class="error">' . $this->getLang('some_patterns_invalid') . '</div>';
1301a97af9eSJohann Duscher        }
1311a97af9eSJohann Duscher
1321a97af9eSJohann Duscher        echo '</div>';
1331a97af9eSJohann Duscher    }
1341a97af9eSJohann Duscher
1351a97af9eSJohann Duscher    /**
136*9a383d51SJohann Duscher     * Validate a single pattern by delegating to the action plugin's validator.
137*9a383d51SJohann Duscher     * This ensures consistent validation logic between admin UI and runtime checks.
138*9a383d51SJohann Duscher     *
1391a97af9eSJohann Duscher     * @param string $pattern The pattern to validate
1401a97af9eSJohann Duscher     * @return string|true True if valid, error message if invalid
1411a97af9eSJohann Duscher     */
1421a97af9eSJohann Duscher    private function validateSinglePattern($pattern) {
143*9a383d51SJohann Duscher        // Load the action plugin to use its centralized validation logic
144*9a383d51SJohann Duscher        $actionPlugin = plugin_load('action', 'deletepageguard');
145*9a383d51SJohann Duscher        if (!$actionPlugin) {
146*9a383d51SJohann Duscher            return 'Error: Could not load validation service';
1471a97af9eSJohann Duscher        }
1481a97af9eSJohann Duscher
149*9a383d51SJohann Duscher        // Use the action plugin's validateRegexPattern method (without line number)
150*9a383d51SJohann Duscher        $result = $actionPlugin->validateRegexPattern($pattern, 0);
151*9a383d51SJohann Duscher
152*9a383d51SJohann Duscher        // The action plugin returns true for valid, string for invalid
153*9a383d51SJohann Duscher        // We need to strip the "Line 0: " prefix if present
154*9a383d51SJohann Duscher        if (is_string($result)) {
155*9a383d51SJohann Duscher            $result = preg_replace('/^Line 0: /', '', $result);
1561a97af9eSJohann Duscher        }
1571a97af9eSJohann Duscher
158*9a383d51SJohann Duscher        return $result;
1591a97af9eSJohann Duscher    }
1601a97af9eSJohann Duscher}