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