1<?php
2
3/**
4 * This plugin allows to insert a section of a page
5 * The section can be shown in different ways:
6 * 1. The section is shown as it is like a simple include
7 * 2. The first link in the section is shown (direct or with the parameters used)
8 * 3. The text before an after the link is shown as a footnote or plain text or not
9 * It can be used to reference one link or text on multiple pages
10 * It is usefull to reference to one links that are often updatet
11 *
12 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
13 * @author     Dietrich Wittenberg <info.wittenberg@online.de>
14 */
15
16// must be run within Dokuwiki
17//if(!defined('DOKU_INC')) die();
18
19if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
20if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
21require_once(DOKU_PLUGIN.'syntax.php');
22require_once (DWTOOLS.'lib.php');
23
24function _getFN($ns, $file){
25
26	// check for wiki page = $ns:$file (or $file where no namespace)
27	$nsFile = ($ns) ? "$ns:$file" : $file;
28	if (@file_exists(wikiFN($nsFile)) && auth_quickaclcheck($nsFile)) return $nsFile;
29	// no namespace left, exit with no file found
30	if (!$ns) return '';
31	// remove deepest namespace level and call function recursively
32	$i = strrpos($ns, ":");
33	$ns = ($i) ? substr($ns, 0, $i) : false;
34	return _getFN($ns, $file);
35}
36
37// defaults to the root linkfile: links
38function _get_linkfile($file_ns, $file) {
39	global $ID;
40	// discover file containing the links
41	$file_ns = ($file_ns == "") ? getNS($ID) : $file_ns;
42	$linksfile = _getFN($file_ns, $file);
43	if ($linksfile != "") return (io_readFile(wikiFN($linksfile)));
44	return "";
45}
46
47/**
48 * split a string by a special string
49 *
50 * @param string $section
51 * @param string $link
52 * @return array(string, string)
53 */
54function _split_text($section, $link) {
55  $ret=explode($link, trim($section), 2);
56  return $ret;
57}
58
59// change params of link depending on type
60function _check_translate($type, $link, $params) {
61	if (trim($params) != "") {		// change syntax-params --> link-params
62		switch ($type) {
63			case 'internallink':			// rendrerer maybe: interwikilink, locallink, internallink, windowssharelink, externallink, emaillink
64				// convert [[$ns|$para]] --> [[$ns|$params]]
65				list($ns, $para) = preg_split('/[\|]/',substr($link, 2, -2), 2);
66				$link=substr($link,0,2).$ns."|".$params.substr($link,-2,2);
67				break;
68			case 'media': 						// rendrerer mayabe: externalmedia, internalmedia
69				// convert {{$ns?$para}} --> {{$ns?$params}}
70				list($ns, $para) = preg_split('/[\?]/',substr($link, 2, -2), 2);
71				$link=substr($link,0,2).$ns."?".$params.substr($link,-2,2);
72				break;
73			case "windowssharelink":	// rendrerer mayabe: windowssharelink
74			case 'externallink':			// rendrerer mayabe: externallink
75			case "emaillink":					// rendrerer mayabe: emaillink
76			case 'filelink':					// rendrerer mayabe: filelink
77				// convert to internallink and set new params
78				$link="[[".$link."|".$params."]]";
79				$type="internallink";
80				break;
81		}
82	}
83	return (array($type, $link));
84}
85
86class syntax_plugin_dwinsect extends DokuWiki_Syntax_Plugin {
87
88	function syntax_plugin_dwinsect() {
89	}
90
91/* not longer needed for DokuWiki 2009-12-25 “Lemming” and later
92	function getInfo(){
93    return array(
94      'author' => 'Dietrich Wittenberg',
95      'email'  => 'info.wittenberg@online.de',
96      'date'   => '2012-07-01',
97      'name'   => 'plugin dwinsect',
98      'desc'   => 'INcludes a SECtion or the first link in the section. The link can be interpreted',
99      'url'    => 'http://dokuwiki.org/plugin:dwinsect',
100    );
101  }
102*/
103  function getType(){ return 'substition'; }
104	function getAllowedTypes() { return array('disabled'); }	// 'formatting', 'substition',
105  function getPType(){ return 'normal'; }
106  function getSort(){ return 199; }
107
108
109	function connectTo($mode) {
110		$pattern='\[\*\(.*?(?=\)\])\)\]';	// [*(.....)]
111		$this->Lexer->addSpecialPattern($pattern, $mode, 'plugin_dwinsect' );
112	}
113
114	//function postConnect() 		{	$this->Lexer->addExitPattern('}', 'plugin_dwinsect');}
115
116   /**
117   * Handle the match
118   */
119  function handle($match, $state, $pos, &$handler){
120
121	  switch ($state) {
122			case DOKU_LEXER_ENTER:
123      case DOKU_LEXER_MATCHED:
124			case DOKU_LEXER_UNMATCHED:
125      case DOKU_LEXER_EXIT:
126      	break;
127
128      case DOKU_LEXER_SPECIAL:
129      	//match_all:[ * ( ...                                ...  )]
130	  		//syntax   :[ * (   ns:file#anchor          |     params  )]
131	      $pattern='/\[\*\('.'(?:(.*?)#)?([^|\)]*)'.'[|]?'.'(.*)'.'\)]/';
132	      preg_match($pattern, $match, $subjects);
133	      list($match_all, $ns_file, $anchor, $params)=$subjects;
134
135	      // load nearest pagefile to wikitext
136	      $this->wikitext=_get_linkfile($ns_file, $this->getConf('linklistname'));
137
138	      // anchor: anchor_name?param1=val1&param2=val2 ...
139				// $anchor_params => array(param1 => val1, param2 => val2, ...)
140				list($anchor_name, $anchor_params) = $this->_get_params($anchor);
141
142				//         (            section[0]                                                    )
143				//         (            section[1]                                   )(  section[2]   )
144				//         (===         anchor_name                               ===)(text1 url text2)      ==== | $end
145	      $pattern='#(={2,}+[ ]*'.preg_quote(trim($anchor_name)).'[ ]*={2,}+\s*)(.*?)'           .'(?=={2,}+|$)#s';
146	      if (preg_match($pattern, $this->wikitext, $section)) {
147
148	      	// found section-name matching $anchor !!! trim spaces from anchor
149	      	list($link_type, $link)		= _get_firstlink($section[2]);						// find link in section[2]:						link
150	      	list($text1, $text2)			= _split_text($section[2], $link);		// split text1, text2 by link:	text1 link text2
151
152	      	switch ($anchor_params['link']) {
153						case "translate":
154							// translate link depending on type:			link'
155							list($link_type,  $link)	=	_check_translate($link_type, $link, $params);
156							break;
157						case "none":
158							$link = "";
159							break;
160						case "plane":
161						default:
162							break;
163					}
164
165					switch ($anchor_params['text']) {
166						case "footnote":
167							$text1 =	($text1) ? "((".$text1."))" : "";
168							$text2 =	($text2) ? "((".$text2."))" : "";
169							break;
170						case "none":
171							$text1 = "";
172							$text2 = "";
173							break;
174						case "plain":
175						default:
176							break;
177     			}
178
179					switch ($anchor_params['include']) {
180						case "plain":
181							$wiki	=	$section[0];
182							break;
183						case "link":
184							$wiki	=	$text1.$link.$text2;
185							break;
186						case "none":
187						default:
188							$wiki = "";
189							break;
190					}
191					$instructions=p_get_instructions($wiki);
192					array_shift($instructions);	//remove document open
193					array_shift($instructions);	//remove paragraph open
194					array_pop($instructions);		//remove document close
195					array_pop($instructions);		//remove paragraph close
196					return array($state, array($instructions, false));
197	      } else {
198	      	$wiki=$anchor_name.(($params) ? "|".$params : "");	// not found section-name matching: anchor_name|anchor_params
199	      	return array($state, array($wiki, true));
200	      }
201      	break;
202		}
203    return array();
204	}
205
206  /**
207   * Create output
208   */
209	function render($mode, &$renderer, $data) {
210
211		if($mode == 'xhtml'){
212			list($state, $result) = $data;
213      switch ($state) {
214      	case DOKU_LEXER_ENTER:
215      	case DOKU_LEXER_MATCHED:
216      	case DOKU_LEXER_UNMATCHED:
217      	case DOKU_LEXER_EXIT:
218       		//$renderer->info['cache'] = false;
219      		break;
220
221      	case DOKU_LEXER_SPECIAL:
222     			list($instructions, $error) = $result;
223     			if ($error === true) {																			// render the link as an syntax-error
224     				$renderer->internallink("[*(".$instructions.")]");					// instructions contains the error-text
225     			} else {
226     				//$renderer->doc.=p_render('xhtml', $instructions, $info);	// instruction contains an array of instructions
227     				$renderer->nest($instructions);
228     			}
229     			break;
230      }
231      return true;
232    }
233    return false;
234	}
235
236// private class functions
237	function _get_params($anchor) {
238	  // anchor: "anchorname?param1=val1&param2=val2 ..."
239		// init defaults to valid params
240		$anchor_params['text']		= $this->getConf('insecttext'); 		// "footnote";
241		$anchor_params['link']		= $this->getConf('insectlink'); 		// "translate";
242		$anchor_params['include']	= $this->getConf('insectinclude');	// "link";
243		// split anchor_name from params
244		list($anchor_name, $params) = preg_split('/[\?]/', $anchor, 2);
245		// split params into anchor_params
246		if ($params) {
247			$a=explode("&", $params);
248			foreach ($a as $p) {
249				list($key, $val) = explode("=", $p);
250				$anchor_params[$key]=$val;
251			}
252		}
253		return array($anchor_name, $anchor_params);
254	}
255
256	function _render_text(&$renderer, $text, $flag) {
257		if ($text) {
258			switch ($flag) {
259				case 'footnote':
260					$renderer->footnote_open();
261					$renderer->doc.=_stripp(p_render('xhtml',p_get_instructions($text),$info));
262					$renderer->footnote_close();
263					break;
264				case 'plain':
265					$renderer->doc.=_stripp(p_render('xhtml',p_get_instructions($text),$info));
266					break;
267			}
268		}
269	}
270
271	function _render_link(&$renderer, $hndl, $args) {
272		// render the link with type of $hndl: use dokuwiki core-functions
273		switch ($hndl) {
274			case 'internallink':
275			case 'locallink':
276			case 'filelink':
277			case "windowssharelink":
278			case 'externallink':
279			case "emaillink":					$renderer->$hndl($args[0], $args[1]); break;
280			case 'interwikilink':			$renderer->$hndl($args[0], $args[1], $args[2], $args[3]); break;
281			case 'internalmedia':
282			case 'externalmedia':			$renderer->$hndl($args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6]); break;
283		}
284	}
285
286}
287//Setup VIM: ex: et ts=4 enc=utf-8 :