xref: /dokuwiki/inc/Ui/Editor.php (revision ce55bf2bd4dc62dcba4a8109becac8b523966cb3)
1<?php
2
3namespace dokuwiki\Ui;
4
5use dokuwiki\Draft;
6use dokuwiki\Extension\Event;
7use dokuwiki\Form\Form;
8
9/**
10 * DokuWiki Page Editor
11 *
12 * @package dokuwiki\Ui
13 */
14class Editor extends Ui
15{
16    /**
17     * Display the Edit Window
18     * preprocess edit form data
19     *
20     * @return void
21     * @author   Andreas Gohr <andi@splitbrain.org>
22     *
23     * @triggers EDIT_FORM_ADDTEXTAREA
24     */
25    public function show()
26    {
27        global $INPUT;
28        global $ID;
29        global $REV;
30        global $DATE;
31        global $PRE;
32        global $SUF;
33        global $INFO;
34        global $SUM;
35        global $lang;
36        global $conf;
37        global $TEXT;
38
39        global $license;
40
41        if ($INPUT->has('changecheck')) {
42            $check = $INPUT->str('changecheck');
43        } elseif (!$INFO['exists']) {
44            // $TEXT has been loaded from page template
45            $check = md5('');
46        } else {
47            $check = md5($TEXT);
48        }
49        $mod = (md5($TEXT) !== $check);
50
51        $wr = $INFO['writable'] && !$INFO['locked'];
52
53        // intro locale text (edit, rditrev, or read)
54        if ($wr) {
55            $intro = ($REV) ? 'editrev' : 'edit';
56        } else {
57            // check pseudo action 'source'
58            if (!actionOK('source')) {
59                msg('Command disabled: source', -1);
60                return;
61            }
62            $intro = 'read';
63        }
64
65        // create the Editor form
66        $form = new Form(['id' => 'dw__editform']);
67        $form->setHiddenField('id', $ID);
68        $form->setHiddenField('rev', $REV);
69        $form->setHiddenField('date', $DATE);
70        $form->setHiddenField('prefix', $PRE . '.');
71        $form->setHiddenField('suffix', $SUF);
72        $form->setHiddenField('changecheck', $check);
73
74        // prepare data for EDIT_FORM_ALTERNATE event
75        $data = [
76            'form' => $form,
77            'wr' => $wr,
78            'media_manager' => true,
79            'target' => ($INPUT->has('target') && $wr) ? $INPUT->str('target') : 'section',
80            'intro_locale' => $intro
81        ];
82
83        if ($data['target'] !== 'section') {
84            // Only emit event if page is writable, section edit data is valid and
85            // edit target is not section.
86            Event::createAndTrigger('EDIT_FORM_ADDTEXTAREA', $data, [$this, 'addTextarea'], true);
87        } else {
88            $this->addTextarea($data);
89        }
90
91        $form->setHiddenField('target', $data['target']);
92
93        if ($INPUT->has('hid')) {
94            $form->setHiddenField('hid', $INPUT->str('hid'));
95        }
96        if ($INPUT->has('codeblockOffset')) {
97            $form->setHiddenField('codeblockOffset', $INPUT->str('codeblockOffset'));
98        }
99
100        $form->addTagOpen('div')->id('wiki__editbar')->addClass('editBar');
101
102        $form->addTagOpen('div')->id('size__ctl');
103        $form->addTagClose('div');
104
105        if ($wr) {
106            // add edit buttons: save, preview, cancel
107            $form->addTagOpen('div')->addClass('editButtons');
108            $form->addButton('do[save]', $lang['btn_save'])->attr('type', 'submit')
109                ->attrs(['accesskey' => 's'])
110                ->id('edbtn__save');
111            $form->addButton('do[preview]', $lang['btn_preview'])->attr('type', 'submit')
112                ->attrs(['accesskey' => 'p'])
113                ->id('edbtn__preview');
114            $form->addButton('do[cancel]', $lang['btn_cancel'])->attr('type', 'submit');
115            $form->addTagClose('div'); // close div editButtons class
116
117            // add a textbox for edit summary
118            $form->addTagOpen('div')->addClass('summary');
119            $input = $form->addTextInput('summary', $lang['summary'])
120                ->attrs(['size' => '50'])
121                ->id('edit__summary')->addClass('edit')
122                ->val($SUM);
123            $input->getLabel()->attr('class', 'nowrap');
124
125            // adds a checkbox for minor edits for logged in users
126            if ($conf['useacl'] && $INPUT->server->str('REMOTE_USER')) {
127                $form->addHTML(' ');
128                $form->addCheckbox('minor', $lang['minoredit'])->id('edit__minoredit')->addClass('nowrap')->val('1');
129            }
130            $form->addTagClose('div'); // close div summary class
131        }
132
133        $form->addTagClose('div'); // close div editBar class
134
135        // license note
136        if ($wr && $conf['license']) {
137            $attr = [
138                'href' => $license[$conf['license']]['url'],
139                'rel' => 'license',
140                'class' => 'urlextern',
141                'target' => $conf['target']['extern'] ?: ''
142            ];
143            $form->addTagOpen('div')->addClass('license');
144            $form->addHTML($lang['licenseok']
145                . ' <a ' . buildAttributes($attr, true) . '>' . $license[$conf['license']]['name'] . '</a>');
146            $form->addTagClose('div');
147        }
148
149        // start editor html output
150        if ($wr) {
151            // sets changed to true when previewed
152            tpl_inlineScript('textChanged = ' . ($mod ? 'true' : 'false') . ';');
153        }
154
155        // print intro locale text (edit, rditrev, or read.txt)
156        if (isset($data['intro_locale'])) {
157            echo p_locale_xhtml($data['intro_locale']);
158        }
159
160        echo '<div class="editBox" role="application">';
161
162        echo '<div class="toolbar group">';
163        echo '<div id="tool__bar" class="tool__bar">';
164        if ($wr && $data['media_manager']) {
165            echo '<a href="' . DOKU_BASE . 'lib/exe/mediamanager.php?ns=' . $INFO['namespace'] . '" target="_blank">';
166            echo $lang['mediaselect'];
167            echo '</a>';
168        }
169        echo '</div>';
170        echo '</div>';
171
172        echo '<div id="draft__status" class="draft__status">';
173        $draft = new Draft($ID, $INFO['client']);
174        if ($draft->isDraftAvailable()) {
175            echo $draft->getDraftMessage();
176        }
177        echo '</div>';
178
179        echo $form->toHTML('Edit');
180
181        echo '</div>'; // close div editBox class
182    }
183
184    /**
185     * Display the default edit form (textarea)
186     *
187     * the default action for EDIT_FORM_ADDTEXTAREA
188     *
189     * @param array{wr: bool, media_manager: bool, target: string, intro_locale: string, form: Form} $data
190     */
191    public function addTextarea(&$data)
192    {
193        global $TEXT;
194
195        if ($data['target'] !== 'section') {
196            msg('No editor for edit target ' . hsc($data['target']) . ' found.', -1);
197        }
198
199        // set textarea attributes
200        $attr = [];
201        if (!$data['wr']) $attr['readonly'] = 'readonly';
202        $attr['dir'] = 'auto';
203        $attr['cols'] = '80';
204        $attr['rows'] = '10';
205
206        $data['form']->addTextarea('wikitext', '')->attrs($attr)->val($TEXT)
207            ->id('wiki__text')->addClass('edit');
208    }
209}
210