1<?php
2/*
3 * To change this template, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7function formatXml($data)
8{
9    $xmlFormat = '
10<sphinx:document id="{id}">
11<title><![CDATA[[{title}]]></title>
12<body><![CDATA[[{body}]]></body>
13<namespace><![CDATA[[{namespace}]]></namespace>
14<pagename><![CDATA[[{pagename}]]></pagename>
15<level>{level}</level>
16<modified>{modified}</modified>
17</sphinx:document>
18
19';
20
21    return str_replace( array('{id}', '{title}', '{body}', '{namespace}', '{pagename}', '{level}', '{modified}'),
22                        array($data['id'], escapeTextValue($data['title_to_index']),
23                            escapeTextValue($data['body']),
24                            escapeTextValue($data['namespace']),
25                            escapeTextValue($data['pagename']),
26                             $data['level'], $data['modified']),
27                $xmlFormat
28            );
29}
30
31function escapeTextValue($value)
32{
33    if ("" === $value)
34    {
35        return "";
36    }
37    //$value = mb_convert_encoding($value,'UTF-8','ISO-8859-1');
38    $value = str_replace('<?php', 'PHPTAGSTART', $value);
39    $value = str_replace('?>', 'PHPTAGEND', $value);
40    $value = strip_tags($value);
41    $value = stripInvalidXml($value);
42    return str_replace("]]>", "]]><![CDATA[]]]]><![CDATA[>]]><![CDATA[", $value);
43 }
44
45function stripInvalidXml($value)
46{
47    $ret = "";
48    if (empty($value))
49    {
50      return $ret;
51    }
52
53    $current = null;
54    $length = strlen($value);
55    for ($i=0; $i < $length; $i++)
56    {
57      $current = ord($value{$i});
58      if (($current == 0x9) ||
59          ($current == 0xA) ||
60          ($current == 0xD) ||
61          (($current >= 0x20) && ($current <= 0xD7FF)) ||
62          (($current >= 0xE000) && ($current <= 0xFFFD)) ||
63          (($current >= 0x10000) && ($current <= 0x10FFFF)))
64      {
65        $ret .= chr($current);
66      }
67      else
68      {
69        $ret .= " ";
70      }
71    }
72    return $ret;
73  }
74
75function getDocumentsByHeadings($id, $metadata)
76{
77    if (empty($metadata) || empty($metadata['description']['tableofcontents'])) return false;
78
79    $sections = array();
80    $level = 1;
81    $previouse_title = '';
82    $firstSection = true;
83    foreach($metadata['description']['tableofcontents'] as $row){
84        if ($firstSection){
85            $zerocontent  = getZeroSectionContent($id, $row['title']);
86            if ($zerocontent){
87                $sections[$id] = array(
88                    'section' => $zerocontent,
89                    'level' => 0,
90                    'title' => $id,
91                    'title_to_index' => $id
92                );
93            }
94            $firstSection = false;
95        }
96        $sections[$row['hid']] = array(
97                                    'section' => getSectionByTitleLevel($id, $row['title'], false),
98                                    'level' => $row['level'],
99                                    'title' => $row['title']
100                                    );
101        if ($row['level'] > $level && !empty($previouse_title)){
102            $sections[$row['hid']]['title_text'] = $previouse_title . " &raquo; ".$row['title'];
103        } else {
104            $sections[$row['hid']]['title_text'] = $row['title'];
105            $previouse_title = $row['title'];
106        }
107        $sections[$row['hid']]['title_to_index'] = $row['title'];
108    }
109    return $sections;
110}
111
112function getZeroSectionContent($id, $header)
113{
114    $headerReg = preg_quote($header, '/');
115    $regex = "(={1,6})\s*({$headerReg})\s*(={1,6})";
116    $doc = io_readFile(wikiFN($id));
117    $matches = array();
118    if (!preg_match("/$regex/i",$doc,$matches)) {
119        return false;
120    }
121    if (empty($matches[1])){
122        return false;
123    }
124    $end = strpos($doc, $matches[1]);
125    if (!$end){
126        return false;
127    }
128    $zerocontent = substr($doc, 0, $end);
129    return $zerocontent;
130}
131
132function getSectionByTitleLevel($id, $header, $extended=false)
133{
134    $headerReg = preg_quote($header, '/');
135    $doc = io_readFile(wikiFN($id));
136    $regex = "(={1,6})\s*({$headerReg})\s*(={1,6})";
137    $section = '';
138    if (preg_match("/$regex/i",$doc,$matches)) {
139        $startHeader = $matches[0];
140        $startHeaderPos = strpos($doc, $startHeader) + strlen($startHeader);
141        $endDoc = substr($doc, $startHeaderPos);
142
143        $regex = '(={4,6})(.*?)(={4,6})';
144        if (preg_match("/$regex/i",$endDoc,$matches)) {
145            $endHeader = $matches[0];
146            $endHeaderPos = strpos($doc, $endHeader);
147        } else {
148            $endHeaderPos = 0;
149        }
150        if ($endHeaderPos){
151            $section = substr($doc, $startHeaderPos, $endHeaderPos - $startHeaderPos);
152        } else {
153            $section = substr($doc, $startHeaderPos);
154        }
155    }
156    $section = trim($section);
157    //trying to get next section content if body for first section is empty
158    //working only for extended mode
159    if ($extended && empty($section)){
160        $startHeaderPos = $endHeaderPos + strlen($endHeader);
161        $endDoc = substr($endDoc, $startHeaderPos);
162        $regex = '(={4,6})(.*?)(={4,6})';
163        if (preg_match("/$regex/i",$endDoc,$matches)) {
164            $endHeader = $matches[0];
165            $endHeaderPos = strpos($doc, $endHeader);
166        } else {
167            $endHeaderPos = 0;
168        }
169        if ($endHeaderPos){
170            $section = substr($doc, $startHeaderPos, $endHeaderPos - $startHeaderPos);
171        } else {
172            $section = substr($doc, $startHeaderPos);
173        }
174    }
175    $section = trim($section);
176    return $section;
177}
178
179function getSection($id, $header)
180{
181    static $cacheInstructions = null;
182    static $cacheDoc = null;
183
184    if (empty($cacheDoc[$id])){
185        // Create the parser
186        $Parser = & new Doku_Parser();
187
188        // Add the Handler
189        $Parser->Handler = & new Doku_Handler();
190
191        // Load the header mode to find headers
192        $Parser->addMode('header',new Doku_Parser_Mode_Header());
193        $Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock());
194
195        // Loads the raw wiki document
196        $doc = io_readFile(wikiFN($id));
197
198        // Get a list of instructions
199        $instructions = $Parser->parse($doc);
200
201        unset($Parser->Handler);
202        unset($Parser);
203
204        //free old cache
205        $cacheInstructions = null;
206        $cacheDoc = null;
207
208        //initialize new cache
209        $cacheInstructions[$id] = $instructions;
210        $cacheDoc[$id] = $doc;
211    } else {
212        $instructions = $cacheInstructions[$id];
213        $doc = $cacheDoc[$id];
214    }
215
216
217
218    // Use this to watch when we're inside the section we want
219    $inSection = FALSE;
220    $startPos = 0;
221    $endPos = 0;
222
223    // Loop through the instructions
224    foreach ( $instructions as $instruction ) {
225
226        if ( !$inSection ) {
227
228            // Look for the header for the "Lists" heading
229            if ( $instruction[0] == 'header' &&
230                    trim($instruction[1][0]) == $header ) {
231
232                $startPos = $instruction[2];
233                $inSection = TRUE;
234            }
235        } else {
236
237            // Look for the end of the section
238            if ( $instruction[0] == 'section_close' ) {
239                $endPos = $instruction[2];
240                break;
241            }
242        }
243    }
244
245    // Normalize and pad the document in the same way the parse does
246    // so that byte indexes with match
247    $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
248    $section = substr($doc, $startPos, ($endPos-$startPos));
249
250    return $section;
251}
252
253function getCategories($id)
254{
255    if (empty($id)) return '';
256
257    if (false === strpos($id, ":")){
258        return '';
259    }
260
261    $ns = explode(":", $id);
262    $nsCount = count($ns) - 1;
263
264    $result = '';
265    do{
266        for($i = 0; $i < $nsCount; $i++){
267            $name = $ns[$i];
268            $result .= $name;
269            if ($i < $nsCount - 1){
270                 $result .= ':';
271            }
272        }
273        $result .= ' ';
274    }while($nsCount--);
275    return $result;
276}
277
278function getPagename($id)
279{
280    if (empty($id)) return '';
281
282    if (false === strpos($id, ":")){
283        return $id;
284    }
285
286    $ns = explode(":", $id);
287    return $ns[count($ns) - 1];
288}
289
290
291
292 /**
293  * Method return all wiki page names
294  * @global array $conf
295  * @return array
296  */
297 function getPagesList()
298 {
299    global $conf;
300
301    $data = array();
302    sort($data);
303    search($data,$conf['datadir'],'search_allpages',array('skipacl'=>1),'');
304
305    return $data;
306}
307
308function getNsLinks($id, $keywords, $search)
309{
310    global $conf;
311    $parts = explode(':', $id);
312    $count = count($parts);
313
314    // print intermediate namespace links
315    $part = '';
316    $data = array();
317    $titles = array();
318    for($i=0; $i<$count; $i++){
319        $part .= $parts[$i].':';
320        $page = $part;
321        resolve_pageid('',$page,$exists);
322
323        if (preg_match("#:start$#", $page) && !preg_match("#:start:$#", $part)) {
324            $page = substr($page, 0, strpos($page, ":start"));
325        };
326
327        // output
328        if ($exists){
329            $titles[wl($page)] = $parts[$i];
330        } else {
331            $titles[wl($page)] = $parts[$i];
332        }
333        $data[] = array('link' => "?do=search&id={$keywords}".urlencode(" @ns $page"));
334    }
335    $titleExcerpt = $search->getExcerpt($titles, $search->starQuery($keywords));
336    $i = 0;
337    foreach ($data as $key => $notused){
338        $data[$key]['title'] = $titleExcerpt[$i++];
339    }
340    return $data;
341}
342
343function printNamespaces($query)
344{
345  $data = array();
346  $query = str_replace(" ", "_", $query);
347  $data = ft_pageLookup($query, false);
348
349  if(!count($data)) return false;
350
351  print '<h3>Matching pagenames</h3>';
352  print '<ul>';
353  $counter = 0;
354  foreach($data as $id){
355    print '<li>';
356    $ns = getNS($id);
357    if($ns){
358      $name = shorten(noNS($id), ' ('.$ns.')',30);
359    }else{
360      $name = $id;
361    }
362    $href = wl($id);
363
364    tpl_link($href,$id, "class='wikilink1'");
365    print '</li>';
366    if(++$counter == 20){
367        break;
368    }
369  }
370  print '</ul>';
371}
372
373function printNamespacesNew($pageNames)
374{
375    if(empty($pageNames)) return false;
376
377    $limit = 10;
378    print '<h3>Matching pagenames</h3>';
379    print '<ul>';
380    $counter = 0;
381    foreach($pageNames as $id => $header){
382        $ns = getNS($id);
383        if($ns){
384          $name = shorten(noNS($id), ' ('.$ns.')',30);
385        }else{
386          $name = $id;
387        }
388        print '<li>';
389        /*if (!empty($header)){
390            print '<a href="'.wl($id).'#'.$header.'" '. "class='wikilink1'>".$id."</a>".'#'.$header;
391        } else {
392            print '<a href="'.wl($id).'" '. "class='wikilink1'>".$id."</a>";
393        }*/
394        print '<a href="'.wl($id).'" '. "class='wikilink1'>".$id."</a>";
395        print '</li>';
396        if (++$counter == $limit){
397            break;
398        }
399    }
400    print '</ul>';
401}
402
403if(!function_exists('shorten')){
404    /**
405     * Shorten a given string by removing data from the middle
406     *
407     * You can give the string in two parts, teh first part $keep
408     * will never be shortened. The second part $short will be cut
409     * in the middle to shorten but only if at least $min chars are
410     * left to display it. Otherwise it will be left off.
411     *
412     * @param string $keep   the part to keep
413     * @param string $short  the part to shorten
414     * @param int    $max    maximum chars you want for the whole string
415     * @param int    $min    minimum number of chars to have left for middle shortening
416     * @param string $char   the shortening character to use
417     */
418    function shorten($keep,$short,$max,$min=9,$char='⌇'){
419        $max = $max - utf8_strlen($keep);
420       if($max < $min) return $keep;
421        $len = utf8_strlen($short);
422        if($len <= $max) return $keep.$short;
423        $half = floor($max/2);
424        return $keep.utf8_substr($short,0,$half-1).$char.utf8_substr($short,$len-$half);
425    }
426}
427