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