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