Failed Conditions
Pull Request — master (#3198)
by
unknown
02:55
created

html.php ➔ html_btn()   B

Complexity

Conditions 9
Paths 96

Size

Total Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 96
nop 8
dl 0
loc 54
rs 7.448
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * HTML output functions
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Andreas Gohr <[email protected]>
7
 */
8
9
use dokuwiki\ChangeLog\MediaChangeLog;
10
use dokuwiki\ChangeLog\PageChangeLog;
11
use dokuwiki\Extension\AuthPlugin;
12
use dokuwiki\Extension\Event;
13
14
if (!defined('SEC_EDIT_PATTERN')) {
15
    define('SEC_EDIT_PATTERN', '#<!-- EDIT({.*?}) -->#');
16
}
17
18
19
/**
20
 * Convenience function to quickly build a wikilink
21
 *
22
 * @author Andreas Gohr <[email protected]>
23
 * @param string  $id      id of the target page
24
 * @param string  $name    the name of the link, i.e. the text that is displayed
25
 * @param string|array  $search  search string(s) that shall be highlighted in the target page
26
 * @return string the HTML code of the link
27
 */
28
function html_wikilink($id,$name=null,$search=''){
29
    /** @var Doku_Renderer_xhtml $xhtml_renderer */
30
    static $xhtml_renderer = null;
31
    if(is_null($xhtml_renderer)){
32
        $xhtml_renderer = p_get_renderer('xhtml');
33
    }
34
35
    return $xhtml_renderer->internallink($id,$name,$search,true,'navigation');
36
}
37
38
/**
39
 * The loginform
40
 *
41
 * @author   Andreas Gohr <[email protected]>
42
 *
43
 * @param bool $svg Whether to show svg icons in the register and resendpwd links or not
44
 */
45
function html_login($svg = false){
46
    global $lang;
47
    global $conf;
48
    global $ID;
49
    global $INPUT;
50
51
    print p_locale_xhtml('login');
52
    print '<div class="centeralign">'.NL;
53
    $form = new Doku_Form(array('id' => 'dw__login', 'action'=>wl($ID)));
54
    $form->startFieldset($lang['btn_login']);
55
    $form->addHidden('id', $ID);
56
    $form->addHidden('do', 'login');
57
    $form->addElement(form_makeTextField(
58
        'u',
59
        ((!$INPUT->bool('http_credentials')) ? $INPUT->str('u') : ''),
60
        $lang['user'],
61
        'focus__this',
62
        'block')
63
    );
64
    $form->addElement(form_makePasswordField('p', $lang['pass'], '', 'block'));
65
    if($conf['rememberme']) {
66
        $form->addElement(form_makeCheckboxField('r', '1', $lang['remember'], 'remember__me', 'simple'));
67
    }
68
    $form->addElement(form_makeButton('submit', '', $lang['btn_login']));
69
    $form->endFieldset();
70
71
    if(actionOK('register')){
72
        $registerLink = (new \dokuwiki\Menu\Item\Register())->asHtmlLink('', $svg);
73
        $form->addElement('<p>'.$lang['reghere'].': '. $registerLink .'</p>');
74
    }
75
76
    if (actionOK('resendpwd')) {
77
        $resendPwLink = (new \dokuwiki\Menu\Item\Resendpwd())->asHtmlLink('', $svg);
78
        $form->addElement('<p>'.$lang['pwdforget'].': '. $resendPwLink .'</p>');
79
    }
80
81
    html_form('login', $form);
82
    print '</div>'.NL;
83
}
84
85
86
/**
87
 * Denied page content
88
 *
89
 * @return string html
90
 */
91
function html_denied() {
92
    print p_locale_xhtml('denied');
93
94
    if(empty($_SERVER['REMOTE_USER']) && actionOK('login')){
95
        html_login();
96
    }
97
}
98
99
/**
100
 * inserts section edit buttons if wanted or removes the markers
101
 *
102
 * @author Andreas Gohr <[email protected]>
103
 *
104
 * @param string $text
105
 * @param bool   $show show section edit buttons?
106
 * @return string
107
 */
108
function html_secedit($text,$show=true){
109
    global $INFO;
110
111
    if((isset($INFO) && !$INFO['writable']) || !$show || (isset($INFO) && $INFO['rev'])){
112
        return preg_replace(SEC_EDIT_PATTERN,'',$text);
113
    }
114
115
    return preg_replace_callback(SEC_EDIT_PATTERN,
116
                'html_secedit_button', $text);
117
}
118
119
/**
120
 * prepares section edit button data for event triggering
121
 * used as a callback in html_secedit
122
 *
123
 * @author Andreas Gohr <[email protected]>
124
 *
125
 * @param array $matches matches with regexp
126
 * @return string
127
 * @triggers HTML_SECEDIT_BUTTON
128
 */
129
function html_secedit_button($matches){
130
    $json = htmlspecialchars_decode($matches[1], ENT_QUOTES);
131
    $data = json_decode($json, true);
132
    if ($data == NULL) {
133
        return;
134
    }
135
    $data ['target'] = strtolower($data['target']);
136
    $data ['hid'] = strtolower($data['hid']);
137
138
    return Event::createAndTrigger('HTML_SECEDIT_BUTTON', $data,
139
                         'html_secedit_get_button');
140
}
141
142
/**
143
 * prints a section editing button
144
 * used as default action form HTML_SECEDIT_BUTTON
145
 *
146
 * @author Adrian Lang <[email protected]>
147
 *
148
 * @param array $data name, section id and target
149
 * @return string html
150
 */
151
function html_secedit_get_button($data) {
152
    global $ID;
153
    global $INFO;
154
155
    if (!isset($data['name']) || $data['name'] === '') return '';
156
157
    $name = $data['name'];
158
    unset($data['name']);
159
160
    $secid = $data['secid'];
161
    unset($data['secid']);
162
163
    return "<div class='secedit editbutton_" . $data['target'] .
164
                       " editbutton_" . $secid . "'>" .
165
           html_btn('secedit', $ID, '',
166
                    array_merge(array('do'  => 'edit',
167
                                      'rev' => $INFO['lastmod'],
168
                                      'summary' => '['.$name.'] '), $data),
169
                    'post', $name) . '</div>';
170
}
171
172
/**
173
 * Just the back to top button (in its own form)
174
 *
175
 * @author Andreas Gohr <[email protected]>
176
 *
177
 * @return string html
178
 */
179
function html_topbtn(){
180
    global $lang;
181
182
    $ret = '<a class="nolink" href="#dokuwiki__top">' .
183
        '<button class="button" onclick="window.scrollTo(0, 0)" title="' . $lang['btn_top'] . '">' .
184
        $lang['btn_top'] .
185
        '</button></a>';
186
187
    return $ret;
188
}
189
190
/**
191
 * Displays a button (using its own form)
192
 * If tooltip exists, the access key tooltip is replaced.
193
 *
194
 * @author Andreas Gohr <[email protected]>
195
 *
196
 * @param string         $name
197
 * @param string         $id
198
 * @param string         $akey   access key
199
 * @param string[] $params key-value pairs added as hidden inputs
200
 * @param string         $method
201
 * @param string         $tooltip
202
 * @param bool|string    $label  label text, false: lookup btn_$name in localization
203
 * @param string         $svg (optional) svg code, inserted into the button
204
 * @return string
205
 */
206
function html_btn($name, $id, $akey, $params, $method='get', $tooltip='', $label=false, $svg=null){
207
    global $conf;
208
    global $lang;
209
210
    if (!$label)
211
        $label = $lang['btn_'.$name];
212
213
    $ret = '';
214
215
    //filter id (without urlencoding)
216
    $id = idfilter($id,false);
217
218
    //make nice URLs even for buttons
219
    if($conf['userewrite'] == 2){
220
        $script = DOKU_BASE.DOKU_SCRIPT.'/'.$id;
221
    }elseif($conf['userewrite']){
222
        $script = DOKU_BASE.$id;
223
    }else{
224
        $script = DOKU_BASE.DOKU_SCRIPT;
225
        $params['id'] = $id;
226
    }
227
228
    $ret .= '<form class="button btn_'.$name.'" method="'.$method.'" action="'.$script.'"><div class="no">';
229
230
    if(is_array($params)){
231
        foreach($params as $key => $val) {
232
            $ret .= '<input type="hidden" name="'.$key.'" ';
233
            $ret .= 'value="'.hsc($val).'" />';
234
        }
235
    }
236
237
    if ($tooltip!='') {
238
        $tip = hsc($tooltip);
239
    }else{
240
        $tip = hsc($label);
241
    }
242
243
    $ret .= '<button type="submit" ';
244
    if($akey){
245
        $tip .= ' ['.strtoupper($akey).']';
246
        $ret .= 'accesskey="'.$akey.'" ';
247
    }
248
    $ret .= 'title="'.$tip.'">';
249
    if ($svg) {
250
        $ret .= '<span>' . hsc($label) . '</span>';
251
        $ret .= inlineSVG($svg);
252
    } else {
253
        $ret .= hsc($label);
254
    }
255
    $ret .= '</button>';
256
    $ret .= '</div></form>';
257
258
    return $ret;
259
}
260
/**
261
 * show a revision warning
262
 *
263
 * @author Szymon Olewniczak <[email protected]>
264
 */
265
function html_showrev() {
266
    print p_locale_xhtml('showrev');
267
}
268
269
/**
270
 * Show a wiki page
271
 *
272
 * @author Andreas Gohr <[email protected]>
273
 *
274
 * @param null|string $txt wiki text or null for showing $ID
275
 */
276
function html_show($txt=null){
277
    global $ID;
278
    global $REV;
279
    global $HIGH;
280
    global $INFO;
281
    global $DATE_AT;
282
    //disable section editing for old revisions or in preview
283
    if($txt || $REV){
284
        $secedit = false;
285
    }else{
286
        $secedit = true;
287
    }
288
289
    if (!is_null($txt)){
290
        //PreviewHeader
291
        echo '<br id="scroll__here" />';
292
        echo p_locale_xhtml('preview');
293
        echo '<div class="preview"><div class="pad">';
294
        $html = html_secedit(p_render('xhtml',p_get_instructions($txt),$info),$secedit);
295
        if($INFO['prependTOC']) $html = tpl_toc(true).$html;
296
        echo $html;
297
        echo '<div class="clearer"></div>';
298
        echo '</div></div>';
299
300
    }else{
301
        if ($REV||$DATE_AT){
302
            $data = array('rev' => &$REV, 'date_at' => &$DATE_AT);
303
            Event::createAndTrigger('HTML_SHOWREV_OUTPUT', $data, 'html_showrev');
304
        }
305
        $html = p_wiki_xhtml($ID,$REV,true,$DATE_AT);
306
        $html = html_secedit($html,$secedit);
307
        if($INFO['prependTOC']) $html = tpl_toc(true).$html;
308
        $html = html_hilight($html,$HIGH);
309
        echo $html;
310
    }
311
}
312
313
/**
314
 * ask the user about how to handle an exisiting draft
315
 *
316
 * @author Andreas Gohr <[email protected]>
317
 */
318
function html_draft(){
319
    global $INFO;
320
    global $ID;
321
    global $lang;
322
    $draft = new \dokuwiki\Draft($ID, $INFO['client']);
323
    $text  = $draft->getDraftText();
324
325
    print p_locale_xhtml('draft');
326
    html_diff($text, false);
327
    $form = new Doku_Form(array('id' => 'dw__editform'));
328
    $form->addHidden('id', $ID);
329
    $form->addHidden('date', $draft->getDraftDate());
330
    $form->addHidden('wikitext', $text);
331
    $form->addElement(form_makeOpenTag('div', array('id'=>'draft__status')));
332
    $form->addElement($draft->getDraftMessage());
333
    $form->addElement(form_makeCloseTag('div'));
334
    $form->addElement(form_makeButton('submit', 'recover', $lang['btn_recover'], array('tabindex'=>'1')));
335
    $form->addElement(form_makeButton('submit', 'draftdel', $lang['btn_draftdel'], array('tabindex'=>'2')));
336
    $form->addElement(form_makeButton('submit', 'show', $lang['btn_cancel'], array('tabindex'=>'3')));
337
    html_form('draft', $form);
338
}
339
340
/**
341
 * Highlights searchqueries in HTML code
342
 *
343
 * @author Andreas Gohr <[email protected]>
344
 * @author Harry Fuecks <[email protected]>
345
 *
346
 * @param string $html
347
 * @param array|string $phrases
348
 * @return string html
349
 */
350
function html_hilight($html,$phrases){
351
    $phrases = (array) $phrases;
352
    $phrases = array_map('preg_quote_cb', $phrases);
353
    $phrases = array_map('ft_snippet_re_preprocess', $phrases);
354
    $phrases = array_filter($phrases);
355
    $regex = join('|',$phrases);
356
357
    if ($regex === '') return $html;
358
    if (!\dokuwiki\Utf8\Clean::isUtf8($regex)) return $html;
359
    $html = @preg_replace_callback("/((<[^>]*)|$regex)/ui",'html_hilight_callback',$html);
360
    return $html;
361
}
362
363
/**
364
 * Callback used by html_hilight()
365
 *
366
 * @author Harry Fuecks <[email protected]>
367
 *
368
 * @param array $m matches
369
 * @return string html
370
 */
371
function html_hilight_callback($m) {
372
    $hlight = unslash($m[0]);
373
    if ( !isset($m[2])) {
374
        $hlight = '<span class="search_hit">'.$hlight.'</span>';
375
    }
376
    return $hlight;
377
}
378
379
/**
380
 * Display error on locked pages
381
 *
382
 * @author Andreas Gohr <[email protected]>
383
 */
384
function html_locked(){
385
    global $ID;
386
    global $conf;
387
    global $lang;
388
    global $INFO;
389
390
    $locktime = filemtime(wikiLockFN($ID));
391
    $expire = dformat($locktime + $conf['locktime']);
392
    $min    = round(($conf['locktime'] - (time() - $locktime) )/60);
393
394
    print p_locale_xhtml('locked');
395
    print '<ul>';
396
    print '<li><div class="li"><strong>'.$lang['lockedby'].'</strong> '.editorinfo($INFO['locked']).'</div></li>';
397
    print '<li><div class="li"><strong>'.$lang['lockexpire'].'</strong> '.$expire.' ('.$min.' min)</div></li>';
398
    print '</ul>';
399
}
400
401
/**
402
 * list old revisions
403
 *
404
 * @author Andreas Gohr <[email protected]>
405
 * @author Ben Coburn <[email protected]>
406
 * @author Kate Arzamastseva <[email protected]>
407
 *
408
 * @param int $first skip the first n changelog lines
409
 * @param bool|string $media_id id of media, or false for current page
410
 */
411
function html_revisions($first=0, $media_id = false){
412
    global $ID;
413
    global $INFO;
414
    global $conf;
415
    global $lang;
416
    $id = $ID;
417
    if ($media_id) {
418
        $id = $media_id;
419
        $changelog = new MediaChangeLog($id);
420
    } else {
421
        $changelog = new PageChangeLog($id);
422
    }
423
424
    /* we need to get one additional log entry to be able to
425
     * decide if this is the last page or is there another one.
426
     * see html_recent()
427
     */
428
429
    $revisions = $changelog->getRevisions($first, $conf['recent']+1);
430
431
    if(count($revisions)==0 && $first!=0){
432
        $first=0;
433
        $revisions = $changelog->getRevisions($first, $conf['recent']+1);
434
    }
435
    $hasNext = false;
436
    if (count($revisions)>$conf['recent']) {
437
        $hasNext = true;
438
        array_pop($revisions); // remove extra log entry
439
    }
440
441
    if (!$media_id) print p_locale_xhtml('revisions');
442
443
    $params = array('id' => 'page__revisions', 'class' => 'changes');
444
    if($media_id) {
445
        $params['action'] = media_managerURL(array('image' => $media_id), '&');
446
    }
447
448
    if(!$media_id) {
449
        $exists = $INFO['exists'];
450
        $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
451
        if(!$display_name) {
452
            $display_name = $id;
453
        }
454
    } else {
455
        $exists = file_exists(mediaFN($id));
456
        $display_name = $id;
457
    }
458
459
    $form = new Doku_Form($params);
460
    $form->addElement(form_makeOpenTag('ul'));
461
462
    if($exists && $first == 0) {
463
        $minor = false;
464
        if($media_id) {
465
            $date = dformat(@filemtime(mediaFN($id)));
466
            $href = media_managerURL(array('image' => $id, 'tab_details' => 'view'), '&');
467
468
            $changelog->setChunkSize(1024);
469
            $revinfo = $changelog->getRevisionInfo(@filemtime(fullpath(mediaFN($id))));
470
471
            $summary = $revinfo['sum'];
472
            if($revinfo['user']) {
473
                $editor = $revinfo['user'];
474
            } else {
475
                $editor = $revinfo['ip'];
476
            }
477
            $sizechange = $revinfo['sizechange'];
478
        } else {
479
            $date = dformat($INFO['lastmod']);
480
            if(isset($INFO['meta']) && isset($INFO['meta']['last_change'])) {
481
                if($INFO['meta']['last_change']['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) {
482
                    $minor = true;
483
                }
484
                if(isset($INFO['meta']['last_change']['sizechange'])) {
485
                    $sizechange = $INFO['meta']['last_change']['sizechange'];
486
                } else {
487
                    $sizechange = null;
488
                }
489
            }
490
            $pagelog = new PageChangeLog($ID);
491
            $latestrev = $pagelog->getRevisions(-1, 1);
492
            $latestrev = array_pop($latestrev);
493
            $href = wl($id,"rev=$latestrev",false,'&');
494
            $summary = $INFO['sum'];
495
            $editor = $INFO['editor'];
496
        }
497
498
        $form->addElement(form_makeOpenTag('li', array('class' => ($minor ? 'minor' : ''))));
499
        $form->addElement(form_makeOpenTag('div', array('class' => 'li')));
500
        $form->addElement(form_makeTag('input', array(
501
                        'type' => 'checkbox',
502
                        'name' => 'rev2[]',
503
                        'value' => 'current')));
504
505
        $form->addElement(form_makeOpenTag('span', array('class' => 'date')));
506
        $form->addElement($date);
507
        $form->addElement(form_makeCloseTag('span'));
508
509
        $form->addElement('<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />');
510
511
        $form->addElement(form_makeOpenTag('a', array(
512
                        'class' => 'wikilink1',
513
                        'href'  => $href)));
514
        $form->addElement($display_name);
515
        $form->addElement(form_makeCloseTag('a'));
516
517
        if ($media_id) $form->addElement(form_makeOpenTag('div'));
518
519
        if($summary) {
520
            $form->addElement(form_makeOpenTag('span', array('class' => 'sum')));
521
            if(!$media_id) $form->addElement(' – ');
522
            $form->addElement('<bdi>' . hsc($summary) . '</bdi>');
523
            $form->addElement(form_makeCloseTag('span'));
524
        }
525
526
        $form->addElement(form_makeOpenTag('span', array('class' => 'user')));
527
        $form->addElement((empty($editor))?('('.$lang['external_edit'].')'):'<bdi>'.editorinfo($editor).'</bdi>');
528
        $form->addElement(form_makeCloseTag('span'));
529
530
        html_sizechange($sizechange, $form);
531
532
        $form->addElement('('.$lang['current'].')');
533
534
        if ($media_id) $form->addElement(form_makeCloseTag('div'));
535
536
        $form->addElement(form_makeCloseTag('div'));
537
        $form->addElement(form_makeCloseTag('li'));
538
    }
539
540
    foreach($revisions as $rev) {
541
        $date = dformat($rev);
542
        $info = $changelog->getRevisionInfo($rev);
543
        if($media_id) {
544
            $exists = file_exists(mediaFN($id, $rev));
545
        } else {
546
            $exists = page_exists($id, $rev);
547
        }
548
549
        $class = '';
550
        if($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) {
551
            $class = 'minor';
552
        }
553
        $form->addElement(form_makeOpenTag('li', array('class' => $class)));
554
        $form->addElement(form_makeOpenTag('div', array('class' => 'li')));
555
        if($exists){
556
            $form->addElement(form_makeTag('input', array(
557
                            'type' => 'checkbox',
558
                            'name' => 'rev2[]',
559
                            'value' => $rev)));
560
        }else{
561
            $form->addElement('<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />');
562
        }
563
564
        $form->addElement(form_makeOpenTag('span', array('class' => 'date')));
565
        $form->addElement($date);
566
        $form->addElement(form_makeCloseTag('span'));
567
568
        if($exists){
569
            if (!$media_id) {
570
                $href = wl($id,"rev=$rev,do=diff", false, '&');
571
            } else {
572
                $href = media_managerURL(array('image' => $id, 'rev' => $rev, 'mediado' => 'diff'), '&');
573
            }
574
            $form->addElement(form_makeOpenTag('a', array(
575
                            'class' => 'diff_link',
576
                            'href' => $href)));
577
            $form->addElement(form_makeTag('img', array(
578
                            'src'    => DOKU_BASE.'lib/images/diff.png',
579
                            'width'  => 15,
580
                            'height' => 11,
581
                            'title'  => $lang['diff'],
582
                            'alt'    => $lang['diff'])));
583
            $form->addElement(form_makeCloseTag('a'));
584
585
            if (!$media_id) {
586
                $href = wl($id,"rev=$rev",false,'&');
587
            } else {
588
                $href = media_managerURL(array('image' => $id, 'tab_details' => 'view', 'rev' => $rev), '&');
589
            }
590
            $form->addElement(form_makeOpenTag('a', array(
591
                            'class' => 'wikilink1',
592
                            'href' => $href)));
593
            $form->addElement($display_name);
594
            $form->addElement(form_makeCloseTag('a'));
595
        }else{
596
            $form->addElement('<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />');
597
            $form->addElement($display_name);
598
        }
599
600
        if ($media_id) $form->addElement(form_makeOpenTag('div'));
601
602
        if ($info['sum']) {
603
            $form->addElement(form_makeOpenTag('span', array('class' => 'sum')));
604
            if(!$media_id) $form->addElement(' – ');
605
            $form->addElement('<bdi>'.hsc($info['sum']).'</bdi>');
606
            $form->addElement(form_makeCloseTag('span'));
607
        }
608
609
        $form->addElement(form_makeOpenTag('span', array('class' => 'user')));
610
        if($info['user']){
611
            $form->addElement('<bdi>'.editorinfo($info['user']).'</bdi>');
612
            if(auth_ismanager()){
613
                $form->addElement(' <bdo dir="ltr">('.$info['ip'].')</bdo>');
614
            }
615
        }else{
616
            $form->addElement('<bdo dir="ltr">'.$info['ip'].'</bdo>');
617
        }
618
        $form->addElement(form_makeCloseTag('span'));
619
620
        html_sizechange($info['sizechange'], $form);
621
622
        if ($media_id) $form->addElement(form_makeCloseTag('div'));
623
624
        $form->addElement(form_makeCloseTag('div'));
625
        $form->addElement(form_makeCloseTag('li'));
626
    }
627
    $form->addElement(form_makeCloseTag('ul'));
628
    if (!$media_id) {
629
        $form->addElement(form_makeButton('submit', 'diff', $lang['diff2']));
630
    } else {
631
        $form->addHidden('mediado', 'diff');
632
        $form->addElement(form_makeButton('submit', '', $lang['diff2']));
633
    }
634
    html_form('revisions', $form);
635
636
    print '<div class="pagenav">';
637
    $last = $first + $conf['recent'];
638
    if ($first > 0) {
639
        $first -= $conf['recent'];
640
        if ($first < 0) $first = 0;
641
        print '<div class="pagenav-prev">';
642
        if ($media_id) {
643
            print html_btn('newer',$media_id,"p",media_managerURL(array('first' => $first), '&amp;', false, true));
644
        } else {
645
            print html_btn('newer',$id,"p",array('do' => 'revisions', 'first' => $first));
646
        }
647
        print '</div>';
648
    }
649
    if ($hasNext) {
650
        print '<div class="pagenav-next">';
651
        if ($media_id) {
652
            print html_btn('older',$media_id,"n",media_managerURL(array('first' => $last), '&amp;', false, true));
653
        } else {
654
            print html_btn('older',$id,"n",array('do' => 'revisions', 'first' => $last));
655
        }
656
        print '</div>';
657
    }
658
    print '</div>';
659
660
}
661
662
/**
663
 * display recent changes
664
 *
665
 * @author Andreas Gohr <[email protected]>
666
 * @author Matthias Grimm <[email protected]>
667
 * @author Ben Coburn <[email protected]>
668
 * @author Kate Arzamastseva <[email protected]>
669
 *
670
 * @param int $first
671
 * @param string $show_changes
672
 */
673
function html_recent($first = 0, $show_changes = 'both') {
674
    global $conf;
675
    global $lang;
676
    global $ID;
677
    /* we need to get one additionally log entry to be able to
678
     * decide if this is the last page or is there another one.
679
     * This is the cheapest solution to get this information.
680
     */
681
    $flags = 0;
682
    if($show_changes == 'mediafiles' && $conf['mediarevisions']) {
683
        $flags = RECENTS_MEDIA_CHANGES;
684
    } elseif($show_changes == 'pages') {
685
        $flags = 0;
686
    } elseif($conf['mediarevisions']) {
687
        $show_changes = 'both';
688
        $flags = RECENTS_MEDIA_PAGES_MIXED;
689
    }
690
691
    $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
692
    if(count($recents) == 0 && $first != 0) {
693
        $first = 0;
694
        $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
695
    }
696
    $hasNext = false;
697
    if(count($recents) > $conf['recent']) {
698
        $hasNext = true;
699
        array_pop($recents); // remove extra log entry
700
    }
701
702
    print p_locale_xhtml('recent');
703
704
    if(getNS($ID) != '') {
705
        print '<div class="level1"><p>' .
706
            sprintf($lang['recent_global'], getNS($ID), wl('', 'do=recent')) .
707
            '</p></div>';
708
    }
709
710
    $form = new Doku_Form(array('id' => 'dw__recent', 'method' => 'GET', 'class' => 'changes', 'action'=>wl($ID)));
711
    $form->addHidden('sectok', null);
712
    $form->addHidden('do', 'recent');
713
    $form->addHidden('id', $ID);
714
715
    if($conf['mediarevisions']) {
716
        $form->addElement('<div class="changeType">');
717
        $form->addElement(form_makeListboxField(
718
                    'show_changes',
719
                    array(
720
                        'pages'      => $lang['pages_changes'],
721
                        'mediafiles' => $lang['media_changes'],
722
                        'both'       => $lang['both_changes']
723
                    ),
724
                    $show_changes,
725
                    $lang['changes_type'],
726
                    '', '',
727
                    array('class' => 'quickselect')));
728
729
        $form->addElement(form_makeButton('submit', 'recent', $lang['btn_apply']));
730
        $form->addElement('</div>');
731
    }
732
733
    $form->addElement(form_makeOpenTag('ul'));
734
735
    foreach($recents as $recent) {
736
        $date = dformat($recent['date']);
737
738
        $class = '';
739
        if($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) {
740
            $class = 'minor';
741
        }
742
        $form->addElement(form_makeOpenTag('li', array('class' => $class)));
743
        $form->addElement(form_makeOpenTag('div', array('class' => 'li')));
744
745
        if(!empty($recent['media'])) {
746
            $form->addElement(media_printicon($recent['id']));
747
        } else {
748
            $icon = DOKU_BASE . 'lib/images/fileicons/file.png';
749
            $form->addElement('<img src="' . $icon . '" alt="' . $recent['id'] . '" class="icon" />');
750
        }
751
752
        $form->addElement(form_makeOpenTag('span', array('class' => 'date')));
753
        $form->addElement($date);
754
        $form->addElement(form_makeCloseTag('span'));
755
756
        $diff = false;
757
        $href = '';
758
759
        if(!empty($recent['media'])) {
760
            $changelog = new MediaChangeLog($recent['id']);
761
            $revs = $changelog->getRevisions(0, 1);
762
            $diff = (count($revs) && file_exists(mediaFN($recent['id'])));
763
            if($diff) {
764
                $href = media_managerURL(array(
765
                                            'tab_details' => 'history',
766
                                            'mediado' => 'diff',
767
                                            'image' => $recent['id'],
768
                                            'ns' => getNS($recent['id'])
769
                                        ), '&');
770
            }
771
        } else {
772
            $href = wl($recent['id'], "do=diff", false, '&');
773
        }
774
775
        if(!empty($recent['media']) && !$diff) {
776
            $form->addElement('<img src="' . DOKU_BASE . 'lib/images/blank.gif" width="15" height="11" alt="" />');
777
        } else {
778
            $form->addElement(form_makeOpenTag('a', array('class' => 'diff_link', 'href' => $href)));
779
            $form->addElement(form_makeTag('img', array(
780
                            'src'    => DOKU_BASE . 'lib/images/diff.png',
781
                            'width'  => 15,
782
                            'height' => 11,
783
                            'title'  => $lang['diff'],
784
                            'alt'    => $lang['diff']
785
                        )));
786
            $form->addElement(form_makeCloseTag('a'));
787
        }
788
789
        if(!empty($recent['media'])) {
790
            $href = media_managerURL(
791
                array(
792
                    'tab_details' => 'history',
793
                    'image' => $recent['id'],
794
                    'ns' => getNS($recent['id'])
795
                ),
796
                '&'
797
            );
798
        } else {
799
            $href = wl($recent['id'], "do=revisions", false, '&');
800
        }
801
        $form->addElement(form_makeOpenTag('a', array(
802
                        'class' => 'revisions_link',
803
                        'href'  => $href)));
804
        $form->addElement(form_makeTag('img', array(
805
                        'src'    => DOKU_BASE . 'lib/images/history.png',
806
                        'width'  => 12,
807
                        'height' => 14,
808
                        'title'  => $lang['btn_revs'],
809
                        'alt'    => $lang['btn_revs']
810
                    )));
811
        $form->addElement(form_makeCloseTag('a'));
812
813
        if(!empty($recent['media'])) {
814
            $href = media_managerURL(
815
                array(
816
                    'tab_details' => 'view',
817
                    'image' => $recent['id'],
818
                    'ns' => getNS($recent['id'])
819
                ),
820
                '&'
821
            );
822
            $class = file_exists(mediaFN($recent['id'])) ? 'wikilink1' : 'wikilink2';
823
            $form->addElement(form_makeOpenTag('a', array(
824
                        'class' => $class,
825
                        'href'  => $href)));
826
            $form->addElement($recent['id']);
827
            $form->addElement(form_makeCloseTag('a'));
828
        } else {
829
            $form->addElement(html_wikilink(':' . $recent['id'], useHeading('navigation') ? null : $recent['id']));
830
        }
831
        $form->addElement(form_makeOpenTag('span', array('class' => 'sum')));
832
        $form->addElement(' – ' . hsc($recent['sum']));
833
        $form->addElement(form_makeCloseTag('span'));
834
835
        $form->addElement(form_makeOpenTag('span', array('class' => 'user')));
836
        if($recent['user']) {
837
            $form->addElement('<bdi>' . editorinfo($recent['user']) . '</bdi>');
838
            if(auth_ismanager()) {
839
                $form->addElement(' <bdo dir="ltr">(' . $recent['ip'] . ')</bdo>');
840
            }
841
        } else {
842
            $form->addElement('<bdo dir="ltr">' . $recent['ip'] . '</bdo>');
843
        }
844
        $form->addElement(form_makeCloseTag('span'));
845
846
        html_sizechange($recent['sizechange'], $form);
847
848
        $form->addElement(form_makeCloseTag('div'));
849
        $form->addElement(form_makeCloseTag('li'));
850
    }
851
    $form->addElement(form_makeCloseTag('ul'));
852
853
    $form->addElement(form_makeOpenTag('div', array('class' => 'pagenav')));
854
    $last = $first + $conf['recent'];
855
    if($first > 0) {
856
        $first -= $conf['recent'];
857
        if($first < 0) $first = 0;
858
        $form->addElement(form_makeOpenTag('div', array('class' => 'pagenav-prev')));
859
        $form->addElement(form_makeOpenTag('button', array(
860
                        'type'      => 'submit',
861
                        'name'      => 'first[' . $first . ']',
862
                        'accesskey' => 'n',
863
                        'title'     => $lang['btn_newer'] . ' [N]',
864
                        'class'     => 'button show'
865
                    )));
866
        $form->addElement($lang['btn_newer']);
867
        $form->addElement(form_makeCloseTag('button'));
868
        $form->addElement(form_makeCloseTag('div'));
869
    }
870
    if($hasNext) {
871
        $form->addElement(form_makeOpenTag('div', array('class' => 'pagenav-next')));
872
        $form->addElement(form_makeOpenTag('button', array(
873
                        'type'      => 'submit',
874
                        'name'      => 'first[' . $last . ']',
875
                        'accesskey' => 'p',
876
                        'title'     => $lang['btn_older'] . ' [P]',
877
                        'class'     => 'button show'
878
                    )));
879
        $form->addElement($lang['btn_older']);
880
        $form->addElement(form_makeCloseTag('button'));
881
        $form->addElement(form_makeCloseTag('div'));
882
    }
883
    $form->addElement(form_makeCloseTag('div'));
884
    html_form('recent', $form);
885
}
886
887
/**
888
 * Display page index
889
 *
890
 * @author Andreas Gohr <[email protected]>
891
 *
892
 * @param string $ns
893
 */
894
function html_index($ns){
895
    global $conf;
896
    global $ID;
897
    $ns  = cleanID($ns);
898
    if(empty($ns)){
899
        $ns = getNS($ID);
900
        if($ns === false) $ns ='';
901
    }
902
    $ns  = utf8_encodeFN(str_replace(':','/',$ns));
903
904
    echo p_locale_xhtml('index');
905
    echo '<div id="index__tree" class="index__tree">';
906
907
    $data = array();
908
    search($data,$conf['datadir'],'search_index',array('ns' => $ns));
909
    echo html_buildlist($data,'idx','html_list_index','html_li_index');
910
911
    echo '</div>';
912
}
913
914
/**
915
 * Index item formatter
916
 *
917
 * User function for html_buildlist()
918
 *
919
 * @author Andreas Gohr <[email protected]>
920
 *
921
 * @param array $item
922
 * @return string
923
 */
924
function html_list_index($item){
925
    global $ID, $conf;
926
927
    // prevent searchbots needlessly following links
928
    $nofollow = ($ID != $conf['start'] || $conf['sitemap']) ? 'rel="nofollow"' : '';
929
930
    $ret = '';
931
    $base = ':'.$item['id'];
932
    $base = substr($base,strrpos($base,':')+1);
933
    if($item['type']=='d'){
934
        // FS#2766, no need for search bots to follow namespace links in the index
935
        $link = wl($ID, 'idx=' . rawurlencode($item['id']));
936
        $ret .= '<a href="' . $link . '" title="' . $item['id'] . '" class="idx_dir" ' . $nofollow . '><strong>';
937
        $ret .= $base;
938
        $ret .= '</strong></a>';
939
    }else{
940
        // default is noNSorNS($id), but we want noNS($id) when useheading is off FS#2605
941
        $ret .= html_wikilink(':'.$item['id'], useHeading('navigation') ? null : noNS($item['id']));
942
    }
943
    return $ret;
944
}
945
946
/**
947
 * Index List item
948
 *
949
 * This user function is used in html_buildlist to build the
950
 * <li> tags for namespaces when displaying the page index
951
 * it gives different classes to opened or closed "folders"
952
 *
953
 * @author Andreas Gohr <[email protected]>
954
 *
955
 * @param array $item
956
 * @return string html
957
 */
958
function html_li_index($item){
959
    global $INFO;
960
    global $ACT;
961
962
    $class = '';
963
    $id = '';
964
965
    if($item['type'] == "f"){
966
        // scroll to the current item
967
        if(isset($INFO) && $item['id'] == $INFO['id'] && $ACT == 'index') {
968
            $id = ' id="scroll__here"';
969
            $class = ' bounce';
970
        }
971
        return '<li class="level'.$item['level'].$class.'" '.$id.'>';
972
    }elseif($item['open']){
973
        return '<li class="open">';
974
    }else{
975
        return '<li class="closed">';
976
    }
977
}
978
979
/**
980
 * Default List item
981
 *
982
 * @author Andreas Gohr <[email protected]>
983
 *
984
 * @param array $item
985
 * @return string html
986
 */
987
function html_li_default($item){
988
    return '<li class="level'.$item['level'].'">';
989
}
990
991
/**
992
 * Build an unordered list
993
 *
994
 * Build an unordered list from the given $data array
995
 * Each item in the array has to have a 'level' property
996
 * the item itself gets printed by the given $func user
997
 * function. The second and optional function is used to
998
 * print the <li> tag. Both user function need to accept
999
 * a single item.
1000
 *
1001
 * Both user functions can be given as array to point to
1002
 * a member of an object.
1003
 *
1004
 * @author Andreas Gohr <[email protected]>
1005
 *
1006
 * @param array    $data  array with item arrays
1007
 * @param string   $class class of ul wrapper
1008
 * @param callable $func  callback to print an list item
1009
 * @param callable $lifunc callback to the opening li tag
1010
 * @param bool     $forcewrapper Trigger building a wrapper ul if the first level is
1011
 *                               0 (we have a root object) or 1 (just the root content)
1012
 * @return string html of an unordered list
1013
 */
1014
function html_buildlist($data,$class,$func,$lifunc='html_li_default',$forcewrapper=false){
1015
    if (count($data) === 0) {
1016
        return '';
1017
    }
1018
1019
    $firstElement = reset($data);
1020
    $start_level = $firstElement['level'];
1021
    $level = $start_level;
1022
    $ret   = '';
1023
    $open  = 0;
1024
1025
    foreach ($data as $item){
1026
1027
        if( $item['level'] > $level ){
1028
            //open new list
1029
            for($i=0; $i<($item['level'] - $level); $i++){
1030
                if ($i) $ret .= "<li class=\"clear\">";
1031
                $ret .= "\n<ul class=\"$class\">\n";
1032
                $open++;
1033
            }
1034
            $level = $item['level'];
1035
1036
        }elseif( $item['level'] < $level ){
1037
            //close last item
1038
            $ret .= "</li>\n";
1039
            while( $level > $item['level'] && $open > 0 ){
1040
                //close higher lists
1041
                $ret .= "</ul>\n</li>\n";
1042
                $level--;
1043
                $open--;
1044
            }
1045
        } elseif ($ret !== '') {
1046
            //close previous item
1047
            $ret .= "</li>\n";
1048
        }
1049
1050
        //print item
1051
        $ret .= call_user_func($lifunc,$item);
1052
        $ret .= '<div class="li">';
1053
1054
        $ret .= call_user_func($func,$item);
1055
        $ret .= '</div>';
1056
    }
1057
1058
    //close remaining items and lists
1059
    $ret .= "</li>\n";
1060
    while($open-- > 0) {
1061
        $ret .= "</ul></li>\n";
1062
    }
1063
1064
    if ($forcewrapper || $start_level < 2) {
1065
        // Trigger building a wrapper ul if the first level is
1066
        // 0 (we have a root object) or 1 (just the root content)
1067
        $ret = "\n<ul class=\"$class\">\n".$ret."</ul>\n";
1068
    }
1069
1070
    return $ret;
1071
}
1072
1073
/**
1074
 * display backlinks
1075
 *
1076
 * @author Andreas Gohr <[email protected]>
1077
 * @author Michael Klier <[email protected]>
1078
 */
1079
function html_backlinks(){
1080
    global $ID;
1081
    global $lang;
1082
1083
    print p_locale_xhtml('backlinks');
1084
1085
    $data = ft_backlinks($ID);
1086
1087
    if(!empty($data)) {
1088
        print '<ul class="idx">';
1089
        foreach($data as $blink){
1090
            print '<li><div class="li">';
1091
            print html_wikilink(':'.$blink,useHeading('navigation')?null:$blink);
1092
            print '</div></li>';
1093
        }
1094
        print '</ul>';
1095
    } else {
1096
        print '<div class="level1"><p>' . $lang['nothingfound'] . '</p></div>';
1097
    }
1098
}
1099
1100
/**
1101
 * Get header of diff HTML
1102
 *
1103
 * @param string $l_rev   Left revisions
1104
 * @param string $r_rev   Right revision
1105
 * @param string $id      Page id, if null $ID is used
1106
 * @param bool   $media   If it is for media files
1107
 * @param bool   $inline  Return the header on a single line
1108
 * @return string[] HTML snippets for diff header
1109
 */
1110
function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = false) {
1111
    global $lang;
1112
    if ($id === null) {
1113
        global $ID;
1114
        $id = $ID;
1115
    }
1116
    $head_separator = $inline ? ' ' : '<br />';
1117
    $media_or_wikiFN = $media ? 'mediaFN' : 'wikiFN';
1118
    $ml_or_wl = $media ? 'ml' : 'wl';
1119
    $l_minor = $r_minor = '';
1120
1121
    if($media) {
1122
        $changelog = new MediaChangeLog($id);
1123
    } else {
1124
        $changelog = new PageChangeLog($id);
1125
    }
1126
    if(!$l_rev){
1127
        $l_head = '&mdash;';
1128
    }else{
1129
        $l_info   = $changelog->getRevisionInfo($l_rev);
1130
        if($l_info['user']){
1131
            $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
1132
            if(auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
1133
        } else {
1134
            $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>';
1135
        }
1136
        $l_user  = '<span class="user">'.$l_user.'</span>';
1137
        $l_sum   = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : '';
1138
        if ($l_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"';
1139
1140
        $l_head_title = ($media) ? dformat($l_rev) : $id.' ['.dformat($l_rev).']';
1141
        $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'.
1142
        $l_head_title.'</a></bdi>'.
1143
        $head_separator.$l_user.' '.$l_sum;
1144
    }
1145
1146
    if($r_rev){
1147
        $r_info   = $changelog->getRevisionInfo($r_rev);
1148
        if($r_info['user']){
1149
            $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
1150
            if(auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
1151
        } else {
1152
            $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>';
1153
        }
1154
        $r_user = '<span class="user">'.$r_user.'</span>';
1155
        $r_sum  = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : '';
1156
        if ($r_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
1157
1158
        $r_head_title = ($media) ? dformat($r_rev) : $id.' ['.dformat($r_rev).']';
1159
        $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'.
1160
        $r_head_title.'</a></bdi>'.
1161
        $head_separator.$r_user.' '.$r_sum;
1162
    }elseif($_rev = @filemtime($media_or_wikiFN($id))){
1163
        $_info   = $changelog->getRevisionInfo($_rev);
1164
        if($_info['user']){
1165
            $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
1166
            if(auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
1167
        } else {
1168
            $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>';
1169
        }
1170
        $_user = '<span class="user">'.$_user.'</span>';
1171
        $_sum  = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : '';
1172
        if ($_info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
1173
1174
        $r_head_title = ($media) ? dformat($_rev) : $id.' ['.dformat($_rev).']';
1175
        $r_head  = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id).'">'.
1176
        $r_head_title.'</a></bdi> '.
1177
        '('.$lang['current'].')'.
1178
        $head_separator.$_user.' '.$_sum;
1179
    }else{
1180
        $r_head = '&mdash; ('.$lang['current'].')';
1181
    }
1182
1183
    return array($l_head, $r_head, $l_minor, $r_minor);
1184
}
1185
1186
/**
1187
 * Show diff
1188
 * between current page version and provided $text
1189
 * or between the revisions provided via GET or POST
1190
 *
1191
 * @author Andreas Gohr <[email protected]>
1192
 * @param  string $text  when non-empty: compare with this text with most current version
1193
 * @param  bool   $intro display the intro text
1194
 * @param  string $type  type of the diff (inline or sidebyside)
1195
 */
1196
function html_diff($text = '', $intro = true, $type = null) {
1197
    global $ID;
1198
    global $REV;
1199
    global $lang;
1200
    global $INPUT;
1201
    global $INFO;
1202
    $pagelog = new PageChangeLog($ID);
1203
1204
    /*
1205
     * Determine diff type
1206
     */
1207
    if (!$type) {
1208
        $type = $INPUT->str('difftype');
1209
        if (empty($type)) {
1210
            $type = get_doku_pref('difftype', $type);
1211
            if (empty($type) && $INFO['ismobile']) {
1212
                $type = 'inline';
1213
            }
1214
        }
1215
    }
1216
    if ($type != 'inline') $type = 'sidebyside';
1217
1218
    /*
1219
     * Determine requested revision(s)
1220
     */
1221
    // we're trying to be clever here, revisions to compare can be either
1222
    // given as rev and rev2 parameters, with rev2 being optional. Or in an
1223
    // array in rev2.
1224
    $rev1 = $REV;
1225
1226
    $rev2 = $INPUT->ref('rev2');
1227
    if (is_array($rev2)) {
1228
        $rev1 = (int) $rev2[0];
1229
        $rev2 = (int) $rev2[1];
1230
1231
        if (!$rev1) {
1232
            $rev1 = $rev2;
1233
            unset($rev2);
1234
        }
1235
    } else {
1236
        $rev2 = $INPUT->int('rev2');
1237
    }
1238
1239
    /*
1240
     * Determine left and right revision, its texts and the header
1241
     */
1242
    $r_minor = '';
1243
    $l_minor = '';
1244
1245
    if ($text) { // compare text to the most current revision
1246
        $l_rev = '';
1247
        $l_text = rawWiki($ID, '');
1248
        $l_head = '<a class="wikilink1" href="'. wl($ID) .'">'
1249
            . $ID .' '. dformat((int) @filemtime(wikiFN($ID))) .'</a> '
1250
            . $lang['current'];
1251
1252
        $r_rev = '';
1253
        $r_text = cleanText($text);
1254
        $r_head = $lang['yours'];
1255
    } else {
1256
        if ($rev1 && isset($rev2) && $rev2) { // two specific revisions wanted
1257
            // make sure order is correct (older on the left)
1258
            if ($rev1 < $rev2) {
1259
                $l_rev = $rev1;
1260
                $r_rev = $rev2;
1261
            } else {
1262
                $l_rev = $rev2;
1263
                $r_rev = $rev1;
1264
            }
1265
        } elseif ($rev1) { // single revision given, compare to current
1266
            $r_rev = '';
1267
            $l_rev = $rev1;
1268
        } else { // no revision was given, compare previous to current
1269
            $r_rev = '';
1270
            $revs = $pagelog->getRevisions(0, 1);
1271
            $l_rev = $revs[0];
1272
            $REV = $l_rev; // store revision back in $REV
1273
        }
1274
1275
        // when both revisions are empty then the page was created just now
1276
        if (!$l_rev && !$r_rev) {
1277
            $l_text = '';
1278
        } else {
1279
            $l_text = rawWiki($ID, $l_rev);
1280
        }
1281
        $r_text = rawWiki($ID, $r_rev);
1282
1283
        list($l_head, $r_head, $l_minor, $r_minor) = html_diff_head($l_rev, $r_rev, null, false, $type == 'inline');
1284
    }
1285
1286
    /*
1287
     * Build navigation
1288
     */
1289
    $l_nav = '';
1290
    $r_nav = '';
1291
    if (!$text) {
1292
        list($l_nav, $r_nav) = html_diff_navigation($pagelog, $type, $l_rev, $r_rev);
1293
    }
1294
    /*
1295
     * Create diff object and the formatter
1296
     */
1297
    $diff = new Diff(explode("\n", $l_text), explode("\n", $r_text));
1298
1299
    if ($type == 'inline') {
1300
        $diffformatter = new InlineDiffFormatter();
1301
    } else {
1302
        $diffformatter = new TableDiffFormatter();
1303
    }
1304
    /*
1305
     * Display intro
1306
     */
1307
    if ($intro) print p_locale_xhtml('diff');
1308
1309
    /*
1310
     * Display type and exact reference
1311
     */
1312
    if (!$text) {
1313
        print '<div class="diffoptions group">';
1314
1315
1316
        $form = new Doku_Form(array('action' => wl()));
1317
        $form->addHidden('id', $ID);
1318
        $form->addHidden('rev2[0]', $l_rev);
1319
        $form->addHidden('rev2[1]', $r_rev);
1320
        $form->addHidden('do', 'diff');
1321
        $form->addElement(
1322
             form_makeListboxField(
1323
                 'difftype',
1324
                 array(
1325
                     'sidebyside' => $lang['diff_side'],
1326
                     'inline' => $lang['diff_inline']
1327
                 ),
1328
                 $type,
1329
                 $lang['diff_type'],
1330
                 '', '',
1331
                 array('class' => 'quickselect')
1332
             )
1333
        );
1334
        $form->addElement(form_makeButton('submit', 'diff', 'Go'));
1335
        $form->printForm();
1336
1337
        print '<p>';
1338
        // link to exactly this view FS#2835
1339
        print html_diff_navigationlink($type, 'difflink', $l_rev, $r_rev ? $r_rev : $INFO['currentrev']);
1340
        print '</p>';
1341
1342
        print '</div>'; // .diffoptions
1343
    }
1344
1345
    /*
1346
     * Display diff view table
1347
     */
1348
    print '<div class="table">';
1349
    print '<table class="diff diff_'. $type .'">';
1350
1351
    //navigation and header
1352
    if ($type == 'inline') {
1353
        if (!$text) {
1354
            print '<tr>'
1355
                . '<td class="diff-lineheader">-</td>'
1356
                . '<td class="diffnav">'. $l_nav .'</td>'
1357
                . '</tr>';
1358
            print '<tr>'
1359
                . '<th class="diff-lineheader">-</th>'
1360
                . '<th '. $l_minor .'>'. $l_head .'</th>'
1361
                .'</tr>';
1362
        }
1363
        print '<tr>'
1364
            . '<td class="diff-lineheader">+</td>'
1365
            . '<td class="diffnav">'. $r_nav .'</td>'
1366
            .'</tr>';
1367
        print '<tr>'
1368
            . '<th class="diff-lineheader">+</th>'
1369
            . '<th '. $r_minor .'>'. $r_head .'</th>'
1370
            . '</tr>';
1371
    } else {
1372
        if (!$text) {
1373
            print '<tr>'
1374
                . '<td colspan="2" class="diffnav">'. $l_nav .'</td>'
1375
                . '<td colspan="2" class="diffnav">'. $r_nav .'</td>'
1376
                . '</tr>';
1377
        }
1378
        print '<tr>'
1379
            . '<th colspan="2" '. $l_minor ,'>'. $l_head .'</th>'
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ','
Loading history...
1380
            . '<th colspan="2" '. $r_minor .'>'. $r_head .'</th>'
1381
            . '</tr>';
1382
    }
1383
1384
    //diff view
1385
    print html_insert_softbreaks($diffformatter->format($diff));
1386
1387
    print '</table>';
1388
    print '</div>'. DOKU_LF;
1389
}
1390
1391
/**
1392
 * Create html for revision navigation
1393
 *
1394
 * @param PageChangeLog $pagelog changelog object of current page
1395
 * @param string        $type    inline vs sidebyside
1396
 * @param int           $l_rev   left revision timestamp
1397
 * @param int           $r_rev   right revision timestamp
1398
 * @return string[] html of left and right navigation elements
1399
 */
1400
function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) {
1401
    global $INFO, $ID;
1402
1403
    // last timestamp is not in changelog, retrieve timestamp from metadata
1404
    // note: when page is removed, the metadata timestamp is zero
1405
    if (!$r_rev) {
1406
        if (isset($INFO['meta']['last_change']['date'])) {
1407
            $r_rev = $INFO['meta']['last_change']['date'];
1408
        } else {
1409
            $r_rev = 0;
1410
        }
1411
    }
1412
1413
    //retrieve revisions with additional info
1414
    list($l_revs, $r_revs) = $pagelog->getRevisionsAround($l_rev, $r_rev);
1415
    $l_revisions = array();
1416
    if (!$l_rev) {
1417
        $l_revisions[0] = array(0, "", false); //no left revision given, add dummy
1418
    }
1419
    foreach ($l_revs as $rev) {
1420
        $info = $pagelog->getRevisionInfo($rev);
1421
        $l_revisions[$rev] = array(
1422
            $rev,
1423
            dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'],
1424
            $r_rev ? $rev >= $r_rev : false //disable?
1425
        );
1426
    }
1427
    $r_revisions = array();
1428
    if (!$r_rev) {
1429
        $r_revisions[0] = array(0, "", false); //no right revision given, add dummy
1430
    }
1431
    foreach ($r_revs as $rev) {
1432
        $info = $pagelog->getRevisionInfo($rev);
1433
        $r_revisions[$rev] = array(
1434
            $rev,
1435
            dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'],
1436
            $rev <= $l_rev //disable?
1437
        );
1438
    }
1439
1440
    //determine previous/next revisions
1441
    $l_index = array_search($l_rev, $l_revs);
1442
    $l_prev = $l_revs[$l_index + 1];
1443
    $l_next = $l_revs[$l_index - 1];
1444
    if ($r_rev) {
1445
        $r_index = array_search($r_rev, $r_revs);
1446
        $r_prev = $r_revs[$r_index + 1];
1447
        $r_next = $r_revs[$r_index - 1];
1448
    } else {
1449
        //removed page
1450
        if ($l_next) {
1451
            $r_prev = $r_revs[0];
1452
        } else {
1453
            $r_prev = null;
1454
        }
1455
        $r_next = null;
1456
    }
1457
1458
    /*
1459
     * Left side:
1460
     */
1461
    $l_nav = '';
1462
    //move back
1463
    if ($l_prev) {
1464
        $l_nav .= html_diff_navigationlink($type, 'diffbothprevrev', $l_prev, $r_prev);
1465
        $l_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_prev, $r_rev);
1466
    }
1467
    //dropdown
1468
    $form = new Doku_Form(array('action' => wl()));
1469
    $form->addHidden('id', $ID);
1470
    $form->addHidden('difftype', $type);
1471
    $form->addHidden('rev2[1]', $r_rev);
1472
    $form->addHidden('do', 'diff');
1473
    $form->addElement(
1474
         form_makeListboxField(
1475
             'rev2[0]',
1476
             $l_revisions,
1477
             $l_rev,
1478
             '', '', '',
1479
             array('class' => 'quickselect')
1480
         )
1481
    );
1482
    $form->addElement(form_makeButton('submit', 'diff', 'Go'));
1483
    $l_nav .= $form->getForm();
1484
    //move forward
1485
    if ($l_next && ($l_next < $r_rev || !$r_rev)) {
1486
        $l_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_next, $r_rev);
1487
    }
1488
1489
    /*
1490
     * Right side:
1491
     */
1492
    $r_nav = '';
1493
    //move back
1494
    if ($l_rev < $r_prev) {
1495
        $r_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_rev, $r_prev);
1496
    }
1497
    //dropdown
1498
    $form = new Doku_Form(array('action' => wl()));
1499
    $form->addHidden('id', $ID);
1500
    $form->addHidden('rev2[0]', $l_rev);
1501
    $form->addHidden('difftype', $type);
1502
    $form->addHidden('do', 'diff');
1503
    $form->addElement(
1504
         form_makeListboxField(
1505
             'rev2[1]',
1506
             $r_revisions,
1507
             $r_rev,
1508
             '', '', '',
1509
             array('class' => 'quickselect')
1510
         )
1511
    );
1512
    $form->addElement(form_makeButton('submit', 'diff', 'Go'));
1513
    $r_nav .= $form->getForm();
1514
    //move forward
1515
    if ($r_next) {
1516
        if ($pagelog->isCurrentRevision($r_next)) {
1517
            $r_nav .= html_diff_navigationlink($type, 'difflastrev', $l_rev); //last revision is diff with current page
1518
        } else {
1519
            $r_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_rev, $r_next);
1520
        }
1521
        $r_nav .= html_diff_navigationlink($type, 'diffbothnextrev', $l_next, $r_next);
1522
    }
1523
    return array($l_nav, $r_nav);
1524
}
1525
1526
/**
1527
 * Create html link to a diff defined by two revisions
1528
 *
1529
 * @param string $difftype display type
1530
 * @param string $linktype
1531
 * @param int $lrev oldest revision
1532
 * @param int $rrev newest revision or null for diff with current revision
1533
 * @return string html of link to a diff
1534
 */
1535
function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null) {
1536
    global $ID, $lang;
1537
    if (!$rrev) {
1538
        $urlparam = array(
1539
            'do' => 'diff',
1540
            'rev' => $lrev,
1541
            'difftype' => $difftype,
1542
        );
1543
    } else {
1544
        $urlparam = array(
1545
            'do' => 'diff',
1546
            'rev2[0]' => $lrev,
1547
            'rev2[1]' => $rrev,
1548
            'difftype' => $difftype,
1549
        );
1550
    }
1551
    return  '<a class="'. $linktype .'" href="'. wl($ID, $urlparam) .'" title="'. $lang[$linktype] .'">'
1552
          . '<span>'. $lang[$linktype] .'</span>'
1553
          . '</a>'. DOKU_LF;
1554
}
1555
1556
/**
1557
 * Insert soft breaks in diff html
1558
 *
1559
 * @param string $diffhtml
1560
 * @return string
1561
 */
