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 plugin\struct\meta\Assignments; 13use plugin\struct\meta\SchemaData; 14use plugin\struct\meta\ValidationException; 15use plugin\struct\types\AbstractBaseType; 16 17class action_plugin_struct_entry extends DokuWiki_Action_Plugin { 18 19 /** 20 * @var string The form name we use to transfer schema data 21 */ 22 protected static $VAR = 'struct_schema_data'; 23 24 /** @var helper_plugin_sqlite */ 25 protected $sqlite; 26 27 /** 28 * Registers a callback function for a given event 29 * 30 * @param Doku_Event_Handler $controller DokuWiki's event controller object 31 * @return void 32 */ 33 public function register(Doku_Event_Handler $controller) { 34 35 $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'handle_editform'); 36 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_pagesave'); 37 38 } 39 40 /** 41 * Validate the input data and save on ACT=save. 42 * 43 * @param Doku_Event $event event object by reference 44 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 45 * handler was registered] 46 * @return bool 47 */ 48 public function handle_pagesave(Doku_Event &$event, $param) { 49 global $ID, $INPUT; 50 $act = act_clean($event->data); 51 if(!in_array($act, array('save', 'preview'))) return false; 52 53 $assignments = new Assignments(); 54 $tables = $assignments->getPageAssignments($ID); 55 $structData = $INPUT->arr(self::$VAR); 56 $timestamp = time(); //FIXME we should use the time stamp used to save the page data 57 58 $ok = true; 59 foreach($tables as $table) { 60 $schema = new SchemaData($table, $ID, $timestamp); 61 if(!$schema->getId()) { 62 // this schema is not available for some reason. skip it 63 continue; 64 } 65 66 $schemaData = $structData[$table]; 67 foreach($schema->getColumns() as $col) { 68 // fix multi value types 69 $type = $col->getType(); 70 $label = $type->getLabel(); 71 $trans = $type->getTranslatedLabel(); 72 if($type->isMulti() && !is_array($schemaData[$label])) { 73 $schemaData[$label] = $type->splitValues($schemaData[$label]); 74 } 75 76 // validate data 77 $ok = $ok & $this->validate($type, $trans, $schemaData[$label]); 78 } 79 80 // save if validated okay 81 if($ok && $act == 'save') { 82 $schema->saveData($schemaData); 83 } 84 85 // write back cleaned up schemaData 86 $structData[$table] = $schemaData; 87 } 88 // write back cleaned up structData 89 $INPUT->post->set('Schema', $structData); 90 91 // did validation go through? other wise abort saving 92 if(!$ok && $act == 'save') { 93 $event->data = 'edit'; 94 } 95 96 return false; 97 } 98 99 /** 100 * Validate the given data 101 * 102 * Catches the Validation exceptions and transforms them into proper messages. 103 * 104 * Blank values are not validated and always pass 105 * 106 * @param AbstractBaseType $type 107 * @param string $label 108 * @param array|string|int $data 109 * @return bool true if the data validates, otherwise false 110 */ 111 protected function validate(AbstractBaseType $type, $label, $data) { 112 $prefix = sprintf($this->getLang('validation_prefix'), $label); 113 114 $ok = true; 115 if(is_array($data)) { 116 foreach($data as $value) { 117 if(!blank($value)) { 118 try { 119 $type->validate($value); 120 } catch (ValidationException $e) { 121 msg($prefix . $e->getMessage(), -1); 122 $ok = false; 123 } 124 } 125 } 126 } else { 127 if(!blank($data)) { 128 try { 129 $type->validate($data); 130 } catch (ValidationException $e) { 131 msg($prefix . $e->getMessage(), -1); 132 $ok = false; 133 } 134 } 135 } 136 137 return $ok; 138 } 139 140 141 /* 142 * Enhance the editing form with structural data editing 143 * 144 * @param Doku_Event $event event object by reference 145 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 146 * handler was registered] 147 * @return bool 148 */ 149 public function handle_editform(Doku_Event $event, $param) { 150 global $ID; 151 152 $assignments = new Assignments(); 153 $tables = $assignments->getPageAssignments($ID); 154 155 $html = ''; 156 foreach($tables as $table) { 157 $html .= $this->createForm($table); 158 } 159 160 /** @var Doku_Form $form */ 161 $form = $event->data; 162 $html = "<div class=\"struct\">$html</div>"; 163 $pos = $form->findElementById('wiki__editbar'); // insert the form before the main buttons 164 $form->insertElement($pos, $html); 165 166 return true; 167 } 168 169 /** 170 * Create the form to edit schemadata 171 * 172 * @param string $tablename 173 * @return string The HTML for this schema's form 174 */ 175 protected function createForm($tablename) { 176 global $ID; 177 global $REV; 178 global $INPUT; 179 $schema = new SchemaData($tablename, $ID, $REV); 180 $schemadata = $schema->getData(); 181 182 $structdata = $INPUT->arr(self::$VAR); 183 if(isset($structdata[$tablename])) { 184 $postdata = $structdata[$tablename]; 185 } else { 186 $postdata = array(); 187 } 188 189 $html = "<h3>$tablename</h3>"; 190 foreach($schemadata as $field) { 191 $label = $field->getColumn()->getLabel(); 192 if(isset($postdata[$label])) { 193 // posted data trumps stored data 194 $field->setValue($postdata[$label]); 195 } 196 $trans = hsc($field->getColumn()->getTranslatedLabel()); 197 $name = self::$VAR . "[$tablename][$label]"; 198 $input = $field->getValueEditor($name); 199 $element = "<label>$trans $input</label><br />"; 200 $html .= $element; 201 } 202 203 return $html; 204 } 205 206} 207 208// vim:ts=4:sw=4:et: 209