1<?php 2 3/** 4 * DokuWiki Plugin struct (Action Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 8 */ 9 10use dokuwiki\Extension\ActionPlugin; 11use dokuwiki\Extension\EventHandler; 12use dokuwiki\Extension\Event; 13use dokuwiki\plugin\struct\meta\AccessDataValidator; 14use dokuwiki\plugin\struct\meta\AccessTable; 15use dokuwiki\plugin\struct\meta\Assignments; 16 17/** 18 * Class action_plugin_struct_entry 19 * 20 * Handles the entry process of struct data with type "page" 21 */ 22class action_plugin_struct_entry extends ActionPlugin 23{ 24 /** 25 * @var string The form name we use to transfer schema data 26 */ 27 protected static $VAR = 'struct_schema_data'; 28 29 /** @var helper_plugin_sqlite */ 30 protected $sqlite; 31 32 /** @var bool has the data been validated correctly? */ 33 protected $validated; 34 35 /** @var AccessDataValidator[] these schemas are validated and have changed data and need to be saved */ 36 protected $tosave; 37 38 /** 39 * Registers a callback function for a given event 40 * 41 * @param EventHandler $controller DokuWiki's event controller object 42 * @return void 43 */ 44 public function register(EventHandler $controller) 45 { 46 // validate data on preview and save; 47 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleValidation'); 48 // ensure a page revision is created when struct data changes: 49 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handlePagesaveBefore'); 50 // save struct data after page has been saved: 51 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handlePagesaveAfter'); 52 } 53 54 /** 55 * Clean up and validate the input data 56 * 57 * @param Event $event event object by reference 58 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 59 * handler was registered] 60 * @return bool 61 */ 62 public function handleValidation(Event $event, $param) 63 { 64 global $ID, $INPUT; 65 $act = act_clean($event->data); 66 if (!in_array($act, ['save', 'preview'])) return false; 67 $this->tosave = []; 68 69 // run the validation for each assignded schema 70 $valid = AccessDataValidator::validateDataForPage($INPUT->arr(self::$VAR), $ID, $errors); 71 if ($valid === false) { 72 $this->validated = false; 73 foreach ($errors as $error) { 74 msg(hsc($error), -1); 75 } 76 } else { 77 $this->validated = true; 78 $this->tosave = $valid; 79 } 80 81 // FIXME we used to set the cleaned data as new input data. this caused #140 82 // could we just not do that, and keep the cleaning to saving only? and fix that bug this way? 83 84 // did validation go through? otherwise abort saving 85 if (!$this->validated && $act == 'save') { 86 $event->data = 'edit'; 87 } 88 89 return true; 90 } 91 92 /** 93 * Check if the page has to be changed 94 * 95 * @param Event $event event object by reference 96 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 97 * handler was registered] 98 * @return bool 99 */ 100 public function handlePagesaveBefore(Event $event, $param) 101 { 102 if ($event->data['contentChanged']) return false; // will be saved for page changes 103 global $ACT; 104 if ($ACT == 'revert') return false; // this is handled in revert.php 105 106 if ((is_array($this->tosave) && count($this->tosave)) || isset($GLOBALS['struct_plugin_force_page_save'])) { 107 if (trim($event->data['newContent']) === '') { 108 // this happens when a new page is tried to be created with only struct data 109 msg($this->getLang('emptypage'), -1); 110 } else { 111 $event->data['contentChanged'] = true; // save for data changes 112 113 // add a summary 114 if (empty($event->data['summary'])) { 115 $event->data['summary'] = $this->getLang('summary'); 116 } 117 } 118 } 119 120 return true; 121 } 122 123 /** 124 * Save the data 125 * 126 * When this is called, INPUT data has been validated already. 127 * 128 * @param Event $event event object by reference 129 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 130 * handler was registered] 131 * @return bool 132 */ 133 public function handlePagesaveAfter(Event $event, $param) 134 { 135 global $ACT; 136 if ($ACT == 'revert') return false; // handled in revert 137 138 $assignments = Assignments::getInstance(); 139 if ($event->data['changeType'] == DOKU_CHANGE_TYPE_DELETE && empty($GLOBALS['PLUGIN_MOVE_WORKING'])) { 140 // clear all data on delete unless it's a move operation 141 $tables = $assignments->getPageAssignments($event->data['id']); 142 foreach ($tables as $table) { 143 $schemaData = AccessTable::getPageAccess($table, $event->data['id']); 144 if ($schemaData->getSchema()->isEditable()) { 145 $schemaData->clearData(); 146 } 147 } 148 } elseif ($this->tosave) { 149 // save the provided data 150 foreach ($this->tosave as $validation) { 151 if ($validation->getAccessTable()->getSchema()->isEditable()) { 152 $validation->saveData($event->data['newRevision']); 153 154 // make sure this schema is assigned 155 $assignments->assignPageSchema( 156 $event->data['id'], 157 $validation->getAccessTable()->getSchema()->getTable() 158 ); 159 } 160 } 161 } 162 return true; 163 } 164} 165 166// vim:ts=4:sw=4:et: 167