1562
function html_insert_softbreaks($diffhtml) {
1563
    // search the diff html string for both:
1564
    // - html tags, so these can be ignored
1565
    // - long strings of characters without breaking characters
1566
    return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/','html_softbreak_callback',$diffhtml);
1567
}
1568
1569
/**
1570
 * callback which adds softbreaks
1571
 *
1572
 * @param array $match array with first the complete match
1573
 * @return string the replacement
1574
 */
1575
function html_softbreak_callback($match){
1576
    // if match is an html tag, return it intact
1577
    if ($match[0][0] == '<') return $match[0];
1578
1579
    // its a long string without a breaking character,
1580
    // make certain characters into breaking characters by inserting a
1581
    // word break opportunity (<wbr> tag) in front of them.
1582
    $regex = <<< REGEX
1583
(?(?=              # start a conditional expression with a positive look ahead ...
1584
&\#?\\w{1,6};)     # ... for html entities - we don't want to split them (ok to catch some invalid combinations)
1585
&\#?\\w{1,6};      # yes pattern - a quicker match for the html entity, since we know we have one
1586
|
1587
[?/,&\#;:]         # no pattern - any other group of 'special' characters to insert a breaking character after
1588
)+                 # end conditional expression
1589
REGEX;
1590
1591
    return preg_replace('<'.$regex.'>xu','\0<wbr>',$match[0]);
1592
}
1593
1594
/**
1595
 * show warning on conflict detection
1596
 *
1597
 * @author Andreas Gohr <[email protected]>
1598
 *
1599
 * @param string $text
1600
 * @param string $summary
1601
 */
1602
function html_conflict($text,$summary){
1603
    global $ID;
1604
    global $lang;
1605
1606
    print p_locale_xhtml('conflict');
1607
    $form = new Doku_Form(array('id' => 'dw__editform'));
1608
    $form->addHidden('id', $ID);
1609
    $form->addHidden('wikitext', $text);
1610
    $form->addHidden('summary', $summary);
1611
    $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('accesskey'=>'s')));
1612
    $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel']));
1613
    html_form('conflict', $form);
1614
    print '<br /><br /><br /><br />'.NL;
1615
}
1616
1617
/**
1618
 * Prints the global message array
1619
 *
1620
 * @author Andreas Gohr <[email protected]>
1621
 */
