1<?php
2/**
3 * Plugin relativens: Links & media that don't start with / or : default
4 * to being relative to the namespace in which the current page is.
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Peter Lamberg (pe78 [at] lodju.dyndns dot org)
8 * @based_on   "pagespace" plugin by Symon Bent and "baselink" plugin Robert Meerman. Contains portion of code from dokuwiki source file handler.php.
9 */
10
11if(!defined('DOKU_INC')) die();
12
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14require_once(DOKU_PLUGIN.'syntax.php');
15
16class syntax_plugin_relativens extends DokuWiki_Syntax_Plugin {
17
18    function getInfo() {
19        return array('author' => 'Peter Lamberg',
20                     'email'  => 'pe78 [at] lodju.dyndns dot org',
21                     'date'   => '2008-12-30',
22                     'name'   => 'relativens',
23                     'desc'   => "Plugin relativens: Links & media that don't start with / or : default to being relative to the namespace in which the current page is.",
24                     'url'    => 'http://www.dokuwiki.org/plugin:relativens');
25    }
26
27    function getType() {
28        return 'substition';
29    }
30
31    // before built in links & media
32    function getSort(){ return 299; }
33
34    function connectTo($mode) {
35        $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'plugin_relativens');
36        $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'plugin_relativens');
37    }
38
39    function handle($match, $state, $pos, &$handler) {
40        // Following link parsing code is originally copied from Dokuwiki handler.php
41
42        // See which one we caught
43        $isMedia = preg_match('/^\{\{/', $link);
44
45        $isMedia = 0;
46
47        $originalMatch = $match;
48
49        // Strip the opening and closing markup
50        // At same time detect if this is media or link
51        // handler.media and handler.internallink do this too, but
52        // they don't check if they replaced anything.
53        $match = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match, 2, $isMedia);
54        $match = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match, 2);
55
56        // Split title from URL
57        $linkAndTitle = preg_split('/\|/u',$match,2);
58        $linkTrimmed = trim($linkAndTitle[0]);
59
60        $modifiedMatch = $originalMatch;
61
62        // Give special treatment to the first few characters
63        // of internal links and media links (media links are always "internal"?).
64        // Sadly excluding the non internal links is a complicated process
65        // and we end up doing it twice, but at least the results of these
66        // handle functions are cached.
67        if($isMedia || $this->isLinkInternal($linkTrimmed)) {
68            // unless it's explicitly absolute,
69            // Make it look like relative
70            $modifiedMatch = preg_replace('/(^(?:\[\[|\{\{)\s*)(?![\:\/])/', '\\1./', $modifiedMatch, 1);
71        }
72        // let the regular handler take care of the rest
73        if($isMedia) {
74            $handler->media($modifiedMatch, $state, $pos);
75        }
76        else
77        {
78            $handler->internallink($modifiedMatch, $state, $pos);
79        }
80    }
81
82    function isLinkInternal($linkPart) {
83        // If conditions copied from Dokuwiki handler.php
84        if ( preg_match('/^[a-zA-Z\.]+>{1}.*$/u',$linkPart) ) {
85            return false;
86        }elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$linkPart) ) {
87            return false;
88        }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$linkPart) ) {
89            return false;
90        }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$linkPart) ) {
91            return false;
92        }elseif ( preg_match('!^#.+!',$linkPart) ) {
93            return false;
94        }else{
95            return true;
96        }
97    }
98
99    function render($mode, &$renderer, $data) {
100        // Should never come here, since we leech the original handler for most processing
101        return false;
102    }
103
104}
105
106
107