Completed
Push — syntaxtableclasses ( 0c4c02 )
by Gerrit
04:12
created

Doku_Renderer_xhtml::tablecell_open()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
rs 8.8571
cc 5
eloc 14
nc 16
nop 4
1
<?php
2
/**
3
 * Renderer for XHTML output
4
 *
5
 * @author Harry Fuecks <[email protected]>
6
 * @author Andreas Gohr <[email protected]>
7
 */
8
if(!defined('DOKU_INC')) die('meh.');
9
10
if(!defined('DOKU_LF')) {
11
    // Some whitespace to help View > Source
12
    define ('DOKU_LF', "\n");
13
}
14
15
if(!defined('DOKU_TAB')) {
16
    // Some whitespace to help View > Source
17
    define ('DOKU_TAB', "\t");
18
}
19
20
/**
21
 * The XHTML Renderer
22
 *
23
 * This is DokuWiki's main renderer used to display page content in the wiki
24
 */
25
class Doku_Renderer_xhtml extends Doku_Renderer {
26
    /** @var array store the table of contents */
27
    public $toc = array();
28
29
    /** @var array A stack of section edit data */
30
    protected $sectionedits = array();
31
    var $date_at = '';    // link pages and media against this revision
32
33
    /** @var int last section edit id, used by startSectionEdit */
34
    protected $lastsecid = 0;
35
36
    /** @var array the list of headers used to create unique link ids */
37
    protected $headers = array();
38
39
    /** @var array a list of footnotes, list starts at 1! */
40
    protected $footnotes = array();
41
42
    /** @var int current section level */
43
    protected $lastlevel = 0;
44
    /** @var array section node tracker */
45
    protected $node = array(0, 0, 0, 0, 0);
46
47
    /** @var string temporary $doc store */
48
    protected $store = '';
49
50
    /** @var array global counter, for table classes etc. */
51
    protected $_counter = array(); //
52
53
    /** @var int counts the code and file blocks, used to provide download links */
54
    protected $_codeblock = 0;
55
56
    /** @var array list of allowed URL schemes */
57
    protected $schemes = null;
58
59
    /**
60
     * Register a new edit section range
61
     *
62
     * @param string $type   The section type identifier
63
     * @param string $title  The section title
64
     * @param int    $start  The byte position for the edit start
65
     * @return string  A marker class for the starting HTML element
66
     *
67
     * @author Adrian Lang <[email protected]>
68
     */
69
    public function startSectionEdit($start, $type, $title = null) {
70
        $this->sectionedits[] = array(++$this->lastsecid, $start, $type, $title);
71
        return 'sectionedit'.$this->lastsecid;
72
    }
73
74
    /**
75
     * Finish an edit section range
76
     *
77
     * @param int  $end     The byte position for the edit end; null for the rest of the page
78
     *
79
     * @author Adrian Lang <[email protected]>
80
     */
81
    public function finishSectionEdit($end = null) {
82
        list($id, $start, $type, $title) = array_pop($this->sectionedits);
83
        if(!is_null($end) && $end <= $start) {
84
            return;
85
        }
86
        $this->doc .= "<!-- EDIT$id ".strtoupper($type).' ';
87
        if(!is_null($title)) {
88
            $this->doc .= '"'.str_replace('"', '', $title).'" ';
89
        }
90
        $this->doc .= "[$start-".(is_null($end) ? '' : $end).'] -->';
91
    }
92
93
    /**
94
     * Returns the format produced by this renderer.
95
     *
96
     * @return string always 'xhtml'
97
     */
98
    function getFormat() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
99
        return 'xhtml';
100
    }
101
102
    /**
103
     * Initialize the document
104
     */
105
    function document_start() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
106
        //reset some internals
107
        $this->toc     = array();
108
        $this->headers = array();
109
    }
110
111
    /**
112
     * Finalize the document
113
     */
114
    function document_end() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
115
        // Finish open section edits.
116
        while(count($this->sectionedits) > 0) {
117
            if($this->sectionedits[count($this->sectionedits) - 1][1] <= 1) {
118
                // If there is only one section, do not write a section edit
119
                // marker.
120
                array_pop($this->sectionedits);
121
            } else {
122
                $this->finishSectionEdit();
123
            }
124
        }
125
126
        if(count($this->footnotes) > 0) {
127
            $this->doc .= '<div class="footnotes">'.DOKU_LF;
128
129
            foreach($this->footnotes as $id => $footnote) {
130
                // check its not a placeholder that indicates actual footnote text is elsewhere
131
                if(substr($footnote, 0, 5) != "@@FNT") {
132
133
                    // open the footnote and set the anchor and backlink
134
                    $this->doc .= '<div class="fn">';
135
                    $this->doc .= '<sup><a href="#fnt__'.$id.'" id="fn__'.$id.'" class="fn_bot">';
136
                    $this->doc .= $id.')</a></sup> '.DOKU_LF;
137
138
                    // get any other footnotes that use the same markup
139
                    $alt = array_keys($this->footnotes, "@@FNT$id");
140
141
                    if(count($alt)) {
142
                        foreach($alt as $ref) {
143
                            // set anchor and backlink for the other footnotes
144
                            $this->doc .= ', <sup><a href="#fnt__'.($ref).'" id="fn__'.($ref).'" class="fn_bot">';
145
                            $this->doc .= ($ref).')</a></sup> '.DOKU_LF;
146
                        }
147
                    }
148
149
                    // add footnote markup and close this footnote
150
                    $this->doc .= $footnote;
151
                    $this->doc .= '</div>'.DOKU_LF;
152
                }
153
            }
154
            $this->doc .= '</div>'.DOKU_LF;
155
        }
156
157
        // Prepare the TOC
158
        global $conf;
159
        if($this->info['toc'] && is_array($this->toc) && $conf['tocminheads'] && count($this->toc) >= $conf['tocminheads']) {
160
            global $TOC;
161
            $TOC = $this->toc;
162
        }
163
164
        // make sure there are no empty paragraphs
165
        $this->doc = preg_replace('#<p>\s*</p>#', '', $this->doc);
166
    }
167
168
    /**
169
     * Add an item to the TOC
170
     *
171
     * @param string $id       the hash link
172
     * @param string $text     the text to display
173
     * @param int    $level    the nesting level
174
     */
175
    function toc_additem($id, $text, $level) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
176
        global $conf;
177
178
        //handle TOC
179
        if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']) {
180
            $this->toc[] = html_mktocitem($id, $text, $level - $conf['toptoclevel'] + 1);
181
        }
182
    }
183
184
    /**
185
     * Render a heading
186
     *
187
     * @param string $text  the text to display
188
     * @param int    $level header level
189
     * @param int    $pos   byte position in the original source
190
     */
191
    function header($text, $level, $pos) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
192
        global $conf;
193
194
        if(!$text) return; //skip empty headlines
195
196
        $hid = $this->_headerToLink($text, true);
197
198
        //only add items within configured levels
199
        $this->toc_additem($hid, $text, $level);
200
201
        // adjust $node to reflect hierarchy of levels
202
        $this->node[$level - 1]++;
203
        if($level < $this->lastlevel) {
204
            for($i = 0; $i < $this->lastlevel - $level; $i++) {
205
                $this->node[$this->lastlevel - $i - 1] = 0;
206
            }
207
        }
208
        $this->lastlevel = $level;
209
210
        if($level <= $conf['maxseclevel'] &&
211
            count($this->sectionedits) > 0 &&
212
            $this->sectionedits[count($this->sectionedits) - 1][2] === 'section'
213
        ) {
214
            $this->finishSectionEdit($pos - 1);
215
        }
216
217
        // write the header
218
        $this->doc .= DOKU_LF.'<h'.$level;
219
        if($level <= $conf['maxseclevel']) {
220
            $this->doc .= ' class="'.$this->startSectionEdit($pos, 'section', $text).'"';
221
        }
222
        $this->doc .= ' id="'.$hid.'">';
223
        $this->doc .= $this->_xmlEntities($text);
224
        $this->doc .= "</h$level>".DOKU_LF;
225
    }