1622
function html_msgarea(){
1623
    global $MSG, $MSG_shown;
1624
    /** @var array $MSG */
1625
    // store if the global $MSG has already been shown and thus HTML output has been started
1626
    $MSG_shown = true;
1627
1628
    if(!isset($MSG)) return;
1629
1630
    $shown = array();
1631
    foreach($MSG as $msg){
1632
        $hash = md5($msg['msg']);
1633
        if(isset($shown[$hash])) continue; // skip double messages
1634
        if(info_msg_allowed($msg)){
1635
            print '<div class="'.$msg['lvl'].'">';
1636
            print $msg['msg'];
1637
            print '</div>';
1638
        }
1639
        $shown[$hash] = 1;
1640
    }
1641
1642
    unset($GLOBALS['MSG']);
1643
}
1644
1645
/**
1646
 * Prints the registration form
1647
 *
1648
 * @author Andreas Gohr <[email protected]>
1649
 */
1650
function html_register(){
1651
    global $lang;
1652
    global $conf;
1653
    global $INPUT;
1654
1655
    $base_attrs = array('size'=>50,'required'=>'required');
1656
    $email_attrs = $base_attrs + array('type'=>'email','class'=>'edit');
1657
1658
    print p_locale_xhtml('register');
1659
    print '<div class="centeralign">'.NL;
1660
    $form = new Doku_Form(array('id' => 'dw__register'));
1661
    $form->startFieldset($lang['btn_register']);
1662
    $form->addHidden('do', 'register');
1663
    $form->addHidden('save', '1');
1664
    $form->addElement(
1665
        form_makeTextField(
1666
            'login',
1667
            $INPUT->post->str('login'),
1668
            $lang['user'],
1669
            '',
1670
            'block',
1671
            $base_attrs
1672
        )
1673
    );
1674
    if (!$conf['autopasswd']) {
1675
        $form->addElement(form_makePasswordField('pass', $lang['pass'], '', 'block', $base_attrs));
1676
        $form->addElement(form_makePasswordField('passchk', $lang['passchk'], '', 'block', $base_attrs));
1677
    }
1678
    $form->addElement(
1679
        form_makeTextField(
1680
            'fullname',
1681
            $INPUT->post->str('fullname'),
1682
            $lang['fullname'],
1683
            '',
1684
            'block',
1685
            $base_attrs
1686
        )
1687
    );
1688
    $form->addElement(
1689
        form_makeField(
1690
            'email',
1691
            'email',
1692
            $INPUT->post->str('email'),
1693
            $lang['email'],
1694
            '',
1695
            'block',
1696
            $email_attrs
1697
        )
1698
    );
1699
    $form->addElement(form_makeButton('submit', '', $lang['btn_register']));
1700
    $form->endFieldset();
1701
    html_form('register', $form);
1702
1703
    print '</div>'.NL;
1704
}
1705
1706
/**
1707
 * Print the update profile form
1708
 *
1709
 * @author Christopher Smith <[email protected]>
1710
 * @author Andreas Gohr <[email protected]>
1711
 */
