1<?php 2# handle {{linkcheck>on|off}} to enable/disable link-checking within the page. 3if(!defined('DOKU_INC')) die(); 4require_once(DOKU_PLUGIN.'syntax.php'); 5require_once __DIR__.'/helperfunctions.php'; 6 7class syntax_plugin_linkcheck extends DokuWiki_Syntax_Plugin { 8 protected $helper; 9 public function __construct() 10 { 11 $this->helper = $this->loadHelper('linkcheck', false); 12 } 13 14 function getType(){ return 'substition'; } 15 function getPType(){ return 'normal'; } 16 function getSort(){ return 196; } 17 function connectTo($mode) { 18 $this->Lexer->addSpecialPattern('{{linkcheck>[^}]+}}',$mode,'plugin_linkcheck'); 19 } 20 21 #$s is $R->doc that we are modifying. 22function injectclassforlinks(&$doc,$urlmap,$otherurls){ 23 #We ignore the unlikely possibility that a url may appear in different linkcheck:on/off blocks. If a url appears in a linkcheck:on block, the same url will also be registered for linkcheck in other blocks. 24 if(strpos($doc,'urlextern')===false) return; 25 26 preg_match_all('#<a [^>]*href="([^"]+)" [^>]*class="[^"]*\b(urlextern)\b[^"]*"#',$doc,$ums,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); 27 if(!$ums) return; 28 29 if($this->helper->getusecache()){ 30 $expirytime = $this->helper->getcacheexpirytime(); 31 $otherurlmap=array_flip($otherurls); 32 33 for($j=sizeof($ums)-1; $j>=0; $j--){ 34 $m=$ums[$j]; 35 $url=$m[1][0]; 36 $r=&$urlmap[$url]; 37 38 #up-to-date urls are written javascript:LINKCHECKDATA variable. in action.php: ontplmetaheaderoutput(). 39 #We handle them in javascript and update their class accordingly. no need to inject a class here. 40 #CAVEAT: We get lastcheck/codegroup information during parse time, so we may not have the latest information here. For such cases, the link will be ajax-check in javascript. No big deal. If the page is edited/rendered again, the latest information will be available. 41 if(isset($r)&&$r['lastcheck']>=$expirytime){ 42 #msg("Skipping [ $url ], b/c it will be included in javascript variable LINKCHECKDATA ..."); 43 } 44 #for others, inject the linkcheck class to trigger an ajax call in javascript. 45 elseif(isset($otherurlmap[$url])){ 46 $doc=substr($doc,0,$m[2][1])."linkcheck ".substr($doc,$m[2][1]); 47 } 48 } 49 } 50 #when cache is not being used, we inject the linkcheck class to trigger an ajax call in javascript for all links. 51 else{ 52 #$doc=preg_replace('#(<a [^>]*href="[^"]+" [^>]*class="[^"]*)(\burlextern\b[^"]*")#','$1linkcheck $2',$doc); 53 #only inject for the urls that are in lincheck:on blocks. 54 for($j=sizeof($ums)-1; $j>=0; $j--){ 55 $m=$ums[$j]; 56 $url=$m[1][0]; 57 if(isset($otherurlmap[$url])) $doc=substr($doc,0,$m[2][1])."linkcheck ".substr($doc,$m[2][1]); 58 } 59 } 60} 61 62 #-------------------------------------------------------------- 63 function render($mode, Doku_Renderer $R, $data) { 64 static $currentstate; 65 if(!isset($currentstate)) $currentstate=$this->getConf('enabledbydefault'); 66 list($state,$data)=$data; 67 68 #these is the $urlmap injected by the action.php: onparserhandlerdone() function. 69 #this also marks the end of a page, so we go back and modify the externurl links in R->doc. 70 if(is_array($data)){ 71 $id=$data[0]; #this would not be the same as the global $ID when this is a rendering of an include'd page. 72 $urlmap=$data[1]; 73 $otherurls=$data[2]; 74 if($mode=='metadata'){ 75 #we may have multiple wiki pages being processed (sidebar, mainpage, etc.) 76 if(!isset($R->meta['linkcheck_urlmap'])) $R->meta['linkcheck_urlmap']=$urlmap; 77 else $R->meta['linkcheck_urlmap']=array_merge($R->meta['linkcheck_urlmap'],$urlmap); 78 } 79 elseif($mode=='xhtml'){ 80 $this->injectclassforlinks($R->doc,$urlmap,$otherurls); 81 #restore the default state 82 $currentstate=$this->getConf('enabledbydefault'); 83 } 84 } 85 elseif($mode=='xhtml'){ 86 if($data=='on'||$data=='off'){ 87 $currentstate=$data=='on'; 88 } 89 else{ 90 $R->info['cache'] = FALSE; #otherwise msg() will not work after the first call. 91 msg("Invalid linkcheck state: [".htmlspecialchars($data)."]. Must be 'on' or 'off'."); 92 $currentstate=$this->getConf('enabledbydefault'); 93 } 94 } 95 return false; 96 } 97 98 #parse task, args, and options. 99 function handle($match, $state, $pos, Doku_Handler $handler) 100 { 101 preg_match('#{{linkcheck>([^}]+)}}#',$match,$m); 102 $data=trim($m[1]); 103 return [$state,$data]; 104 } 105} 106