226
227
    /**
228
     * Open a new section
229
     *
230
     * @param int $level section level (as determined by the previous header)
231
     */
232
    function section_open($level) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
233
        $this->doc .= '<div class="level'.$level.'">'.DOKU_LF;
234
    }
235
236
    /**
237
     * Close the current section
238
     */
239
    function section_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
240
        $this->doc .= DOKU_LF.'</div>'.DOKU_LF;
241
    }
242
243
    /**
244
     * Render plain text data
245
     *
246
     * @param $text
247
     */
248
    function cdata($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
249
        $this->doc .= $this->_xmlEntities($text);
250
    }
251
252
    /**
253
     * Open a paragraph
254
     */
255
    function p_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
256
        $this->doc .= DOKU_LF.'<p>'.DOKU_LF;
257
    }
258
259
    /**
260
     * Close a paragraph
261
     */
262
    function p_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
263
        $this->doc .= DOKU_LF.'</p>'.DOKU_LF;
264
    }
265
266
    /**
267
     * Create a line break
268
     */
269
    function linebreak() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
270
        $this->doc .= '<br/>'.DOKU_LF;
271
    }
272
273
    /**
274
     * Create a horizontal line
275
     */
276
    function hr() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
277
        $this->doc .= '<hr />'.DOKU_LF;
278
    }
279
280
    /**
281
     * Start strong (bold) formatting
282
     */
283
    function strong_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
284
        $this->doc .= '<strong>';
285
    }
286
287
    /**
288
     * Stop strong (bold) formatting
289
     */
290
    function strong_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
291
        $this->doc .= '</strong>';
292
    }
293
294
    /**
295
     * Start emphasis (italics) formatting
296
     */
297
    function emphasis_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
298
        $this->doc .= '<em>';
299
    }
300
301
    /**
302
     * Stop emphasis (italics) formatting
303
     */
304
    function emphasis_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
305
        $this->doc .= '</em>';
306
    }
307
308
    /**
309
     * Start underline formatting
310
     */
311
    function underline_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
312
        $this->doc .= '<em class="u">';
313
    }
314
315
    /**
316
     * Stop underline formatting
317
     */
318
    function underline_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
319
        $this->doc .= '</em>';
320
    }
321
322
    /**
323
     * Start monospace formatting
324
     */
325
    function monospace_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
326
        $this->doc .= '<code>';
327
    }
328
329
    /**
330
     * Stop monospace formatting
331
     */
332
    function monospace_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
333
        $this->doc .= '</code>';
334
    }
335
336
    /**
337
     * Start a subscript
338
     */
339
    function subscript_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
340
        $this->doc .= '<sub>';
341
    }
342
343
    /**
344
     * Stop a subscript
345
     */
346
    function subscript_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
347
        $this->doc .= '</sub>';
348
    }
349
350
    /**
351
     * Start a superscript
352
     */
353
    function superscript_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
354
        $this->doc .= '<sup>';
355
    }
356
357
    /**
358
     * Stop a superscript
359
     */
360
    function superscript_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
361
        $this->doc .= '</sup>';
362
    }
363
364
    /**
365
     * Start deleted (strike-through) formatting
366
     */
367
    function deleted_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
368
        $this->doc .= '<del>';
369
    }
370
371
    /**
372
     * Stop deleted (strike-through) formatting
373
     */
374
    function deleted_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
375
        $this->doc .= '</del>';
376
    }
377
378
    /**
379
     * Callback for footnote start syntax
380
     *
381
     * All following content will go to the footnote instead of
382
     * the document. To achieve this the previous rendered content
383
     * is moved to $store and $doc is cleared
384
     *
385
     * @author Andreas Gohr <[email protected]>
386
     */
387
    function footnote_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
388
389
        // move current content to store and record footnote
390
        $this->store = $this->doc;
391
        $this->doc   = '';
392
    }
393
394
    /**
395
     * Callback for footnote end syntax
396
     *
397
     * All rendered content is moved to the $footnotes array and the old
398
     * content is restored from $store again
399
     *
400
     * @author Andreas Gohr
401
     */
402
    function footnote_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
403
        /** @var $fnid int takes track of seen footnotes, assures they are unique even across multiple docs FS#2841 */
404
        static $fnid = 0;
405
        // assign new footnote id (we start at 1)
406
        $fnid++;
407
408
        // recover footnote into the stack and restore old content
409
        $footnote    = $this->doc;
410
        $this->doc   = $this->store;
411
        $this->store = '';
412
413
        // check to see if this footnote has been seen before
414
        $i = array_search($footnote, $this->footnotes);
415
416
        if($i === false) {
417
            // its a new footnote, add it to the $footnotes array
418
            $this->footnotes[$fnid] = $footnote;
419
        } else {
420
            // seen this one before, save a placeholder
421
            $this->footnotes[$fnid] = "@@FNT".($i);
422
        }
423
424
        // output the footnote reference and link
425
        $this->doc .= '<sup><a href="#fn__'.$fnid.'" id="fnt__'.$fnid.'" class="fn_top">'.$fnid.')</a></sup>';
426
    }
427
428
    /**
429
     * Open an unordered list
430
     *
431
     * @param string $classes css class
432
     */
433
    function listu_open($classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
434
        $class = '';
435
        if($classes !== null) {
436
            $class = " class=\"$classes\"";
437
        }
438
        $this->doc .= "<ul$class>".DOKU_LF;
439
    }
440
441
    /**
442
     * Close an unordered list
443
     */
444
    function listu_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
445
        $this->doc .= '</ul>'.DOKU_LF;
446
    }
447
448
    /**
449
     * Open an ordered list
450
     *
451
     * @param string $classes css class
452
     */
453
    function listo_open($classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
454
        $class = '';
455
        if($classes !== null) {
456
            $class = " class=\"$classes\"";
457
        }
458
        $this->doc .= "<ol$class>".DOKU_LF;
459
    }
460
461
    /**
462
     * Close an ordered list
463
     */
464
    function listo_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
465
        $this->doc .= '</ol>'.DOKU_LF;
466
    }
467
468
    /**
469
     * Open a list item
470
     *
471
     * @param int $level the nesting level
472
     * @param bool $node true when a node; false when a leaf
473
     */
474
    function listitem_open($level, $node=false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
475
        $branching = $node ? ' node' : '';
476
        $this->doc .= '<li class="level'.$level.$branching.'">';
477
    }
478
479
    /**
480
     * Close a list item
481
     */
482
    function listitem_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
483
        $this->doc .= '</li>'.DOKU_LF;
484
    }
485
486
    /**
487
     * Start the content of a list item
488
     */
489
    function listcontent_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
490
        $this->doc .= '<div class="li">';
491
    }
492
493
    /**
494
     * Stop the content of a list item
495
     */
496
    function listcontent_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
497
        $this->doc .= '</div>'.DOKU_LF;
498
    }
499
500
    /**
501
     * Output unformatted $text
502
     *
503
     * Defaults to $this->cdata()
504
     *
505
     * @param string $text
506
     */
507
    function unformatted($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
508
        $this->doc .= $this->_xmlEntities($text);
509
    }
510
511
    /**
512
     * Execute PHP code if allowed
513
     *
514
     * @param  string $text      PHP code that is either executed or printed
515
     * @param  string $wrapper   html element to wrap result if $conf['phpok'] is okff
516
     *
517
     * @author Andreas Gohr <[email protected]>
518
     */
519
    function php($text, $wrapper = 'code') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
520
        global $conf;
521
522
        if($conf['phpok']) {
523
            ob_start();
524
            eval($text);
525
            $this->doc .= ob_get_contents();
526
            ob_end_clean();
527
        } else {
528
            $this->doc .= p_xhtml_cached_geshi($text, 'php', $wrapper);
529
        }
530
    }
531
532
    /**
533
     * Output block level PHP code
534
     *
535
     * If $conf['phpok'] is true this should evaluate the given code and append the result
536
     * to $doc
537
     *
538
     * @param string $text The PHP code
539
     */
540
    function phpblock($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
541
        $this->php($text, 'pre');
542
    }
