1<?php
2// High performance pagetemplate backlink
3// subsystem
4// @author 'Luke Howson'
5
6if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
7
8class PageTemplateBacklink {
9    function getBacklinks($id) {
10        $checkedBacklinks = array();
11        $backlinks = $this->_load($id);
12        foreach ($backlinks as $backlink) {
13            $link = $this->_verifyLink($backlink, $id);
14            if ( $link) {
15                $checkedBacklinks[] = $link;
16            }
17        }
18        $this->_save($checkedBacklinks, $id);
19        return $checkedBacklinks;
20    }
21
22    function _save($backlinks, $page) {
23        if (!sizeof($backlinks) ) return;
24        $pickle = serialize($backlinks);
25        $file = $this->_pageTemplateMetaFN($page);
26        io_makeFileDir($file);
27        io_saveFile($file, $pickle);
28        return;
29    }
30
31    function _load($page) {
32        $file = $this->_pageTemplateMetaFN($page);
33        $backlinks = array();
34        if ( file_exists($file) ) {
35            $contents = io_readFile($file);
36            $backlinks = unserialize($contents);
37        }
38        return $backlinks;
39    }
40
41    function insert($backlink) {
42        $to = $backlink[1];
43        $context = $backlink[4];
44        $context = getNS($context);
45        $to = resolve_id($context,$to);
46        $backlinks = $this->_load($to);
47        foreach ($backlinks as $bl) {
48            if ($bl == $backlink) return;
49        }
50        $backlinks[] = $backlink;
51        $this->_save($backlinks, $to);
52        return;
53    }
54
55    function _verifyLink($backlink, $to) {
56        //absolute search id
57        $to = cleanID($to);
58
59        $page = $backlink[4];
60        $file = wikiFN($page);
61        if (!file_exists($file)) return false;
62
63        //fetch instructions
64        global $__PAGETEMPLATE_ID;
65        $__PAGETEMPLATE_ID = $page;
66        $instructions = _pt_get_instructions(io_readfile($file));
67        if(is_null($instructions)) return false;
68        $ret = false;
69
70        //check all links for match
71        foreach($instructions as $ins){
72          if($ins[0] == 'plugin' && $ins[1][0] == 'pagetemplate' && strlen($ins[1][1][0]) > 0) {
73            $mid = $ins[1][1][1];
74            resolve_pageid(getNS($page),$mid,$exists); //exists is not used
75            if($mid == $to){
76              //we have a match - finish
77              $ins[1][1][1] = resolve_id($cns,$ins[1][1][1]);
78              $ins[1][1][2] = resolve_id($cns,$ins[1][1][2]);
79              $backlink = $ins[1][1];
80              return $backlink;
81            }
82          }
83        }
84        return false;
85    }
86
87    function _pageTemplateMetaFN($raw_id,$rev='',$clean=true){
88      global $conf;
89
90      $id = cleanID($raw_id);
91      $id = str_replace(':','/',$raw_id);
92      $id .= '.link';
93      $backlinkDir = DOKU_PLUGIN.'/pagetemplate';
94      $backlinkDir .= '/cache';
95      $fn = $backlinkDir.'/'.utf8_encodeFN($id);
96      io_makeFileDir($fn);
97      return $fn;
98    }
99
100    function _pt_get_instructions($text) {
101    // get the instructions
102    // Create the parser
103    $Parser = & new Doku_Parser();
104
105    // Add the Handler
106    $Parser->Handler = & new Doku_Handler();
107
108    //add modes to parser
109    $pagetemplate_obj =& plugin_load('syntax','pagetemplate');
110    $std_modes = array('listblock','preformatted','notoc','nocache',
111                       'header','table','linebreak','footnote','hr',
112                       'unformatted','php','html','code','file','quote',
113                       'internallink','rss','media','externallink',
114                       'emaillink','windowssharelink','eol');
115    foreach($std_modes as $m){
116      $class = "Doku_Parser_Mode_$m";
117      $obj   = new $class();
118      $mode = array(
119                   'sort' => $obj->getSort(),
120                   'mode' => $m,
121                   'obj'  => $obj
122                 );
123      $Parser->addMode($m,$obj);
124    }
125    $Parser->addMode('plugin_pagetemplate',$pagetemplate_obj);
126    // Do the parsing
127    $p = $Parser->parse($text);
128    return $p;
129  }
130
131}