1712
function html_updateprofile(){
1713
    global $lang;
1714
    global $conf;
1715
    global $INPUT;
1716
    global $INFO;
1717
    /** @var AuthPlugin $auth */
1718
    global $auth;
1719
1720
    print p_locale_xhtml('updateprofile');
1721
    print '<div class="centeralign">'.NL;
1722
1723
    $fullname = $INPUT->post->str('fullname', $INFO['userinfo']['name'], true);
1724
    $email = $INPUT->post->str('email', $INFO['userinfo']['mail'], true);
1725
    $form = new Doku_Form(array('id' => 'dw__register'));
1726
    $form->startFieldset($lang['profile']);
1727
    $form->addHidden('do', 'profile');
1728
    $form->addHidden('save', '1');
1729
    $form->addElement(
1730
        form_makeTextField(
1731
            'login',
1732
            $_SERVER['REMOTE_USER'],
1733
            $lang['user'],
1734
            '',
1735
            'block',
1736
            array('size' => '50', 'disabled' => 'disabled')
1737
        )
1738
    );
1739
    $attr = array('size'=>'50');
1740
    if (!$auth->canDo('modName')) $attr['disabled'] = 'disabled';
1741
    $form->addElement(form_makeTextField('fullname', $fullname, $lang['fullname'], '', 'block', $attr));
1742
    $attr = array('size'=>'50', 'class'=>'edit');
1743
    if (!$auth->canDo('modMail')) $attr['disabled'] = 'disabled';
1744
    $form->addElement(form_makeField('email','email', $email, $lang['email'], '', 'block', $attr));
1745
    $form->addElement(form_makeTag('br'));
1746
    if ($auth->canDo('modPass')) {
1747
        $form->addElement(form_makePasswordField('newpass', $lang['newpass'], '', 'block', array('size'=>'50')));
1748
        $form->addElement(form_makePasswordField('passchk', $lang['passchk'], '', 'block', array('size'=>'50')));
1749
    }
1750
    if ($conf['profileconfirm']) {
1751
        $form->addElement(form_makeTag('br'));
1752
        $form->addElement(
1753
            form_makePasswordField(
1754
                'oldpass',
1755
                $lang['oldpass'],
1756
                '',
1757
                'block',
1758
                array('size' => '50', 'required' => 'required')
1759
            )
1760
        );
1761
    }
1762
    $form->addElement(form_makeButton('submit', '', $lang['btn_save']));
1763
    $form->addElement(form_makeButton('reset', '', $lang['btn_reset']));
1764
1765
    $form->endFieldset();
1766
    html_form('updateprofile', $form);
1767
1768
    if ($auth->canDo('delUser') && actionOK('profile_delete')) {
1769
        $form_profiledelete = new Doku_Form(array('id' => 'dw__profiledelete'));
1770
        $form_profiledelete->startFieldset($lang['profdeleteuser']);
1771
        $form_profiledelete->addHidden('do', 'profile_delete');
1772
        $form_profiledelete->addHidden('delete', '1');
1773
        $form_profiledelete->addElement(
1774
            form_makeCheckboxField(
1775
                'confirm_delete',
1776
                '1',
1777
                $lang['profconfdelete'],
1778
                'dw__confirmdelete',
1779
                '',
1780
                array('required' => 'required')
1781
            )
1782
        );
1783
        if ($conf['profileconfirm']) {
1784
            $form_profiledelete->addElement(form_makeTag('br'));
1785
            $form_profiledelete->addElement(
1786
                form_makePasswordField(
1787
                    'oldpass',
1788
                    $lang['oldpass'],
1789
                    '',
1790
                    'block',
1791
                    array('size' => '50', 'required' => 'required')
1792
                )
1793
            );
1794
        }
1795
        $form_profiledelete->addElement(form_makeButton('submit', '', $lang['btn_deleteuser']));
1796
        $form_profiledelete->endFieldset();
1797
1798
        html_form('profiledelete', $form_profiledelete);
1799
    }
1800
1801
    print '</div>'.NL;
1802
}
1803
1804
/**
1805
 * Preprocess edit form data
1806
 *
1807
 * @author   Andreas Gohr <[email protected]>
1808
 *
1809
 * @triggers HTML_EDITFORM_OUTPUT
1810
 */