543
544
    /**
545
     * Insert HTML if allowed
546
     *
547
     * @param  string $text      html text
548
     * @param  string $wrapper   html element to wrap result if $conf['htmlok'] is okff
549
     *
550
     * @author Andreas Gohr <[email protected]>
551
     */
552
    function html($text, $wrapper = 'code') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
553
        global $conf;
554
555
        if($conf['htmlok']) {
556
            $this->doc .= $text;
557
        } else {
558
            $this->doc .= p_xhtml_cached_geshi($text, 'html4strict', $wrapper);
559
        }
560
    }
561
562
    /**
563
     * Output raw block-level HTML
564
     *
565
     * If $conf['htmlok'] is true this should add the code as is to $doc
566
     *
567
     * @param string $text The HTML
568
     */
569
    function htmlblock($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
570
        $this->html($text, 'pre');
571
    }
572
573
    /**
574
     * Start a block quote
575
     */
576
    function quote_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
577
        $this->doc .= '<blockquote><div class="no">'.DOKU_LF;
578
    }
579
580
    /**
581
     * Stop a block quote
582
     */
583
    function quote_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
584
        $this->doc .= '</div></blockquote>'.DOKU_LF;
585
    }
586
587
    /**
588
     * Output preformatted text
589
     *
590
     * @param string $text
591
     */
592
    function preformatted($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
593
        $this->doc .= '<pre class="code">'.trim($this->_xmlEntities($text), "\n\r").'</pre>'.DOKU_LF;
594
    }
595
596
    /**
597
     * Display text as file content, optionally syntax highlighted
598
     *
599
     * @param string $text     text to show
600
     * @param string $language programming language to use for syntax highlighting
601
     * @param string $filename file path label
602
     */
603
    function file($text, $language = null, $filename = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
604
        $this->_highlight('file', $text, $language, $filename);
605
    }
606
607
    /**
608
     * Display text as code content, optionally syntax highlighted
609
     *
610
     * @param string $text     text to show
611
     * @param string $language programming language to use for syntax highlighting
612
     * @param string $filename file path label
613
     */
614
    function code($text, $language = null, $filename = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
615
        $this->_highlight('code', $text, $language, $filename);
616
    }
617
618
    /**
619
     * Use GeSHi to highlight language syntax in code and file blocks
620
     *
621
     * @author Andreas Gohr <[email protected]>
622
     * @param string $type     code|file
623
     * @param string $text     text to show
624
     * @param string $language programming language to use for syntax highlighting
625
     * @param string $filename file path label
626
     */
627
    function _highlight($type, $text, $language = null, $filename = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
628
        global $ID;
629
        global $lang;
630
631
        if($filename) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filename of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
632
            // add icon
633
            list($ext) = mimetype($filename, false);
634
            $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
635
            $class = 'mediafile mf_'.$class;
636
637
            $this->doc .= '<dl class="'.$type.'">'.DOKU_LF;
638
            $this->doc .= '<dt><a href="'.exportlink($ID, 'code', array('codeblock' => $this->_codeblock)).'" title="'.$lang['download'].'" class="'.$class.'">';
639
            $this->doc .= hsc($filename);
640
            $this->doc .= '</a></dt>'.DOKU_LF.'<dd>';
641
        }
642
643
        if($text{0} == "\n") {
644
            $text = substr($text, 1);
645
        }
646
        if(substr($text, -1) == "\n") {
647
            $text = substr($text, 0, -1);
648
        }
649
650
        if(is_null($language)) {
651
            $this->doc .= '<pre class="'.$type.'">'.$this->_xmlEntities($text).'</pre>'.DOKU_LF;
652
        } else {
653
            $class = 'code'; //we always need the code class to make the syntax highlighting apply
654
            if($type != 'code') $class .= ' '.$type;
655
656
            $this->doc .= "<pre class=\"$class $language\">".p_xhtml_cached_geshi($text, $language, '').'</pre>'.DOKU_LF;
657
        }
658
659
        if($filename) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filename of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
660
            $this->doc .= '</dd></dl>'.DOKU_LF;
661
        }
662
663
        $this->_codeblock++;
664
    }
665
666
    /**
667
     * Format an acronym
668
     *
669
     * Uses $this->acronyms
670
     *
671
     * @param string $acronym
672
     */
673
    function acronym($acronym) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
674
675
        if(array_key_exists($acronym, $this->acronyms)) {
676
677
            $title = $this->_xmlEntities($this->acronyms[$acronym]);
678
679
            $this->doc .= '<abbr title="'.$title
680
                .'">'.$this->_xmlEntities($acronym).'</abbr>';
681
682
        } else {
683
            $this->doc .= $this->_xmlEntities($acronym);
684
        }
685
    }
686
687
    /**
688
     * Format a smiley
689
     *
690
     * Uses $this->smiley
691
     *
692
     * @param string $smiley
693
     */
694
    function smiley($smiley) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
695
        if(array_key_exists($smiley, $this->smileys)) {
696
            $this->doc .= '<img src="'.DOKU_BASE.'lib/images/smileys/'.$this->smileys[$smiley].
697
                '" class="icon" alt="'.
698
                $this->_xmlEntities($smiley).'" />';
699
        } else {
700
            $this->doc .= $this->_xmlEntities($smiley);
701
        }
702
    }
703
704
    /**
705
     * Format an entity
706
     *
707
     * Entities are basically small text replacements
708
     *
709
     * Uses $this->entities
710
     *
711
     * @param string $entity
712
     */
713
    function entity($entity) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
714
        if(array_key_exists($entity, $this->entities)) {
715
            $this->doc .= $this->entities[$entity];
716
        } else {
717
            $this->doc .= $this->_xmlEntities($entity);
718
        }
719
    }
720
721
    /**
722
     * Typographically format a multiply sign
723
     *
724
     * Example: ($x=640, $y=480) should result in "640×480"
725
     *
726
     * @param string|int $x first value
727
     * @param string|int $y second value
728
     */
729
    function multiplyentity($x, $y) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
730
        $this->doc .= "$x&times;$y";
731
    }
732
733
    /**
734
     * Render an opening single quote char (language specific)
735
     */
736
    function singlequoteopening() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
737
        global $lang;
738
        $this->doc .= $lang['singlequoteopening'];
739
    }
740
741
    /**
742
     * Render a closing single quote char (language specific)
743
     */
744
    function singlequoteclosing() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
745
        global $lang;
746
        $this->doc .= $lang['singlequoteclosing'];
747
    }
748
749
    /**
750
     * Render an apostrophe char (language specific)
751
     */
752
    function apostrophe() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
753
        global $lang;
754
        $this->doc .= $lang['apostrophe'];
755
    }
756
757
    /**
758
     * Render an opening double quote char (language specific)
759
     */
760
    function doublequoteopening() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
761
        global $lang;
762
        $this->doc .= $lang['doublequoteopening'];
763
    }
764
765
    /**
766
     * Render an closinging double quote char (language specific)
767
     */
768
    function doublequoteclosing() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
769
        global $lang;
770
        $this->doc .= $lang['doublequoteclosing'];
771
    }
772
773
    /**
774
     * Render a CamelCase link
775
     *
776
     * @param string $link       The link name
777
     * @param bool   $returnonly whether to return html or write to doc attribute
778
     * @return void|string writes to doc attribute or returns html depends on $returnonly
779
     *
780
     * @see http://en.wikipedia.org/wiki/CamelCase
781
     */
782
    function camelcaselink($link, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
783
        if($returnonly) {
784
          return $this->internallink($link, $link, null, true);
785
        } else {
786
          $this->internallink($link, $link);
787
        }
788
    }
789
790
    /**
791
     * Render a page local link
792
     *
793
     * @param string $hash       hash link identifier
794
     * @param string $name       name for the link
795
     * @param bool   $returnonly whether to return html or write to doc attribute
796
     * @return void|string writes to doc attribute or returns html depends on $returnonly
797
     */
