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\Assignments; 12use dokuwiki\plugin\struct\meta\Schema; 13use dokuwiki\plugin\struct\meta\Search; 14use dokuwiki\plugin\struct\types\Lookup; 15 16/** 17 * Handles bureaucracy additions 18 * 19 * This registers to the template action of the bureaucracy plugin and saves all struct data 20 * submitted through the bureaucracy form to all newly created pages (if the schema applies). 21 * 22 * It also registers the struct_schema type for bureaucracy which will add all fields of the 23 * schema to the form. The struct_field type is added through standard naming convention - see 24 * helper/fiels.php for that. 25 */ 26class action_plugin_struct_bureaucracy extends DokuWiki_Action_Plugin 27{ 28 /** 29 * Registers a callback function for a given event 30 * 31 * @param Doku_Event_Handler $controller DokuWiki's event controller object 32 * @return void 33 */ 34 public function register(Doku_Event_Handler $controller) 35 { 36 $controller->register_hook('PLUGIN_BUREAUCRACY_PAGENAME', 'BEFORE', $this, 'handleLookupFields'); 37 $controller->register_hook('PLUGIN_BUREAUCRACY_EMAIL_SEND', 'BEFORE', $this, 'handleLookupFields'); 38 $controller->register_hook('PLUGIN_BUREAUCRACY_TEMPLATE_SAVE', 'AFTER', $this, 'handleSave'); 39 $controller->register_hook('PLUGIN_BUREAUCRACY_FIELD_UNKNOWN', 'BEFORE', $this, 'handleSchema'); 40 } 41 42 /** 43 * Load a whole schema as fields 44 * 45 * @param Doku_Event $event event object by reference 46 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 47 * handler was registered] 48 * @return bool 49 */ 50 public function handleSchema(Doku_Event $event, $param) 51 { 52 $args = $event->data['args']; 53 if ($args[0] != 'struct_schema') return false; 54 $event->preventDefault(); 55 $event->stopPropagation(); 56 57 /** @var helper_plugin_bureaucracy_field $helper */ 58 $helper = plugin_load('helper', 'bureaucracy_field'); 59 $helper->initialize($args); 60 61 $schema = new Schema($helper->opt['label']); 62 if (!$schema->getId()) { 63 msg('This schema does not exist', -1); 64 return false; 65 } 66 67 foreach ($schema->getColumns(false) as $column) { 68 /** @var helper_plugin_struct_field $field */ 69 $field = plugin_load('helper', 'struct_field'); 70 // we don't initialize the field but set the appropriate values 71 $field->opt = $helper->opt; // copy all the settings to each field 72 $field->opt['label'] = $column->getFullQualifiedLabel(); 73 $field->column = $column; 74 $event->data['fields'][] = $field; 75 } 76 return true; 77 } 78 79 /** 80 * Replace lookup fields placeholder's values 81 * 82 * @param Doku_Event $event event object by reference 83 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 84 * handler was registered] 85 * @return bool 86 */ 87 public function handleLookupFields(Doku_Event $event, $param) 88 { 89 foreach ($event->data['fields'] as $field) { 90 if (!is_a($field, 'helper_plugin_struct_field')) continue; 91 if (!$field->column->getType() instanceof Lookup) continue; 92 93 $value = $field->getParam('value'); 94 if (!is_array($value)) $value = array($value); 95 96 $config = $field->column->getType()->getConfig(); 97 98 // find proper value 99 // current Search implementation doesn't allow doing it using SQL 100 $search = new Search(); 101 $search->addSchema($config['schema']); 102 $search->addColumn($config['field']); 103 $result = $search->execute(); 104 $pids = $search->getPids(); 105 $rids = $search->getRids(); 106 107 $field->opt['struct_pids'] = array(); 108 $new_value = array(); 109 foreach ($value as $pid) { 110 for ($i = 0; $i < count($result); $i++) { 111 // lookups can reference pages or global data, so check both pid and rid 112 // make sure not to double decode pid! 113 $originalPid = $pid; 114 $pid = json_decode($pid)[0] ?? $pid; 115 $rid = json_decode($originalPid)[1] ?? null; 116 if (($pid && $pids[$i] === $pid) || ($rid && $rids[$i] === (string)$rid)) { 117 $field->opt['struct_pids'][] = $pid; 118 $new_value[] = $result[$i][0]->getDisplayValue(); 119 } 120 } 121 } 122 123 //replace previous value 124 if ($field->column->isMulti()) { 125 $field->opt['value'] = $new_value; 126 } else { 127 $event->data['values'][$field->column->getFullQualifiedLabel()] = $new_value[0] ?? ''; 128 } 129 } 130 return true; 131 } 132 133 /** 134 * Save the struct data 135 * 136 * @param Doku_Event $event event object by reference 137 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 138 * handler was registered] 139 * @return bool 140 */ 141 public function handleSave(Doku_Event $event, $param) 142 { 143 // get all struct values and their associated schemas 144 $tosave = array(); 145 foreach ($event->data['fields'] as $field) { 146 if (!is_a($field, 'helper_plugin_struct_field')) continue; 147 /** @var helper_plugin_struct_field $field */ 148 $tbl = $field->column->getTable(); 149 $lbl = $field->column->getLabel(); 150 if (!isset($tosave[$tbl])) $tosave[$tbl] = array(); 151 152 if ($field->column->isMulti() && $field->column->getType() instanceof Lookup) { 153 $tosave[$tbl][$lbl] = $field->opt['struct_pids']; 154 } else { 155 $tosave[$tbl][$lbl] = $field->getParam('value'); 156 } 157 } 158 159 // save all the struct data of assigned schemas 160 $id = $event->data['id']; 161 $time = filemtime(wikiFN($id)); 162 163 $assignments = Assignments::getInstance(); 164 $assigned = $assignments->getPageAssignments($id); 165 foreach ($tosave as $table => $data) { 166 if (!in_array($table, $assigned)) continue; 167 $access = AccessTable::getPageAccess($table, $id, $time); 168 $validator = $access->getValidator($data); 169 if ($validator->validate()) { 170 $validator->saveData($time); 171 172 // make sure this schema is assigned 173 $assignments->assignPageSchema( 174 $id, 175 $validator->getAccessTable()->getSchema()->getTable() 176 ); 177 178 // trigger meta data rendering to set page title 179 p_get_metadata($id); 180 } 181 } 182 183 return true; 184 } 185} 186 187// vim:ts=4:sw=4:et: 188