xref: /plugin/bookmark2wiki/action.php (revision fd5d3c8a122aefbeb8d5725eeb71f2886bbd14cf)
19a41d28dSedwardcodelab<?php
29a41d28dSedwardcodelab/**
39a41d28dSedwardcodelab * DokuWiki Plugin bookmark2wiki (Action Component)
49a41d28dSedwardcodelab * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
59a41d28dSedwardcodelab * @author dodotori <dodotori@localhost>
69a41d28dSedwardcodelab * forked from post2wiki.php by riny [at] bk [dot] ru
79a41d28dSedwardcodelab * To bookmark webpage using bookmarklet
8*fd5d3c8aSedwardlab * The app will add the url, title and hightlighed text you want to the end of the content of the targeted namespace. It does not directly read/write the dokuwiki page folder.
99a41d28dSedwardcodelab * Version 1.0
10*fd5d3c8aSedwardlab * @license GPL 2[](http://www.gnu.org/licenses/gpl.html)
119a41d28dSedwardcodelab * @author dodotori https://github.com/edwardcodelab
12*fd5d3c8aSedwardlab */
139a41d28dSedwardcodelab// TYPICAL USAGE :
149a41d28dSedwardcodelab// Create bookmarklet as shown in the bookmarklet part below:
159a41d28dSedwardcodelab// Change the window.open statement to reflect the location of the bookmark2wiki.php script.
169a41d28dSedwardcodelab// Drag bookmarklet to your toolbar.
179a41d28dSedwardcodelab// BOOKMARKLET :
18*fd5d3c8aSedwardlab// javascript:Q=document.selection?document.selection.createRange().text:document.getSelection(); void(window.open('https://myserver/doku.php?do=bookmark2wiki&te='+escape(Q)+'&ur='+ escape(location.href)+'&ti='+escape(document.title),'dokuwikiadd','scrollbars=yes,resizable=yes,toolbars=yes,width=400,height=200,left=200,top=200,status=yes'));
199a41d28dSedwardcodelab
20*fd5d3c8aSedwardlabuse dokuwiki\Extension\ActionPlugin;
21*fd5d3c8aSedwardlabuse dokuwiki\Extension\EventHandler;
22*fd5d3c8aSedwardlabuse dokuwiki\Extension\Event;
239a41d28dSedwardcodelab
24*fd5d3c8aSedwardlabclass action_plugin_bookmark2wiki extends ActionPlugin
259a41d28dSedwardcodelab{
269a41d28dSedwardcodelab    /** @inheritDoc */
27*fd5d3c8aSedwardlab    public function register(EventHandler $controller)
289a41d28dSedwardcodelab    {
299a41d28dSedwardcodelab        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'allowMyAction');
309a41d28dSedwardcodelab        $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'performMyAction');
319a41d28dSedwardcodelab    }
329a41d28dSedwardcodelab
339a41d28dSedwardcodelab    /**
34*fd5d3c8aSedwardlab     * Event handler for ACTION_ACT_PREPROCESS
359a41d28dSedwardcodelab     *
36*fd5d3c8aSedwardlab     * @param Event $event event object by reference
379a41d28dSedwardcodelab     * @param mixed $param optional parameter passed when event was registered
389a41d28dSedwardcodelab     * @return void
399a41d28dSedwardcodelab     */
40*fd5d3c8aSedwardlab    public function allowMyAction(Event $event, $param) {
419a41d28dSedwardcodelab        if($event->data != 'bookmark2wiki') return;
429a41d28dSedwardcodelab        $event->preventDefault();
439a41d28dSedwardcodelab    }
449a41d28dSedwardcodelab
45*fd5d3c8aSedwardlab    /**
46*fd5d3c8aSedwardlab     * Event handler for TPL_ACT_UNKNOWN
47*fd5d3c8aSedwardlab     *
48*fd5d3c8aSedwardlab     * @param Event $event event object by reference
49*fd5d3c8aSedwardlab     * @param mixed $param optional parameter passed when event was registered
50*fd5d3c8aSedwardlab     * @return void
51*fd5d3c8aSedwardlab     */
52*fd5d3c8aSedwardlab    public function performMyAction(Event $event, $param) {
539a41d28dSedwardcodelab       if($event->data != 'bookmark2wiki') return;
549a41d28dSedwardcodelab       $event->preventDefault();
559a41d28dSedwardcodelab
56*fd5d3c8aSedwardlab       // Get params (support both GET from bookmarklet and POST from form)
57*fd5d3c8aSedwardlab       $te = $_REQUEST['te'] ?? '';
58*fd5d3c8aSedwardlab       $ur = $_REQUEST['ur'] ?? '';
59*fd5d3c8aSedwardlab       $ti = $_REQUEST['ti'] ?? '';
60*fd5d3c8aSedwardlab
61*fd5d3c8aSedwardlab       // Decode unicode (from original)
62*fd5d3c8aSedwardlab       $string = preg_replace('/%u([0-9A-F]+)/', '&#x$1;', $ti);
63*fd5d3c8aSedwardlab       $ti = html_entity_decode($string, ENT_COMPAT, 'UTF-8');
64*fd5d3c8aSedwardlab       $string = preg_replace('/%u([0-9A-F]+)/', '&#x$1;', $te);
65*fd5d3c8aSedwardlab       $te = html_entity_decode($string, ENT_COMPAT, 'UTF-8');
66*fd5d3c8aSedwardlab
67*fd5d3c8aSedwardlab       if (!$ur || !$ti) {
68*fd5d3c8aSedwardlab           echo 'Error: Missing URL or title.';
69*fd5d3c8aSedwardlab           return;
709a41d28dSedwardcodelab       }
719a41d28dSedwardcodelab
72*fd5d3c8aSedwardlab       // Basic URL validation
73*fd5d3c8aSedwardlab       if (!filter_var($ur, FILTER_VALIDATE_URL)) {
74*fd5d3c8aSedwardlab           echo 'Error: Invalid URL.';
75*fd5d3c8aSedwardlab           return;
76*fd5d3c8aSedwardlab       }
77*fd5d3c8aSedwardlab
78*fd5d3c8aSedwardlab       $timestamp = date("Y:m:d:H:i:s");
79*fd5d3c8aSedwardlab       $new_entry = "  * [[" . $ur . "|" . $ti . "]] \\\\ " . $te . " -- " . $timestamp;
80*fd5d3c8aSedwardlab
81*fd5d3c8aSedwardlab       if (isset($_POST['save'])) {
82*fd5d3c8aSedwardlab           // Handle form submit: directly save using DokuWiki functions
83*fd5d3c8aSedwardlab           $namespace = cleanID($_POST['page']);
84*fd5d3c8aSedwardlab           if (!$namespace) {
85*fd5d3c8aSedwardlab               echo 'Error: No page selected.';
86*fd5d3c8aSedwardlab               return;
87*fd5d3c8aSedwardlab           }
88*fd5d3c8aSedwardlab
89*fd5d3c8aSedwardlab           // Check edit permission
90*fd5d3c8aSedwardlab           if (auth_quickaclcheck($namespace) < AUTH_EDIT) {
91*fd5d3c8aSedwardlab               echo 'Error: No permission to edit the selected page.';
92*fd5d3c8aSedwardlab               return;
93*fd5d3c8aSedwardlab           }
94*fd5d3c8aSedwardlab
95*fd5d3c8aSedwardlab           // Get raw position config and map to internal value
96*fd5d3c8aSedwardlab           $raw_position = $this->getConf('position');
97*fd5d3c8aSedwardlab           $position_map = [
98*fd5d3c8aSedwardlab               'After Heading (prepend)' => 'top',
99*fd5d3c8aSedwardlab               'End of Page (append)' => 'bottom'
100*fd5d3c8aSedwardlab           ];
101*fd5d3c8aSedwardlab           $position = isset($position_map[$raw_position]) ? $position_map[$raw_position] : $raw_position;
102*fd5d3c8aSedwardlab           // Fallback to 'bottom' if config is invalid
103*fd5d3c8aSedwardlab           if (!in_array($position, ['top', 'bottom'])) {
104*fd5d3c8aSedwardlab               $position = 'bottom';
105*fd5d3c8aSedwardlab           }
106*fd5d3c8aSedwardlab
107*fd5d3c8aSedwardlab           // Read current page content
108*fd5d3c8aSedwardlab           $text = rawWiki($namespace);
109*fd5d3c8aSedwardlab           $text = str_replace("\r", "", $text);  // Normalize line endings to \n
110*fd5d3c8aSedwardlab
111*fd5d3c8aSedwardlab           if (trim($text) === '') {
112*fd5d3c8aSedwardlab               $text = "====== New Bookmarks ====== \n";
113*fd5d3c8aSedwardlab           }
114*fd5d3c8aSedwardlab
115*fd5d3c8aSedwardlab           $lines = explode("\n", $text);
116*fd5d3c8aSedwardlab
117*fd5d3c8aSedwardlab           if ($position == 'top') {
118*fd5d3c8aSedwardlab               // Find the position after the first heading (match after trim)
119*fd5d3c8aSedwardlab               $insert_pos = 0;
120*fd5d3c8aSedwardlab               $found_heading = false;
121*fd5d3c8aSedwardlab               for ($i = 0; $i < count($lines); $i++) {
122*fd5d3c8aSedwardlab                   $trimmed = trim($lines[$i]);
123*fd5d3c8aSedwardlab                   if (preg_match('/^=+.*=+$/', $trimmed)) {
124*fd5d3c8aSedwardlab                       $insert_pos = $i + 1;
125*fd5d3c8aSedwardlab                       $found_heading = true;
126*fd5d3c8aSedwardlab                       break;
127*fd5d3c8aSedwardlab                   }
128*fd5d3c8aSedwardlab               }
129*fd5d3c8aSedwardlab
130*fd5d3c8aSedwardlab               // Skip empty lines after the heading
131*fd5d3c8aSedwardlab               while ($insert_pos < count($lines) && trim($lines[$insert_pos]) === '') {
132*fd5d3c8aSedwardlab                   $insert_pos++;
133*fd5d3c8aSedwardlab               }
134*fd5d3c8aSedwardlab
135*fd5d3c8aSedwardlab               // Insert the new entry
136*fd5d3c8aSedwardlab               array_splice($lines, $insert_pos, 0, $new_entry);
137*fd5d3c8aSedwardlab           } else {
138*fd5d3c8aSedwardlab               // Append to end, but add a newline if not empty
139*fd5d3c8aSedwardlab               if (!empty(trim($lines[count($lines) - 1]))) {
140*fd5d3c8aSedwardlab                   $lines[] = '';
141*fd5d3c8aSedwardlab               }
142*fd5d3c8aSedwardlab               $lines[] = $new_entry;
143*fd5d3c8aSedwardlab           }
144*fd5d3c8aSedwardlab
145*fd5d3c8aSedwardlab           $newtext = implode("\n", $lines);
146*fd5d3c8aSedwardlab
147*fd5d3c8aSedwardlab           // Save the updated content
148*fd5d3c8aSedwardlab           saveWikiText($namespace, $newtext, 'Added bookmark: ' . $ti, false);  // false = not minor edit
149*fd5d3c8aSedwardlab
150*fd5d3c8aSedwardlab           echo 'Bookmark saved to ' . hsc($namespace) . '! <script>setTimeout(function(){window.close();}, 3000);</script>';
151*fd5d3c8aSedwardlab       } else {
152*fd5d3c8aSedwardlab           // Display form for page selection
153*fd5d3c8aSedwardlab           $configured_pages = explode("\n", trim($this->getConf('pages')));
154*fd5d3c8aSedwardlab           if (empty($configured_pages)) {
155*fd5d3c8aSedwardlab               echo 'Error: No pages configured in plugin settings.';
156*fd5d3c8aSedwardlab               return;
157*fd5d3c8aSedwardlab           }
158*fd5d3c8aSedwardlab
159*fd5d3c8aSedwardlab           echo '<form method="post" action="">';
160*fd5d3c8aSedwardlab           echo '<label for="page">Save to page:</label><br>';
161*fd5d3c8aSedwardlab           echo '<select name="page" id="page">';
162*fd5d3c8aSedwardlab           foreach ($configured_pages as $p) {
163*fd5d3c8aSedwardlab               $p = trim($p);
164*fd5d3c8aSedwardlab               if ($p) {
165*fd5d3c8aSedwardlab                   echo '<option value="' . hsc($p) . '">' . hsc($p) . '</option>';
166*fd5d3c8aSedwardlab               }
167*fd5d3c8aSedwardlab           }
168*fd5d3c8aSedwardlab           echo '</select><br>';
169*fd5d3c8aSedwardlab           echo '<input type="hidden" name="te" value="' . hsc($te) . '">';
170*fd5d3c8aSedwardlab           echo '<input type="hidden" name="ur" value="' . hsc($ur) . '">';
171*fd5d3c8aSedwardlab           echo '<input type="hidden" name="ti" value="' . hsc($ti) . '">';
172*fd5d3c8aSedwardlab           echo '<input type="submit" name="save" value="Save">';
173*fd5d3c8aSedwardlab           echo '</form>';
174*fd5d3c8aSedwardlab       }
175*fd5d3c8aSedwardlab    }
1769a41d28dSedwardcodelab}