798
    function locallink($hash, $name = null, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
799
        global $ID;
800
        $name  = $this->_getLinkTitle($name, $hash, $isImage);
801
        $hash  = $this->_headerToLink($hash);
802
        $title = $ID.' ↵';
803
804
        $doc = '<a href="#'.$hash.'" title="'.$title.'" class="wikilink1">';
805
        $doc .= $name;
806
        $doc .= '</a>';
807
808
        if($returnonly) {
809
          return $doc;
810
        } else {
811
          $this->doc .= $doc;
812
        }
813
    }
814
815
    /**
816
     * Render an internal Wiki Link
817
     *
818
     * $search,$returnonly & $linktype are not for the renderer but are used
819
     * elsewhere - no need to implement them in other renderers
820
     *
821
     * @author Andreas Gohr <[email protected]>
822
     * @param string      $id         pageid
823
     * @param string|null $name       link name
824
     * @param string|null $search     adds search url param
825
     * @param bool        $returnonly whether to return html or write to doc attribute
826
     * @param string      $linktype   type to set use of headings
827
     * @return void|string writes to doc attribute or returns html depends on $returnonly
828
     */
829
    function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
830
        global $conf;
831
        global $ID;
832
        global $INFO;
833
834
        $params = '';
835
        $parts  = explode('?', $id, 2);
836
        if(count($parts) === 2) {
837
            $id     = $parts[0];
838
            $params = $parts[1];
839
        }
840
841
        // For empty $id we need to know the current $ID
842
        // We need this check because _simpleTitle needs
843
        // correct $id and resolve_pageid() use cleanID($id)
844
        // (some things could be lost)
845
        if($id === '') {
846
            $id = $ID;
847
        }
848
849
        // default name is based on $id as given
850
        $default = $this->_simpleTitle($id);
851
852
        // now first resolve and clean up the $id
853
        resolve_pageid(getNS($ID), $id, $exists, $this->date_at, true);
0 ignored issues
show
Security Bug introduced by
It seems like getNS($ID) targeting getNS() can also be of type false; however, resolve_pageid() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
854
855
        $link = array();
856
        $name = $this->_getLinkTitle($name, $default, $isImage, $id, $linktype);
857
        if(!$isImage) {
858
            if($exists) {
859
                $class = 'wikilink1';
860
            } else {
861
                $class       = 'wikilink2';
862
                $link['rel'] = 'nofollow';
863
            }
864
        } else {
865
            $class = 'media';
866
        }
867
868
        //keep hash anchor
869
        @list($id, $hash) = explode('#', $id, 2);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
870
        if(!empty($hash)) $hash = $this->_headerToLink($hash);
871
872
        //prepare for formating
873
        $link['target'] = $conf['target']['wiki'];
874
        $link['style']  = '';
875
        $link['pre']    = '';
876
        $link['suf']    = '';
877
        // highlight link to current page
878
        if($id == $INFO['id']) {
879
            $link['pre'] = '<span class="curid">';
880
            $link['suf'] = '</span>';
881
        }
882
        $link['more']   = '';
883
        $link['class']  = $class;
884
        if($this->date_at) {
885
            $params['at'] = $this->date_at;
886
        }
887
        $link['url']    = wl($id, $params);
888
        $link['name']   = $name;
889
        $link['title']  = $id;
890
        //add search string
891
        if($search) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $search of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
892
            ($conf['userewrite']) ? $link['url'] .= '?' : $link['url'] .= '&amp;';
893
            if(is_array($search)) {
894
                $search = array_map('rawurlencode', $search);
895
                $link['url'] .= 's[]='.join('&amp;s[]=', $search);
896
            } else {
897
                $link['url'] .= 's='.rawurlencode($search);
898
            }
899
        }
900
901
        //keep hash
902
        if($hash) $link['url'] .= '#'.$hash;
903
904
        //output formatted
905
        if($returnonly) {
906
            return $this->_formatLink($link);
907
        } else {
908
            $this->doc .= $this->_formatLink($link);
909
        }
910
    }
911
912
    /**
913
     * Render an external link
914
     *
915
     * @param string       $url        full URL with scheme
916
     * @param string|array $name       name for the link, array for media file
917
     * @param bool         $returnonly whether to return html or write to doc attribute
918
     * @return void|string writes to doc attribute or returns html depends on $returnonly
919
     */
920
    function externallink($url, $name = null, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
921
        global $conf;
922
923
        $name = $this->_getLinkTitle($name, $url, $isImage);
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type null; however, Doku_Renderer_xhtml::_getLinkTitle() does only seem to accept string|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
924
925
        // url might be an attack vector, only allow registered protocols
926
        if(is_null($this->schemes)) $this->schemes = getSchemes();
927
        list($scheme) = explode('://', $url);
928
        $scheme = strtolower($scheme);
929
        if(!in_array($scheme, $this->schemes)) $url = '';
930
931
        // is there still an URL?
932
        if(!$url) {
933
            if($returnonly) {
934
                return $name;
935
            } else {
936
                $this->doc .= $name;
937
            }
938
            return;
939
        }
940
941
        // set class
942
        if(!$isImage) {
943
            $class = 'urlextern';
944
        } else {
945
            $class = 'media';
946
        }
947
948
        //prepare for formating
949
        $link = array();
950
        $link['target'] = $conf['target']['extern'];
951
        $link['style']  = '';
952
        $link['pre']    = '';
953
        $link['suf']    = '';
954
        $link['more']   = '';
955
        $link['class']  = $class;
956
        $link['url']    = $url;
957
        $link['rel']    = '';
958
959
        $link['name']  = $name;
960
        $link['title'] = $this->_xmlEntities($url);
961
        if($conf['relnofollow']) $link['rel'] .= ' nofollow';
962
        if($conf['target']['extern']) $link['rel'] .= ' noopener';
963
964
        //output formatted
965
        if($returnonly) {
966
            return $this->_formatLink($link);
967
        } else {
968
            $this->doc .= $this->_formatLink($link);
969
        }
970
    }
971
972
    /**
973
     * Render an interwiki link
974
     *
975
     * You may want to use $this->_resolveInterWiki() here
976
     *
977
     * @param string       $match      original link - probably not much use
978
     * @param string|array $name       name for the link, array for media file
979
     * @param string       $wikiName   indentifier (shortcut) for the remote wiki
980
     * @param string       $wikiUri    the fragment parsed from the original link
981
     * @param bool         $returnonly whether to return html or write to doc attribute
982
     * @return void|string writes to doc attribute or returns html depends on $returnonly
983
     */
984
    function interwikilink($match, $name = null, $wikiName, $wikiUri, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
985
        global $conf;
986
987
        $link           = array();
988
        $link['target'] = $conf['target']['interwiki'];
989
        $link['pre']    = '';
990
        $link['suf']    = '';
991
        $link['more']   = '';
992
        $link['name']   = $this->_getLinkTitle($name, $wikiUri, $isImage);
0 ignored issues
show
Bug introduced by
It seems like $name defined by parameter $name on line 984 can also be of type null; however, Doku_Renderer_xhtml::_getLinkTitle() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
993
        $link['rel']    = '';
994
995
        //get interwiki URL
996
        $exists = null;
997
        $url    = $this->_resolveInterWiki($wikiName, $wikiUri, $exists);
998
999
        if(!$isImage) {
1000
            $class         = preg_replace('/[^_\-a-z0-9]+/i', '_', $wikiName);
1001
            $link['class'] = "interwiki iw_$class";
1002
        } else {
1003
            $link['class'] = 'media';
1004
        }
1005
1006
        //do we stay at the same server? Use local target
1007
        if(strpos($url, DOKU_URL) === 0 OR strpos($url, DOKU_BASE) === 0) {
1008
            $link['target'] = $conf['target']['wiki'];
1009
        }
1010
        if($exists !== null && !$isImage) {
1011
            if($exists) {
1012
                $link['class'] .= ' wikilink1';
1013
            } else {
1014
                $link['class'] .= ' wikilink2';
1015
                $link['rel'] .= ' nofollow';
1016
            }
1017
        }
1018
        if($conf['target']['interwiki']) $link['rel'] .= ' noopener';
1019
1020
        $link['url']   = $url;
1021
        $link['title'] = htmlspecialchars($link['url']);
1022
1023
        //output formatted
1024
        if($returnonly) {
1025
            return $this->_formatLink($link);
1026
        } else {
1027
            $this->doc .= $this->_formatLink($link);
1028
        }
1029
    }