1811
function html_edit(){
1812
    global $INPUT;
1813
    global $ID;
1814
    global $REV;
1815
    global $DATE;
1816
    global $PRE;
1817
    global $SUF;
1818
    global $INFO;
1819
    global $SUM;
1820
    global $lang;
1821
    global $conf;
1822
    global $TEXT;
1823
1824
    if ($INPUT->has('changecheck')) {
1825
        $check = $INPUT->str('changecheck');
1826
    } elseif(!$INFO['exists']){
1827
        // $TEXT has been loaded from page template
1828
        $check = md5('');
1829
    } else {
1830
        $check = md5($TEXT);
1831
    }
1832
    $mod = md5($TEXT) !== $check;
1833
1834
    $wr = $INFO['writable'] && !$INFO['locked'];
1835
    $include = 'edit';
1836
    if($wr){
1837
        if ($REV) $include = 'editrev';
1838
    }else{
1839
        // check pseudo action 'source'
1840
        if(!actionOK('source')){
1841
            msg('Command disabled: source',-1);
1842
            return;
1843
        }
1844
        $include = 'read';
1845
    }
1846
1847
    global $license;
1848
1849
    $form = new Doku_Form(array('id' => 'dw__editform'));
1850
    $form->addHidden('id', $ID);
1851
    $form->addHidden('rev', $REV);
1852
    $form->addHidden('date', $DATE);
1853
    $form->addHidden('prefix', $PRE . '.');
1854
    $form->addHidden('suffix', $SUF);
1855
    $form->addHidden('changecheck', $check);
1856
1857
    $data = array('form' => $form,
1858
                  'wr'   => $wr,
1859
                  'media_manager' => true,
1860
                  'target' => ($INPUT->has('target') && $wr) ? $INPUT->str('target') : 'section',
1861
                  'intro_locale' => $include);
1862
1863
    if ($data['target'] !== 'section') {
1864
        // Only emit event if page is writable, section edit data is valid and
1865
        // edit target is not section.
1866
        Event::createAndTrigger('HTML_EDIT_FORMSELECTION', $data, 'html_edit_form', true);
1867
    } else {
1868
        html_edit_form($data);
1869
    }
1870
    if (isset($data['intro_locale'])) {
1871
        echo p_locale_xhtml($data['intro_locale']);
1872
    }
1873
1874
    $form->addHidden('target', $data['target']);
1875
    if ($INPUT->has('hid')) {
1876
        $form->addHidden('hid', $INPUT->str('hid'));
1877
    }
1878
    if ($INPUT->has('codeblockOffset')) {
1879
        $form->addHidden('codeblockOffset', $INPUT->str('codeblockOffset'));
1880
    }
1881
    $form->addElement(form_makeOpenTag('div', array('id'=>'wiki__editbar', 'class'=>'editBar')));
1882
    $form->addElement(form_makeOpenTag('div', array('id'=>'size__ctl')));
1883
    $form->addElement(form_makeCloseTag('div'));
1884
    if ($wr) {
1885
        $form->addElement(form_makeOpenTag('div', array('class'=>'editButtons')));
1886
        $form->addElement(
1887
            form_makeButton(
1888
                'submit',
1889
                'save',
1890
                $lang['btn_save'],
1891
                array('id' => 'edbtn__save', 'accesskey' => 's', 'tabindex' => '4')
1892
            )
1893
        );
1894
        $form->addElement(
1895
            form_makeButton(
1896
                'submit',
1897
                'preview',
1898
                $lang['btn_preview'],
1899
                array('id' => 'edbtn__preview', 'accesskey' => 'p', 'tabindex' => '5')
1900
            )
1901
        );
1902
        $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('tabindex'=>'6')));
