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\Extension\ActionPlugin;
11use dokuwiki\Extension\EventHandler;
12use dokuwiki\Extension\Event;
13use dokuwiki\Form\Form;
14use dokuwiki\plugin\struct\meta\AccessTable;
15use dokuwiki\plugin\struct\meta\Assignments;
16use dokuwiki\plugin\struct\meta\Value;
17
18/**
19 * Class action_plugin_struct_entry
20 *
21 * Handles adding struct forms to the default editor
22 */
23class action_plugin_struct_edit extends ActionPlugin
24{
25    /**
26     * @var string The form name we use to transfer schema data
27     */
28    protected static $VAR = 'struct_schema_data';
29
30    /**
31     * Registers a callback function for a given event
32     *
33     * @param EventHandler $controller DokuWiki's event controller object
34     * @return void
35     */
36    public function register(EventHandler $controller)
37    {
38        // add the struct editor to the edit form;
39        $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'handleEditform');
40        $controller->register_hook('FORM_EDIT_OUTPUT', 'BEFORE', $this, 'addFromData');
41    }
42
43    /**
44     * Adds the html for the struct editors to the edit from
45     *
46     * Handles the FORM_EDIT_OUTPUT event
47     *
48     * @return bool
49     */
50    public function addFromData(Event $event, $_param)
51    {
52        $html = $this->getEditorHtml();
53
54        /** @var Form $form */
55        $form = $event->data;
56        $pos = $form->findPositionByAttribute('id', 'wiki__editbar'); // insert the form before the main buttons
57        $form->addHTML($html, $pos);
58
59        return true;
60    }
61
62    /**
63     * Enhance the editing form with structural data editing
64     *
65     * TODO: Remove this after HTML_EDITFORM_OUTPUT is no longer released in DokuWiki stable
66     *
67     * @param Event $event event object by reference
68     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
69     *                           handler was registered]
70     * @return bool
71     */
72    public function handleEditform(Event $event, $param)
73    {
74        $html = $this->getEditorHtml();
75
76        /** @var Doku_Form $form */
77        $form = $event->data;
78        $pos = $form->findElementById('wiki__editbar'); // insert the form before the main buttons
79        $form->insertElement($pos, $html);
80
81        return true;
82    }
83
84    /**
85     * @return string
86     */
87    private function getEditorHtml()
88    {
89        global $ID;
90
91        $assignments = Assignments::getInstance();
92        $tables = $assignments->getPageAssignments($ID);
93
94        $html = '';
95        foreach ($tables as $table) {
96            $html .= $this->createForm($table);
97        }
98
99        return "<div class=\"struct_entry_form\">$html</div>";
100    }
101
102    /**
103     * Create the form to edit schemadata
104     *
105     * @param string $tablename
106     * @return string The HTML for this schema's form
107     */
108    protected function createForm($tablename)
109    {
110        global $ID;
111        global $REV;
112        global $INPUT;
113        if (auth_quickaclcheck($ID) == AUTH_READ) return '';
114        if (checklock($ID)) return '';
115        $ts = $REV ?: time();
116        $schema = AccessTable::getPageAccess($tablename, $ID, $ts);
117        if (!$schema->getSchema()->isEditable()) {
118            return '';
119        }
120        $schemadata = $schema->getData();
121
122        $structdata = $INPUT->arr(self::$VAR);
123        if (isset($structdata[$tablename])) {
124            $postdata = $structdata[$tablename];
125        } else {
126            $postdata = [];
127        }
128
129        // we need a short, unique identifier to use in the cookie. this should be good enough
130        $schemaid = 'SRCT' . substr(str_replace(['+', '/'], '', base64_encode(sha1($tablename, true))), 0, 5);
131        $html = '<fieldset data-schema="' . $schemaid . '">';
132        $html .= '<legend>' . hsc($schema->getSchema()->getTranslatedLabel()) . '</legend>';
133        foreach ($schemadata as $field) {
134            $label = $field->getColumn()->getLabel();
135            if (isset($postdata[$label])) {
136                // posted data trumps stored data
137                $data = $postdata[$label];
138                if (is_array($data)) {
139                    $data = array_map("cleanText", $data);
140                } else {
141                    $data = cleanText($data);
142                }
143                $field->setValue($data, true);
144            }
145            $html .= $this->makeField($field, self::$VAR . "[$tablename][$label]");
146        }
147        $html .= '</fieldset>';
148
149        return $html;
150    }
151
152    /**
153     * Create the input field
154     *
155     * @param Value $field
156     * @param String $name field's name
157     * @return string
158     */
159    public function makeField(Value $field, $name)
160    {
161        $trans = hsc($field->getColumn()->getTranslatedLabel());
162        $hint = hsc($field->getColumn()->getTranslatedHint());
163        $class = $hint ? 'hashint' : '';
164        $colname = $field->getColumn()->getFullQualifiedLabel();
165
166        $id = uniqid('struct__', false);
167        $input = $field->getValueEditor($name, $id);
168
169        // we keep all the custom form stuff the field might produce, but hide it
170        if (!$field->getColumn()->isVisibleInEditor()) {
171            $hide = 'style="display:none"';
172        } else {
173            $hide = '';
174        }
175
176        $html = '<div class="field">';
177        $html .= "<label $hide data-column=\"$colname\" for=\"$id\">";
178        $html .= "<span class=\"label $class\" title=\"$hint\">$trans</span>";
179        $html .= '</label>';
180        $html .= "<span class=\"input\">$input</span>";
181        $html .= '</div>';
182
183        return $html;
184    }
185}
186
187// vim:ts=4:sw=4:et:
188