1030
1031
    /**
1032
     * Link to windows share
1033
     *
1034
     * @param string       $url        the link
1035
     * @param string|array $name       name for the link, array for media file
1036
     * @param bool         $returnonly whether to return html or write to doc attribute
1037
     * @return void|string writes to doc attribute or returns html depends on $returnonly
1038
     */
1039
    function windowssharelink($url, $name = null, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1040
        global $conf;
1041
1042
        //simple setup
1043
        $link = array();
1044
        $link['target'] = $conf['target']['windows'];
1045
        $link['pre']    = '';
1046
        $link['suf']    = '';
1047
        $link['style']  = '';
1048
1049
        $link['name'] = $this->_getLinkTitle($name, $url, $isImage);
0 ignored issues
show
Bug introduced by
It seems like $name defined by parameter $name on line 1039 can also be of type null; however, Doku_Renderer_xhtml::_getLinkTitle() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
1050
        if(!$isImage) {
1051
            $link['class'] = 'windows';
1052
        } else {
1053
            $link['class'] = 'media';
1054
        }
1055
1056
        $link['title'] = $this->_xmlEntities($url);
1057
        $url           = str_replace('\\', '/', $url);
1058
        $url           = 'file:///'.$url;
1059
        $link['url']   = $url;
1060
1061
        //output formatted
1062
        if($returnonly) {
1063
            return $this->_formatLink($link);
1064
        } else {
1065
            $this->doc .= $this->_formatLink($link);
1066
        }
1067
    }
1068
1069
    /**
1070
     * Render a linked E-Mail Address
1071
     *
1072
     * Honors $conf['mailguard'] setting
1073
     *
1074
     * @param string       $address    Email-Address
1075
     * @param string|array $name       name for the link, array for media file
1076
     * @param bool         $returnonly whether to return html or write to doc attribute
1077
     * @return void|string writes to doc attribute or returns html depends on $returnonly
1078
     */
1079
    function emaillink($address, $name = null, $returnonly = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1080
        global $conf;
1081
        //simple setup
1082
        $link           = array();
1083
        $link['target'] = '';
1084
        $link['pre']    = '';
1085
        $link['suf']    = '';
1086
        $link['style']  = '';
1087
        $link['more']   = '';
1088
1089
        $name = $this->_getLinkTitle($name, '', $isImage);
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type null; however, Doku_Renderer_xhtml::_getLinkTitle() does only seem to accept string|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1090
        if(!$isImage) {
1091
            $link['class'] = 'mail';
1092
        } else {
1093
            $link['class'] = 'media';
1094
        }
1095
1096
        $address = $this->_xmlEntities($address);
1097
        $address = obfuscate($address);
1098
        $title   = $address;
1099
1100
        if(empty($name)) {
1101
            $name = $address;
1102
        }
1103
1104
        if($conf['mailguard'] == 'visible') $address = rawurlencode($address);
1105
1106
        $link['url']   = 'mailto:'.$address;
1107
        $link['name']  = $name;
1108
        $link['title'] = $title;
1109
1110
        //output formatted
1111
        if($returnonly) {
1112
            return $this->_formatLink($link);
1113
        } else {
1114
            $this->doc .= $this->_formatLink($link);
1115
        }
1116
    }
1117
1118
    /**
1119
     * Render an internal media file
1120
     *
1121
     * @param string $src       media ID
1122
     * @param string $title     descriptive text
1123
     * @param string $align     left|center|right
1124
     * @param int    $width     width of media in pixel
1125
     * @param int    $height    height of media in pixel
1126
     * @param string $cache     cache|recache|nocache
1127
     * @param string $linking   linkonly|detail|nolink
1128
     * @param bool   $return    return HTML instead of adding to $doc
1129
     * @return void|string writes to doc attribute or returns html depends on $return
1130
     */
1131
    function internalmedia($src, $title = null, $align = null, $width = null,
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1132
                           $height = null, $cache = null, $linking = null, $return = false) {
1133
        global $ID;
1134
        list($src, $hash) = explode('#', $src, 2);
1135
        resolve_mediaid(getNS($ID), $src, $exists, $this->date_at, true);
0 ignored issues
show
Security Bug introduced by
It seems like getNS($ID) targeting getNS() can also be of type false; however, resolve_mediaid() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1136
1137
        $noLink = false;
1138
        $render = ($linking == 'linkonly') ? false : true;
1139
        $link   = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
1140
1141
        list($ext, $mime) = mimetype($src, false);
1142
        if(substr($mime, 0, 5) == 'image' && $render) {
1143
            $link['url'] = ml($src, array('id' => $ID, 'cache' => $cache, 'rev'=>$this->_getLastMediaRevisionAt($src)), ($linking == 'direct'));
1144
        } elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render) {
1145
            // don't link movies
1146
            $noLink = true;
1147
        } else {
1148
            // add file icons
1149
            $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
1150
            $link['class'] .= ' mediafile mf_'.$class;
1151
            $link['url'] = ml($src, array('id' => $ID, 'cache' => $cache , 'rev'=>$this->_getLastMediaRevisionAt($src)), true);
1152
            if($exists) $link['title'] .= ' ('.filesize_h(filesize(mediaFN($src))).')';
1153
        }
1154
1155
        if($hash) $link['url'] .= '#'.$hash;
1156
1157
        //markup non existing files
1158
        if(!$exists) {
1159
            $link['class'] .= ' wikilink2';
1160
        }
1161
1162
        //output formatted
1163
        if($return) {
1164
            if($linking == 'nolink' || $noLink) return $link['name'];
1165
            else return $this->_formatLink($link);
1166
        } else {
1167
            if($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
1168
            else $this->doc .= $this->_formatLink($link);
1169
        }
1170
    }
1171
1172
    /**
1173
     * Render an external media file
1174
     *
1175
     * @param string $src     full media URL
1176
     * @param string $title   descriptive text
1177
     * @param string $align   left|center|right
1178
     * @param int    $width   width of media in pixel
1179
     * @param int    $height  height of media in pixel
1180
     * @param string $cache   cache|recache|nocache
1181
     * @param string $linking linkonly|detail|nolink
1182
     * @param bool   $return  return HTML instead of adding to $doc
1183
     * @return void|string writes to doc attribute or returns html depends on $return
1184
     */
1185
    function externalmedia($src, $title = null, $align = null, $width = null,
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1186
                           $height = null, $cache = null, $linking = null, $return = false) {
1187
        list($src, $hash) = explode('#', $src, 2);
1188
        $noLink = false;
1189
        $render = ($linking == 'linkonly') ? false : true;
1190
        $link   = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
1191
1192
        $link['url'] = ml($src, array('cache' => $cache));
1193
1194
        list($ext, $mime) = mimetype($src, false);
1195
        if(substr($mime, 0, 5) == 'image' && $render) {
1196
            // link only jpeg images
1197
            // if ($ext != 'jpg' && $ext != 'jpeg') $noLink = true;
1198
        } elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render) {
1199
            // don't link movies
1200
            $noLink = true;
1201
        } else {
1202
            // add file icons
1203
            $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
1204
            $link['class'] .= ' mediafile mf_'.$class;
1205
        }
1206
1207
        if($hash) $link['url'] .= '#'.$hash;
1208
1209
        //output formatted
1210
        if($return) {
1211
            if($linking == 'nolink' || $noLink) return $link['name'];
1212
            else return $this->_formatLink($link);
1213
        } else {
1214
            if($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
1215
            else $this->doc .= $this->_formatLink($link);
1216
        }
1217
    }
1218
1219
    /**
1220
     * Renders an RSS feed
1221
     *
1222
     * @param string $url    URL of the feed
1223
     * @param array  $params Finetuning of the output
1224
     *
1225
     * @author Andreas Gohr <[email protected]>
1226
     */
1227
    function rss($url, $params) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1228
        global $lang;
1229
        global $conf;
1230
1231
        require_once(DOKU_INC.'inc/FeedParser.php');
