1308cc83fSAndreas Gohr<?php 2308cc83fSAndreas Gohr 3308cc83fSAndreas Gohr/** 4308cc83fSAndreas Gohr * DokuWiki Plugin struct (Action Component) 5308cc83fSAndreas Gohr * 6308cc83fSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7308cc83fSAndreas Gohr * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 8308cc83fSAndreas Gohr */ 9308cc83fSAndreas Gohr 10308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTable; 11308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTableGlobal; 12308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\AggregationEditorTable; 130549dcc5SAndreas Gohruse dokuwiki\plugin\struct\meta\Column; 14308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\Schema; 15308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\SearchConfig; 16308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\StructException; 17308cc83fSAndreas Gohruse dokuwiki\plugin\struct\meta\Value; 18308cc83fSAndreas Gohr 19308cc83fSAndreas Gohr/** 20308cc83fSAndreas Gohr * Class action_plugin_struct_lookup 21308cc83fSAndreas Gohr * 22308cc83fSAndreas Gohr * Handle global and serial data table editing 23308cc83fSAndreas Gohr */ 24308cc83fSAndreas Gohrclass action_plugin_struct_aggregationeditor extends DokuWiki_Action_Plugin 25308cc83fSAndreas Gohr{ 26308cc83fSAndreas Gohr /** @var Column */ 27308cc83fSAndreas Gohr protected $column = null; 28308cc83fSAndreas Gohr 29308cc83fSAndreas Gohr /** @var string */ 30308cc83fSAndreas Gohr protected $pid = ''; 31308cc83fSAndreas Gohr 32308cc83fSAndreas Gohr /** @var int */ 33308cc83fSAndreas Gohr protected $rid = 0; 34308cc83fSAndreas Gohr 35308cc83fSAndreas Gohr /** 36308cc83fSAndreas Gohr * Registers a callback function for a given event 37308cc83fSAndreas Gohr * 38308cc83fSAndreas Gohr * @param Doku_Event_Handler $controller DokuWiki's event controller object 39308cc83fSAndreas Gohr * @return void 40308cc83fSAndreas Gohr */ 41308cc83fSAndreas Gohr public function register(Doku_Event_Handler $controller) 42308cc83fSAndreas Gohr { 4317dda596SAnna Dabrowska $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'addJsinfo'); 44308cc83fSAndreas Gohr $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax'); 45308cc83fSAndreas Gohr } 46308cc83fSAndreas Gohr 47308cc83fSAndreas Gohr /** 4817dda596SAnna Dabrowska * Add user's permissions to JSINFO 4917dda596SAnna Dabrowska * 50308cc83fSAndreas Gohr * @param Doku_Event $event 51308cc83fSAndreas Gohr */ 5217dda596SAnna Dabrowska public function addJsinfo(Doku_Event $event) 5317dda596SAnna Dabrowska { 5417dda596SAnna Dabrowska global $ID; 5517dda596SAnna Dabrowska global $JSINFO; 5617dda596SAnna Dabrowska $JSINFO['plugins']['struct']['isPageEditor'] = (bool)(auth_quickaclcheck($ID) >= AUTH_EDIT); 5717dda596SAnna Dabrowska } 5817dda596SAnna Dabrowska 5917dda596SAnna Dabrowska 6017dda596SAnna Dabrowska /** 6117dda596SAnna Dabrowska * @param Doku_Event $event 6217dda596SAnna Dabrowska */ 6317dda596SAnna Dabrowska public function handleAjax(Doku_Event $event) 64308cc83fSAndreas Gohr { 65308cc83fSAndreas Gohr $len = strlen('plugin_struct_aggregationeditor_'); 66308cc83fSAndreas Gohr if (substr($event->data, 0, $len) != 'plugin_struct_aggregationeditor_') { 67308cc83fSAndreas Gohr return; 68308cc83fSAndreas Gohr } 69308cc83fSAndreas Gohr $event->preventDefault(); 70308cc83fSAndreas Gohr $event->stopPropagation(); 71308cc83fSAndreas Gohr 72308cc83fSAndreas Gohr try { 73308cc83fSAndreas Gohr if (substr($event->data, $len) == 'new') { 74308cc83fSAndreas Gohr $this->newRowEditor(); 75308cc83fSAndreas Gohr } 76308cc83fSAndreas Gohr 77308cc83fSAndreas Gohr if (substr($event->data, $len) == 'save') { 78308cc83fSAndreas Gohr $this->saveRow(); 79308cc83fSAndreas Gohr } 80308cc83fSAndreas Gohr 81308cc83fSAndreas Gohr if (substr($event->data, $len) == 'delete') { 82308cc83fSAndreas Gohr $this->deleteRow(); 83308cc83fSAndreas Gohr } 84308cc83fSAndreas Gohr } catch (StructException $e) { 85308cc83fSAndreas Gohr http_status(500); 86308cc83fSAndreas Gohr header('Content-Type: text/plain'); 87308cc83fSAndreas Gohr echo $e->getMessage(); 88308cc83fSAndreas Gohr } 89308cc83fSAndreas Gohr } 90308cc83fSAndreas Gohr 91308cc83fSAndreas Gohr /** 92308cc83fSAndreas Gohr * Deletes a row 93308cc83fSAndreas Gohr */ 94308cc83fSAndreas Gohr protected function deleteRow() 95308cc83fSAndreas Gohr { 96308cc83fSAndreas Gohr global $INPUT; 97308cc83fSAndreas Gohr $tablename = $INPUT->str('schema'); 98308cc83fSAndreas Gohr if (!$tablename) { 99308cc83fSAndreas Gohr throw new StructException('No schema given'); 100308cc83fSAndreas Gohr } 101308cc83fSAndreas Gohr 102308cc83fSAndreas Gohr $this->rid = $INPUT->int('rid'); 103308cc83fSAndreas Gohr $this->validate(); 104308cc83fSAndreas Gohr 105308cc83fSAndreas Gohr action_plugin_struct_inline::checkCSRF(); 106308cc83fSAndreas Gohr 107308cc83fSAndreas Gohr $access = $this->getAccess($tablename); 108308cc83fSAndreas Gohr if (!$access->getSchema()->isEditable()) { 109308cc83fSAndreas Gohr throw new StructException('lookup delete error: no permission for schema'); 110308cc83fSAndreas Gohr } 111308cc83fSAndreas Gohr $access->clearData(); 112308cc83fSAndreas Gohr } 113308cc83fSAndreas Gohr 114308cc83fSAndreas Gohr /** 115308cc83fSAndreas Gohr * Save one new row 116308cc83fSAndreas Gohr */ 117308cc83fSAndreas Gohr protected function saveRow() 118308cc83fSAndreas Gohr { 119308cc83fSAndreas Gohr global $INPUT; 120308cc83fSAndreas Gohr $tablename = $INPUT->str('schema'); 121308cc83fSAndreas Gohr $data = $INPUT->arr('entry'); 122308cc83fSAndreas Gohr $this->pid = $INPUT->str('pid'); 123308cc83fSAndreas Gohr action_plugin_struct_inline::checkCSRF(); 124308cc83fSAndreas Gohr 125308cc83fSAndreas Gohr // create a new row based on the original aggregation config 126308cc83fSAndreas Gohr $access = $this->getAccess($tablename); 127308cc83fSAndreas Gohr 128308cc83fSAndreas Gohr /** @var helper_plugin_struct $helper */ 129308cc83fSAndreas Gohr $helper = plugin_load('helper', 'struct'); 130308cc83fSAndreas Gohr $helper->saveLookupData($access, $data); 131308cc83fSAndreas Gohr 132308cc83fSAndreas Gohr $config = json_decode($INPUT->str('searchconf'), true); 133308cc83fSAndreas Gohr // update row id 134308cc83fSAndreas Gohr $this->rid = $access->getRid(); 135308cc83fSAndreas Gohr $config = $this->addTypeFilter($config); 136308cc83fSAndreas Gohr 137308cc83fSAndreas Gohr $editorTable = new AggregationEditorTable( 138308cc83fSAndreas Gohr $this->pid, 139308cc83fSAndreas Gohr 'xhtml', 140308cc83fSAndreas Gohr new Doku_Renderer_xhtml(), 141308cc83fSAndreas Gohr new SearchConfig($config) 142308cc83fSAndreas Gohr ); 143308cc83fSAndreas Gohr 144308cc83fSAndreas Gohr echo $editorTable->getFirstRow(); 145308cc83fSAndreas Gohr } 146308cc83fSAndreas Gohr 147308cc83fSAndreas Gohr /** 148308cc83fSAndreas Gohr * Create the Editor for a new row 149308cc83fSAndreas Gohr */ 150308cc83fSAndreas Gohr protected function newRowEditor() 151308cc83fSAndreas Gohr { 152308cc83fSAndreas Gohr global $INPUT; 153308cc83fSAndreas Gohr global $lang; 154*87788c7fSAnna Dabrowska $tablename = $INPUT->arr('data')['schema']; 155308cc83fSAndreas Gohr 156308cc83fSAndreas Gohr $schema = new Schema($tablename); 157308cc83fSAndreas Gohr if (!$schema->isEditable()) { 158308cc83fSAndreas Gohr return; 159308cc83fSAndreas Gohr } // no permissions, no editor 16017dda596SAnna Dabrowska // separate check for serial data in JS 161308cc83fSAndreas Gohr 162308cc83fSAndreas Gohr echo '<div class="struct_entry_form">'; 163308cc83fSAndreas Gohr echo '<fieldset>'; 164308cc83fSAndreas Gohr echo '<legend>' . $this->getLang('lookup new entry') . '</legend>'; 165308cc83fSAndreas Gohr /** @var action_plugin_struct_edit $edit */ 166308cc83fSAndreas Gohr $edit = plugin_load('action', 'struct_edit'); 167*87788c7fSAnna Dabrowska 168*87788c7fSAnna Dabrowska // filter columns based on searchconf cols from syntax 169*87788c7fSAnna Dabrowska $columns = []; 170*87788c7fSAnna Dabrowska if (!empty($INPUT->arr('data')['searchconf']['cols']) && is_array($INPUT->arr('data')['searchconf']['cols'])) { 171*87788c7fSAnna Dabrowska foreach ($INPUT->arr('data')['searchconf']['cols'] as $col) { 172*87788c7fSAnna Dabrowska $columns[] = $schema->findColumn($col); 173*87788c7fSAnna Dabrowska } 174*87788c7fSAnna Dabrowska } else { 175*87788c7fSAnna Dabrowska $columns = $schema->getColumns(false); 176*87788c7fSAnna Dabrowska } 177*87788c7fSAnna Dabrowska 178*87788c7fSAnna Dabrowska foreach ($columns as $column) { 179308cc83fSAndreas Gohr $label = $column->getLabel(); 180308cc83fSAndreas Gohr $field = new Value($column, ''); 181308cc83fSAndreas Gohr echo $edit->makeField($field, "entry[$label]"); 182308cc83fSAndreas Gohr } 183308cc83fSAndreas Gohr formSecurityToken(); // csrf protection 184308cc83fSAndreas Gohr echo '<input type="hidden" name="call" value="plugin_struct_aggregationeditor_save" />'; 185308cc83fSAndreas Gohr echo '<input type="hidden" name="schema" value="' . hsc($tablename) . '" />'; 186308cc83fSAndreas Gohr 187308cc83fSAndreas Gohr echo '<button type="submit">' . $lang['btn_save'] . '</button>'; 188308cc83fSAndreas Gohr 189308cc83fSAndreas Gohr echo '<div class="err"></div>'; 190308cc83fSAndreas Gohr echo '</fieldset>'; 191308cc83fSAndreas Gohr echo '</div>'; 192308cc83fSAndreas Gohr } 193308cc83fSAndreas Gohr 194308cc83fSAndreas Gohr /** 195308cc83fSAndreas Gohr * Returns data accessor 196308cc83fSAndreas Gohr * 197308cc83fSAndreas Gohr * @param string $tablename 198308cc83fSAndreas Gohr * @return AccessTableGlobal 199308cc83fSAndreas Gohr */ 200308cc83fSAndreas Gohr protected function getAccess($tablename) 201308cc83fSAndreas Gohr { 202308cc83fSAndreas Gohr if ($this->pid) { 203308cc83fSAndreas Gohr return AccessTable::getSerialAccess($tablename, $this->pid, $this->rid); 204308cc83fSAndreas Gohr } 205ed77599cSAnna Dabrowska return AccessTable::getGlobalAccess($tablename, $this->rid); 206308cc83fSAndreas Gohr } 207308cc83fSAndreas Gohr 208308cc83fSAndreas Gohr /** 209308cc83fSAndreas Gohr * Adds filter to search config to differentiate data types 210308cc83fSAndreas Gohr * 211308cc83fSAndreas Gohr * @param array $config 212308cc83fSAndreas Gohr * @return array 213308cc83fSAndreas Gohr */ 214308cc83fSAndreas Gohr protected function addTypeFilter($config) 215308cc83fSAndreas Gohr { 216308cc83fSAndreas Gohr $config['filter'][] = ['%rowid%', '=', $this->rid, 'AND']; 217308cc83fSAndreas Gohr if ($this->pid) { 218308cc83fSAndreas Gohr $config['filter'][] = ['%pageid%', '=', $this->pid, 'AND']; 219308cc83fSAndreas Gohr } 220308cc83fSAndreas Gohr return $config; 221308cc83fSAndreas Gohr } 222308cc83fSAndreas Gohr 223308cc83fSAndreas Gohr /** 224308cc83fSAndreas Gohr * Throws an exception if data is invalid 225308cc83fSAndreas Gohr */ 226308cc83fSAndreas Gohr protected function validate() 227308cc83fSAndreas Gohr { 228308cc83fSAndreas Gohr if (!$this->rid) { 229308cc83fSAndreas Gohr throw new StructException('No row id given'); 230308cc83fSAndreas Gohr } 231308cc83fSAndreas Gohr } 232308cc83fSAndreas Gohr} 233