<?php
/**
 * Plugin relativens: Links & media that don't start with / or : default
 * to being relative to the namespace in which the current page is.
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Peter Lamberg (pe78 [at] lodju.dyndns dot org)
 * @based_on   "pagespace" plugin by Symon Bent and "baselink" plugin Robert Meerman. Contains portion of code from dokuwiki source file handler.php.
 */

if(!defined('DOKU_INC')) die();

if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');

class syntax_plugin_relativens extends DokuWiki_Syntax_Plugin {

    function getInfo() {
        return array('author' => 'Peter Lamberg',
                     'email'  => 'pe78 [at] lodju.dyndns dot org',
                     'date'   => '2008-12-30',
                     'name'   => 'relativens',
                     'desc'   => "Plugin relativens: Links & media that don't start with / or : default to being relative to the namespace in which the current page is.",
                     'url'    => 'http://www.dokuwiki.org/plugin:relativens');
    }

    function getType() {
        return 'substition';
    }

    // before built in links & media
    function getSort(){ return 299; }

    function connectTo($mode) {
        $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'plugin_relativens');
        $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'plugin_relativens');
    }

    function handle($match, $state, $pos, &$handler) {
        // Following link parsing code is originally copied from Dokuwiki handler.php

        // See which one we caught
        $isMedia = preg_match('/^\{\{/', $link);

        $isMedia = 0;

        $originalMatch = $match;

        // Strip the opening and closing markup
        // At same time detect if this is media or link
        // handler.media and handler.internallink do this too, but
        // they don't check if they replaced anything.
        $match = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match, 2, $isMedia);
        $match = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match, 2);

        // Split title from URL
        $linkAndTitle = preg_split('/\|/u',$match,2);
        $linkTrimmed = trim($linkAndTitle[0]);

        $modifiedMatch = $originalMatch;

        // Give special treatment to the first few characters
        // of internal links and media links (media links are always "internal"?).
        // Sadly excluding the non internal links is a complicated process
        // and we end up doing it twice, but at least the results of these
        // handle functions are cached.
        if($isMedia || $this->isLinkInternal($linkTrimmed)) {
            // unless it's explicitly absolute,
            // Make it look like relative
            $modifiedMatch = preg_replace('/(^(?:\[\[|\{\{)\s*)(?![\:\/])/', '\\1./', $modifiedMatch, 1);
        }
        // let the regular handler take care of the rest
        if($isMedia) {
            $handler->media($modifiedMatch, $state, $pos);
        }
        else
        {
            $handler->internallink($modifiedMatch, $state, $pos);
        }
    }

    function isLinkInternal($linkPart) {
        // If conditions copied from Dokuwiki handler.php
        if ( preg_match('/^[a-zA-Z\.]+>{1}.*$/u',$linkPart) ) {
            return false;
        }elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$linkPart) ) {
            return false;
        }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$linkPart) ) {
            return false;
        }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$linkPart) ) {
            return false;
        }elseif ( preg_match('!^#.+!',$linkPart) ) {
            return false;
        }else{
            return true;
        }
    }

    function render($mode, &$renderer, $data) {
        // Should never come here, since we leech the original handler for most processing
        return false;
    }

}