1232
        $feed = new FeedParser();
1233
        $feed->set_feed_url($url);
1234
1235
        //disable warning while fetching
1236
        if(!defined('DOKU_E_LEVEL')) {
1237
            $elvl = error_reporting(E_ERROR);
1238
        }
1239
        $rc = $feed->init();
1240
        if(isset($elvl)) {
1241
            error_reporting($elvl);
1242
        }
1243
1244
        if($params['nosort']) $feed->enable_order_by_date(false);
1245
1246
        //decide on start and end
1247
        if($params['reverse']) {
1248
            $mod   = -1;
1249
            $start = $feed->get_item_quantity() - 1;
1250
            $end   = $start - ($params['max']);
1251
            $end   = ($end < -1) ? -1 : $end;
1252
        } else {
1253
            $mod   = 1;
1254
            $start = 0;
1255
            $end   = $feed->get_item_quantity();
1256
            $end   = ($end > $params['max']) ? $params['max'] : $end;
1257
        }
1258
1259
        $this->doc .= '<ul class="rss">';
1260
        if($rc) {
1261
            for($x = $start; $x != $end; $x += $mod) {
1262
                $item = $feed->get_item($x);
1263
                $this->doc .= '<li><div class="li">';
1264
                // support feeds without links
1265
                $lnkurl = $item->get_permalink();
1266
                if($lnkurl) {
1267
                    // title is escaped by SimplePie, we unescape here because it
1268
                    // is escaped again in externallink() FS#1705
1269
                    $this->externallink(
1270
                        $item->get_permalink(),
1271
                        html_entity_decode($item->get_title(), ENT_QUOTES, 'UTF-8')
1272
                    );
1273
                } else {
1274
                    $this->doc .= ' '.$item->get_title();
1275
                }
1276
                if($params['author']) {
1277
                    $author = $item->get_author(0);
1278
                    if($author) {
1279
                        $name = $author->get_name();
1280
                        if(!$name) $name = $author->get_email();
1281
                        if($name) $this->doc .= ' '.$lang['by'].' '.$name;
1282
                    }
1283
                }
1284
                if($params['date']) {
1285
                    $this->doc .= ' ('.$item->get_local_date($conf['dformat']).')';
1286
                }
1287
                if($params['details']) {
1288
                    $this->doc .= '<div class="detail">';
1289
                    if($conf['htmlok']) {
1290
                        $this->doc .= $item->get_description();
1291
                    } else {
1292
                        $this->doc .= strip_tags($item->get_description());
1293
                    }
1294
                    $this->doc .= '</div>';
1295
                }
1296
1297
                $this->doc .= '</div></li>';
1298
            }
1299
        } else {
1300
            $this->doc .= '<li><div class="li">';
1301
            $this->doc .= '<em>'.$lang['rssfailed'].'</em>';
1302
            $this->externallink($url);
1303
            if($conf['allowdebug']) {
1304
                $this->doc .= '<!--'.hsc($feed->error).'-->';
1305
            }
1306
            $this->doc .= '</div></li>';
1307
        }
1308
        $this->doc .= '</ul>';
1309
    }
1310
1311
    /**
1312
     * Start a table
1313
     *
1314
     * @param int $maxcols maximum number of columns
1315
     * @param int $numrows NOT IMPLEMENTED
1316
     * @param int $pos byte position in the original source
1317
     * @param string $classes css class
1318
     */
1319
    function table_open($maxcols = null, $numrows = null, $pos = null, $classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1320
        // initialize the row counter used for classes
1321
        $this->_counter['row_counter'] = 0;
1322
        $class                         = 'table';
1323
        if($classes !== null) {
1324
            $class .= ' ' . $classes;
1325
        }
1326
        if($pos !== null) {
1327
            $class .= ' '.$this->startSectionEdit($pos, 'table');
1328
        }
1329
        $this->doc .= '<div class="'.$class.'"><table class="inline">'.
1330
            DOKU_LF;
1331
    }
1332
1333
    /**
1334
     * Close a table
1335
     *
1336
     * @param int $pos byte position in the original source
1337
     */
1338
    function table_close($pos = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1339
        $this->doc .= '</table></div>'.DOKU_LF;
1340
        if($pos !== null) {
1341
            $this->finishSectionEdit($pos);
1342
        }
1343
    }
1344
1345
    /**
1346
     * Open a table header
1347
     */
1348
    function tablethead_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1349
        $this->doc .= DOKU_TAB.'<thead>'.DOKU_LF;
1350
    }
1351
1352
    /**
1353
     * Close a table header
1354
     */
1355
    function tablethead_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1356
        $this->doc .= DOKU_TAB.'</thead>'.DOKU_LF;
1357
    }
1358
1359
    /**
1360
     * Open a table body
1361
     */
1362
    function tabletbody_open() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1363
        $this->doc .= DOKU_TAB.'<tbody>'.DOKU_LF;
1364
    }
1365
1366
    /**
1367
     * Close a table body
1368
     */
1369
    function tabletbody_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1370
        $this->doc .= DOKU_TAB.'</tbody>'.DOKU_LF;
1371
    }
1372
1373
    /**
1374
     * Open a table row
1375
     *
1376
     * @param string $classes css class
1377
     */
1378
    function tablerow_open($classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1379
        // initialize the cell counter used for classes
1380
        $this->_counter['cell_counter'] = 0;
1381
        $class                          = 'row'.$this->_counter['row_counter']++;
1382
        if($classes !== null) {
1383
            $class .= ' ' . $classes;
1384
        }
1385
        $this->doc .= DOKU_TAB.'<tr class="'.$class.'">'.DOKU_LF.DOKU_TAB.DOKU_TAB;
1386
    }
1387
1388
    /**
1389
     * Close a table row
1390
     */
1391
    function tablerow_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1392
        $this->doc .= DOKU_LF.DOKU_TAB.'</tr>'.DOKU_LF;
1393
    }
1394
1395
    /**
1396
     * Open a table header cell
1397
     *
1398
     * @param int    $colspan
1399
     * @param string $align left|center|right
1400
     * @param int    $rowspan
1401
     * @param string $classes css class
1402
     */
1403
    function tableheader_open($colspan = 1, $align = null, $rowspan = 1, $classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1404
        $class = 'class="col'.$this->_counter['cell_counter']++;
1405
        if(!is_null($align)) {
1406
            $class .= ' '.$align.'align';
1407
        }
1408
        if($classes !== null) {
1409
            $class .= ' ' . $classes;
1410
        }
1411
        $class .= '"';
1412
        $this->doc .= '<th '.$class;
1413
        if($colspan > 1) {
1414
            $this->_counter['cell_counter'] += $colspan - 1;
1415
            $this->doc .= ' colspan="'.$colspan.'"';
1416
        }
1417
        if($rowspan > 1) {
1418
            $this->doc .= ' rowspan="'.$rowspan.'"';
1419
        }
1420
        $this->doc .= '>';
1421
    }
1422
1423
    /**
1424
     * Close a table header cell
1425
     */
1426
    function tableheader_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1427
        $this->doc .= '</th>';
1428
    }
1429
1430
    /**
1431
     * Open a table cell
1432
     *
1433
     * @param int       $colspan
1434
     * @param string    $align left|center|right
1435
     * @param int       $rowspan
1436
     * @param string    $classes css class
1437
     */
1438
    function tablecell_open($colspan = 1, $align = null, $rowspan = 1, $classes = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1439
        $class = 'class="col'.$this->_counter['cell_counter']++;
1440
        if(!is_null($align)) {
1441
            $class .= ' '.$align.'align';
1442
        }
1443
        if($classes !== null) {
1444
            $class .= ' ' . $classes;
1445
        }
1446
        $class .= '"';
1447
        $this->doc .= '<td '.$class;
1448
        if($colspan > 1) {
1449
            $this->_counter['cell_counter'] += $colspan - 1;
1450
            $this->doc .= ' colspan="'.$colspan.'"';
1451
        }
1452
        if($rowspan > 1) {
1453
            $this->doc .= ' rowspan="'.$rowspan.'"';
1454
        }
1455
        $this->doc .= '>';
1456
    }
