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