1<?php 2/** 3 * DokuWiki Plugin struct (Action Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12use dokuwiki\plugin\struct\meta\AccessTable; 13use dokuwiki\plugin\struct\meta\Assignments; 14use dokuwiki\plugin\struct\meta\AccessDataValidator; 15use dokuwiki\plugin\struct\meta\Value; 16 17/** 18 * Class action_plugin_struct_entry 19 * 20 * Handles the whole struct data entry process 21 */ 22class action_plugin_struct_entry extends DokuWiki_Action_Plugin { 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 Doku_Event_Handler $controller DokuWiki's event controller object 42 * @return void 43 */ 44 public function register(Doku_Event_Handler $controller) { 45 // validate data on preview and save; 46 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_validation'); 47 // ensure a page revision is created when struct data changes: 48 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handle_pagesave_before'); 49 // save struct data after page has been saved: 50 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after'); 51 } 52 53 /** 54 * Clean up and validate the input data 55 * 56 * @param Doku_Event $event event object by reference 57 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 58 * handler was registered] 59 * @return bool 60 */ 61 public function handle_validation(Doku_Event $event, $param) { 62 global $ID, $INPUT; 63 $act = act_clean($event->data); 64 if(!in_array($act, array('save', 'preview'))) return false; 65 $this->tosave = array(); 66 67 // run the validation for each assignded schema 68 $valid = AccessDataValidator::validateDataForPage($INPUT->arr(self::$VAR), $ID, $errors); 69 if($valid === false) { 70 $this->validated = false; 71 foreach($errors as $error) { 72 msg(hsc($error), -1); 73 } 74 } else { 75 $this->validated = true; 76 $this->tosave = $valid; 77 } 78 79 // FIXME we used to set the cleaned data as new input data. this caused #140 80 // could we just not do that, and keep the cleaning to saving only? and fix that bug this way? 81 82 // did validation go through? otherwise abort saving 83 if(!$this->validated && $act == 'save') { 84 $event->data = 'edit'; 85 } 86 87 return true; 88 } 89 90 /** 91 * Check if the page has to be changed 92 * 93 * @param Doku_Event $event event object by reference 94 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 95 * handler was registered] 96 * @return bool 97 */ 98 public function handle_pagesave_before(Doku_Event $event, $param) { 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(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 handle_pagesave_after(Doku_Event $event, $param) { 131 global $ACT; 132 if($ACT == 'revert') return false; // handled in revert 133 134 $assignments = Assignments::getInstance(); 135 if($event->data['changeType'] == DOKU_CHANGE_TYPE_DELETE && empty($GLOBALS['PLUGIN_MOVE_WORKING'])) { 136 // clear all data on delete unless it's a move operation 137 $tables = $assignments->getPageAssignments($event->data['id']); 138 foreach($tables as $table) { 139 $schemaData = AccessTable::byTableName($table, $event->data['id'], time()); 140 if($schemaData->getSchema()->isEditable()){ 141 $schemaData->clearData(); 142 } 143 } 144 } else { 145 // save the provided data 146 if($this->tosave) foreach($this->tosave as $validation) { 147 if($validation->getAccessTable()->getSchema()->isEditable()) { 148 $validation->saveData($event->data['newRevision']); 149 150 // make sure this schema is assigned 151 $assignments->assignPageSchema( 152 $event->data['id'], 153 $validation->getAccessTable()->getSchema()->getTable() 154 ); 155 } 156 } 157 } 158 return true; 159 } 160} 161 162// vim:ts=4:sw=4:et: 163