ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilLinkChecker.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
13 {
14  var $db = null;
15  var $log_messages = array();
16  var $invalid_links = array();
17 
18  var $validate_all = true;
19  var $mail_status = false;
20  var $page_id = 0;
21 
22 
23  function ilLinkChecker(&$db,$a_validate_all = true)
24  {
25  global $ilDB;
26 
27  define('DEBUG',1);
28  define('SOCKET_TIMEOUT',5);
29 
30  $this->db =& $db;
31 
32  // SET GLOBAL DB HANDLER FOR STATIC METHODS OTHER CLASSES
33  $ilDB =& $db;
34 
35  $this->validate_all = $a_validate_all;
36  }
37 
38  function setCheckPeriod($a_period)
39  {
40  $this->period = $a_period;
41  }
42  function getCheckPeriod()
43  {
44  return $this->period;
45  }
46 
47  function setMailStatus($a_status)
48  {
49  $this->mail_status = (bool) $a_status;
50  }
51  function getMailStatus()
52  {
53  return (bool) $this->mail_status;
54  }
55 
56  function __setType($a_type)
57  {
58  $this->type = $a_type;
59  }
60  function __getType()
61  {
62  return $this->type;
63  }
64 
65  function setObjId($a_page_id)
66  {
67  return $this->page_id = $a_page_id;
68  }
69  function getObjId()
70  {
71  return $this->page_id;
72  }
73 
74  function getValidateAll()
75  {
76  return $this->validate_all ? true : false;
77  }
78 
79  function getLogMessages()
80  {
81  return $this->log_messages ? $this->log_messages : array();
82  }
83 
84  function getInvalidLinks()
85  {
86  return $this->invalid_links ? $this->invalid_links : array();
87  }
88 
90  {
91  global $ilDB;
92 
93  $query = "SELECT * FROM link_check ".
94  "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer')." ";
95 
96  $res = $this->db->query($query);
97  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
98  {
99  $invalid[] = array('page_id' => $row->page_id,
100  'url' => $row->url);
101  }
102 
103  return $invalid ? $invalid : array();
104  }
105 
107  {
108  global $ilDB;
109 
110  if($this->getValidateAll())
111  {
112  $query = "SELECT MAX(last_check) last_check FROM link_check ";
113  }
114  else
115  {
116  $query = "SELECT MAX(last_check) last_check FROM link_check ".
117  "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer')." ";
118  }
119  $res = $ilDB->query($query);
120  $row = $ilDB->fetchObject($res);
121 
122  return $row->last_check ? $row->last_check : 0;
123  }
124 
126  {
127  $pages = array();
128 
129  $this->__setType('webr');
130  $this->__clearLogMessages();
131  $this->__clearInvalidLinks();
132  $this->__appendLogMessage('LinkChecker: Start checkLinks()');
133 
134  if(count($invalid = $this->__validateLinks($this->__getWebResourceLinks())))
135  {
136  foreach($invalid as $invalid_item)
137  {
138  $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
139  $this->__appendInvalidLink($invalid_item);
140  }
141  }
142 
143  $this->__appendLogMessage('LinkChecker: End checkLinks()');
144  $this->__saveInDB();
145 
146  $this->__sendMail();
147 
148  return $this->getInvalidLinks();
149  }
150 
151  function checkLinks()
152  {
153  global $ilDB;
154 
155  $pages = array();
156 
157  $this->__setType('lm');
158  $this->__clearLogMessages();
159  $this->__clearInvalidLinks();
160  $this->__appendLogMessage('LinkChecker: Start checkLinks()');
161 
162  if(!$this->getValidateAll() and !$this->getObjId())
163  {
164  echo "ilLinkChecker::checkLinks() No Page id given";
165 
166  return false;
167  }
168  elseif(!$this->getValidateAll() and $this->getObjId())
169  {
170  $query = "SELECT * FROM page_object ".
171  "WHERE parent_id = ".$ilDB->quote($this->getObjId())." ".
172  "AND parent_type = 'lm'";
173 
174  $res = $this->db->query($query);
175  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
176  {
177  $pages[] = array('page_id' => $row->page_id,
178  'content' => $row->content,
179  'type' => $row->parent_type);
180  }
181  }
182  elseif($this->getValidateAll())
183  {
184  $query = "SELECT * FROM page_object ".
185  "WHERE parent_type = 'lm'";
186 
187  $res = $this->db->query($query);
188  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
189  {
190  $pages[] = array('page_id' => $row->page_id,
191  'content' => $row->content,
192  'type' => $row->parent_type);
193  }
194  }
195 
196  // VALIDATE
197  foreach($pages as $page)
198  {
199  if(count($invalid = $this->__validateLinks($this->__getLinks($page))))
200  {
201  foreach($invalid as $invalid_item)
202  {
203  $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
204  $this->__appendInvalidLink($invalid_item);
205  }
206  }
207  }
208 
209  $this->__appendLogMessage('LinkChecker: End checkLinks()');
210  $this->__saveInDB();
211 
212  $this->__sendMail();
213 
214  return $this->getInvalidLinks();
215  }
216 
217  function checkPear()
218  {
219  if(!@include_once('HTTP/Request.php'))
220  {
221  return false;
222  }
223  return true;
224  }
225 
226 
227  // PRIVATE
228  function __txt($language,$key,$module = 'common')
229  {
230  global $ilDB;
231 
232  include_once './Services/Language/classes/class.ilLanguage.php';
233  return ilLanguage::_lookupEntry($language, $module, $key);
234  }
235 
236  function __fetchUserData($a_usr_id)
237  {
238  global $ilDB;
239 
240  $query = "SELECT email FROM usr_data WHERE usr_id = ".$ilDB->quote($a_usr_id)."";
241 
242  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
243 
244  $data['email'] = $row->email;
245 
246  $set = $ilDB->query("SELECT * FROM usr_pref ".
247  "WHERE usr_id = ".$ilDB->quote($a_usr_id, "integer")." ".
248  "AND keyword = ".$ilDB->quote('language', "text"));
249 
250  $row = $ilDB->fetchObject($set);
251 
252  $data['lang'] = $row->value;
253 
254  return $data;
255  }
256 
257  function __getTitle($a_lm_obj_id)
258  {
259  global $ilDB;
260 
261  $query = "SELECT title FROM object_data ".
262  "WHERE obj_id = ".$ilDB->quote($a_lm_obj_id ,'integer')." ";
263 
264  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
265 
266  return $row->title;
267  }
268 
269  function __sendMail()
270  {
271  global $ilUser;
272 
273 
274  if(!count($notify = $this->__getNotifyLinks()))
275  {
276  // Nothing to do
277  return true;
278  }
279  if(!$this->getMailStatus())
280  {
281  return true;
282  }
283 
284  include_once './classes/class.ilLinkCheckNotify.php';
285 
286  foreach(ilLinkCheckNotify::_getAllNotifiers($this->db) as $usr_id => $obj_ids)
287  {
288  if(!is_object($tmp_user =& ilObjectFactory::getInstanceByObjId($usr_id,false)))
289  {
290  $this->__appendLogMessage('LinkChecker: Cannot find user with id: '.$usr_id);
291  continue;
292  }
293 
294  $counter = 0;
295  foreach($obj_ids as $obj_id)
296  {
297  if(!isset($notify[$obj_id]))
298  {
299  continue;
300  }
301  ++$counter;
302 
303  switch($this->__getType())
304  {
305  case 'webr':
306  $body .= $this->__txt($tmp_user->getLanguage(),'obj_webr');
307  break;
308 
309  case 'lm':
310  default:
311  $body .= $this->__txt($tmp_user->getLanguage(),'lo');
312  break;
313  }
314 
315  $body .= ': ';
316  $body .= $this->__getTitle($obj_id)."\r\n";
317 
318  // Print all invalid
319  foreach($notify[$obj_id] as $data)
320  {
321  $body .= $data['url']."\r\n";
322  }
323  $body .= "\r\n";
324  }
325  if($counter)
326  {
327  include_once "Services/Mail/classes/class.ilFormatMail.php";
328 
329  $umail = new ilFormatMail($tmp_user->getId());
330  $subject = $this->__txt($tmp_user->getLanguage(),'link_check_subject');
331 
332  $umail->sendMail($tmp_user->getLogin(),"","",$subject,$body,array(),array("normal"));
333  $this->__appendLogMessage('LinkChecker: Sent mail to '.$tmp_user->getEmail());
334  }
335 
336  }
337 
338 
339  }
340 
341  function __getNotifyLinks()
342  {
343  return $this->notify ? $this->notify : array();
344  }
345 
346 
348  {
349  $this->invalid_links = array();
350  }
351  function __appendInvalidLink($a_link)
352  {
353  $this->invalid_links[] = $a_link;
354  }
355 
356 
357  function __appendLogMessage($a_string)
358  {
359  $this->log_messages[] = $a_string;
360  }
362  {
363  return $this->log_messages = array();
364  }
365 
366  function __getLinks($a_page)
367  {
368  $matches = array();
369 
370  $pattern_complete = '/<ExtLink Href="([^"]*)">/';
371  if(preg_match_all($pattern_complete,$a_page['content'],$matches))
372  {
373  for($i = 0;$i < count($matches[0]); ++$i)
374  {
375  $url_data = @parse_url($matches[1][$i]);
376  // continue if mailto link
377  if($url_data['scheme'] == 'mailto')
378  {
379  continue;
380  }
381 
382  // PUH, HTTP_REQUEST needs a beginning http://
383  if(!$url_data['scheme'])
384  {
385  $matches[1][$i] = 'http://'.$matches[1][$i];
386  }
387 
388  $lm_id = $this->__getObjIdByPageId($a_page['page_id']);
389  $link[] = array('page_id' => $a_page['page_id'],
390  'obj_id' => $lm_id,
391  'type' => $a_page['type'],
392  'complete' => $matches[1][$i],
393  'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
394  'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
395  }
396  }
397 
398  return $link ? $link : array();
399  }
400 
402  {
403  include_once 'Modules/WebResource/classes/class.ilLinkResourceItems.php';
404 
405  $link_res_obj = new ilLinkResourceItems($this->getObjId());
406 
407  foreach($check_links = $link_res_obj->getCheckItems($this->getCheckPeriod()) as $item_data)
408  {
409  $url_data = @parse_url($item_data['target']);
410 
411  // PUH, HTTP_REQUEST needs a beginning http://
412  if(!$url_data['scheme'])
413  {
414  $item_data['target'] = 'http://'.$item_data['target'];
415  }
416 
417  $link[] = array('page_id' => $item_data['link_id'],
418  'obj_id' => $this->getObjId(),
419  'type' => 'webr',
420  'complete' => $item_data['target'],
421  'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
422  'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
423  }
424  return $link ? $link : array();
425  }
426 
427 
428 
429  function __validateLinks($a_links)
430  {
431  if(!@include_once('HTTP/Request.php'))
432  {
433  $this->__appendLogMessage('LinkChecker: Pear HTTP_Request is not installed. Aborting');
434 
435  return array();
436  }
437 
438  foreach($a_links as $link)
439  {
440  if(gethostbyname($link['host']) == $link['host'])
441  {
442  $invalid[] = $link;
443  continue;
444  }
445 
446  if($link['scheme'] !== 'http' and $link['scheme'] !== 'https')
447  {
448  continue;
449  }
450  $req =& new HTTP_Request($link['complete']);
451  $req->sendRequest();
452 
453  switch($req->getResponseCode())
454  {
455  // EVERYTHING OK
456  case '200':
457  // In the moment 301 will be handled as ok
458  case '301':
459  case '302':
460  break;
461 
462  default:
463  $link['http_status_code'] = $req->getResponseCode();
464  $invalid[] = $link;
465  break;
466  }
467  }
468  return $invalid ? $invalid : array();
469  }
470 
471  function __getObjIdByPageId($a_page_id)
472  {
473  $query = "SELECT lm_id FROM lm_data ".
474  "WHERE obj_id = '".$a_page_id."'";
475 
476  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
477 
478  return $row->lm_id ? $row->lm_id : 0;
479  }
480 
481  function __isInvalid($a_page_id, $a_url)
482  {
483  foreach($this->getInvalidLinks() as $link)
484  {
485  if($link['page_id'] == $a_page_id and
486  substr($link['complete'],0,255) == $a_url)
487  {
488  return true;
489  }
490  }
491  return false;
492  }
493 
494  function __saveInDB()
495  {
496  global $ilDB;
497 
498  if($this->getMailStatus())
499  {
500  $this->__checkNotify();
501  }
502  $this->__clearDBData();
503 
504 
505  foreach($this->getInvalidLinks() as $link)
506  {
507  $query = "INSERT INTO link_check (obj_id,page_id,url,parent_type,http_status_code,last_check) ".
508  "VALUES ( ".
509  $ilDB->quote($link['obj_id'],'integer').", ".
510  $ilDB->quote($link['page_id'],'integer').", ".
511  $ilDB->quote(substr($link['complete'],0,255),'text').", ".
512  $ilDB->quote($link['type'],'text').", ".
513  $ilDB->quote($link['http_status_code'] ? $link['http_status_code'] : 0,'integer').", ".
514  $ilDB->quote(time(),'integer')." ".
515  ")";
516  $res = $ilDB->manipulate($query);
517  }
518  }
519 
520  function __checkNotify()
521  {
522  global $ilDB;
523 
524  foreach($this->getInvalidLinks() as $link)
525  {
526  $query = "SELECT * FROM link_check ".
527  "WHERE page_id = ".$ilDB->quote($link['page_id'],'integer')." ".
528  "AND url = ".$ilDB->quote(substr($link['complete'],0,255),'text')." ";
529  $res = $ilDB->query($query);
530 
531  if(!$res->numRows())
532  {
533  $this->notify[$link["obj_id"]][] = array('page_id' => $link['page_id'],
534  'url' => $link['complete']);
535  }
536  }
537  }
538 
539 
540  function __clearDBData()
541  {
542  global $ilDB;
543 
544  if($this->getValidateAll())
545  {
546  $query = "DELETE FROM link_check";
547  }
548  else
549  {
550  $query = "DELETE FROM link_check ".
551  "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer');
552  }
553  $res = $ilDB->manipulate($query);
554 
555  return true;
556  }
557 }
558 ?>