1<?php 2/** 3 * DokuWiki Plugin saveandedit (Action Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Michael Hamann <michael@content-space.de> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 13if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 15 16class action_plugin_saveandedit extends DokuWiki_Action_Plugin { 17 18 /** The action that has been handled before the current action */ 19 private $previous_act = null; 20 21 public function register(Doku_Event_Handler $controller) { 22 // try to register our handler at a late position so e.g. the edittable plugin has a possibility to process its data 23 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess', null, 1000); 24 $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'handle_html_editform_output'); 25 } 26 27 /** 28 * Clean the environment after saving for the next edit. 29 */ 30 private function clean_after_save() { 31 global $ID, $INFO, $REV, $RANGE, $TEXT, $PRE, $SUF; 32 $REV = ''; // now we are working on the current revision 33 // Handle section edits 34 if ($PRE || $SUF) { 35 // $from and $to are 1-based indexes of the actually edited content 36 $from = strlen($PRE) + 1; 37 $to = $from + strlen($TEXT); 38 $RANGE = $from . '-' . $to; 39 } 40 // Ensure the current text is loaded again from the file 41 unset($GLOBALS['TEXT'], $GLOBALS['PRE'], $GLOBALS['SUF']); 42 // Reset the date of the last modification to avoid conflict messages 43 unset($GLOBALS['DATE']); 44 // Reset the change check 45 unset($_REQUEST['changecheck']); 46 // Force rendering of the metadata in order to ensure metadata is correct 47 p_set_metadata($ID, array(), true); 48 $INFO = pageinfo(); // reset pageinfo to new data (e.g. if the page exists) 49 } 50 51 public function handle_action_act_preprocess(Doku_Event $event, $param) { 52 global $INPUT; 53 54 if (!$INPUT->bool('saveandedit')) { 55 return; 56 } 57 58 // check if the action was given as array key 59 if(is_array($event->data)){ 60 list($act) = array_keys($event->data); 61 } else { 62 $act = $event->data; 63 } 64 65 // Greebo and above 66 if (class_exists('\\dokuwiki\\ActionRouter', false)) { 67 /* 68 The ACTION_ACT_PREPROCESS event is triggered several 69 times, once for every action. After the save has been 70 executed, the next event is 'draftdel'. We intercept 71 the 'draftdel' action and replace it by 'edit'. As this 72 is a logical place where other plugins may want to save 73 data (e.g. blogtng), we try to be handled relatively 74 late. To fix plugins that want to handle the 'edit' 75 action, we trigger a new event for the 'edit' action. 76 */ 77 if ($this->previous_act === 'save' && $act === 'draftdel') { 78 $this->clean_after_save(); 79 $event->data = 'edit'; 80 81 /* 82 The edittable plugin would restore $TEXT from the 83 edittable_data post data on each 84 ACTION_ACT_PREPROCESS call. This breaks the 85 automatic restore of the prefix and suffix 86 data. Stop it from doing this by unsetting its 87 data. 88 */ 89 $INPUT->post->remove('edittable_data'); 90 91 /* 92 Stop propagation of the event. All subsequent event 93 handlers will be called anyway again by the event 94 triggered below. 95 */ 96 $event->stopPropagation(); 97 98 /* 99 Trigger a new event for the edit action. 100 This ensures that all event handlers for the edit 101 action are called. However, we only advise the 102 before handlers and re-use the default action and 103 the after handling of the original event. 104 */ 105 $new_evt = new \Doku_Event('ACTION_ACT_PREPROCESS', $event->data); 106 // prevent the default action of the original event 107 if (!$new_evt->advise_before()) { 108 $event->preventDefault(); 109 } 110 111 } 112 113 $this->previous_act = $act; 114 115 // pre-Greebo compatibility 116 } else if ($act === 'save' && actionOK($act) && act_permcheck($act) == 'save' && checkSecurityToken()) { 117 $event->data = act_save($act); 118 119 if ($event->data === 'show') { 120 $event->data = 'edit'; 121 $this->clean_after_save(); 122 } elseif ($event->data === 'conflict') { 123 // DokuWiki won't accept 'conflict' as action here. 124 // Just execute save again, the conflict will be detected again 125 $event->data = 'save'; 126 } 127 } 128 } 129 130 public function handle_html_editform_output(Doku_Event $event, $param) { 131 global $INPUT; 132 133 $pos = $event->data->findElementByAttribute('type','submit'); 134 if(!$pos) return; // no submit button found, source view 135 $pos -= 1; 136 $event->data->insertElement($pos++, form_makeOpenTag('div', array())); 137 $attrs = $INPUT->bool('saveandedit') ? array('checked' => 'checked') : array(); 138 $event->data->insertElement($pos++, form_makeCheckboxField('saveandedit', '1', $this->getLang('btn_saveandedit'), '', '', $attrs)); 139 $event->data->insertElement($pos++, form_makeCloseTag('div')); 140 } 141} 142 143// vim:ts=4:sw=4:et: 144