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