1903
        $form->addElement(form_makeCloseTag('div'));
1904
        $form->addElement(form_makeOpenTag('div', array('class'=>'summary')));
1905
        $form->addElement(
1906
            form_makeTextField(
1907
                'summary',
1908
                $SUM,
1909
                $lang['summary'],
1910
                'edit__summary',
1911
                'nowrap',
1912
                array('size' => '50', 'tabindex' => '2')
1913
            )
1914
        );
1915
        $elem = html_minoredit();
1916
        if ($elem) $form->addElement($elem);
1917
        $form->addElement(form_makeCloseTag('div'));
1918
    }
1919
    $form->addElement(form_makeCloseTag('div'));
1920
    if($wr && $conf['license']){
1921
        $form->addElement(form_makeOpenTag('div', array('class'=>'license')));
1922
        $out  = $lang['licenseok'];
1923
        $out .= ' <a href="'.$license[$conf['license']]['url'].'" rel="license" class="urlextern"';
1924
        if($conf['target']['extern']) $out .= ' target="'.$conf['target']['extern'].'"';
1925
        $out .= '>'.$license[$conf['license']]['name'].'</a>';
1926
        $form->addElement($out);
1927
        $form->addElement(form_makeCloseTag('div'));
1928
    }
1929
1930
    if ($wr) {
1931
        // sets changed to true when previewed
1932
        echo '<script>/*<![CDATA[*/'. NL;
1933
        echo 'textChanged = ' . ($mod ? 'true' : 'false');
1934
        echo '/*!]]>*/</script>' . NL;
1935
    } ?>
