xref: /dokuwiki/inc/parser/metadata.php (revision 9a3b7d9f166ec2227b91614228c308f50d3e259f)
1<?php
2/**
3 * Renderer for metadata
4 *
5 * @author Esther Brunner <wikidesign@gmail.com>
6 */
7
8if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../../').'/');
9
10if ( !defined('DOKU_LF') ) {
11    // Some whitespace to help View > Source
12    define ('DOKU_LF',"\n");
13}
14
15if ( !defined('DOKU_TAB') ) {
16    // Some whitespace to help View > Source
17    define ('DOKU_TAB',"\t");
18}
19
20require_once DOKU_INC . 'inc/parser/renderer.php';
21
22/**
23 * The Renderer
24 */
25class Doku_Renderer_metadata extends Doku_Renderer {
26
27  var $doc  = '';
28  var $meta = array();
29  var $persistent = array();
30
31  var $headers = array();
32  var $capture = true;
33  var $store   = '';
34
35  function getFormat(){
36    return 'metadata';
37  }
38
39  function document_start(){
40    // reset metadata to persistent values
41    $this->meta = $this->persistent;
42  }
43
44  function document_end(){
45    // store internal info in metadata (notoc,nocache)
46    $this->meta['internal'] = $this->info;
47
48    if (!$this->meta['description']['abstract']){
49      // cut off too long abstracts
50      $this->doc = trim($this->doc);
51      if (strlen($this->doc) > 500)
52        $this->doc = substr($this->doc, 0, 500).'…';
53      $this->meta['description']['abstract'] = $this->doc;
54    }
55  }
56
57  function toc_additem($id, $text, $level) {
58    global $conf;
59
60    //only add items within configured levels
61    if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){
62      // the TOC is one of our standard ul list arrays ;-)
63      $this->meta['description']['tableofcontents'][] = array(
64        'hid'   => $id,
65        'title' => $text,
66        'type'  => 'ul',
67        'level' => $level-$conf['toptoclevel']+1
68      );
69    }
70
71  }
72
73  function header($text, $level, $pos) {
74
75    if (!$this->meta['title']) $this->meta['title'] = $text;
76
77    // add the header to the TOC
78    $hid = $this->_headerToLink($text,'true');
79    $this->toc_additem($hid, $text, $level);
80
81    // add to summary
82    if ($this->capture && ($level > 1)) $this->doc .= DOKU_LF.$text.DOKU_LF;
83  }
84
85  function section_open($level){}
86  function section_close(){}
87
88  function cdata($text){
89    if ($this->capture) $this->doc .= $text;
90  }
91
92  function p_open(){
93    if ($this->capture) $this->doc .= DOKU_LF;
94  }
95
96  function p_close(){
97    if ($this->capture){
98      if (strlen($this->doc) > 250) $this->capture = false;
99      else $this->doc .= DOKU_LF;
100    }
101  }
102
103  function linebreak(){
104    if ($this->capture) $this->doc .= DOKU_LF;
105  }
106
107  function hr(){
108    if ($this->capture){
109      if (strlen($this->doc) > 250) $this->capture = false;
110      else $this->doc .= DOKU_LF.'----------'.DOKU_LF;
111    }
112  }
113
114  function strong_open(){}
115  function strong_close(){}
116
117  function emphasis_open(){}
118  function emphasis_close(){}
119
120  function underline_open(){}
121  function underline_close(){}
122
123  function monospace_open(){}
124  function monospace_close(){}
125
126  function subscript_open(){}
127  function subscript_close(){}
128
129  function superscript_open(){}
130  function superscript_close(){}
131
132  function deleted_open(){}
133  function deleted_close(){}
134
135  /**
136   * Callback for footnote start syntax
137   *
138   * All following content will go to the footnote instead of
139   * the document. To achieve this the previous rendered content
140   * is moved to $store and $doc is cleared
141   *
142   * @author Andreas Gohr <andi@splitbrain.org>
143   */
144  function footnote_open() {
145    if ($this->capture){
146      // move current content to store and record footnote
147      $this->store = $this->doc;
148      $this->doc   = '';
149    }
150  }
151
152  /**
153   * Callback for footnote end syntax
154   *
155   * All rendered content is moved to the $footnotes array and the old
156   * content is restored from $store again
157   *
158   * @author Andreas Gohr
159   */
160  function footnote_close() {
161    if ($this->capture){
162      // restore old content
163      $this->doc = $this->store;
164      $this->store = '';
165    }
166  }
167
168  function listu_open(){
169    if ($this->capture) $this->doc .= DOKU_LF;
170  }
171
172  function listu_close(){
173    if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false;
174  }
175
176  function listo_open(){
177    if ($this->capture) $this->doc .= DOKU_LF;
178  }
179
180  function listo_close(){
181    if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false;
182  }
183
184  function listitem_open($level){
185    if ($this->capture) $this->doc .= str_repeat(DOKU_TAB, $level).'* ';
186  }
187
188  function listitem_close(){
189    if ($this->capture) $this->doc .= DOKU_LF;
190  }
191
192  function listcontent_open(){}
193  function listcontent_close(){}
194
195  function unformatted($text){
196    if ($this->capture) $this->doc .= $text;
197  }
198
199  function php($text){}
200
201  function phpblock($text){}
202
203  function html($text){}
204
205  function htmlblock($text){}
206
207  function preformatted($text){
208    if ($this->capture) $this->doc .= $text;
209  }
210
211  function file($text){
212    if ($this->capture){
213      $this->doc .= DOKU_LF.$text;
214      if (strlen($this->doc) > 250) $this->capture = false;
215      else $this->doc .= DOKU_LF;
216    }
217  }
218
219  function quote_open(){
220    if ($this->capture) $this->doc .= DOKU_LF.DOKU_TAB.'"';
221  }
222
223  function quote_close(){
224    if ($this->capture){
225      $this->doc .= '"';
226      if (strlen($this->doc) > 250) $this->capture = false;
227      else $this->doc .= DOKU_LF;
228    }
229  }
230
231  function code($text, $language = NULL){
232    if ($this->capture){
233      $this->doc .= DOKU_LF.$text;
234      if (strlen($this->doc) > 250) $this->capture = false;
235      else $this->doc .= DOKU_LF;
236    }
237  }
238
239  function acronym($acronym){
240    if ($this->capture) $this->doc .= $acronym;
241  }
242
243  function smiley($smiley){
244    if ($this->capture) $this->doc .= $smiley;
245  }
246
247  function entity($entity){
248    if ($this->capture) $this->doc .= $entity;
249  }
250
251  function multiplyentity($x, $y){
252    if ($this->capture) $this->doc .= $x.'×'.$y;
253  }
254
255  function singlequoteopening(){
256    global $lang;
257    if ($this->capture) $this->doc .= $lang['singlequoteopening'];
258  }
259
260  function singlequoteclosing(){
261    global $lang;
262    if ($this->capture) $this->doc .= $lang['singlequoteclosing'];
263  }
264
265  function apostrophe() {
266    global $lang;
267    if ($this->capture) $this->doc .= $lang['apostrophe'];
268  }
269
270  function doublequoteopening(){
271    global $lang;
272    if ($this->capture) $this->doc .= $lang['doublequoteopening'];
273  }
274
275  function doublequoteclosing(){
276    global $lang;
277    if ($this->capture) $this->doc .= $lang['doublequoteclosing'];
278  }
279
280  function camelcaselink($link) {
281    $this->internallink($link, $link);
282  }
283
284  function locallink($hash, $name = NULL){}
285
286  /**
287   * keep track of internal links in $this->meta['relation']['references']
288   */
289  function internallink($id, $name = NULL){
290    global $ID;
291
292    $default = $this->_simpleTitle($id);
293
294    // first resolve and clean up the $id
295    resolve_pageid(getNS($ID), $id, $exists);
296    list($page, $hash) = split('#', $id, 2);
297
298    // set metadata
299    $this->meta['relation']['references'][$page] = $exists;
300    // $data = array('relation' => array('isreferencedby' => array($ID => true)));
301    // p_set_metadata($id, $data);
302
303    // add link title to summary
304    if ($this->capture){
305      $name = $this->_getLinkTitle($name, $default, $id);
306      $this->doc .= $name;
307    }
308  }
309
310  function externallink($url, $name = NULL){
311    if ($this->capture){
312      if ($name) $this->doc .= $name;
313      else $this->doc .= '<'.$url.'>';
314    }
315  }
316
317  function interwikilink($match, $name = NULL, $wikiName, $wikiUri){
318    if ($this->capture){
319      list($wikiUri, $hash) = explode('#', $wikiUri, 2);
320      $name = $this->_getLinkTitle($name, $wikiName.'>'.$wikiUri);
321      $this->doc .= $name;
322    }
323  }
324
325  function windowssharelink($url, $name = NULL){
326    if ($this->capture){
327      if ($name) $this->doc .= $name;
328      else $this->doc .= '<'.$url.'>';
329    }
330  }
331
332  function emaillink($address, $name = NULL){
333    if ($this->capture){
334      if ($name) $this->doc .= $name;
335      else $this->doc .= '<'.$address.'>';
336    }
337  }
338
339  function internalmedia($src, $title=NULL, $align=NULL, $width=NULL,
340                         $height=NULL, $cache=NULL, $linking=NULL){
341    if ($this->capture && $title) $this->doc .= '['.$title.']';
342  }
343
344  function externalmedia($src, $title=NULL, $align=NULL, $width=NULL,
345                         $height=NULL, $cache=NULL, $linking=NULL){
346    if ($this->capture && $title) $this->doc .= '['.$title.']';
347  }
348
349  function rss($url,$params) {
350    $this->meta['relation']['haspart'][$url] = true;
351
352    $this->meta['date']['valid']['age'] =
353            isset($this->meta['date']['valid']['age']) ?
354                min($this->meta['date']['valid']['age'],$params['refresh']) :
355                $params['refresh'];
356  }
357
358  function table_open($maxcols = NULL, $numrows = NULL){}
359  function table_close(){}
360
361  function tablerow_open(){}
362  function tablerow_close(){}
363
364  function tableheader_open($colspan = 1, $align = NULL){}
365  function tableheader_close(){}
366
367  function tablecell_open($colspan = 1, $align = NULL){}
368  function tablecell_close(){}
369
370  //----------------------------------------------------------
371  // Utils
372
373  /**
374   * Removes any Namespace from the given name but keeps
375   * casing and special chars
376   *
377   * @author Andreas Gohr <andi@splitbrain.org>
378   */
379  function _simpleTitle($name){
380    global $conf;
381
382    if(is_array($name)) return '';
383
384    if($conf['useslash']){
385        $nssep = '[:;/]';
386    }else{
387        $nssep = '[:;]';
388    }
389    $name = preg_replace('!.*'.$nssep.'!','',$name);
390    //if there is a hash we use the anchor name only
391    $name = preg_replace('!.*#!','',$name);
392    return $name;
393  }
394
395  /**
396   * Creates a linkid from a headline
397   *
398   * @param string  $title   The headline title
399   * @param boolean $create  Create a new unique ID?
400   * @author Andreas Gohr <andi@splitbrain.org>
401   */
402  function _headerToLink($title, $create=false) {
403    $title = str_replace(':','',cleanID($title));
404    $title = ltrim($title,'0123456789._-');
405    if(empty($title)) $title='section';
406
407    if($create){
408      // make sure tiles are unique
409      $num = '';
410      while(in_array($title.$num,$this->headers)){
411        ($num) ? $num++ : $num = 1;
412      }
413      $title = $title.$num;
414      $this->headers[] = $title;
415    }
416
417    return $title;
418  }
419
420  /**
421   * Construct a title and handle images in titles
422   *
423   * @author Harry Fuecks <hfuecks@gmail.com>
424   */
425  function _getLinkTitle($title, $default, $id=NULL) {
426    global $conf;
427
428    $isImage = false;
429    if (is_null($title)){
430      if ($conf['useheading'] && $id){
431        $heading = p_get_first_heading($id,false);
432        if ($heading) return $heading;
433      }
434      return $default;
435    } else if (is_string($title)){
436      return $title;
437    } else if (is_array($title)){
438      return '['.$title.']';
439    }
440  }
441
442}
443
444//Setup VIM: ex: et ts=4 enc=utf-8 :
445