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