1457
1458
    /**
1459
     * Close a table cell
1460
     */
1461
    function tablecell_close() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1462
        $this->doc .= '</td>';
1463
    }
1464
1465
    #region Utility functions
1466
1467
    /**
1468
     * Build a link
1469
     *
1470
     * Assembles all parts defined in $link returns HTML for the link
1471
     *
1472
     * @param array $link attributes of a link
1473
     * @return string
1474
     *
1475
     * @author Andreas Gohr <[email protected]>
1476
     */
1477
    function _formatLink($link) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1478
        //make sure the url is XHTML compliant (skip mailto)
1479
        if(substr($link['url'], 0, 7) != 'mailto:') {
1480
            $link['url'] = str_replace('&', '&amp;', $link['url']);
1481
            $link['url'] = str_replace('&amp;amp;', '&amp;', $link['url']);
1482
        }
1483
        //remove double encodings in titles
1484
        $link['title'] = str_replace('&amp;amp;', '&amp;', $link['title']);
1485
1486
        // be sure there are no bad chars in url or title
1487
        // (we can't do this for name because it can contain an img tag)
1488
        $link['url']   = strtr($link['url'], array('>' => '%3E', '<' => '%3C', '"' => '%22'));
1489
        $link['title'] = strtr($link['title'], array('>' => '&gt;', '<' => '&lt;', '"' => '&quot;'));
1490
1491
        $ret = '';
1492
        $ret .= $link['pre'];
1493
        $ret .= '<a href="'.$link['url'].'"';
1494
        if(!empty($link['class'])) $ret .= ' class="'.$link['class'].'"';
1495
        if(!empty($link['target'])) $ret .= ' target="'.$link['target'].'"';
1496
        if(!empty($link['title'])) $ret .= ' title="'.$link['title'].'"';
1497
        if(!empty($link['style'])) $ret .= ' style="'.$link['style'].'"';
1498
        if(!empty($link['rel'])) $ret .= ' rel="'.trim($link['rel']).'"';
1499
        if(!empty($link['more'])) $ret .= ' '.$link['more'];
1500
        $ret .= '>';
1501
        $ret .= $link['name'];
1502
        $ret .= '</a>';
1503
        $ret .= $link['suf'];
1504
        return $ret;
1505
    }
1506
1507
    /**
1508
     * Renders internal and external media
1509
     *
1510
     * @author Andreas Gohr <[email protected]>
1511
     * @param string $src       media ID
1512
     * @param string $title     descriptive text
1513
     * @param string $align     left|center|right
1514
     * @param int    $width     width of media in pixel
1515
     * @param int    $height    height of media in pixel
1516
     * @param string $cache     cache|recache|nocache
1517
     * @param bool   $render    should the media be embedded inline or just linked
1518
     * @return string
1519
     */
1520
    function _media($src, $title = null, $align = null, $width = null,
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1521
                    $height = null, $cache = null, $render = true) {
1522
1523
        $ret = '';
1524
1525
        list($ext, $mime) = mimetype($src);
1526
        if(substr($mime, 0, 5) == 'image') {
1527
            // first get the $title
1528
            if(!is_null($title)) {
1529
                $title = $this->_xmlEntities($title);
1530
            } elseif($ext == 'jpg' || $ext == 'jpeg') {
1531
                //try to use the caption from IPTC/EXIF
1532
                require_once(DOKU_INC.'inc/JpegMeta.php');
1533
                $jpeg = new JpegMeta(mediaFN($src));
1534
                if($jpeg !== false) $cap = $jpeg->getTitle();
1535
                if(!empty($cap)) {
1536
                    $title = $this->_xmlEntities($cap);
1537
                }
1538
            }
1539
            if(!$render) {
1540
                // if the picture is not supposed to be rendered
1541
                // return the title of the picture
1542
                if(!$title) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $title of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1543
                    // just show the sourcename
1544
                    $title = $this->_xmlEntities(utf8_basename(noNS($src)));
1545
                }
1546
                return $title;
1547
            }
1548
            //add image tag
1549
            $ret .= '<img src="'.ml($src, array('w' => $width, 'h' => $height, 'cache' => $cache, 'rev'=>$this->_getLastMediaRevisionAt($src))).'"';
1550
            $ret .= ' class="media'.$align.'"';
1551
1552
            if($title) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $title of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1553
                $ret .= ' title="'.$title.'"';
1554
                $ret .= ' alt="'.$title.'"';
1555
            } else {
1556
                $ret .= ' alt=""';
1557
            }
1558
1559
            if(!is_null($width))
1560
                $ret .= ' width="'.$this->_xmlEntities($width).'"';
1561
1562
            if(!is_null($height))
1563
                $ret .= ' height="'.$this->_xmlEntities($height).'"';
1564
1565
            $ret .= ' />';
1566
1567
        } elseif(media_supportedav($mime, 'video') || media_supportedav($mime, 'audio')) {
1568
            // first get the $title
1569
            $title = !is_null($title) ? $this->_xmlEntities($title) : false;
1570
            if(!$render) {
1571
                // if the file is not supposed to be rendered
1572
                // return the title of the file (just the sourcename if there is no title)
1573
                return $title ? $title : $this->_xmlEntities(utf8_basename(noNS($src)));
1574
            }
1575
1576
            $att          = array();
1577
            $att['class'] = "media$align";
1578
            if($title) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $title of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1579
                $att['title'] = $title;
1580
            }
1581
1582
            if(media_supportedav($mime, 'video')) {
1583
                //add video
1584
                $ret .= $this->_video($src, $width, $height, $att);
1585
            }
1586
            if(media_supportedav($mime, 'audio')) {
1587
                //add audio
1588
                $ret .= $this->_audio($src, $att);
1589
            }
1590
1591
        } elseif($mime == 'application/x-shockwave-flash') {
1592
            if(!$render) {
1593
                // if the flash is not supposed to be rendered
1594
                // return the title of the flash
1595
                if(!$title) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $title of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1596
                    // just show the sourcename
1597
                    $title = utf8_basename(noNS($src));
1598
                }
1599
                return $this->_xmlEntities($title);
1600
            }
1601
1602
            $att          = array();
1603
            $att['class'] = "media$align";
1604
            if($align == 'right') $att['align'] = 'right';
1605
            if($align == 'left') $att['align'] = 'left';
1606
            $ret .= html_flashobject(
1607
                ml($src, array('cache' => $cache), true, '&'), $width, $height,
1608
                array('quality' => 'high'),
1609
                null,
1610
                $att,
1611
                $this->_xmlEntities($title)
1612
            );
1613
        } elseif($title) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $title of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1614
            // well at least we have a title to display
1615
            $ret .= $this->_xmlEntities($title);
1616
        } else {
1617
            // just show the sourcename
1618
            $ret .= $this->_xmlEntities(utf8_basename(noNS($src)));
1619
        }
1620
1621
        return $ret;
1622
    }
1623
1624
    /**
1625
     * Escape string for output
1626
     *
1627
     * @param $string
1628
     * @return string
1629
     */
1630
    function _xmlEntities($string) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1631
        return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
1632
    }
1633
1634
    /**
1635
     * Creates a linkid from a headline
1636
     *
1637
     * @author Andreas Gohr <[email protected]>
1638
     * @param string  $title   The headline title
1639
     * @param boolean $create  Create a new unique ID?
1640
     * @return string
1641
     */
1642
    function _headerToLink($title, $create = false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1643
        if($create) {
1644
            return sectionID($title, $this->headers);
1645
        } else {
1646
            $check = false;
1647
            return sectionID($title, $check);
1648
        }
1649
    }
1650
1651
    /**
1652
     * Construct a title and handle images in titles
1653
     *
1654
     * @author Harry Fuecks <[email protected]>
1655
     * @param string|array $title    either string title or media array
1656
     * @param string       $default  default title if nothing else is found
1657
     * @param bool         $isImage  will be set to true if it's a media file
1658
     * @param null|string  $id       linked page id (used to extract title from first heading)
1659
     * @param string       $linktype content|navigation
1660
     * @return string      HTML of the title, might be full image tag or just escaped text
1661
     */
