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\AccessTableGlobal; 12use dokuwiki\plugin\struct\meta\AggregationEditorTable; 13use dokuwiki\plugin\struct\meta\Column; 14use dokuwiki\plugin\struct\meta\Schema; 15use dokuwiki\plugin\struct\meta\SearchConfig; 16use dokuwiki\plugin\struct\meta\StructException; 17use dokuwiki\plugin\struct\meta\Value; 18 19/** 20 * Class action_plugin_struct_lookup 21 * 22 * Handle global and serial data table editing 23 */ 24class action_plugin_struct_aggregationeditor extends DokuWiki_Action_Plugin 25{ 26 /** @var Column */ 27 protected $column = null; 28 29 /** @var string */ 30 protected $pid = ''; 31 32 /** @var int */ 33 protected $rid = 0; 34 35 /** 36 * Registers a callback function for a given event 37 * 38 * @param Doku_Event_Handler $controller DokuWiki's event controller object 39 * @return void 40 */ 41 public function register(Doku_Event_Handler $controller) 42 { 43 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax'); 44 } 45 46 /** 47 * @param Doku_Event $event 48 * @param $param 49 */ 50 public function handleAjax(Doku_Event $event, $param) 51 { 52 $len = strlen('plugin_struct_aggregationeditor_'); 53 if (substr($event->data, 0, $len) != 'plugin_struct_aggregationeditor_') { 54 return; 55 } 56 $event->preventDefault(); 57 $event->stopPropagation(); 58 59 try { 60 if (substr($event->data, $len) == 'new') { 61 $this->newRowEditor(); 62 } 63 64 if (substr($event->data, $len) == 'save') { 65 $this->saveRow(); 66 } 67 68 if (substr($event->data, $len) == 'delete') { 69 $this->deleteRow(); 70 } 71 } catch (StructException $e) { 72 http_status(500); 73 header('Content-Type: text/plain'); 74 echo $e->getMessage(); 75 } 76 } 77 78 /** 79 * Deletes a row 80 */ 81 protected function deleteRow() 82 { 83 global $INPUT; 84 $tablename = $INPUT->str('schema'); 85 if (!$tablename) { 86 throw new StructException('No schema given'); 87 } 88 89 $this->rid = $INPUT->int('rid'); 90 $this->validate(); 91 92 action_plugin_struct_inline::checkCSRF(); 93 94 $access = $this->getAccess($tablename); 95 if (!$access->getSchema()->isEditable()) { 96 throw new StructException('lookup delete error: no permission for schema'); 97 } 98 $access->clearData(); 99 } 100 101 /** 102 * Save one new row 103 */ 104 protected function saveRow() 105 { 106 global $INPUT; 107 $tablename = $INPUT->str('schema'); 108 $data = $INPUT->arr('entry'); 109 $this->pid = $INPUT->str('pid'); 110 action_plugin_struct_inline::checkCSRF(); 111 112 // create a new row based on the original aggregation config 113 $access = $this->getAccess($tablename); 114 115 /** @var helper_plugin_struct $helper */ 116 $helper = plugin_load('helper', 'struct'); 117 $helper->saveLookupData($access, $data); 118 119 $config = json_decode($INPUT->str('searchconf'), true); 120 // update row id 121 $this->rid = $access->getRid(); 122 $config = $this->addTypeFilter($config); 123 124 $editorTable = new AggregationEditorTable( 125 $this->pid, 126 'xhtml', 127 new Doku_Renderer_xhtml(), 128 new SearchConfig($config) 129 ); 130 131 echo $editorTable->getFirstRow(); 132 } 133 134 /** 135 * Create the Editor for a new row 136 */ 137 protected function newRowEditor() 138 { 139 global $INPUT; 140 global $lang; 141 $tablename = $INPUT->str('schema'); 142 143 $schema = new Schema($tablename); 144 if (!$schema->isEditable()) { 145 return; 146 } // no permissions, no editor 147 148 echo '<div class="struct_entry_form">'; 149 echo '<fieldset>'; 150 echo '<legend>' . $this->getLang('lookup new entry') . '</legend>'; 151 /** @var action_plugin_struct_edit $edit */ 152 $edit = plugin_load('action', 'struct_edit'); 153 foreach ($schema->getColumns(false) as $column) { 154 $label = $column->getLabel(); 155 $field = new Value($column, ''); 156 echo $edit->makeField($field, "entry[$label]"); 157 } 158 formSecurityToken(); // csrf protection 159 echo '<input type="hidden" name="call" value="plugin_struct_aggregationeditor_save" />'; 160 echo '<input type="hidden" name="schema" value="' . hsc($tablename) . '" />'; 161 162 echo '<button type="submit">' . $lang['btn_save'] . '</button>'; 163 164 echo '<div class="err"></div>'; 165 echo '</fieldset>'; 166 echo '</div>'; 167 } 168 169 /** 170 * Returns data accessor 171 * 172 * @param string $tablename 173 * @return AccessTableGlobal 174 */ 175 protected function getAccess($tablename) 176 { 177 if ($this->pid) { 178 return AccessTable::getSerialAccess($tablename, $this->pid, $this->rid); 179 } 180 return AccessTable::getGlobalAccess($tablename, $this->rid); 181 } 182 183 /** 184 * Adds filter to search config to differentiate data types 185 * 186 * @param array $config 187 * @return array 188 */ 189 protected function addTypeFilter($config) 190 { 191 $config['filter'][] = ['%rowid%', '=', $this->rid, 'AND']; 192 if ($this->pid) { 193 $config['filter'][] = ['%pageid%', '=', $this->pid, 'AND']; 194 } 195 return $config; 196 } 197 198 /** 199 * Throws an exception if data is invalid 200 */ 201 protected function validate() 202 { 203 if (!$this->rid) { 204 throw new StructException('No row id given'); 205 } 206 } 207} 208