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