on|off}} to enable/disable link-checking within the page.
if(!defined('DOKU_INC')) die();
require_once(DOKU_PLUGIN.'syntax.php');
require_once __DIR__.'/helperfunctions.php';
class syntax_plugin_linkcheck extends DokuWiki_Syntax_Plugin {
protected $helper;
public function __construct()
{
$this->helper = $this->loadHelper('linkcheck', false);
}
function getType(){ return 'substition'; }
function getPType(){ return 'normal'; }
function getSort(){ return 196; }
function connectTo($mode) {
$this->Lexer->addSpecialPattern('{{linkcheck>[^}]+}}',$mode,'plugin_linkcheck');
}
#$s is $R->doc that we are modifying.
function injectclassforlinks(&$doc,$urlmap,$otherurls){
#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.
if(strpos($doc,'urlextern')===false) return;
preg_match_all('#]*href="([^"]+)" [^>]*class="[^"]*\b(urlextern)\b[^"]*"#',$doc,$ums,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
if(!$ums) return;
if($this->helper->getusecache()){
$expirytime = $this->helper->getcacheexpirytime();
$otherurlmap=array_flip($otherurls);
for($j=sizeof($ums)-1; $j>=0; $j--){
$m=$ums[$j];
$url=$m[1][0];
$r=&$urlmap[$url];
#up-to-date urls are written javascript:LINKCHECKDATA variable. in action.php: ontplmetaheaderoutput().
#We handle them in javascript and update their class accordingly. no need to inject a class here.
#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.
if(isset($r)&&$r['lastcheck']>=$expirytime){
#msg("Skipping [ $url ], b/c it will be included in javascript variable LINKCHECKDATA ...");
}
#for others, inject the linkcheck class to trigger an ajax call in javascript.
elseif(isset($otherurlmap[$url])){
$doc=substr($doc,0,$m[2][1])."linkcheck ".substr($doc,$m[2][1]);
}
}
}
#when cache is not being used, we inject the linkcheck class to trigger an ajax call in javascript for all links.
else{
#$doc=preg_replace('#(]*href="[^"]+" [^>]*class="[^"]*)(\burlextern\b[^"]*")#','$1linkcheck $2',$doc);
#only inject for the urls that are in lincheck:on blocks.
for($j=sizeof($ums)-1; $j>=0; $j--){
$m=$ums[$j];
$url=$m[1][0];
if(isset($otherurlmap[$url])) $doc=substr($doc,0,$m[2][1])."linkcheck ".substr($doc,$m[2][1]);
}
}
}
#--------------------------------------------------------------
function render($mode, Doku_Renderer $R, $data) {
static $currentstate;
if(!isset($currentstate)) $currentstate=$this->getConf('enabledbydefault');
list($state,$data)=$data;
#these is the $urlmap injected by the action.php: onparserhandlerdone() function.
#this also marks the end of a page, so we go back and modify the externurl links in R->doc.
if(is_array($data)){
$id=$data[0]; #this would not be the same as the global $ID when this is a rendering of an include'd page.
$urlmap=$data[1];
$otherurls=$data[2];
if($mode=='metadata'){
#we may have multiple wiki pages being processed (sidebar, mainpage, etc.)
if(!isset($R->meta['linkcheck_urlmap'])) $R->meta['linkcheck_urlmap']=$urlmap;
else $R->meta['linkcheck_urlmap']=array_merge($R->meta['linkcheck_urlmap'],$urlmap);
}
elseif($mode=='xhtml'){
$this->injectclassforlinks($R->doc,$urlmap,$otherurls);
#restore the default state
$currentstate=$this->getConf('enabledbydefault');
}
}
elseif($mode=='xhtml'){
if($data=='on'||$data=='off'){
$currentstate=$data=='on';
}
else{
$R->info['cache'] = FALSE; #otherwise msg() will not work after the first call.
msg("Invalid linkcheck state: [".htmlspecialchars($data)."]. Must be 'on' or 'off'.");
$currentstate=$this->getConf('enabledbydefault');
}
}
return false;
}
#parse task, args, and options.
function handle($match, $state, $pos, Doku_Handler $handler)
{
preg_match('#{{linkcheck>([^}]+)}}#',$match,$m);
$data=trim($m[1]);
return [$state,$data];
}
}