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