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