1936
    <div class="editBox" role="application">
1937
1938
    <div class="toolbar group">
1939
        <div id="tool__bar" class="tool__bar"><?php
1940
            if ($wr && $data['media_manager']){
1941
                ?><a href="<?php echo DOKU_BASE?>lib/exe/mediamanager.php?ns=<?php echo $INFO['namespace']?>"
1942
                target="_blank"><?php echo $lang['mediaselect'] ?></a><?php
1943
            }?>
1944
        </div>
1945
    </div>
1946
    <div id="draft__status" class="draft__status">
1947
        <?php
1948
        $draft = new \dokuwiki\Draft($ID, $INFO['client']);
1949
        if ($draft->isDraftAvailable()) {
1950
            echo $draft->getDraftMessage();
1951
        }
1952
        ?>
1953
    </div>
1954
    <?php
1955
1956
    html_form('edit', $form);
1957
    print '</div>'.NL;
1958
}
1959
1960
/**
1961
 * Display the default edit form
1962
 *
1963
 * Is the default action for HTML_EDIT_FORMSELECTION.
1964
 *
1965
 * @param mixed[] $param
1966
 */
1967
function html_edit_form($param) {
1968
    global $TEXT;
1969
1970
    if ($param['target'] !== 'section') {
1971
        msg('No editor for edit target ' . hsc($param['target']) . ' found.', -1);
1972
    }
1973
1974
    $attr = array('tabindex'=>'1');
1975
    if (!$param['wr']) $attr['readonly'] = 'readonly';
1976
1977
    $param['form']->addElement(form_makeWikiText($TEXT, $attr));
1978
}
1979
1980
/**
1981
 * Adds a checkbox for minor edits for logged in users
1982
 *
1983
 * @author Andreas Gohr <[email protected]>
1984
 *
1985
 * @return array|bool
1986
 */
1987
function html_minoredit(){
1988
    global $conf;
1989
    global $lang;
1990
    global $INPUT;
1991
    // minor edits are for logged in users only
1992
    if(!$conf['useacl'] || !$_SERVER['REMOTE_USER']){
1993
        return false;
1994
    }
1995
1996
    $p = array();
1997
    $p['tabindex'] = 3;
1998
    if($INPUT->bool('minor')) $p['checked']='checked';
1999
    return form_makeCheckboxField('minor', '1', $lang['minoredit'], 'minoredit', 'nowrap', $p);
2000
}
2001
2002
/**
2003
 * prints some debug info
2004
 *
2005
 * @author Andreas Gohr <[email protected]>
2006
 */
2007
function html_debug(){
2008
    global $conf;
2009
    global $lang;
2010
    /** @var AuthPlugin $auth */
2011
    global $auth;
2012
    global $INFO;
2013
2014
    //remove sensitive data
2015
    $cnf = $conf;
2016
    debug_guard($cnf);
2017
    $nfo = $INFO;
2018
    debug_guard($nfo);
2019
    $ses = $_SESSION;
2020
    debug_guard($ses);
2021
2022
    print '<html><body>';
2023
2024
    print '<p>When reporting bugs please send all the following ';
2025
    print 'output as a mail to [email protected] ';
2026
    print 'The best way to do this is to save this page in your browser</p>';
2027
2028
    print '<b>$INFO:</b><pre>';
2029
    print_r($nfo);
2030
    print '</pre>';
2031
2032
    print '<b>$_SERVER:</b><pre>';
2033
    print_r($_SERVER);
2034
    print '</pre>';
2035
2036
    print '<b>$conf:</b><pre>';
2037
    print_r($cnf);
2038
    print '</pre>';
2039
2040
    print '<b>DOKU_BASE:</b><pre>';
2041
    print DOKU_BASE;
2042
    print '</pre>';
2043
2044
    print '<b>abs DOKU_BASE:</b><pre>';
2045
    print DOKU_URL;
2046
    print '</pre>';
2047
2048
    print '<b>rel DOKU_BASE:</b><pre>';
2049
    print dirname($_SERVER['PHP_SELF']).'/';
2050
    print '</pre>';
2051
2052
    print '<b>PHP Version:</b><pre>';
2053
    print phpversion();
2054
    print '</pre>';
2055
2056
    print '<b>locale:</b><pre>';
2057
    print setlocale(LC_ALL,0);
2058
    print '</pre>';
2059
2060
    print '<b>encoding:</b><pre>';
2061
    print $lang['encoding'];
2062
    print '</pre>';
2063
2064
    if($auth){
2065
        print '<b>Auth backend capabilities:</b><pre>';
2066
        foreach ($auth->getCapabilities() as $cando){
2067
            print '   '.str_pad($cando,16) . ' => ' . (int)$auth->canDo($cando) . NL;
2068
        }
2069
        print '</pre>';
2070
    }
2071
2072
    print '<b>$_SESSION:</b><pre>';
2073
    print_r($ses);
2074
    print '</pre>';
2075
2076
    print '<b>Environment:</b><pre>';
2077
    print_r($_ENV);
2078
    print '</pre>';
2079
2080
    print '<b>PHP settings:</b><pre>';
2081
    $inis = ini_get_all();
2082
    print_r($inis);
2083
    print '</pre>';
2084
2085
    if (function_exists('apache_get_version')) {
2086
        $apache = array();
2087
        $apache['version'] = apache_get_version();
2088
2089
        if (function_exists('apache_get_modules')) {
2090
            $apache['modules'] = apache_get_modules();
2091
        }
2092
        print '<b>Apache</b><pre>';
2093
        print_r($apache);
2094
        print '</pre>';
2095
    }
2096
2097
    print '</body></html>';
2098
}
2099
2100
/**
2101
 * Form to request a new password for an existing account
2102
 *
2103
 * @author Benoit Chesneau <[email protected]>
2104
 * @author Andreas Gohr <[email protected]>
2105
 */
