1<?php 2 3use dokuwiki\Extension\AuthPlugin; 4use dokuwiki\HTTP\DokuHTTPClient; 5use dokuwiki\Extension\Event; 6require_once __DIR__.'/helperfunctions.php'; 7 8 9class helper_plugin_linkcheck extends Dokuwiki_Plugin 10{ 11 private $dbfile=null; #use getdbfile() to access this. 12 private $db=null; #use getdb() to access this. 13 private $cacheexpirytime=null; #use getcacheexpirytime() to access this. 14 private $cacertfile=null; #use getcacertfile(). a file is only set if the autodownloadcacert is ON. 15 private $cacertfileexpirytime=null; #use getcacertfileexpirytime() to access this. 16 private $usecache=null; #use usecache() to access this. 17 18 public function __construct(){ 19 $this->usecache = $this->getConf('usecache'); 20 if($this->usecache && !class_exists('SQLite3',false)){ 21 msg('linkcheck:usecache option is enabled but SQLite3 is not available. Disabling cache...'); 22 $this->usecache=false; 23 } 24 } 25 function getusecache(){ 26 return $this->usecache; 27 } 28 function getdbfile(){ 29 if(!isset($this->dbfile)){ 30 if($this->getusecache()) $this->dbfile = metaFN('linkcheck_cache','.sqlite'); 31 else $this->dbfile=false; 32 } 33 return $this->dbfile; 34 } 35 function getcacertfile(){ 36 if(!isset($this->cacertfile)){ 37 if($this->getConf('autodownloadcacert')) $this->cacertfile = metaFN('linkcheck_cacert','.pem'); 38 else $this->cacertfile=false; 39 } 40 return $this->cacertfile; 41 } 42 function getcacertfileexpirytime(){ 43 if(!isset($this->cacertfileexpirytime)){ 44 $this->cacertfileexpirytime=expiry_totime($this->getConf('cacertfileexpiry')); 45 } 46 return $this->cacertfileexpirytime; 47 } 48 49 function &getdb(){ 50 if(!isset($this->db)){ 51 if($file=$this->getdbfile()) $this->db=linkcheck_db($file); 52 else $this->db=false; 53 } 54 return $this->db; 55 } 56 function getcacheexpirytime(){ 57 if(!isset($this->cacheexpirytime)){ 58 $this->cacheexpirytime=expiry_totime($this->getConf('cacheexpiry')); 59 } 60 return $this->cacheexpirytime; 61 } 62 function checkurl($url){ 63 if($this->getusecache()){ 64 $o=[ 65 'dbfile'=>$this->getdbfile(), 66 'cacheexpirytime'=>$this->getcacheexpirytime(), 67 'requireexists'=>$this->getConf('requireexists'), 68 'cacertfile'=>$this->getcacertfile(), 69 'cacertfileexpirytime'=>$this->getcacertfileexpirytime(), 70 ]; 71 return linkcheck_checkurl_withcache($url,$o); 72 } 73 else{ 74 $o=[ 75 'cacertfile'=>$this->getcacertfile(), 76 'cacertfileexpirytime'=>$this->getcacertfileexpirytime(), 77 ]; 78 return linkcheck_checkurl($url,$o); 79 80 } 81 } 82 function getcachedata($id,$urls){ 83 $db=&$this->getdb(); 84 $urlmap=[]; 85 86 #first query: more efficient: get all urls with pages=$id 87 $id_=$db->escapeString($id); 88 $query="SELECT url,codegroup,lastcheck FROM linkcheck_cache WHERE pages='$id_' OR pages LIKE '$id_,%' OR pages LIKE '%,$id_' OR pages LIKE '%,$id_,%'"; 89 foreach(linkcheck_db_query($db,$query) as $row){ 90 $url=$row['url']; unset($row['url']); 91 $urlmap[$url]=$row; 92 } 93 94 #delete any pageurls that no longer appear for $id 95 if($deleteurls = array_diff(array_keys($urlmap),$urls)){ 96 #msg("Deleting urls: ".implode(',',$deleteurls)); 97 $urls_=array_map([$db,'escapeString'],$deleteurls); 98 $urls_=array_map(function($url){return "'$url'";},$urls_); 99 #delete the urls that are only for this page. 100 $query="DELETE FROM linkcheck_cache WHERE pages='$id_' AND url IN (".implode(',',$urls_).")"; 101 $db->exec($query); 102 103 #for urls that are shared with other pages, just empty the pages value (for efficiency, we won't try to individually remove id from each of these rows). 104 $query="UPDATE linkcheck_cache SET pages='' WHERE url IN (".implode(',',$urls_).")"; 105 $db->exec($query); 106 } 107 108 #second query: get remaining urls that have previously not been registered for this $id. 109 if($newurls=array_diff($urls,array_keys($urlmap))){ 110 $urls_=array_map([$db,'escapeString'],$newurls); 111 $urls_=array_map(function($url){return "'$url'";},$urls_); 112 $query="SELECT url,codegroup,lastcheck,pages FROM linkcheck_cache WHERE url IN (".implode(',',$urls_).")"; 113 foreach(linkcheck_db_query($db,$query) as $row){ 114 $url=$row['url']; unset($row['url']); 115 $urlmap[$url]=$row; 116 } 117 } 118 119 if(!$newurls){ 120 #msg("No new urls to insert or update."); 121 return $urlmap; 122 } 123 #insert urls that are not in the cache. update pages if the current $id not in pages column. 124 #insert should be enough, but to account for simultaneous requests, we keep "ignore into" 125 $insertstmt = $db->prepare("INSERT OR IGNORE INTO linkcheck_cache(url,pages) VALUES (:url,:pages)"); 126 $updatestmt = $db->prepare("UPDATE linkcheck_cache SET pages=:pages WHERE url=:url"); 127 foreach($newurls as $url){ 128 if(!isset($urlmap[$url])){ 129 #msg("Inserting new url [ $url ] for page [ $id ]..."); 130 $insertstmt->bindValue(':url', $url, SQLITE3_TEXT); 131 $insertstmt->bindValue(':pages',$id, SQLITE3_TEXT); 132 $insertstmt->execute(); 133 } 134 #elseif($urlmap[$url]['pages']!=$id && !in_array($id,explode(',',$urlmap[$url]['pages']))){ 135 else{ 136 #msg("Registering existing url [ $url ] for page [ $id ]..."); 137 $updatestmt->bindValue(':url', $url, SQLITE3_TEXT); 138 $updatestmt->bindValue(':pages', $urlmap[$url]['pages'].','.$id, SQLITE3_TEXT); 139 $updatestmt->execute(); 140 } 141 } 142 return $urlmap; 143 } 144} 145