1549a0837SAndreas Gohr<?php 2549a0837SAndreas Gohr/** 3549a0837SAndreas Gohr * DokuWiki Plugin struct (Action Component) 4549a0837SAndreas Gohr * 5549a0837SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6549a0837SAndreas Gohr * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 7549a0837SAndreas Gohr */ 8549a0837SAndreas Gohr 9549a0837SAndreas Gohr// must be run within Dokuwiki 10549a0837SAndreas Gohrif(!defined('DOKU_INC')) die(); 11549a0837SAndreas Gohr 12fb31ca9fSAndreas Gohruse plugin\struct\meta\Assignments; 13c2fd0bf0SMichael Großeuse plugin\struct\meta\SchemaData; 14*17560ecbSAndreas Gohruse plugin\struct\meta\ValidationException; 15*17560ecbSAndreas Gohruse plugin\struct\types\AbstractBaseType; 16c2fd0bf0SMichael Große 17549a0837SAndreas Gohrclass action_plugin_struct_entry extends DokuWiki_Action_Plugin { 18549a0837SAndreas Gohr 19*17560ecbSAndreas Gohr /** 20*17560ecbSAndreas Gohr * @var string The form name we use to transfer schema data 21*17560ecbSAndreas Gohr */ 22*17560ecbSAndreas Gohr protected static $VAR = 'struct_schema_data'; 23c2fd0bf0SMichael Große 24c2fd0bf0SMichael Große /** @var helper_plugin_sqlite */ 25c2fd0bf0SMichael Große protected $sqlite; 26c2fd0bf0SMichael Große 27549a0837SAndreas Gohr /** 28549a0837SAndreas Gohr * Registers a callback function for a given event 29549a0837SAndreas Gohr * 30549a0837SAndreas Gohr * @param Doku_Event_Handler $controller DokuWiki's event controller object 31549a0837SAndreas Gohr * @return void 32549a0837SAndreas Gohr */ 33549a0837SAndreas Gohr public function register(Doku_Event_Handler $controller) { 34549a0837SAndreas Gohr 35c2fd0bf0SMichael Große $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'handle_editform'); 3604641d56SMichael Große $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_pagesave'); 37549a0837SAndreas Gohr 38549a0837SAndreas Gohr } 39549a0837SAndreas Gohr 40549a0837SAndreas Gohr /** 41*17560ecbSAndreas Gohr * Validate the input data and save on ACT=save. 4204641d56SMichael Große * 4304641d56SMichael Große * @param Doku_Event $event event object by reference 4404641d56SMichael Große * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 4504641d56SMichael Große * handler was registered] 4604641d56SMichael Große * @return bool 4704641d56SMichael Große */ 4804641d56SMichael Große public function handle_pagesave(Doku_Event &$event, $param) { 493ece9074SMichael Große global $ID, $INPUT; 50*17560ecbSAndreas Gohr $act = act_clean($event->data); 51*17560ecbSAndreas Gohr if(!in_array($act, array('save', 'preview'))) return false; 5204641d56SMichael Große 53a8b9fb5bSAndreas Gohr $assignments = new Assignments(); 54a8b9fb5bSAndreas Gohr $tables = $assignments->getPageAssignments($ID); 55*17560ecbSAndreas Gohr $structData = $INPUT->arr(self::$VAR); 56bd92cd68SAndreas Gohr $timestamp = time(); //FIXME we should use the time stamp used to save the page data 5704641d56SMichael Große 58*17560ecbSAndreas Gohr $ok = true; 5904641d56SMichael Große foreach($tables as $table) { 6004641d56SMichael Große $schema = new SchemaData($table, $ID, $timestamp); 61bd92cd68SAndreas Gohr if(!$schema->getId()) { 62bd92cd68SAndreas Gohr // this schema is not available for some reason. skip it 63bd92cd68SAndreas Gohr continue; 64bd92cd68SAndreas Gohr } 65bd92cd68SAndreas Gohr 6604641d56SMichael Große $schemaData = $structData[$table]; 6704641d56SMichael Große foreach($schema->getColumns() as $col) { 68*17560ecbSAndreas Gohr // fix multi value types 69afbd4e60SMichael Große $type = $col->getType(); 70afbd4e60SMichael Große $label = $type->getLabel(); 71*17560ecbSAndreas Gohr $trans = $type->getTranslatedLabel(); 72afbd4e60SMichael Große if($type->isMulti() && !is_array($schemaData[$label])) { 73afbd4e60SMichael Große $schemaData[$label] = $type->splitValues($schemaData[$label]); 7404641d56SMichael Große } 75*17560ecbSAndreas Gohr 76*17560ecbSAndreas Gohr // validate data 77*17560ecbSAndreas Gohr $ok = $ok & $this->validate($type, $trans, $schemaData[$label]); 7804641d56SMichael Große } 79*17560ecbSAndreas Gohr 80*17560ecbSAndreas Gohr // save if validated okay 81*17560ecbSAndreas Gohr if($ok && $act == 'save') { 8204641d56SMichael Große $schema->saveData($schemaData); 8304641d56SMichael Große } 84*17560ecbSAndreas Gohr 85*17560ecbSAndreas Gohr // write back cleaned up schemaData 86*17560ecbSAndreas Gohr $structData[$table] = $schemaData; 87*17560ecbSAndreas Gohr } 88*17560ecbSAndreas Gohr // write back cleaned up structData 89*17560ecbSAndreas Gohr $INPUT->post->set('Schema', $structData); 90*17560ecbSAndreas Gohr 91*17560ecbSAndreas Gohr // did validation go through? other wise abort saving 92*17560ecbSAndreas Gohr if(!$ok && $act == 'save') { 93*17560ecbSAndreas Gohr $event->data = 'edit'; 94*17560ecbSAndreas Gohr } 95*17560ecbSAndreas Gohr 9604641d56SMichael Große return false; 9704641d56SMichael Große } 9804641d56SMichael Große 99*17560ecbSAndreas Gohr /** 100*17560ecbSAndreas Gohr * Validate the given data 101*17560ecbSAndreas Gohr * 102*17560ecbSAndreas Gohr * Catches the Validation exceptions and transforms them into proper messages. 103*17560ecbSAndreas Gohr * 104*17560ecbSAndreas Gohr * Blank values are not validated and always pass 105*17560ecbSAndreas Gohr * 106*17560ecbSAndreas Gohr * @param AbstractBaseType $type 107*17560ecbSAndreas Gohr * @param string $label 108*17560ecbSAndreas Gohr * @param array|string|int $data 109*17560ecbSAndreas Gohr * @return bool true if the data validates, otherwise false 110*17560ecbSAndreas Gohr */ 111*17560ecbSAndreas Gohr protected function validate(AbstractBaseType $type, $label, $data) { 112*17560ecbSAndreas Gohr $prefix = sprintf($this->getLang('validation_prefix'), $label); 113*17560ecbSAndreas Gohr 114*17560ecbSAndreas Gohr $ok = true; 115*17560ecbSAndreas Gohr if(is_array($data)) { 116*17560ecbSAndreas Gohr foreach($data as $value) { 117*17560ecbSAndreas Gohr if(!blank($value)) { 118*17560ecbSAndreas Gohr try { 119*17560ecbSAndreas Gohr $type->validate($value); 120*17560ecbSAndreas Gohr } catch (ValidationException $e) { 121*17560ecbSAndreas Gohr msg($prefix . $e->getMessage(), -1); 122*17560ecbSAndreas Gohr $ok = false; 123*17560ecbSAndreas Gohr } 124*17560ecbSAndreas Gohr } 125*17560ecbSAndreas Gohr } 126*17560ecbSAndreas Gohr } else { 127*17560ecbSAndreas Gohr if(!blank($data)) { 128*17560ecbSAndreas Gohr try { 129*17560ecbSAndreas Gohr $type->validate($data); 130*17560ecbSAndreas Gohr } catch (ValidationException $e) { 131*17560ecbSAndreas Gohr msg($prefix . $e->getMessage(), -1); 132*17560ecbSAndreas Gohr $ok = false; 133*17560ecbSAndreas Gohr } 134*17560ecbSAndreas Gohr } 135*17560ecbSAndreas Gohr } 136*17560ecbSAndreas Gohr 137*17560ecbSAndreas Gohr return $ok; 138*17560ecbSAndreas Gohr } 139*17560ecbSAndreas Gohr 140*17560ecbSAndreas Gohr 141016bf382SMichael Große /* 142f36fda9dSAndreas Gohr * Enhance the editing form with structural data editing 143549a0837SAndreas Gohr * 144549a0837SAndreas Gohr * @param Doku_Event $event event object by reference 145549a0837SAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 146549a0837SAndreas Gohr * handler was registered] 147c2fd0bf0SMichael Große * @return bool 148549a0837SAndreas Gohr */ 149c07703d4SAndreas Gohr public function handle_editform(Doku_Event $event, $param) { 15065598e4aSAndreas Gohr global $ID; 151c2fd0bf0SMichael Große 152fb31ca9fSAndreas Gohr $assignments = new Assignments(); 153fb31ca9fSAndreas Gohr $tables = $assignments->getPageAssignments($ID); 154c2fd0bf0SMichael Große 15565598e4aSAndreas Gohr $html = ''; 156c2fd0bf0SMichael Große foreach($tables as $table) { 15765598e4aSAndreas Gohr $html .= $this->createForm($table); 158c2fd0bf0SMichael Große } 159c2fd0bf0SMichael Große 16065598e4aSAndreas Gohr /** @var Doku_Form $form */ 16165598e4aSAndreas Gohr $form = $event->data; 16265598e4aSAndreas Gohr $html = "<div class=\"struct\">$html</div>"; 16365598e4aSAndreas Gohr $pos = $form->findElementById('wiki__editbar'); // insert the form before the main buttons 16465598e4aSAndreas Gohr $form->insertElement($pos, $html); 16565598e4aSAndreas Gohr 166c2fd0bf0SMichael Große return true; 167c2fd0bf0SMichael Große } 168c2fd0bf0SMichael Große 169c2fd0bf0SMichael Große /** 17065598e4aSAndreas Gohr * Create the form to edit schemadata 171f36fda9dSAndreas Gohr * 172c2fd0bf0SMichael Große * @param string $tablename 17365598e4aSAndreas Gohr * @return string The HTML for this schema's form 174c2fd0bf0SMichael Große */ 17565598e4aSAndreas Gohr protected function createForm($tablename) { 176c2fd0bf0SMichael Große global $ID; 17783beda18SAndreas Gohr global $REV; 178*17560ecbSAndreas Gohr global $INPUT; 17983beda18SAndreas Gohr $schema = new SchemaData($tablename, $ID, $REV); 180c2fd0bf0SMichael Große $schemadata = $schema->getData(); 181c2fd0bf0SMichael Große 182*17560ecbSAndreas Gohr $structdata = $INPUT->arr(self::$VAR); 183*17560ecbSAndreas Gohr if(isset($structdata[$tablename])) { 184*17560ecbSAndreas Gohr $postdata = $structdata[$tablename]; 185*17560ecbSAndreas Gohr } else { 186*17560ecbSAndreas Gohr $postdata = array(); 187*17560ecbSAndreas Gohr } 188*17560ecbSAndreas Gohr 18965598e4aSAndreas Gohr $html = "<h3>$tablename</h3>"; 190053212b1SAndreas Gohr foreach($schemadata as $field) { 191053212b1SAndreas Gohr $label = $field->getColumn()->getLabel(); 192*17560ecbSAndreas Gohr if(isset($postdata[$label])) { 193*17560ecbSAndreas Gohr // posted data trumps stored data 194*17560ecbSAndreas Gohr $field->setValue($postdata[$label]); 195*17560ecbSAndreas Gohr } 1969e9bee91SAndreas Gohr $trans = hsc($field->getColumn()->getTranslatedLabel()); 197*17560ecbSAndreas Gohr $name = self::$VAR . "[$tablename][$label]"; 198053212b1SAndreas Gohr $input = $field->getValueEditor($name); 1999e9bee91SAndreas Gohr $element = "<label>$trans $input</label><br />"; 20065598e4aSAndreas Gohr $html .= $element; 201c2fd0bf0SMichael Große } 20265598e4aSAndreas Gohr 20365598e4aSAndreas Gohr return $html; 204549a0837SAndreas Gohr } 205549a0837SAndreas Gohr 206549a0837SAndreas Gohr} 207549a0837SAndreas Gohr 208549a0837SAndreas Gohr// vim:ts=4:sw=4:et: 209