1<?php
2/**
3 * Pagetemplate action plugin
4 *
5 * @author     Luke Howson <mail@lukehowson.com>
6 */
7
8if(!defined('DOKU_INC')) die();
9if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
10require_once(DOKU_PLUGIN.'action.php');
11require_once(DOKU_INC.'inc/parserutils.php');
12require_once(DOKU_INC.'inc/search.php');
13require_once(DOKU_INC.'inc/parser/parser.php');
14require_once('pagetemplate_backlinks.php');
15
16class action_plugin_pagetemplate extends DokuWiki_Action_Plugin {
17
18  /**
19   * return some info
20   */
21  function getInfo(){
22    return array(
23		 'author' => 'Luke Howson',
24		 'email'  => 'mail@lukehowson.com',
25		 'date'   => '2007-07-25',
26		 'name'   => 'Page Template',
27		 'desc'   => 'Generates a template when Create this Page is clicked.',
28		 );
29  }
30
31  /*
32   * Register its handlers with the dokuwiki's event controller
33   */
34  function register(Doku_Event_Handler $controller) {
35    $controller->register_hook('HTML_PAGE_FROMTEMPLATE', 'BEFORE',  $this, '_generateTemplate');
36    $controller->register_hook('HTML_PAGE_FROMTEMPLATE', 'AFTER',  $this, '_removeTemplate');
37  }
38
39  function _removeTemplate(&$event, $param) {
40    $page = getID();
41    $theTemplate = _templateFN($page);
42    if (file_exists($theTemplate)) {
43        unlink($theTemplate);
44        io_sweepNS($page);
45    }
46    $backup = $theTemplate.'.bak';
47    if (file_exists($backup) ) {
48      io_rename($backup,$theTemplate);
49    }
50    return;
51  }
52
53  /**
54   * Hooked into a newly created page (as editor boots up).
55   */
56  function _generateTemplate(&$event, $param) {
57        // page already exists?
58        $page = getID();
59        $pageFile = wikiFN($page);
60        if(file_exists($pageFile) ) {
61            return;
62        }
63        global $conf;
64        $ID = getID();
65        //$ID = $event->data[0];
66        $backlinks = array();
67        $lib = new PageTemplateBacklink;
68        $backlinks = $lib->getBacklinks($ID);
69        if (!sizeof($backlinks)) return;
70        $firstLink = $backlinks[0];
71        $templatePage = $firstLink[2];
72        $context = $firstLink[4];
73        $templatePage = resolve_id(getNS($context),$templatePage);
74        // $displayName = $firstLink[3];
75        $pageName = $firstLink[1];
76        $pageName = resolve_id(getNS($context),$pageName);
77        $fp = wikiFN($pageName);
78        $templateFile = wikiFN($templatePage);
79        $newTemplate = _templateFN($pageName);
80        $backup = $newTemplate.'.bak';
81        if (file_exists($newTemplate) ) {
82          io_rename($newTemplate,$backup);
83        }
84
85        io_makeFileDir($newTemplate);
86        copy($templateFile, $newTemplate);
87        return;
88  }
89}
90
91function _templateFN($pageName) {
92  $newTemplate = resolve_id(getNS($pageName),'template');
93  $newTemplate = wikiFN($newTemplate);
94  $newTemplate = preg_replace('/(?<=\\/)(?=template.txt$)/','_',$newTemplate);
95  // hack for page / subpage model
96  $newTemplate = preg_replace('/(?<=\\/)template\\/page.txt$/','_template.txt',$newTemplate);
97  return $newTemplate;
98}
99
100function _pt_search_backlinks(&$data,$base,$file,$type,$lvl,$opts){
101  //we do nothing with directories
102  if($type == 'd') return true;;
103  //only search txt files
104  if(!preg_match('#\.txt$#',$file)) return true;;
105
106  //absolute search id
107  $sid = parentNS(cleanID($opts['ns'].':'.$opts['name']));
108
109  //current id and namespace
110  $cid = pathID($file);
111  $cns = parentNS($cid);
112
113  //check ACL
114  if(auth_quickaclcheck($cid) < AUTH_READ){
115    return false;
116  }
117
118  //fetch instructions
119  $instructions = _pt_get_instructions(io_readfile($base.$file));
120  if(is_null($instructions)) return false;
121  $ret = false;
122
123  //check all links for match
124  foreach($instructions as $ins){
125    if($ins[0] == 'plugin' && $ins[1][0] == 'pagetemplate' && strlen($ins[1][1][0]) > 0) {
126      $mid = $ins[1][1][1];
127      resolve_pageid($cns,$mid,$exists); //exists is not used
128      if($mid == $sid){
129        //we have a match - finish
130        $ins[1][1][1] = resolve_id($cns,$ins[1][1][1]);
131        $ins[1][1][2] = resolve_id($cns,$ins[1][1][2]);
132        $data[]['id'] = $ins[1][1];
133        break;
134      }
135    }
136  }
137  return false;
138}
139
140function _pt_get_instructions($text) {
141    // get the instructions
142      // Create the parser
143  $Parser = & new Doku_Parser();
144
145  // Add the Handler
146  $Parser->Handler = & new Doku_Handler();
147
148  //add modes to parser
149  $pagetemplate_obj =& plugin_load('syntax','pagetemplate');
150  $std_modes = array('listblock','preformatted','notoc','nocache',
151                     'header','table','linebreak','footnote','hr',
152                     'unformatted','php','html','code','file','quote',
153                     'internallink','rss','media','externallink',
154                     'emaillink','windowssharelink','eol');
155  foreach($std_modes as $m){
156    $class = "Doku_Parser_Mode_$m";
157    $obj   = new $class();
158    $mode = array(
159                 'sort' => $obj->getSort(),
160                 'mode' => $m,
161                 'obj'  => $obj
162               );
163    $Parser->addMode($m,$obj);
164  }
165  $Parser->addMode('plugin_pagetemplate',$pagetemplate_obj);
166  // Do the parsing
167  $p = $Parser->parse($text);
168  return $p;
169}