1 <?php
2 
3 namespace dokuwiki\Ui;
4 
5 use dokuwiki\Draft;
6 use dokuwiki\Extension\Event;
7 use dokuwiki\Form\Form;
8 
9 /**
10  * DokuWiki Page Editor
11  *
12  * @package dokuwiki\Ui
13  */
14 class 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', 'tabindex' => '4'])
110                 ->id('edbtn__save');
111             $form->addButton('do[preview]', $lang['btn_preview'])->attr('type', 'submit')
112                 ->attrs(['accesskey' => 'p', 'tabindex' => '5'])
113                 ->id('edbtn__preview');
114             $form->addButton('do[cancel]', $lang['btn_cancel'])->attr('type', 'submit')
115                 ->attrs(['tabindex' => '6']);
116             $form->addTagClose('div'); // close div editButtons class
117 
118             // add a textbox for edit summary
119             $form->addTagOpen('div')->addClass('summary');
120             $input = $form->addTextInput('summary', $lang['summary'])
121                 ->attrs(['size' => '50', 'tabindex' => '2'])
122                 ->id('edit__summary')->addClass('edit')
123                 ->val($SUM);
124             $input->getLabel()->attr('class', 'nowrap');
125 
126             // adds a checkbox for minor edits for logged in users
127             if ($conf['useacl'] && $INPUT->server->str('REMOTE_USER')) {
128                 $form->addHTML(' ');
129                 $form->addCheckbox('minor', $lang['minoredit'])->id('edit__minoredit')->addClass('nowrap')->val('1');
130             }
131             $form->addTagClose('div'); // close div summary class
132         }
133 
134         $form->addTagClose('div'); // close div editBar class
135 
136         // license note
137         if ($wr && $conf['license']) {
138             $attr = [
139                 'href' => $license[$conf['license']]['url'],
140                 'rel' => 'license',
141                 'class' => 'urlextern',
142                 'target' => $conf['target']['extern'] ?: ''
143             ];
144             $form->addTagOpen('div')->addClass('license');
145             $form->addHTML($lang['licenseok']
146                 . ' <a ' . buildAttributes($attr, true) . '>' . $license[$conf['license']]['name'] . '</a>');
147             $form->addTagClose('div');
148         }
149 
150         // start editor html output
151         if ($wr) {
152             // sets changed to true when previewed
153             tpl_inlineScript('textChanged = ' . ($mod ? 'true' : 'false') . ';');
154         }
155 
156         // print intro locale text (edit, rditrev, or read.txt)
157         if (isset($data['intro_locale'])) {
158             echo p_locale_xhtml($data['intro_locale']);
159         }
160 
161         echo '<div class="editBox" role="application">';
162 
163         echo '<div class="toolbar group">';
164         echo '<div id="tool__bar" class="tool__bar">';
165         if ($wr && $data['media_manager']) {
166             echo '<a href="' . DOKU_BASE . 'lib/exe/mediamanager.php?ns=' . $INFO['namespace'] . '" target="_blank">';
167             echo $lang['mediaselect'];
168             echo '</a>';
169         }
170         echo '</div>';
171         echo '</div>';
172 
173         echo '<div id="draft__status" class="draft__status">';
174         $draft = new Draft($ID, $INFO['client']);
175         if ($draft->isDraftAvailable()) {
176             echo $draft->getDraftMessage();
177         }
178         echo '</div>';
179 
180         echo $form->toHTML('Edit');
181 
182         echo '</div>'; // close div editBox class
183     }
184 
185     /**
186      * Display the default edit form (textarea)
187      *
188      * the default action for EDIT_FORM_ADDTEXTAREA
189      *
190      * @param array{wr: bool, media_manager: bool, target: string, intro_locale: string, form: Form} $data
191      */
192     public function addTextarea(&$data)
193     {
194         global $TEXT;
195 
196         if ($data['target'] !== 'section') {
197             msg('No editor for edit target ' . hsc($data['target']) . ' found.', -1);
198         }
199 
200         // set textarea attributes
201         $attr = ['tabindex' => '1'];
202         if (!$data['wr']) $attr['readonly'] = 'readonly';
203         $attr['dir'] = 'auto';
204         $attr['cols'] = '80';
205         $attr['rows'] = '10';
206 
207         $data['form']->addTextarea('wikitext', '')->attrs($attr)->val($TEXT)
208             ->id('wiki__text')->addClass('edit');
209     }
210 }
211