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