1662
    function _getLinkTitle($title, $default, &$isImage, $id = null, $linktype = 'content') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1663
        $isImage = false;
1664
        if(is_array($title)) {
1665
            $isImage = true;
1666
            return $this->_imageTitle($title);
1667
        } elseif(is_null($title) || trim($title) == '') {
1668
            if(useHeading($linktype) && $id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1669
                $heading = p_get_first_heading($id);
1670
                if($heading) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $heading of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1671
                    return $this->_xmlEntities($heading);
1672
                }
1673
            }
1674
            return $this->_xmlEntities($default);
1675
        } else {
1676
            return $this->_xmlEntities($title);
1677
        }
1678
    }
1679
1680
    /**
1681
     * Returns HTML code for images used in link titles
1682
     *
1683
     * @author Andreas Gohr <[email protected]>
1684
     * @param array $img
1685
     * @return string HTML img tag or similar
1686
     */
1687
    function _imageTitle($img) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1688
        global $ID;
1689
1690
        // some fixes on $img['src']
1691
        // see internalmedia() and externalmedia()
1692
        list($img['src']) = explode('#', $img['src'], 2);
1693
        if($img['type'] == 'internalmedia') {
1694
            resolve_mediaid(getNS($ID), $img['src'], $exists ,$this->date_at, true);
0 ignored issues
show
Security Bug introduced by
It seems like getNS($ID) targeting getNS() can also be of type false; however, resolve_mediaid() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1695
        }
1696
1697
        return $this->_media(
1698
            $img['src'],
1699
            $img['title'],
1700
            $img['align'],
1701
            $img['width'],
1702
            $img['height'],
1703
            $img['cache']
1704
        );
1705
    }
1706
1707
    /**
1708
     * helperfunction to return a basic link to a media
1709
     *
1710
     * used in internalmedia() and externalmedia()
1711
     *
1712
     * @author   Pierre Spring <[email protected]>
1713
     * @param string $src       media ID
1714
     * @param string $title     descriptive text
1715
     * @param string $align     left|center|right
1716
     * @param int    $width     width of media in pixel
1717
     * @param int    $height    height of media in pixel
1718
     * @param string $cache     cache|recache|nocache
1719
     * @param bool   $render    should the media be embedded inline or just linked
1720
     * @return array associative array with link config
1721
     */
1722
    function _getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1723
        global $conf;
1724
1725
        $link           = array();
1726
        $link['class']  = 'media';
1727
        $link['style']  = '';
1728
        $link['pre']    = '';
1729
        $link['suf']    = '';
1730
        $link['more']   = '';
1731
        $link['target'] = $conf['target']['media'];
1732
        if($conf['target']['media']) $link['rel'] = 'noopener';
1733
        $link['title']  = $this->_xmlEntities($src);
1734
        $link['name']   = $this->_media($src, $title, $align, $width, $height, $cache, $render);
1735
1736
        return $link;
1737
    }
1738
1739
    /**
1740
     * Embed video(s) in HTML
1741
     *
1742
     * @author Anika Henke <[email protected]>
1743
     *
1744
     * @param string $src         - ID of video to embed
1745
     * @param int    $width       - width of the video in pixels
1746
     * @param int    $height      - height of the video in pixels
1747
     * @param array  $atts        - additional attributes for the <video> tag
1748
     * @return string
1749
     */
1750
    function _video($src, $width, $height, $atts = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1751
        // prepare width and height
1752
        if(is_null($atts)) $atts = array();
1753
        $atts['width']  = (int) $width;
1754
        $atts['height'] = (int) $height;
1755
        if(!$atts['width']) $atts['width'] = 320;
1756
        if(!$atts['height']) $atts['height'] = 240;
1757
1758
        $posterUrl = '';
1759
        $files = array();
1760
        $isExternal = media_isexternal($src);
1761
1762
        if ($isExternal) {
1763
            // take direct source for external files
1764
            list(/*ext*/, $srcMime) = mimetype($src);
1765
            $files[$srcMime] = $src;
1766
        } else {
1767
            // prepare alternative formats
1768
            $extensions   = array('webm', 'ogv', 'mp4');
1769
            $files        = media_alternativefiles($src, $extensions);
1770
            $poster       = media_alternativefiles($src, array('jpg', 'png'));
1771
            if(!empty($poster)) {
1772
                $posterUrl = ml(reset($poster), '', true, '&');
1773
            }
1774
        }
1775
1776
        $out = '';
1777
        // open video tag
1778
        $out .= '<video '.buildAttributes($atts).' controls="controls"';
1779
        if($posterUrl) $out .= ' poster="'.hsc($posterUrl).'"';
1780
        $out .= '>'.NL;
1781
        $fallback = '';
1782
1783
        // output source for each alternative video format
1784
        foreach($files as $mime => $file) {
1785
            if ($isExternal) {
1786
                $url = $file;
1787
                $linkType = 'externalmedia';
1788
            } else {
1789
                $url = ml($file, '', true, '&');
1790
                $linkType = 'internalmedia';
1791
            }
1792
            $title = $atts['title'] ? $atts['title'] : $this->_xmlEntities(utf8_basename(noNS($file)));
1793
1794
            $out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
1795
            // alternative content (just a link to the file)
1796
            $fallback .= $this->$linkType($file, $title, null, null, null, $cache = null, $linking = 'linkonly', $return = true);
1797
        }
1798
1799
        // finish
1800
        $out .= $fallback;
1801
        $out .= '</video>'.NL;
1802
        return $out;
1803
    }
1804
1805
    /**
1806
     * Embed audio in HTML
1807
     *
1808
     * @author Anika Henke <[email protected]>
1809
     *
1810
     * @param string $src       - ID of audio to embed
1811
     * @param array  $atts      - additional attributes for the <audio> tag
1812
     * @return string
1813
     */
1814
    function _audio($src, $atts = array()) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1815
        $files = array();
1816
        $isExternal = media_isexternal($src);
1817
1818
        if ($isExternal) {
1819
            // take direct source for external files
1820
            list(/*ext*/, $srcMime) = mimetype($src);
1821
            $files[$srcMime] = $src;
1822
        } else {
1823
            // prepare alternative formats
1824
            $extensions   = array('ogg', 'mp3', 'wav');
1825
            $files        = media_alternativefiles($src, $extensions);
1826
        }
1827
1828
        $out = '';
1829
        // open audio tag
1830
        $out .= '<audio '.buildAttributes($atts).' controls="controls">'.NL;
1831
        $fallback = '';
1832
1833
        // output source for each alternative audio format
1834
        foreach($files as $mime => $file) {
1835
            if ($isExternal) {
1836
                $url = $file;
1837
                $linkType = 'externalmedia';
1838
            } else {
1839
                $url = ml($file, '', true, '&');
1840
                $linkType = 'internalmedia';
1841
            }
1842
            $title = $atts['title'] ? $atts['title'] : $this->_xmlEntities(utf8_basename(noNS($file)));
1843
1844
            $out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
1845
            // alternative content (just a link to the file)
1846
            $fallback .= $this->$linkType($file, $title, null, null, null, $cache = null, $linking = 'linkonly', $return = true);
1847
        }
1848
1849
        // finish
1850
        $out .= $fallback;
1851
        $out .= '</audio>'.NL;
1852
        return $out;
1853
    }
1854
1855
    /**
1856
     * _getLastMediaRevisionAt is a helperfunction to internalmedia() and _media()
1857
     * which returns an existing media revision less or equal to rev or date_at
1858
     *
1859
     * @author lisps
1860
     * @param string $media_id
1861
     * @access protected
1862
     * @return string revision ('' for current)
1863
     */
1864
    function _getLastMediaRevisionAt($media_id){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1865
        if(!$this->date_at || media_isexternal($media_id)) return '';
1866
        $pagelog = new MediaChangeLog($media_id);
1867
        return $pagelog->getLastRevisionAt($this->date_at);
1868
    }
1869
1870
    #endregion
1871
}
1872
1873
//Setup VIM: ex: et ts=4 :
1874