2106
function html_resendpwd() {
2107
    global $lang;
2108
    global $conf;
2109
    global $INPUT;
2110
2111
    $token = preg_replace('/[^a-f0-9]+/','',$INPUT->str('pwauth'));
2112
2113
    if(!$conf['autopasswd'] && $token){
2114
        print p_locale_xhtml('resetpwd');
2115
        print '<div class="centeralign">'.NL;
2116
        $form = new Doku_Form(array('id' => 'dw__resendpwd'));
2117
        $form->startFieldset($lang['btn_resendpwd']);
2118
        $form->addHidden('token', $token);
2119
        $form->addHidden('do', 'resendpwd');
2120
2121
        $form->addElement(form_makePasswordField('pass', $lang['pass'], '', 'block', array('size'=>'50')));
2122
        $form->addElement(form_makePasswordField('passchk', $lang['passchk'], '', 'block', array('size'=>'50')));
2123
2124
        $form->addElement(form_makeButton('submit', '', $lang['btn_resendpwd']));
2125
        $form->endFieldset();
2126
        html_form('resendpwd', $form);
2127
        print '</div>'.NL;
2128
    }else{
2129
        print p_locale_xhtml('resendpwd');
2130
        print '<div class="centeralign">'.NL;
2131
        $form = new Doku_Form(array('id' => 'dw__resendpwd'));
2132
        $form->startFieldset($lang['resendpwd']);
2133
        $form->addHidden('do', 'resendpwd');
2134
        $form->addHidden('save', '1');
2135
        $form->addElement(form_makeTag('br'));
2136
        $form->addElement(form_makeTextField('login', $INPUT->post->str('login'), $lang['user'], '', 'block'));
2137
        $form->addElement(form_makeTag('br'));
2138
        $form->addElement(form_makeTag('br'));
2139
        $form->addElement(form_makeButton('submit', '', $lang['btn_resendpwd']));
2140
        $form->endFieldset();
2141
        html_form('resendpwd', $form);
2142
        print '</div>'.NL;
2143
    }
2144
}
2145
2146
/**
2147
 * Return the TOC rendered to XHTML
2148
 *
2149
 * @author Andreas Gohr <[email protected]>
2150
 *
2151
 * @param array $toc
2152
 * @return string html
2153
 */
2154
function html_TOC($toc){
2155
    if(!count($toc)) return '';
2156
    global $lang;
2157
    $out  = '<!-- TOC START -->'.DOKU_LF;
2158
    $out .= '<div id="dw__toc" class="dw__toc">'.DOKU_LF;
2159
    $out .= '<h3 class="toggle">';
2160
    $out .= $lang['toc'];
2161
    $out .= '</h3>'.DOKU_LF;
2162
    $out .= '<div>'.DOKU_LF;
2163
    $out .= html_buildlist($toc,'toc','html_list_toc','html_li_default',true);
2164
    $out .= '</div>'.DOKU_LF.'</div>'.DOKU_LF;
2165
    $out .= '<!-- TOC END -->'.DOKU_LF;
2166
    return $out;
2167
}
2168
2169
/**
2170
 * Callback for html_buildlist
2171
 *
2172
 * @param array $item
2173
 * @return string html
2174
 */
2175
function html_list_toc($item){
2176
    if(isset($item['hid'])){
2177
        $link = '#'.$item['hid'];
2178
    }else{
2179
        $link = $item['link'];
2180
    }
2181
2182
    return '<a href="'.$link.'">'.hsc($item['title']).'</a>';
2183
}
2184
2185
/**
2186
 * Helper function to build TOC items
2187
 *
2188
 * Returns an array ready to be added to a TOC array
2189
 *
2190
 * @param string $link  - where to link (if $hash set to '#' it's a local anchor)
2191
 * @param string $text  - what to display in the TOC
2192
 * @param int    $level - nesting level
2193
 * @param string $hash  - is prepended to the given $link, set blank if you want full links
2194
 * @return array the toc item
2195
 */
2196
function html_mktocitem($link, $text, $level, $hash='#'){
2197
    return  array( 'link'  => $hash.$link,
2198
            'title' => $text,
2199
            'type'  => 'ul',
2200
            'level' => $level);
2201
}
2202
2203
/**
2204
 * Output a Doku_Form object.
2205
 * Triggers an event with the form name: HTML_{$name}FORM_OUTPUT
2206
 *
2207
 * @author Tom N Harris <[email protected]>
2208
 *
2209
 * @param string     $name The name of the form
2210
 * @param Doku_Form  $form The form
2211
 */
2212
function html_form($name, &$form) {
2213
    // Safety check in case the caller forgets.
2214
    $form->endFieldset();
2215
    Event::createAndTrigger('HTML_'.strtoupper($name).'FORM_OUTPUT', $form, 'html_form_output', false);
2216
}
2217
2218
/**
2219
 * Form print function.
2220
 *
2221
 * @param Form|Doku_Form $form The form
2222
 */
2223
function html_form_output($form) {
2224
    if ($form instanceof dokuwiki\Form\Form) {
2225
        print $form->toHTML();
2226
    } else { // $form is instanceof Doku_Form
2227
        // Just calls printForm() on the form object.
2228
        $form->printForm();
2229
    }
2230
}
2231
2232
/**
2233
 * Embed a flash object in HTML
2234
 *
2235
 * This will create the needed HTML to embed a flash movie in a cross browser
2236
 * compatble way using valid XHTML
2237
 *
2238
 * The parameters $params, $flashvars and $atts need to be associative arrays.
2239
 * No escaping needs to be done for them. The alternative content *has* to be
2240
 * escaped because it is used as is. If no alternative content is given
2241
 * $lang['noflash'] is used.
2242
 *
2243
 * @author Andreas Gohr <[email protected]>
2244
 * @link   http://latrine.dgx.cz/how-to-correctly-insert-a-flash-into-xhtml
2245
 *
2246
 * @param string $swf      - the SWF movie to embed
2247
 * @param int $width       - width of the flash movie in pixels
2248
 * @param int $height      - height of the flash movie in pixels
2249
 * @param array $params    - additional parameters (<param>)
2250
 * @param array $flashvars - parameters to be passed in the flashvar parameter
2251
 * @param array $atts      - additional attributes for the <object> tag
2252
 * @param string $alt      - alternative content (is NOT automatically escaped!)
2253
 * @return string         - the XHTML markup
2254
 */
2255
function html_flashobject($swf,$width,$height,$params=null,$flashvars=null,$atts=null,$alt=''){
2256
    global $lang;
2257
2258
    $out = '';
2259
2260
    // prepare the object attributes
2261
    if(is_null($atts)) $atts = array();
2262
    $atts['width']  = (int) $width;
2263
    $atts['height'] = (int) $height;
2264
    if(!$atts['width'])  $atts['width']  = 425;
2265
    if(!$atts['height']) $atts['height'] = 350;
2266
2267
    // add object attributes for standard compliant browsers
2268
    $std = $atts;
2269
    $std['type'] = 'application/x-shockwave-flash';
2270
    $std['data'] = $swf;
2271
2272
    // add object attributes for IE
2273
    $ie  = $atts;
2274
    $ie['classid'] = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
2275
2276
    // open object (with conditional comments)
2277
    $out .= '<!--[if !IE]> -->'.NL;
2278
    $out .= '<object '.buildAttributes($std).'>'.NL;
2279
    $out .= '<!-- <![endif]-->'.NL;
2280
    $out .= '<!--[if IE]>'.NL;
2281
    $out .= '<object '.buildAttributes($ie).'>'.NL;
2282
    $out .= '    <param name="movie" value="'.hsc($swf).'" />'.NL;
2283
    $out .= '<!--><!-- -->'.NL;
2284
2285
    // print params
2286
    if(is_array($params)) foreach($params as $key => $val){
2287
        $out .= '  <param name="'.hsc($key).'" value="'.hsc($val).'" />'.NL;
2288
    }
2289
2290
    // add flashvars
2291
    if(is_array($flashvars)){
2292
        $out .= '  <param name="FlashVars" value="'.buildURLparams($flashvars).'" />'.NL;
2293
    }
2294
2295
    // alternative content
2296
    if($alt){
2297
        $out .= $alt.NL;
2298
    }else{
2299
        $out .= $lang['noflash'].NL;
2300
    }
2301
2302
    // finish
2303
    $out .= '</object>'.NL;
2304
    $out .= '<!-- <![endif]-->'.NL;
2305
2306
    return $out;
2307
}
2308
2309
/**
2310
 * Prints HTML code for the given tab structure
2311
 *
2312
 * @param array  $tabs        tab structure
2313
 * @param string $current_tab the current tab id
2314
 */
2315
function html_tabs($tabs, $current_tab = null) {
2316
    echo '<ul class="tabs">'.NL;
2317
2318
    foreach($tabs as $id => $tab) {
2319
        html_tab($tab['href'], $tab['caption'], $id === $current_tab);
2320
    }
2321
2322
    echo '</ul>'.NL;
2323
}
2324
2325
/**
2326
 * Prints a single tab
2327
 *
2328
 * @author Kate Arzamastseva <[email protected]>
2329
 * @author Adrian Lang <[email protected]>
2330
 *
2331
 * @param string $href - tab href
2332
 * @param string $caption - tab caption
2333
 * @param boolean $selected - is tab selected
2334
 */
2335
2336
function html_tab($href, $caption, $selected=false) {
2337
    $tab = '<li>';
2338
    if ($selected) {
2339
        $tab .= '<strong>';
2340
    } else {
2341
        $tab .= '<a href="' . hsc($href) . '">';
2342
    }
2343
    $tab .= hsc($caption)
2344
         .  '</' . ($selected ? 'strong' : 'a') . '>'
2345
         .  '</li>'.NL;
2346
    echo $tab;
2347
}
2348
2349
/**
2350
 * Display size change
2351
 *
2352
 * @param int $sizechange - size of change in Bytes
2353
 * @param Form|Doku_Form $form - form to add elements to
2354
 */
2355
2356
function html_sizechange($sizechange, $form) {
2357
    if(isset($sizechange)) {
2358
        $class = 'sizechange';
2359
        $value = filesize_h(abs($sizechange));
2360
        if ($sizechange > 0) {
2361
            $class .= ' positive';
2362
            $value = '+' . $value;
2363
        } elseif ($sizechange < 0) {
2364
            $class .= ' negative';
2365
            $value = '-' . $value;
2366
        } else {
2367
            $value = '±' . $value;
2368
        }
2369
        if ($form instanceof dokuwiki\Form\Form) {
2370
            $form->addTagOpen('span')->addClass($class);
2371
            $form->addHTML($value);
2372
            $form->addTagClose('span');
2373
        } else { // Doku_Form
2374
            $form->addElement(form_makeOpenTag('span', array('class' => $class)));
2375
            $form->addElement($value);
2376
            $form->addElement(form_makeCloseTag('span'));
2377
        }
2378
    }
2379
}
2380