13ad9c1eaSAndreas Gohr<?php 2d6d97f60SAnna Dabrowska 33ad9c1eaSAndreas Gohr/** 43ad9c1eaSAndreas Gohr * DokuWiki Plugin struct (Action Component) 53ad9c1eaSAndreas Gohr * 63ad9c1eaSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 73ad9c1eaSAndreas Gohr * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 83ad9c1eaSAndreas Gohr */ 93ad9c1eaSAndreas Gohr 107234bfb1Ssplitbrainuse dokuwiki\Extension\ActionPlugin; 117234bfb1Ssplitbrainuse dokuwiki\Extension\EventHandler; 127234bfb1Ssplitbrainuse dokuwiki\Extension\Event; 13f411d872SAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTable; 149fc5ecc2SMichael Grosseuse dokuwiki\plugin\struct\meta\Assignments; 15ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Schema; 16345c3838SSzymon Olewniczakuse dokuwiki\plugin\struct\meta\Search; 17e46eaffdSSzymon Olewniczakuse dokuwiki\plugin\struct\types\Lookup; 183ad9c1eaSAndreas Gohr 193ad9c1eaSAndreas Gohr/** 20cfe2b908SAndreas Gohr * Handles bureaucracy additions 213ad9c1eaSAndreas Gohr * 223ad9c1eaSAndreas Gohr * This registers to the template action of the bureaucracy plugin and saves all struct data 23cfe2b908SAndreas Gohr * submitted through the bureaucracy form to all newly created pages (if the schema applies). 24cfe2b908SAndreas Gohr * 25cfe2b908SAndreas Gohr * It also registers the struct_schema type for bureaucracy which will add all fields of the 26cfe2b908SAndreas Gohr * schema to the form. The struct_field type is added through standard naming convention - see 27cfe2b908SAndreas Gohr * helper/fiels.php for that. 283ad9c1eaSAndreas Gohr */ 297234bfb1Ssplitbrainclass action_plugin_struct_bureaucracy extends ActionPlugin 30d6d97f60SAnna Dabrowska{ 313ad9c1eaSAndreas Gohr /** 323ad9c1eaSAndreas Gohr * Registers a callback function for a given event 333ad9c1eaSAndreas Gohr * 345e29103aSannda * @param EventHandler $controller DokuWiki's event controller object 353ad9c1eaSAndreas Gohr * @return void 363ad9c1eaSAndreas Gohr */ 377234bfb1Ssplitbrain public function register(EventHandler $controller) 38d6d97f60SAnna Dabrowska { 39e0f75a3fSAnna Dabrowska $controller->register_hook('PLUGIN_BUREAUCRACY_PAGENAME', 'BEFORE', $this, 'handleLookupFields'); 4002e7eff2SAnna Dabrowska $controller->register_hook('PLUGIN_BUREAUCRACY_EMAIL_SEND', 'BEFORE', $this, 'handleLookupFields'); 41748e747fSAnna Dabrowska $controller->register_hook('PLUGIN_BUREAUCRACY_TEMPLATE_SAVE', 'AFTER', $this, 'handleSave'); 42748e747fSAnna Dabrowska $controller->register_hook('PLUGIN_BUREAUCRACY_FIELD_UNKNOWN', 'BEFORE', $this, 'handleSchema'); 43cfe2b908SAndreas Gohr } 44cfe2b908SAndreas Gohr 45cfe2b908SAndreas Gohr /** 46cfe2b908SAndreas Gohr * Load a whole schema as fields 47cfe2b908SAndreas Gohr * 485e29103aSannda * @param Event $event event object by reference 49cfe2b908SAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 50cfe2b908SAndreas Gohr * handler was registered] 51cfe2b908SAndreas Gohr * @return bool 52cfe2b908SAndreas Gohr */ 537234bfb1Ssplitbrain public function handleSchema(Event $event, $param) 54d6d97f60SAnna Dabrowska { 55cfe2b908SAndreas Gohr $args = $event->data['args']; 5693ca6f4fSAndreas Gohr if ($args[0] != 'struct_schema') return false; 57cfe2b908SAndreas Gohr $event->preventDefault(); 58cfe2b908SAndreas Gohr $event->stopPropagation(); 59cfe2b908SAndreas Gohr 60cfe2b908SAndreas Gohr /** @var helper_plugin_bureaucracy_field $helper */ 61cfe2b908SAndreas Gohr $helper = plugin_load('helper', 'bureaucracy_field'); 62cfe2b908SAndreas Gohr $helper->initialize($args); 63cfe2b908SAndreas Gohr 64cfe2b908SAndreas Gohr $schema = new Schema($helper->opt['label']); 65cfe2b908SAndreas Gohr if (!$schema->getId()) { 66cfe2b908SAndreas Gohr msg('This schema does not exist', -1); 6793ca6f4fSAndreas Gohr return false; 68cfe2b908SAndreas Gohr } 69cfe2b908SAndreas Gohr 70cfe2b908SAndreas Gohr foreach ($schema->getColumns(false) as $column) { 71cfe2b908SAndreas Gohr /** @var helper_plugin_struct_field $field */ 72cfe2b908SAndreas Gohr $field = plugin_load('helper', 'struct_field'); 73cfe2b908SAndreas Gohr // we don't initialize the field but set the appropriate values 74cfe2b908SAndreas Gohr $field->opt = $helper->opt; // copy all the settings to each field 75cfe2b908SAndreas Gohr $field->opt['label'] = $column->getFullQualifiedLabel(); 76cfe2b908SAndreas Gohr $field->column = $column; 77cfe2b908SAndreas Gohr $event->data['fields'][] = $field; 78cfe2b908SAndreas Gohr } 7993ca6f4fSAndreas Gohr return true; 803ad9c1eaSAndreas Gohr } 813ad9c1eaSAndreas Gohr 823ad9c1eaSAndreas Gohr /** 83345c3838SSzymon Olewniczak * Replace lookup fields placeholder's values 84345c3838SSzymon Olewniczak * 855e29103aSannda * @param Event $event event object by reference 86345c3838SSzymon Olewniczak * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 87345c3838SSzymon Olewniczak * handler was registered] 88345c3838SSzymon Olewniczak * @return bool 89345c3838SSzymon Olewniczak */ 907234bfb1Ssplitbrain public function handleLookupFields(Event $event, $param) 91d6d97f60SAnna Dabrowska { 92345c3838SSzymon Olewniczak foreach ($event->data['fields'] as $field) { 93345c3838SSzymon Olewniczak if (!is_a($field, 'helper_plugin_struct_field')) continue; 94e46eaffdSSzymon Olewniczak if (!$field->column->getType() instanceof Lookup) continue; 95345c3838SSzymon Olewniczak 96987ccc7fSSzymon Olewniczak $value = $field->getParam('value'); 977234bfb1Ssplitbrain if (!is_array($value)) $value = [$value]; 98987ccc7fSSzymon Olewniczak 99345c3838SSzymon Olewniczak $config = $field->column->getType()->getConfig(); 100345c3838SSzymon Olewniczak 101345c3838SSzymon Olewniczak // find proper value 102345c3838SSzymon Olewniczak // current Search implementation doesn't allow doing it using SQL 103345c3838SSzymon Olewniczak $search = new Search(); 104345c3838SSzymon Olewniczak $search->addSchema($config['schema']); 105345c3838SSzymon Olewniczak $search->addColumn($config['field']); 106*ba7f5789SAnna Dabrowska $result = $search->getRows(); 107345c3838SSzymon Olewniczak $pids = $search->getPids(); 10817308e28SAnna Dabrowska $rids = $search->getRids(); 109345c3838SSzymon Olewniczak 1107234bfb1Ssplitbrain $field->opt['struct_pids'] = []; 1117234bfb1Ssplitbrain $new_value = []; 112987ccc7fSSzymon Olewniczak foreach ($value as $pid) { 1137234bfb1Ssplitbrain $counter = count($result); 1147234bfb1Ssplitbrain for ($i = 0; $i < $counter; $i++) { 11517308e28SAnna Dabrowska // lookups can reference pages or global data, so check both pid and rid 11625708572SAnna Dabrowska // make sure not to double decode pid! 11725708572SAnna Dabrowska $originalPid = $pid; 11830ad7b71SAnna Dabrowska // do not throw JSON exception here, we supply alternative values if json_decode doesn't 11930ad7b71SAnna Dabrowska $pid = json_decode($pid, null, 512)[0] ?? $pid; 12030ad7b71SAnna Dabrowska $rid = json_decode($originalPid, null, 512)[1] ?? null; 12130ad7b71SAnna Dabrowska if (($pid && $pids[$i] === $pid) || ($rid && $rids[$i] === $rid)) { 122987ccc7fSSzymon Olewniczak $field->opt['struct_pids'][] = $pid; 123987ccc7fSSzymon Olewniczak $new_value[] = $result[$i][0]->getDisplayValue(); 124987ccc7fSSzymon Olewniczak } 125345c3838SSzymon Olewniczak } 126345c3838SSzymon Olewniczak } 127345c3838SSzymon Olewniczak 128345c3838SSzymon Olewniczak //replace previous value 129987ccc7fSSzymon Olewniczak if ($field->column->isMulti()) { 130987ccc7fSSzymon Olewniczak $field->opt['value'] = $new_value; 131987ccc7fSSzymon Olewniczak } else { 13225708572SAnna Dabrowska $event->data['values'][$field->column->getFullQualifiedLabel()] = $new_value[0] ?? ''; 133345c3838SSzymon Olewniczak } 134345c3838SSzymon Olewniczak } 135345c3838SSzymon Olewniczak return true; 136345c3838SSzymon Olewniczak } 137345c3838SSzymon Olewniczak 138345c3838SSzymon Olewniczak /** 1393ad9c1eaSAndreas Gohr * Save the struct data 1403ad9c1eaSAndreas Gohr * 1415e29103aSannda * @param Event $event event object by reference 1423ad9c1eaSAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 1433ad9c1eaSAndreas Gohr * handler was registered] 1443ad9c1eaSAndreas Gohr * @return bool 1453ad9c1eaSAndreas Gohr */ 1467234bfb1Ssplitbrain public function handleSave(Event $event, $param) 147d6d97f60SAnna Dabrowska { 1483ad9c1eaSAndreas Gohr // get all struct values and their associated schemas 1497234bfb1Ssplitbrain $tosave = []; 1503ad9c1eaSAndreas Gohr foreach ($event->data['fields'] as $field) { 1513ad9c1eaSAndreas Gohr if (!is_a($field, 'helper_plugin_struct_field')) continue; 1523ad9c1eaSAndreas Gohr /** @var helper_plugin_struct_field $field */ 1533ad9c1eaSAndreas Gohr $tbl = $field->column->getTable(); 1543ad9c1eaSAndreas Gohr $lbl = $field->column->getLabel(); 1557234bfb1Ssplitbrain if (!isset($tosave[$tbl])) $tosave[$tbl] = []; 156987ccc7fSSzymon Olewniczak 157e46eaffdSSzymon Olewniczak if ($field->column->isMulti() && $field->column->getType() instanceof Lookup) { 158987ccc7fSSzymon Olewniczak $tosave[$tbl][$lbl] = $field->opt['struct_pids']; 159987ccc7fSSzymon Olewniczak } else { 1603ad9c1eaSAndreas Gohr $tosave[$tbl][$lbl] = $field->getParam('value'); 1613ad9c1eaSAndreas Gohr } 162987ccc7fSSzymon Olewniczak } 1633ad9c1eaSAndreas Gohr 1643ad9c1eaSAndreas Gohr // save all the struct data of assigned schemas 1653ad9c1eaSAndreas Gohr $id = $event->data['id']; 1663ad9c1eaSAndreas Gohr $time = filemtime(wikiFN($id)); 1679fc5ecc2SMichael Grosse 168025cb9daSAndreas Gohr $assignments = Assignments::getInstance(); 16993ca6f4fSAndreas Gohr $assigned = $assignments->getPageAssignments($id); 17093ca6f4fSAndreas Gohr foreach ($tosave as $table => $data) { 17193ca6f4fSAndreas Gohr if (!in_array($table, $assigned)) continue; 1724cd5cc28SAnna Dabrowska $access = AccessTable::getPageAccess($table, $id, $time); 17393ca6f4fSAndreas Gohr $validator = $access->getValidator($data); 17493ca6f4fSAndreas Gohr if ($validator->validate()) { 17593ca6f4fSAndreas Gohr $validator->saveData($time); 1765c5d9fe5SMichael Grosse 1775c5d9fe5SMichael Grosse // make sure this schema is assigned 1785c5d9fe5SMichael Grosse $assignments->assignPageSchema( 1795c5d9fe5SMichael Grosse $id, 1805c5d9fe5SMichael Grosse $validator->getAccessTable()->getSchema()->getTable() 1815c5d9fe5SMichael Grosse ); 1820e120badSMichael Grosse 1830e120badSMichael Grosse // trigger meta data rendering to set page title 1842a09b9b1SAnna Dabrowska p_get_metadata($id); 18593ca6f4fSAndreas Gohr } 1863ad9c1eaSAndreas Gohr } 1873ad9c1eaSAndreas Gohr 1883ad9c1eaSAndreas Gohr return true; 1893ad9c1eaSAndreas Gohr } 1903ad9c1eaSAndreas Gohr} 1913ad9c1eaSAndreas Gohr 1923ad9c1eaSAndreas Gohr// vim:ts=4:sw=4:et: 193