source: documentation/trunk/packages/dokuwiki-2011-05-25a/lib/plugins/orphanswanted/syntax.php@ 25027

Last change on this file since 25027 was 25027, checked in by jmt12, 12 years ago

Adding the packages directory, and within it a configured version of dokuwiki all ready to run

File size: 12.0 KB
Line 
1<?php
2/**
3 * OrphansWanted Plugin: Display Orphans, Wanteds and Valid link information
4 * syntax ~~ORPHANSWANTED:<choice>[!<exclude list>]~~ <choice> :: orphans | wanted | valid | all
5 * [!<exclude list>] :: optional. prefix each with ! e.g., !wiki!comments:currentyear
6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author <[email protected]>
8 * @author Andy Webber <dokuwiki at andywebber dot com>
9 * @author Federico Ariel Castagnini
10 * @author Cyrille37 <[email protected]>
11 */
12
13if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
14if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
15require_once(DOKU_PLUGIN.'syntax.php');
16
17require_once(DOKU_INC.'inc/search.php');
18
19define('DEBUG', 0);
20
21//-------------------------------------
22
23function orph_callback_search_wanted(&$data,$base,$file,$type,$lvl,$opts) {
24
25 if($type == 'd'){
26 return true; // recurse all directories, but we don't store namespaces
27 }
28
29 if(!preg_match("/.*\.txt$/", $file)) { // Ignore everything but TXT
30 return true;
31 }
32
33 // search the body of the file for links
34 // dae mod
35 // orph_Check_InternalLinks(&$data,$base,$file,$type,$lvl,$opts);
36 orph_Check_InternalLinks($data,$base,$file,$type,$lvl,$opts);
37
38 // get id of this file
39 $id = pathID($file);
40
41 //check ACL
42 if(auth_quickaclcheck($id) < AUTH_READ) {
43 return false;
44 }
45
46 // try to avoid making duplicate entries for forms and pages
47 $item = &$data["$id"];
48 if(isset($item)) {
49 // This item already has a member in the array
50 // Note that the file search found it
51 $item['exists'] = true;
52 } else {
53 // Create a new entry
54 $data["$id"]=array('exists' => true,
55 'links' => 0);
56 }
57 return true;
58}
59
60function orph_handle_link( &$data, $link )
61{
62 if( isset($data[$link]) )
63 {
64 // This item already has a member in the array
65 // Note that the file search found it
66 $data[$link]['links'] ++ ; // count the link
67 } else {
68 // Create a new entry
69 $data[$link] = array(
70 'exists' => false, // Only found a link, not the file
71 'links' => 1
72 );
73 // echo " <!-- added link to list --> \n";
74 }
75 if (DEBUG) echo "<p>-- New count for link <b>" . $link . "</b>: " . $data[$link]['links'] . "</p>\n";
76}
77
78
79/**
80 * Search for internal wiki links in page $file
81 */
82function orph_Check_InternalLinks( &$data, $base, $file, $type, $lvl, $opts )
83{
84 global $conf;
85 define('LINK_PATTERN', '%\[\[([^\]|#]*)(#[^\]|]*)?\|?([^\]]*)]]%');
86
87 if( ! preg_match("/.*\.txt$/", $file) )
88 {
89 return ;
90 }
91
92 $currentID = pathID($file);
93 $currentNS = getNS($currentID);
94
95 if(DEBUG) echo sprintf("<p><b>%s</b>: %s</p>\n", $file, $currentID);
96
97 // echo " <!-- checking file: $file -->\n";
98 $body = @file_get_contents($conf['datadir'] . $file);
99
100 // ignores entries in <nowiki>, %%, <code> and emails with @
101 foreach( array(
102 '/<nowiki>.*?<\/nowiki>/',
103 '/%%.*?%%/',
104 '/<code .*?>.*?<\/code>/'
105 )
106 as $ignored )
107 {
108 $body = preg_replace($ignored, '', $body);
109 }
110
111 $links = array();
112 preg_match_all( LINK_PATTERN, $body, $links );
113
114 foreach( $links[1] as $link )
115 {
116 if(DEBUG) echo sprintf("--- Checking %s<br />\n", $link);
117
118 if( (0 < strlen(ltrim($link)))
119 and ! preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$link) // Interwiki
120 and ! preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link) // Windows Share
121 and ! preg_match('#^([a-z0-9\-\.+]+?)://#i',$link) // external link (accepts all protocols)
122 and ! preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link) // E-Mail (pattern above is defined in inc/mail.php)
123 and ! preg_match('!^#.+!',$link) // inside page link (html anchor)
124 ) {
125 $pageExists=false;
126 resolve_pageid($currentNS,$link,$pageExists );
127 if (DEBUG) echo sprintf("---- link='%s' %s ", $link, $pageExists?'EXISTS':'MISS');
128
129 if(((strlen(ltrim($link)) > 0) // there IS an id?
130 and !auth_quickaclcheck($link) < AUTH_READ)) { // should be visible to user
131 //echo " <!-- adding $link -->\n";
132
133 if(DEBUG) echo ' A_LINK' ;
134
135 $link= strtolower( $link );
136 orph_handle_link($data, $link);
137 }
138 else
139 {
140 if(DEBUG) echo ' EMPTY_OR_FORBIDDEN' ;
141 }
142 } // link is not empty and is a local link?
143 else
144 {
145 if(DEBUG) echo ' NOT_INTERNAL';
146 }
147
148 if(DEBUG) echo "<br />\n";
149 } // end of foreach link
150}
151
152
153
154// --------------------
155
156/**
157 * All DokuWiki plugins to extend the parser/rendering mechanism
158 * need to inherit from this class
159 */
160class syntax_plugin_orphanswanted extends DokuWiki_Syntax_Plugin {
161 /**
162 * return some info
163 */
164 function getInfo(){
165 return array(
166 'author' => 'Doug Edmunds',
167 'email' => '[email protected]',
168 'date' => @file_get_contents(dirname(__FILE__) . '/VERSION'),
169 'name' => 'OrphansWanted Plugin',
170 'desc' => 'Find orphan pages and wanted pages .
171 syntax ~~ORPHANSWANTED:<choice>[!<excluded namespaces>]~~ .
172 <choice> :: orphans|wanted|valid|all .
173 <excluded namespaces> are optional, start each namespace with !' ,
174 'url' => 'http://dokuwiki.org/plugin:orphanswanted',
175 );
176 }
177
178 /**
179 * What kind of syntax are we?
180 */
181 function getType(){
182 return 'substition';
183 }
184
185 /**
186 * What about paragraphs?
187 */
188 function getPType(){
189 return 'normal';
190 }
191
192 /**
193 * Where to sort in?
194 */
195 function getSort(){
196 return 990; //was 990
197 }
198
199
200 /**
201 * Connect pattern to lexer
202 */
203 function connectTo($mode) {
204 $this->Lexer->addSpecialPattern('~~ORPHANSWANTED:[0-9a-zA-Z_:!]+~~',$mode,'plugin_orphanswanted');
205 }
206
207 /**
208 * Handle the match
209 */
210
211 function handle($match, $state, $pos, &$handler){
212 $match_array = array();
213 $match = substr($match,16,-2); //strip ~~ORPHANSWANTED: from start and ~~ from end
214 // Wolfgang 2007-08-29 suggests commenting out the next line
215 // $match = strtolower($match);
216 //create array, using ! as separator
217 $match_array = explode("!", $match);
218 // $match_array[0] will be orphan, wanted, valid, all, or syntax error
219 // if there are excluded namespaces, they will be in $match_array[1] .. [x]
220 // this return value appears in render() as the $data param there
221 return $match_array;
222 }
223
224 /**
225 * Create output
226 */
227 function render($format, &$renderer, $data) {
228 global $INFO, $conf;
229 if($format == 'xhtml'){
230
231 // user needs to add ~~NOCACHE~~ manually to page, to assure ACL rules are followed
232 // coding here is too late, it doesn't get parsed
233 // $renderer->doc .= "~~NOCACHE~~";
234
235 // $data is an array
236 // $data[1]..[x] are excluded namespaces, $data[0] is the report type
237 //handle choices
238 switch ($data[0]){
239 case 'orphans':
240 $renderer->doc .= $this->orphan_pages($data);
241 break;
242 case 'wanted':
243 $renderer->doc .= $this->wanted_pages($data);
244 break;
245 case 'valid':
246 $renderer->doc .= $this->valid_pages($data);
247 break;
248 case 'all':
249 $renderer->doc .= $this->all_pages($data);
250 break;
251 default:
252 $renderer->doc .= "ORPHANSWANTED syntax error";
253 // $renderer->doc .= "syntax ~~ORPHANSWANTED:<choice>~~<optional_excluded> <choice> :: orphans|wanted|valid|all Ex: ~~ORPHANSWANTED:valid~~";
254 }
255
256 return true;
257 }
258 return false;
259 }
260
261
262// three choices
263// $params_array used to extract excluded namespaces for report
264// orphans = orph_report_table($data, true, false, $params_array);
265// wanted = orph_report_table($data, false, true), $params_array;
266// valid = orph_report_table($data, true, true, $params_array);
267
268
269 function orphan_pages($params_array) {
270 global $conf;
271 $result = '';
272 $data = array();
273 search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns));
274 $result .= $this->orph_report_table($data, true, false,$params_array);
275
276 return $result;
277 }
278
279 function wanted_pages($params_array) {
280 global $conf;
281 $result = '';
282 $data = array();
283 search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns));
284 $result .= $this->orph_report_table($data, false, true,$params_array);
285
286 return $result;
287 }
288
289 function valid_pages($params_array) {
290 global $conf;
291 $result = '';
292 $data = array();
293 search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns));
294 $result .= $this->orph_report_table($data, true, true, $params_array);
295
296 return $result;
297 }
298
299 function all_pages($params_array) {
300 global $conf;
301 $result = '';
302 $data = array();
303 search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns));
304
305 $result .= "</p><p>Orphans</p><p>";
306 $result .= $this->orph_report_table($data, true, false,$params_array);
307 $result .= "</p><p>Wanted</p><p>";
308 $result .= $this->orph_report_table($data, false, true,$params_array);
309 $result .= "</p><p>Valid</p><p>";
310 $result .= $this->orph_report_table($data, true, true, $params_array);
311
312
313 return $result;
314 }
315
316 function orph_report_table( $data, $page_exists, $has_links, $params_array )
317 {
318 global $conf;
319
320 $show_heading = ($page_exists && $conf['useheading']) ? true : false ;
321
322 //take off $params_array[0];
323 $exclude_array = array_slice($params_array,1);
324
325 $count = 1;
326 $output = '';
327
328 // for valid html - need to close the <p> that is feed before this
329 $output .= '</p>';
330 $output .= '<table class="inline"><tr><th> # </th><th> ID </th>'
331 . ($show_heading ? '<th>Title</th>' : '' )
332 . '<th>Links</th></tr>'
333 ."\n" ;
334
335 arsort($data);
336
337 foreach($data as $id=>$item)
338 {
339
340 if( ! (($item['exists'] == $page_exists) and (($item['links'] <> 0)== $has_links)) )
341 {
342 continue ;
343 }
344
345 // $id is a string, looks like this: page, namespace:page, or namespace:<subspaces>:page
346 $match_array = explode(":", $id);
347 //remove last item in array, the page identifier
348 $match_array = array_slice($match_array, 0, -1);
349 //put it back together
350 $page_namespace = implode (":", $match_array);
351 //add a trailing :
352 $page_namespace = $page_namespace . ':';
353
354 //set it to show, unless blocked by exclusion list
355 $show_it = true;
356 foreach ($exclude_array as $exclude_item)
357 {
358 //add a trailing : to each $item too
359 $exclude_item = $exclude_item . ":";
360 // need === to avoid boolean false
361 // strpos(haystack, needle)
362 // if exclusion is beginning of page's namespace , block it
363 if (strpos($page_namespace, $exclude_item) === 0){
364 //there is a match, so block it
365 $show_it = false;
366 }
367 }
368
369 if( $show_it )
370 {
371 $output .= "<tr><td>$count</td><td><a href=\"". wl($id)
372 . "\" class=\"" . ($page_exists ? "wikilink1" : "wikilink2")
373 . "\" onclick=\"return svchk()\" onkeypress=\"return svchk()\">"
374 . $id .'</a></td>'
375 . ($show_heading ? '<td>' . hsc(p_get_first_heading($id)) .'</td>' : '' )
376 . '<td>' . $item['links']
377 . ($has_links
378 ? "&nbsp;:&nbsp;<a href=\"". wl($id, 'do=backlink') ."\" class=\"wikilink1\">Show&nbsp;backlinks</a>"
379 : ''
380 )
381 . "</td></tr>\n";
382
383 $count++;
384 }
385
386 }
387
388 $output .= "</table>\n";
389 //for valid html = need to reopen a <p>
390 $output .= '<p>';
391
392 return $output;
393 }
394
395}
396
397//Setup VIM: ex: et ts=4 enc=utf-8 :
398?>
Note: See TracBrowser for help on using the repository browser.