1<?php
2
3use dokuwiki\Form\Form;
4
5/**
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Michael Klier <chi@chimeric.de>
8 */
9
10class action_plugin_blogtng_edit extends DokuWiki_Action_Plugin{
11
12    /** @var helper_plugin_blogtng_entry */
13    var $entryhelper = null;
14    /** @var  helper_plugin_blogtng_tags */
15    var $taghelper;
16    /** @var  helper_plugin_blogtng_tools */
17    var $tools;
18
19    var $preact = null;
20
21    /**
22     * Constructor
23     */
24    function __construct() {
25        $this->entryhelper = plugin_load('helper', 'blogtng_entry');
26        $this->taghelper = plugin_load('helper', 'blogtng_tags');
27        $this->tools = plugin_load('helper', 'blogtng_tools');
28    }
29
30    /**
31     * Registers a callback function for a given event
32     *
33     * @param Doku_Event_Handler $controller
34     */
35    function register(Doku_Event_Handler $controller) {
36        //create extra form fields below DokuWiki's edit window
37        $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'extraFieldsBelowEditform_old', array());
38        $controller->register_hook('FORM_EDIT_OUTPUT', 'BEFORE', $this, 'extraFieldsBelowEditform', array());
39        //try to save the submitted extra form data
40        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'saveSubmittedFormData', array('before'));
41        $controller->register_hook('ACTION_ACT_PREPROCESS', 'AFTER', $this, 'saveSubmittedFormData', array('after'));
42    }
43
44    /**
45     * Adds additional fields of used by the BlogTNG plugin to the editor.
46     *
47     * @param Doku_Event $event
48     * @param $param
49     *
50     * @deprecated 2022-07-31
51     */
52    function extraFieldsBelowEditform_old(Doku_Event $event, $param) {
53        global $ID, $INFO, $INPUT;
54
55        $pos = $event->data->findElementByAttribute('type','submit');
56        if(!$pos) return; // no submit button found, source view
57        $pos -= 1;
58
59        $pid = md5($ID);
60        $this->entryhelper->load_by_pid($pid);
61        $isNotExistingBlog = $this->entryhelper->entry['blog'] === null;
62
63        $blog = $this->entryhelper->get_blog();
64        $blog = $INPUT->post->str('post-blog', $blog);
65        if (!$blog && !$INFO['exists']) $blog = $this->getConf('default_blog');
66        $blogs = $this->entryhelper->getAllBlogs();
67
68        $event->data->insertElement($pos, form_openfieldset(array('_legend' => 'BlogTNG', 'class' => 'edit', 'id' => 'blogtng__edit')));
69        $pos += 1;
70
71        $event->data->insertElement($pos, form_makeMenuField('post-blog', $blogs, $blog, 'Blog', 'blogtng__blog', 'edit'));
72        $pos += 1;
73
74        $this->taghelper->load($pid);
75
76        $tags = $this->getPostedTags();
77        if (empty($tags)) {
78            $tags = $this->taghelper->getTags();
79        }
80        if (!$tags && $isNotExistingBlog) $tags = helper_plugin_blogtng_tools::filterExplodeCSVinput($this->getConf('default_tags'));
81
82        $allowed_tags = $this->getAllowedTags();
83        if (count($allowed_tags) > 0) {
84            $event->data->insertElement($pos++, form_makeOpenTag('div', array('class' => 'blogtng__tags_checkboxes')));
85            foreach($this->getAllowedTags() as $val) {
86                $data = array('style' => 'margin-top: 0.3em;');
87                if (in_array($val, $tags)) $data['checked'] = 'checked';
88                $event->data->insertElement($pos++, form_makeCheckboxField('post-tags[]', $val, $val, '', '', $data));
89            }
90            $event->data->insertElement($pos++, form_makeCloseTag('div'));
91        } else {
92            $event->data->insertElement($pos, form_makeTextField('post-tags', join(', ', $tags), 'Tags', 'blogtng__tags', 'edit'));
93            $pos += 1;
94        }
95
96        $commentstatus = $this->entryhelper->entry['commentstatus'];
97        $commentstatus = $INPUT->post->str('post-commentstatus', $commentstatus);
98        if(!$commentstatus) {
99            $commentstatus = $this->getConf('default_commentstatus');
100        }
101
102        $event->data->insertElement($pos, form_makeMenuField('post-commentstatus', array('enabled', 'closed', 'disabled'), $commentstatus, $this->getLang('commentstatus'), 'blogtng__commentstatus', 'edit'));
103        $pos += 1;
104
105            if($this->getConf('editform_set_date')) {
106                if ($INPUT->post->has('post-date')) {
107                    $date = $INPUT->post->arr('post-date');
108                    $YY = (int) $date['YY'];
109                    $MM = (int) $date['MM'];
110                    $DD = (int) $date['DD'];
111                    $hh = (int) $date['hh'];
112                    $mm = (int) $date['mm'];
113                } else {
114                    $created = $this->entryhelper->entry['created'];
115                    if($created) {
116                        $YY = date('Y', $created);
117                        $MM = date('m', $created);
118                        $DD = date('d', $created);
119                        $hh = date('H', $created);
120                        $mm = date('i', $created);
121                    } else {
122                        $time = time();
123                        $YY = date('Y', $time);
124                        $MM = date('m', $time);
125                        $DD = date('d', $time);
126                        $hh = date('H', $time);
127                        $mm = date('i', $time);
128                    }
129                }
130
131            $event->data->insertElement($pos, form_makeTextField('post-date[YY]', $YY, 'YYYY', 'blogtng__date_YY', 'edit btng__date_YY', array('maxlength'=>4)));
132            $pos += 1;
133            $event->data->insertElement($pos, form_makeTextField('post-date[MM]', $MM, 'MM', 'blogtng__date_MM', 'edit btng__date', array('maxlength'=>2)));
134            $pos += 1;
135            $event->data->insertElement($pos, form_makeTextField('post-date[DD]', $DD, 'DD', 'blogtng__date_DD', 'edit btng__date', array('maxlength'=>2)));
136            $pos += 1;
137            $event->data->insertElement($pos, form_makeTextField('post-date[hh]', $hh, 'hh', 'blogtng__date_hh', 'edit btng__date', array('maxlength'=>2)));
138            $pos += 1;
139            $event->data->insertElement($pos, form_makeTextField('post-date[mm]', $mm, 'mm', 'blogtng__date_mm', 'edit btng__date', array('maxlength'=>2)));
140            $pos += 1;
141        }
142
143        $event->data->insertElement($pos, form_closefieldset());
144    }
145
146    /**
147     * Adds additional fields of used by the BlogTNG plugin to the editor.
148     *
149     * @param Doku_Event $event
150     * @param $param
151     */
152    function extraFieldsBelowEditform(Doku_Event $event, $param) {
153        global $ID, $INFO, $INPUT;
154        /** @var Form $form */
155        $form = $event->data;
156        $pos = $form->findPositionByAttribute('type','submit');
157        if(!$pos) {
158            return; // no submit button found, source view
159        }
160        $pos -= 1;
161
162        $pid = md5($ID);
163        $this->entryhelper->load_by_pid($pid);
164        $isNotExistingBlog = $this->entryhelper->entry['blog'] === null;
165
166        $form->addFieldsetOpen('BlogTNG', $pos++)
167            ->id('blogtng__edit')
168            ->addClass('edit');
169
170        $blog = $this->entryhelper->get_blog();
171        $blog = $INPUT->post->str('post-blog', $blog);
172        if (!$blog && !$INFO['exists']) {
173            $blog = $this->getConf('default_blog');
174        }
175        $blogs = $this->entryhelper->getAllBlogs();
176
177        $form->addDropdown('post-blog', $blogs, 'Blog', $pos++)
178            ->id('blogtng__blog')
179            ->addClass('edit')
180            ->val($blog);
181
182
183        $this->taghelper->load($pid);
184        $tags = $this->getPostedTags();
185        if (empty($tags)) {
186            $tags = $this->taghelper->getTags();
187        }
188        if (!$tags && $isNotExistingBlog) {
189            $tags = helper_plugin_blogtng_tools::filterExplodeCSVinput($this->getConf('default_tags'));
190        }
191
192        $allowedTags = $this->getAllowedTags();
193        if (count($allowedTags) > 0) {
194            $form->addTagOpen('div', $pos++)
195                ->addClass('blogtng__tags_checkboxes');
196            foreach($this->getAllowedTags() as $val) {
197                $checkbox = $form->addCheckbox('post-tags[]', $val, $pos++)
198                    ->val($val);
199                if(in_array($val, $tags)) {
200                    $checkbox->attr('checked', 'checked');
201                }
202            }
203            $form->addTagClose('div', $pos++);
204        } else {
205            $form->addTextInput('post-tags', 'Tags', $pos++)
206                ->id('blogtng__tags')
207                ->addClass('edit')
208                ->val(join(', ', $tags));
209        }
210
211        $commentstatus = $this->entryhelper->entry['commentstatus'];
212        $commentstatus = $INPUT->post->str('post-commentstatus', $commentstatus);
213        if(!$commentstatus) {
214            $commentstatus = $this->getConf('default_commentstatus');
215        }
216
217        $form->addDropdown('post-commentstatus', array('enabled', 'closed', 'disabled'), $this->getLang('commentstatus'), $pos++)
218            ->id('blogtng__commentstatus')
219            ->addClass('edit')
220            ->val($commentstatus);
221
222        if($this->getConf('editform_set_date')) {
223            if ($INPUT->post->has('post-date')) {
224                $date = $INPUT->post->arr('post-date');
225                $YY = (int) $date['YY'];
226                $MM = (int) $date['MM'];
227                $DD = (int) $date['DD'];
228                $hh = (int) $date['hh'];
229                $mm = (int) $date['mm'];
230            } else {
231                $created = $this->entryhelper->entry['created'];
232                if($created) {
233                    $YY = date('Y', $created);
234                    $MM = date('m', $created);
235                    $DD = date('d', $created);
236                    $hh = date('H', $created);
237                    $mm = date('i', $created);
238                } else {
239                    $time = time();
240                    $YY = date('Y', $time);
241                    $MM = date('m', $time);
242                    $DD = date('d', $time);
243                    $hh = date('H', $time);
244                    $mm = date('i', $time);
245                }
246            }
247
248            $form->addTextInput('post-date[YY]', 'YYYY', $pos++)
249                ->id('blogtng__date_YY')->addClass('edit btng__date_YY')
250                ->val($YY)->attr('maxlength', 4);
251            $form->addTextInput('post-date[MM]', 'MM', $pos++)
252                ->id('blogtng__date_MM')->addClass('edit btng__date')
253                ->val($MM)->attr('maxlength', 2);
254            $form->addTextInput('post-date[DD]', 'DD', $pos++)
255                ->id('blogtng__date_DD')->addClass('edit btng__date')
256                ->val($DD)->attr('maxlength', 2);
257            $form->addTextInput('post-date[hh]', 'hh', $pos++)
258                ->id('blogtng__date_hh')->addClass('edit btng__date')
259                ->val($hh)->attr('maxlength', 2);
260            $form->addTextInput('post-date[mm]', 'mm', $pos++)
261                ->id('blogtng__date_mm')->addClass('edit btng__date')
262                ->val($mm)->attr('maxlength', 2);
263        }
264
265        $form->addFieldsetClose($pos);
266    }
267
268    /**
269     * Save the blog related meta data of a page to the sqlite DB
270     *
271     * @param Doku_Event $event
272     * @param $param
273     */
274    function saveSubmittedFormData(Doku_Event $event, $param) {
275        global $INPUT;
276        list($type) = $param;
277
278        if (is_array($event->data)) {
279            list($act) = array_keys($event->data);
280        } else {
281            $act = $event->data;
282        }
283
284        if ($type === 'before' && $act === 'save') {
285            $this->preact = 'save';
286        // Before Greebo, intercept the after type where $act is 'show'.
287        // In Greebo and later, the before type is triggered again but with action 'draftdel'.
288        } else if ($this->preact === 'save' && (($act === 'show' && $type === 'after') || ($act === 'draftdel' && $type === 'before'))) {
289            global $ID;
290
291            // does the page still exist? might be a deletion
292            if(!page_exists($ID)) return;
293
294            $blog = $INPUT->post->str('post-blog');
295            $blogs = $this->entryhelper->getAllBlogs();
296            if (!in_array($blog, $blogs)) {
297                $blog = null;
298            }
299
300            if($blog === null) {
301                $this->entryhelper->poke();
302            } else {
303                $pid = md5($ID);
304
305                $this->entryhelper->load_by_pid($pid);
306
307                $entry = $this->collectInfoForEntry();
308                $this->entryhelper->set($entry);
309
310                $this->entryhelper->entry['blog'] = $blog;
311                $this->entryhelper->entry['commentstatus'] = $INPUT->post->str('post-commentstatus');
312
313
314                if (empty($this->entryhelper->entry['page'])) {
315                    $this->entryhelper->entry['page'] = $ID;
316                }
317
318                // allow to override created date
319                if($this->getConf('editform_set_date')) {
320                    if($INPUT->post->has('post-date')) {
321                        $date = $INPUT->post->arr('post-date');
322                        $time = mktime(
323                            (int) $date['hh'],
324                            (int) $date['mm'],
325                            0,
326                            (int) $date['MM'],
327                            (int) $date['DD'],
328                            (int) $date['YY']
329                        );
330                        $this->entryhelper->entry['created'] = $time;
331                    }
332                }
333                $this->entryhelper->save();
334
335                $tags = $this->getPostedTags();
336                $allowed_tags = $this->getAllowedTags();
337                if (count($allowed_tags) > 0) {
338                    foreach($tags as $n => $tag) {
339                        if (!in_array($tag, $allowed_tags)) {
340                            unset($tags[$n]);
341                        }
342                    }
343                }
344                $this->taghelper->load($pid);
345                $this->taghelper->setTags($tags);
346                $this->taghelper->save();
347            }
348        }
349    }
350
351    /**
352     * Return the configured allowed tags as an array, if empty all tags are allowed
353     *
354     * @return array
355     */
356    private function getAllowedTags() {
357        return helper_plugin_blogtng_tools::filterExplodeCSVinput($this->getConf('tags'));
358    }
359
360    /**
361     * Return the tags received in the current request
362     *
363     * @return array
364     */
365    private function getPostedTags() {
366        global $INPUT;
367        if(count($this->getAllowedTags()) > 0) {
368            $tags = $INPUT->post->arr('post-tags');
369        } else {
370            $tags = $INPUT->post->str('post-tags');
371            $tags = helper_plugin_blogtng_tools::filterExplodeCSVinput($tags);
372        }
373        return $tags;
374    }
375
376    /**
377     * Gather general info for a blogentry
378     *
379     * @return array
380     */
381    protected function collectInfoForEntry() {
382        /** @var DokuWiki_Auth_Plugin $auth */
383        global $auth, $ID, $INPUT;
384
385        // fetch author info
386        $login = $this->entryhelper->entry['login'];
387        if(!$login) $login = p_get_metadata($ID, 'user');
388        if(!$login) $login = $INPUT->server->str('REMOTE_USER');
389
390        $userdata = false;
391        if($login) {
392            if($auth != null) {
393                $userdata = $auth->getUserData($login);
394            }
395        }
396
397        // fetch dates
398        $date_created = p_get_metadata($ID, 'date created');
399        $date_modified = p_get_metadata($ID, 'date modified');
400
401        // prepare entry ...
402        return [
403            'page' => $ID,
404            'title' => p_get_metadata($ID, 'title'),
405            'image' => p_get_metadata($ID, 'relation firstimage'),
406            'created' => $date_created,
407            'lastmod' => (!$date_modified) ? $date_created : $date_modified,
408            'login' => $login,
409            'author' => ($userdata) ? $userdata['name'] : $login,
410            'mail' => ($userdata) ? $userdata['mail'] : '',
411        ];
412    }
413}
414