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