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 10use dokuwiki\plugin\struct\meta\Column; 11use dokuwiki\plugin\struct\meta\SchemaData; 12use dokuwiki\plugin\struct\meta\StructException; 13use dokuwiki\plugin\struct\meta\Title; 14use dokuwiki\plugin\struct\meta\Validator; 15 16if(!defined('DOKU_INC')) die(); 17 18/** 19 * Class action_plugin_struct_inline 20 * 21 * Handle inline editing 22 */ 23class action_plugin_struct_inline extends DokuWiki_Action_Plugin { 24 25 /** @var SchemaData */ 26 protected $schemadata = null; 27 28 /** @var Column */ 29 protected $column = null; 30 31 /** @var String */ 32 protected $pid = ''; 33 34 /** 35 * Registers a callback function for a given event 36 * 37 * @param Doku_Event_Handler $controller DokuWiki's event controller object 38 * @return void 39 */ 40 public function register(Doku_Event_Handler $controller) { 41 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax'); 42 } 43 44 /** 45 * @param Doku_Event $event 46 * @param $param 47 */ 48 public function handle_ajax(Doku_Event $event, $param) { 49 $len = strlen('plugin_struct_inline_'); 50 if(substr($event->data, 0, $len) != 'plugin_struct_inline_') return; 51 $event->preventDefault(); 52 $event->stopPropagation(); 53 54 if(substr($event->data,$len) == 'editor') { 55 $this->inline_editor(); 56 } 57 58 if(substr($event->data,$len) == 'save') { 59 try { 60 $this->inline_save(); 61 } catch(StructException $e) { 62 http_status(500); 63 header('Content-Type: text/plain; charset=utf-8'); 64 echo $e->getMessage(); 65 } 66 } 67 } 68 69 70 protected function inline_editor() { 71 if(!$this->initFromInput()) return; 72 73 74 // FIXME check read permission 75 76 // FIXME lock page 77 78 $value = $this->schemadata->getDataColumn($this->column); 79 echo '<div>'; 80 echo $value->getValueEditor('entry'); 81 echo '</div>'; 82 83 $hint = $this->column->getType()->getTranslatedHint(); 84 if($hint) { 85 echo '<div class="hint">'; 86 echo hsc($hint); 87 echo '</div>'; 88 } 89 } 90 91 protected function inline_save() { 92 global $INPUT; 93 94 if(!$this->initFromInput()) { 95 throw new StructException('inline save error'); 96 } 97 98 // FIXME 99 100 // FIXME handle CSRF protection 101 // FIXME check write permission 102 // FIXME make sure page still locked 103 104 // validate 105 $value = $INPUT->param('entry'); 106 $validator = new Validator(); 107 if(!$validator->validateValue($this->column, $value)) { 108 throw new StructException(join("\n", $validator->getErrors())); 109 } 110 111 // current data 112 $tosave = $this->schemadata->getDataArray(); 113 $tosave[$this->column->getLabel()] = $value; 114 $tosave = array($this->schemadata->getTable() => $tosave); 115 116 // save 117 /** @var helper_plugin_struct $helper */ 118 $helper = plugin_load('helper', 'struct'); 119 $helper->saveData($this->pid, $tosave, 'inline edit'); 120 121 122 // reinit then render 123 $this->initFromInput(); 124 $value = $this->schemadata->getDataColumn($this->column); 125 $R = new Doku_Renderer_xhtml(); 126 $value->render($R, 'xhtml'); // FIXME use configured default renderer 127 128 echo $R->doc; 129 } 130 131 /** 132 * Initialize internal state based on input variables 133 * 134 * @return bool if initialization was successfull 135 */ 136 protected function initFromInput() { 137 global $INPUT; 138 139 $this->schemadata = null; 140 $this->column = null; 141 142 $pid = $INPUT->str('pid'); 143 list($table, $field) = explode('.', $INPUT->str('field')); 144 if(blank($pid)) return false; 145 if(blank($table)) return false; 146 if(blank($field)) return false; 147 148 $this->pid = $pid; 149 150 $this->schemadata = new SchemaData($table, $pid, 0); 151 if(!$this->schemadata->getId()) { 152 $this->schemadata = null; 153 return false; 154 } 155 156 157 $this->column = $this->schemadata->findColumn($field); 158 if(!$this->column || !$this->column->isVisibleInEditor()) { 159 $this->schemadata = null; 160 $this->column = null; 161 return false; 162 } 163 164 return true; 165 } 166 167} 168