1<?php
2if(!defined('DOKU_INC')) die();
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
4require_once DOKU_PLUGIN.'action.php';
5require_once __DIR__.'/helperfunctions.php';
6
7class action_plugin_linkcheck extends DokuWiki_Action_Plugin {
8protected $helper;
9public function __construct()
10{
11    $this->helper = $this->loadHelper('linkcheck', false);
12}
13
14
15  function getInfo(){ return conf_loadfile(dirname(__FILE__).'/plugin.info.txt'); }
16  function register($contr){
17    $contr->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'onajaxcallunknown');
18    $contr->register_hook('PARSER_HANDLER_DONE', 'BEFORE', $this, 'onparserhandlerdone');
19    $contr->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'ontplmetaheaderoutput');
20
21    global $JSINFO;
22    if($this->getConf('jqueryselector')){
23        $JSINFO['linkcheck_selector']=$this->getConf('jqueryselector');
24    }
25}
26
27
28function onajaxcallunknown(Doku_Event $ev, $param) {
29    if($ev->data != 'linkcheck') return;
30    $url=$_REQUEST['url'];
31    if(!$url){
32        $r=['code'=>500,'codegroup'=>'error','msg'=>'url parameter missing'];
33         echo json_encode($r);
34         $ev->preventDefault();
35         return;
36    }
37    $code=$this->helper->checkurl($url,$o);
38
39    $r=['code'=>is_array($code)?$code[0]:$code];
40    if(is_array($code)) $r['msg']=$code[1];
41    else $r['msg']=linkcheck_code2msg($r['code']);
42    $r['codegroup']=linkcheck_code2group($r['code']);
43    echo json_encode($r);
44    $ev->preventDefault();
45}
46#collect links and store them in db. Inject a plugin linkcheck entry to the parser calls to trigger it to use the syntax.php handler, which will update the page meta data.
47function onparserhandlerdone(Doku_Event $ev, $param) {
48    $currentstate=$this->getConf('enabledbydefault');
49    $urls=[];
50    foreach($ev->data->calls as $i=>$e){
51        #ve($e);
52        if($e[0]=='plugin' && $e[1][0]=='linkcheck'){
53            $newstate=$e[1][1][1];
54            if($newstate=='on' || $newstate=='off'){
55                $currentstate=$newstate=='on';
56            }
57            #else ignore the new state.
58        }
59        elseif($e[0]=='externallink' && $currentstate){
60            $urls[]=$e[1][0];
61        }
62    }
63    global $ID;
64    $urlmap=$this->helper->getusecache()?$this->helper->getcachedata($ID,$urls):[];
65    if($urls){
66        #in the syntax handler, global $ID is no longer true for included pages. so, we need to save the ID within the parser entries.
67        $e=['plugin',['linkcheck',[5,[$ID,$urlmap,array_diff($urls,array_keys($urlmap))]],5,''],3]; #copied the structure by examining the $e variable for plugin linkcheck above.
68        #ve($e);
69        $ev->data->calls[]=$e;
70    }
71}
72function ontplmetaheaderoutput(Doku_Event $ev, $param) {
73    global $INFO;
74    $urlmap=$INFO['meta']['linkcheck_urlmap']??[];
75    if(!$urlmap) return;
76    #in javascript, we'll only need the url=>codegroup mapping for up to date entries.
77    $expirytime = $this->helper->getcacheexpirytime();
78    $urlmap=array_filter($urlmap,function($r) use($expirytime){return $r['lastcheck']>=$expirytime;});
79    foreach($urlmap as $url=>&$r){
80       unset($r['lastcheck']);
81       unset($r['pages']);
82       $r=$r['codegroup'];
83    }unset($r);
84
85    if(!$urlmap) return;
86    $s="var LINKCHECKDATA=".json_encode($urlmap).";\n";
87    #$s.="console.log(LINKCHECKDATA);";
88
89    $ev->data['script'][] = array(
90        'type'    => 'text/javascript',
91     // 'charset' => 'utf-8',
92        '_data'   => $s,
93    );
94}
95
96
97}
98