00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00033 class ilLinkChecker
00034 {
00035 var $db = null;
00036 var $log_messages = array();
00037 var $invalid_links = array();
00038
00039 var $validate_all = true;
00040 var $mail_status = false;
00041 var $page_id = 0;
00042
00043
00044 function ilLinkChecker(&$db,$a_validate_all = true)
00045 {
00046 global $ilDB;
00047
00048 define('DEBUG',1);
00049 define('SOCKET_TIMEOUT',5);
00050
00051 $this->db =& $db;
00052
00053
00054 $ilDB =& $db;
00055
00056 $this->validate_all = $a_validate_all;
00057 }
00058
00059 function setCheckPeriod($a_period)
00060 {
00061 $this->period = $a_period;
00062 }
00063 function getCheckPeriod()
00064 {
00065 return $this->period;
00066 }
00067
00068 function setMailStatus($a_status)
00069 {
00070 $this->mail_status = (bool) $a_status;
00071 }
00072 function getMailStatus()
00073 {
00074 return (bool) $this->mail_status;
00075 }
00076
00077 function __setType($a_type)
00078 {
00079 $this->type = $a_type;
00080 }
00081 function __getType()
00082 {
00083 return $this->type;
00084 }
00085
00086 function setObjId($a_page_id)
00087 {
00088 return $this->page_id = $a_page_id;
00089 }
00090 function getObjId()
00091 {
00092 return $this->page_id;
00093 }
00094
00095 function getValidateAll()
00096 {
00097 return $this->validate_all ? true : false;
00098 }
00099
00100 function getLogMessages()
00101 {
00102 return $this->log_messages ? $this->log_messages : array();
00103 }
00104
00105 function getInvalidLinks()
00106 {
00107 return $this->invalid_links ? $this->invalid_links : array();
00108 }
00109
00110 function getInvalidLinksFromDB()
00111 {
00112 $query = "SELECT * FROM link_check ".
00113 "WHERE obj_id = '".$this->getObjId()."'";
00114
00115 $res = $this->db->query($query);
00116 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00117 {
00118 $invalid[] = array('page_id' => $row->page_id,
00119 'url' => $row->url);
00120 }
00121
00122 return $invalid ? $invalid : array();
00123 }
00124
00125 function getLastCheckTimestamp()
00126 {
00127 if($this->getValidateAll())
00128 {
00129 $query = "SELECT MAX(last_check) as last_check FROM link_check ";
00130 }
00131 else
00132 {
00133 $query = "SELECT MAX(last_check) as last_check FROM link_check ".
00134 "WHERE obj_id = '".$this->getObjId()."'";
00135 }
00136 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00137
00138 return $row->last_check ? $row->last_check : 0;
00139 }
00140
00141 function checkWebResourceLinks()
00142 {
00143 $pages = array();
00144
00145 $this->__setType('webr');
00146 $this->__clearLogMessages();
00147 $this->__clearInvalidLinks();
00148 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
00149
00150 if(count($invalid = $this->__validateLinks($this->__getWebResourceLinks())))
00151 {
00152 foreach($invalid as $invalid_item)
00153 {
00154 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
00155 $this->__appendInvalidLink($invalid_item);
00156 }
00157 }
00158
00159 $this->__appendLogMessage('LinkChecker: End checkLinks()');
00160 $this->__saveInDB();
00161
00162 $this->__sendMail();
00163
00164 return $this->getInvalidLinks();
00165 }
00166
00167 function checkLinks()
00168 {
00169 $pages = array();
00170
00171 $this->__setType('lm');
00172 $this->__clearLogMessages();
00173 $this->__clearInvalidLinks();
00174 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
00175
00176 if(!$this->getValidateAll() and !$this->getObjId())
00177 {
00178 echo "ilLinkChecker::checkLinks() No Page id given";
00179
00180 return false;
00181 }
00182 elseif(!$this->getValidateAll() and $this->getObjId())
00183 {
00184 $query = "SELECT * FROM page_object ".
00185 "WHERE parent_id = '".$this->getObjId()."' ".
00186 "AND parent_type = 'lm'";
00187
00188 $res = $this->db->query($query);
00189 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00190 {
00191 $pages[] = array('page_id' => $row->page_id,
00192 'content' => $row->content,
00193 'type' => $row->parent_type);
00194 }
00195 }
00196 elseif($this->getValidateAll())
00197 {
00198 $query = "SELECT * FROM page_object ".
00199 "WHERE parent_type = 'lm'";
00200
00201 $res = $this->db->query($query);
00202 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00203 {
00204 $pages[] = array('page_id' => $row->page_id,
00205 'content' => $row->content,
00206 'type' => $row->parent_type);
00207 }
00208 }
00209
00210
00211 foreach($pages as $page)
00212 {
00213 if(count($invalid = $this->__validateLinks($this->__getLinks($page))))
00214 {
00215 foreach($invalid as $invalid_item)
00216 {
00217 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
00218 $this->__appendInvalidLink($invalid_item);
00219 }
00220 }
00221 }
00222
00223 $this->__appendLogMessage('LinkChecker: End checkLinks()');
00224 $this->__saveInDB();
00225
00226 $this->__sendMail();
00227
00228 return $this->getInvalidLinks();
00229 }
00230
00231 function checkPear()
00232 {
00233 if(!@include_once('HTTP/Request.php'))
00234 {
00235 return false;
00236 }
00237 return true;
00238 }
00239
00240
00241
00242 function __txt($language,$key,$module = 'common')
00243 {
00244 $query = "SELECT value FROM lng_data ".
00245 "WHERE module = '".$module."' ".
00246 "AND identifier = '".$key."' ".
00247 "AND lang_key = '".$language."'";
00248
00249 $res = $this->db->query($query);
00250 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00251 {
00252 $value = $row->value;
00253 }
00254 if(!$value)
00255 {
00256 $query = "SELECT value FROM lng_data ".
00257 "WHERE module = '".$module."' ".
00258 "AND identifier = '".$key."' ".
00259 "AND lang_key = 'en'";
00260
00261 $res = $this->db->query($query);
00262 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00263 {
00264 $value = $row->value;
00265 }
00266 }
00267 return $value ? $value : '-'.$key.'-';
00268 }
00269
00270 function __fetchUserData($a_usr_id)
00271 {
00272 $query = "SELECT email FROM usr_data WHERE usr_id = '".$a_usr_id."'";
00273
00274 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00275
00276 $data['email'] = $row->email;
00277
00278 $query = "SELECT * FROM usr_pref ".
00279 "WHERE usr_id = '".$a_usr_id."' ".
00280 "AND keyword = 'language'";
00281
00282 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00283
00284 $data['lang'] = $row->value;
00285
00286 return $data;
00287 }
00288
00289 function __getTitle($a_lm_obj_id)
00290 {
00291 $query = "SELECT title FROM object_data ".
00292 "WHERE obj_id = '".$a_lm_obj_id."'";
00293
00294 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00295
00296 return $row->title;
00297 }
00298
00299 function __sendMail()
00300 {
00301 global $ilUser;
00302
00303
00304 if(!count($notify = $this->__getNotifyLinks()))
00305 {
00306
00307 return true;
00308 }
00309 if(!$this->getMailStatus())
00310 {
00311 return true;
00312 }
00313
00314 include_once './classes/class.ilLinkCheckNotify.php';
00315
00316 foreach(ilLinkCheckNotify::_getAllNotifiers($this->db) as $usr_id => $obj_ids)
00317 {
00318 if(!is_object($tmp_user =& ilObjectFactory::getInstanceByObjId($usr_id,false)))
00319 {
00320 $this->__appendLogMessage('LinkChecker: Cannot find user with id: '.$usr_id);
00321 continue;
00322 }
00323
00324 $counter = 0;
00325 foreach($obj_ids as $obj_id)
00326 {
00327 if(!isset($notify[$obj_id]))
00328 {
00329 continue;
00330 }
00331 ++$counter;
00332
00333 switch($this->__getType())
00334 {
00335 case 'webr':
00336 $body .= $this->__txt($tmp_user->getLanguage(),'obj_webr');
00337 break;
00338
00339 case 'lm':
00340 default:
00341 $body .= $this->__txt($tmp_user->getLanguage(),'lo');
00342 break;
00343 }
00344
00345 $body .= ': ';
00346 $body .= $this->__getTitle($obj_id)."\r\n";
00347
00348
00349 foreach($notify[$obj_id] as $data)
00350 {
00351 $body .= $data['url']."\r\n";
00352 }
00353 $body .= "\r\n";
00354 }
00355 if($counter)
00356 {
00357 include_once "classes/class.ilFormatMail.php";
00358
00359 $umail = new ilFormatMail($tmp_user->getId());
00360 $subject = $this->__txt($tmp_user->getLanguage(),'link_check_subject');
00361 }
00362
00363 $umail->sendMail($tmp_user->getLogin(),"","",$subject,$body,array(),array("normal"));
00364 $this->__appendLogMessage('LinkChecker: Sent mail to '.$tmp_user->getEmail());
00365 }
00366
00367
00368 }
00369
00370 function __getNotifyLinks()
00371 {
00372 return $this->notify ? $this->notify : array();
00373 }
00374
00375
00376 function __clearInvalidLinks()
00377 {
00378 $this->invalid_links = array();
00379 }
00380 function __appendInvalidLink($a_link)
00381 {
00382 $this->invalid_links[] = $a_link;
00383 }
00384
00385
00386 function __appendLogMessage($a_string)
00387 {
00388 $this->log_messages[] = $a_string;
00389 }
00390 function __clearLogMessages()
00391 {
00392 return $this->log_messages = array();
00393 }
00394
00395 function __getLinks($a_page)
00396 {
00397 $matches = array();
00398
00399 $pattern_complete = '/<ExtLink Href="([^"]*)">/';
00400 if(preg_match_all($pattern_complete,$a_page['content'],$matches))
00401 {
00402 for($i = 0;$i < count($matches[0]); ++$i)
00403 {
00404 $url_data = parse_url($matches[1][$i]);
00405
00406
00407 if(!$url_data['scheme'])
00408 {
00409 $matches[1][$i] = 'http://'.$matches[1][$i];
00410 }
00411
00412 $lm_id = $this->__getObjIdByPageId($a_page['page_id']);
00413 $link[] = array('page_id' => $a_page['page_id'],
00414 'obj_id' => $lm_id,
00415 'type' => $a_page['type'],
00416 'complete' => $matches[1][$i],
00417 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
00418 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
00419 }
00420 }
00421
00422 return $link ? $link : array();
00423 }
00424
00425 function __getWebResourceLinks()
00426 {
00427 include_once 'link/classes/class.ilLinkResourceItems.php';
00428
00429 $link_res_obj = new ilLinkResourceItems($this->getObjId());
00430
00431 foreach($check_links = $link_res_obj->getCheckItems($this->getCheckPeriod()) as $item_data)
00432 {
00433 $url_data = parse_url($item_data['target']);
00434
00435
00436 if(!$url_data['scheme'])
00437 {
00438 $item_data['target'] = 'http://'.$item_data['target'];
00439 }
00440
00441 $link[] = array('page_id' => $item_data['link_id'],
00442 'obj_id' => $this->getObjId(),
00443 'type' => 'webr',
00444 'complete' => $item_data['target'],
00445 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
00446 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
00447 }
00448 return $link ? $link : array();
00449 }
00450
00451
00452
00453 function __validateLinks($a_links)
00454 {
00455 if(!@include_once('HTTP/Request.php'))
00456 {
00457 $this->__appendLogMessage('LinkChecker: Pear HTTP_Request is not installed. Aborting');
00458
00459 return array();
00460 }
00461
00462 foreach($a_links as $link)
00463 {
00464 if(gethostbyname($link['host']) == $link['host'])
00465 {
00466 $invalid[] = $link;
00467 continue;
00468 }
00469
00470 if($link['scheme'] !== 'http' and $link['scheme'] !== 'https')
00471 {
00472 continue;
00473 }
00474
00475 $req =& new HTTP_Request($link['complete']);
00476 $req->sendRequest();
00477
00478 switch($req->getResponseCode())
00479 {
00480
00481 case '200':
00482
00483 case '301':
00484 case '302':
00485 break;
00486
00487 default:
00488 $link['http_status_code'] = $req->getResponseCode();
00489 $invalid[] = $link;
00490 break;
00491 }
00492 }
00493 return $invalid ? $invalid : array();
00494 }
00495
00496 function __getObjIdByPageId($a_page_id)
00497 {
00498 $query = "SELECT lm_id FROM lm_data ".
00499 "WHERE obj_id = '".$a_page_id."'";
00500
00501 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00502
00503 return $row->lm_id ? $row->lm_id : 0;
00504 }
00505
00506 function __isInvalid($a_page_id, $a_url)
00507 {
00508 foreach($this->getInvalidLinks() as $link)
00509 {
00510 if($link['page_id'] == $a_page_id and
00511 substr($link['complete'],0,255) == $a_url)
00512 {
00513 return true;
00514 }
00515 }
00516 return false;
00517 }
00518
00519 function __saveInDB()
00520 {
00521 if($this->getMailStatus())
00522 {
00523 $this->__checkNotify();
00524 }
00525 $this->__clearDBData();
00526
00527
00528 foreach($this->getInvalidLinks() as $link)
00529 {
00530
00531 $query = "INSERT INTO link_check ".
00532 "SET page_id = '".$link['page_id']."', ".
00533 "obj_id = '".$link['obj_id']."', ".
00534 "url = '".substr($link['complete'],0,255)."', ".
00535 "parent_type = '".$link['type']."', ".
00536 "http_status_code = '".$link['http_status_code']."', ".
00537 "last_check = '".time()."'";
00538
00539
00540 $res = $this->db->query($query);
00541 }
00542
00543
00544
00545 }
00546
00547 function __checkNotify()
00548 {
00549 foreach($this->getInvalidLinks() as $link)
00550 {
00551 $query = "SELECT * FROM link_check ".
00552 "WHERE page_id = '".$link['page_id']."' ".
00553 "AND url = '".substr($link['complete'],0,255)."'";
00554 $res = $this->db->query($query);
00555
00556 if(!$res->numRows())
00557 {
00558 $this->notify["$link[obj_id]"][] = array('page_id' => $link['page_id'],
00559 'url' => $link['complete']);
00560 }
00561 }
00562 }
00563
00564
00565 function __clearDBData()
00566 {
00567 if($this->getValidateAll())
00568 {
00569 $query = "DELETE FROM link_check";
00570 }
00571 else
00572 {
00573 $query = "DELETE FROM link_check ".
00574 "WHERE obj_id = '".$this->getObjId()."'";
00575 }
00576
00577 $this->db->query($query);
00578
00579 return true;
00580 }
00581 }
00582 ?>