00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00032 class ilValidator extends PEAR
00033 {
00038 var $rbac_object_types = NULL;
00039
00044
00045
00046
00047
00048 var $object_types_exclude = array("adm","root","mail","usrf","objf","lngf",
00049 "trac","taxf","auth","rolf","file","assf","extt","adve","fold");
00050
00055 var $mode = array(
00056 "scan" => true,
00057 "dump_tree" => false,
00058 "clean" => false,
00059 "restore" => false,
00060 "purge" => false,
00061 "restore_trash" => false,
00062 "purge_trash" => false
00063 );
00064
00069 var $invalid_references = array();
00070
00075 var $invalid_childs = array();
00076
00081 var $missing_objects = array();
00082
00087 var $unbound_objects = array();
00088
00093 var $deleted_objects = array();
00094
00101 var $invalid_rolefolders = array();
00102
00107 var $invalid_objects = array();
00108
00113 var $logging = false;
00114
00119 var $scan_log;
00120
00121 var $scan_log_file = "scanlog.log";
00122
00123 var $scan_log_separator = "<!-- scan log start -->";
00124
00131 function ilValidator($a_log = false)
00132 {
00133 global $objDefinition, $ilDB;
00134
00135 $this->PEAR();
00136 $this->db =& $ilDB;
00137 $this->rbac_object_types = "'".implode("','",$objDefinition->getAllRBACObjects())."'";
00138 $this->setErrorHandling(PEAR_ERROR_CALLBACK,array(&$this, 'handleErr'));
00139
00140 if ($a_log === true)
00141 {
00142 $this->logging = true;
00143
00144
00145
00146 include_once "classes/class.ilLog.php";
00147
00148
00149 $this->scan_log = new ilLog(CLIENT_DATA_DIR,"scanlog.log");
00150 $this->scan_log->setLogFormat("");
00151 $this->writeScanLogLine($this->scan_log_separator);
00152 $this->writeScanLogLine("\n[Systemscan from ".date("y-m-d H:i]"));
00153 }
00154 }
00155
00167 function setMode($a_mode,$a_value)
00168 {
00169 if ((!in_array($a_mode,array_keys($this->mode)) and $a_mode != "all") or !is_bool($a_value))
00170 {
00171 $this->throwError(INVALID_PARAM, FATAL, DEBUG);
00172 return false;
00173 }
00174
00175 if ($a_mode == "all")
00176 {
00177 foreach ($this->mode as $mode => $value)
00178 {
00179 $this->mode[$mode] = $a_value;
00180 }
00181 }
00182 else
00183 {
00184 $this->mode[$a_mode] = $a_value;
00185 }
00186
00187
00188 $this->setModeDependencies();
00189
00190 return true;
00191 }
00192
00201 function isModeEnabled($a_mode)
00202 {
00203 if (!in_array($a_mode,array_keys($this->mode)))
00204 {
00205 $this->throwError(VALIDATER_UNKNOWN_MODE, WARNING, DEBUG);
00206 return false;
00207 }
00208
00209 return $this->mode[$a_mode];
00210 }
00211
00212 function isLogEnabled()
00213 {
00214 return $this->logging;
00215 }
00216
00225 function setModeDependencies()
00226 {
00227
00228
00229 if ($this->mode["restore"] === true)
00230 {
00231 $this->mode["scan"] = true;
00232 $this->mode["purge"] = false;
00233 }
00234
00235 if ($this->mode["purge"] === true)
00236 {
00237 $this->mode["scan"] = true;
00238 $this->mode["restore"] = false;
00239 }
00240
00241 if ($this->mode["restore_trash"] === true)
00242 {
00243 $this->mode["scan"] = true;
00244 $this->mode["purge_trash"] = false;
00245 }
00246
00247 if ($this->mode["purge_trash"] === true)
00248 {
00249 $this->mode["scan"] = true;
00250 $this->mode["restore_trash"] = false;
00251 }
00252
00253 if ($this->mode["clean"] === true)
00254 {
00255 $this->mode["scan"] = true;
00256 }
00257 }
00258
00267 function validate()
00268 {
00269 global $lng;
00270
00271
00272 $summary = "";
00273
00274
00275
00276
00277 $summary .= $lng->txt("scanning_system");
00278 if (!$this->isModeEnabled("scan"))
00279 {
00280 $summary .= $lng->txt("disabled");
00281 }
00282 else
00283 {
00284 $summary .= "<br/>".$lng->txt("searching_invalid_refs");
00285 if ($this->findInvalidReferences())
00286 {
00287 $summary .= count($this->getInvalidReferences())." ".$lng->txt("found");
00288 }
00289 else
00290 {
00291 $summary .= $lng->txt("found_none");
00292 }
00293
00294 $summary .= "<br/>".$lng->txt("searching_invalid_childs");
00295 if ($this->findInvalidChilds())
00296 {
00297 $summary .= count($this->getInvalidChilds())." ".$lng->txt("found");
00298
00299 }
00300 else
00301 {
00302 $summary .= $lng->txt("found_none");
00303 }
00304
00305 $summary .= "<br/>".$lng->txt("searching_missing_objs");
00306 if ($this->findMissingObjects())
00307 {
00308 $summary .= count($this->getMissingObjects())." ".$lng->txt("found");
00309
00310 }
00311 else
00312 {
00313 $summary .= $lng->txt("found_none");
00314 }
00315
00316 $summary .= "<br/>".$lng->txt("searching_unbound_objs");
00317 if ($this->findUnboundObjects())
00318 {
00319 $summary .= count($this->getUnboundObjects())." ".$lng->txt("found");
00320
00321 }
00322 else
00323 {
00324 $summary .= $lng->txt("found_none");
00325 }
00326
00327 $summary .= "<br/>".$lng->txt("searching_deleted_objs");
00328 if ($this->findDeletedObjects())
00329 {
00330 $summary .= count($this->getDeletedObjects())." ".$lng->txt("found");
00331
00332 }
00333 else
00334 {
00335 $summary .= $lng->txt("found_none");
00336 }
00337
00338 $summary .= "<br/>".$lng->txt("searching_invalid_rolfs");
00339 if ($this->findInvalidRolefolders())
00340 {
00341 $summary .= count($this->getInvalidRolefolders())." ".$lng->txt("found");
00342
00343 }
00344 else
00345 {
00346 $summary .= $lng->txt("found_none");
00347 }
00348
00349 $summary .= "<br/><br/>".$lng->txt("analyzing_tree_structure");
00350 if ($this->checkTreeStructure())
00351 {
00352 $summary .= $lng->txt("tree_corrupt");
00353 }
00354 else
00355 {
00356 $summary .= $lng->txt("disabled");
00357 }
00358 }
00359
00360
00361
00362 $summary .= "<br /><br />".$lng->txt("dumping_tree");
00363 if (!$this->isModeEnabled("dump_tree"))
00364 {
00365 $summary .= $lng->txt("disabled");
00366 }
00367 else
00368 {
00369 $error_count = $this->dumpTree();
00370 if ($error_count > 0)
00371 {
00372 $summary .= $lng->txt("tree_corrupt");
00373 }
00374 else
00375 {
00376 $summary .= $lng->txt("done");
00377 }
00378 }
00379
00380
00381
00382 $summary .= "<br /><br />".$lng->txt("cleaning");
00383 if (!$this->isModeEnabled("clean"))
00384 {
00385 $summary .= $lng->txt("disabled");
00386 }
00387 else
00388 {
00389 $summary .= "<br />".$lng->txt("removing_invalid_refs");
00390 if ($this->removeInvalidReferences())
00391 {
00392 $summary .= strtolower($lng->txt("done"));
00393 }
00394 else
00395 {
00396 $summary .= $lng->txt("nothing_to_remove").$lng->txt("skipped");
00397 }
00398
00399 $summary .= "<br />".$lng->txt("removing_invalid_childs");
00400 if ($this->removeInvalidChilds())
00401 {
00402 $summary .= strtolower($lng->txt("done"));
00403 }
00404 else
00405 {
00406 $summary .= $lng->txt("nothing_to_remove").$lng->txt("skipped");
00407 }
00408
00409 $summary .= "<br />".$lng->txt("removing_invalid_rolfs");
00410 if ($this->removeInvalidRolefolders())
00411 {
00412 $summary .= strtolower($lng->txt("done"));
00413 }
00414 else
00415 {
00416 $summary .= $lng->txt("nothing_to_remove").$lng->txt("skipped");
00417 }
00418
00419
00420
00421
00422 $this->findUnboundObjects();
00423 }
00424
00425
00426 $summary .= "<br /><br />".$lng->txt("restoring");
00427
00428 if (!$this->isModeEnabled("restore"))
00429 {
00430 $summary .= $lng->txt("disabled");
00431 }
00432 else
00433 {
00434 $summary .= "<br />".$lng->txt("restoring_missing_objs");
00435 if ($this->restoreMissingObjects())
00436 {
00437 $summary .= strtolower($lng->txt("done"));
00438 }
00439 else
00440 {
00441 $summary .= $lng->txt("nothing_to_restore").$lng->txt("skipped");
00442 }
00443
00444 $summary .= "<br />".$lng->txt("restoring_unbound_objs");
00445 if ($this->restoreUnboundObjects())
00446 {
00447 $summary .= strtolower($lng->txt("done"));
00448 }
00449 else
00450 {
00451 $summary .= $lng->txt("nothing_to_restore").$lng->txt("skipped");
00452 }
00453 }
00454
00455
00456 $summary .= "<br /><br />".$lng->txt("restoring_trash");
00457
00458 if (!$this->isModeEnabled("restore_trash"))
00459 {
00460 $summary .= $lng->txt("disabled");
00461 }
00462 else
00463 {
00464 if ($this->restoreTrash())
00465 {
00466 $summary .= strtolower($lng->txt("done"));
00467 }
00468 else
00469 {
00470 $summary .= $lng->txt("nothing_to_restore").$lng->txt("skipped");
00471 }
00472 }
00473
00474
00475 $summary .= "<br /><br />".$lng->txt("purging");
00476
00477 if (!$this->isModeEnabled("purge"))
00478 {
00479 $summary .= $lng->txt("disabled");
00480 }
00481 else
00482 {
00483 $summary .= "<br />".$lng->txt("purging_missing_objs");
00484 if ($this->purgeMissingObjects())
00485 {
00486 $summary .= strtolower($lng->txt("done"));
00487 }
00488 else
00489 {
00490 $summary .= $lng->txt("nothing_to_purge").$lng->txt("skipped");
00491 }
00492
00493 $summary .= "<br />".$lng->txt("purging_unbound_objs");
00494 if ($this->purgeUnboundObjects())
00495 {
00496 $summary .= strtolower($lng->txt("done"));
00497 }
00498 else
00499 {
00500 $summary .= $lng->txt("nothing_to_purge").$lng->txt("skipped");
00501 }
00502 }
00503
00504
00505 $summary .= "<br /><br />".$lng->txt("purging_trash");
00506
00507 if (!$this->isModeEnabled("purge_trash"))
00508 {
00509 $summary .= $lng->txt("disabled");
00510 }
00511 else
00512 {
00513 if ($this->purgeTrash())
00514 {
00515 $summary .= strtolower($lng->txt("done"));
00516 }
00517 else
00518 {
00519 $summary .= $lng->txt("nothing_to_purge").$lng->txt("skipped");
00520 }
00521 }
00522
00523
00524 if ($this->isModeEnabled("clean"))
00525 {
00526 $summary .= "<br /><br />".$lng->txt("cleaning_final");
00527 if ($this->initGapsInTree())
00528 {
00529 $summary .= "<br />".$lng->txt("initializing_gaps")." ".strtolower($lng->txt("done"));
00530 }
00531 }
00532
00533
00534
00535
00536
00537 foreach ($this->mode as $mode => $value)
00538 {
00539 $arr[] = $mode."[".(int)$value."]";
00540 }
00541
00542 return $summary;
00543 }
00544
00545
00555 function findMissingObjects()
00556 {
00557
00558 if ($this->mode["scan"] !== true)
00559 {
00560 return false;
00561 }
00562
00563
00564 $this->missing_objects = array();
00565
00566 $this->writeScanLogLine("\nfindMissingObjects:");
00567
00568 $q = "SELECT object_data.*, ref_id FROM object_data ".
00569 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id ".
00570 "LEFT JOIN tree ON object_reference.ref_id = tree.child ".
00571 "WHERE (object_reference.obj_id IS NULL OR tree.child IS NULL) ".
00572 "AND object_data.type IN (".$this->rbac_object_types.")";
00573 $r = $this->db->query($q);
00574
00575 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00576 {
00577 if (!in_array($row->type,$this->object_types_exclude))
00578 {
00579 $this->missing_objects[] = array(
00580 "obj_id" => $row->obj_id,
00581 "type" => $row->type,
00582 "ref_id" => $row->ref_id,
00583 "child" => $row->child,
00584 "title" => $row->title,
00585 "desc" => $row->description,
00586 "owner" => $row->owner,
00587 "create_date" => $row->create_date,
00588 "last_update" => $row->last_update
00589 );
00590 }
00591 }
00592
00593 if (count($this->missing_objects) > 0)
00594 {
00595 $this->writeScanLogLine("obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
00596 $this->writeScanLogArray($this->missing_objects);
00597 return true;
00598 }
00599
00600 $this->writeScanLogLine("none");
00601 return false;
00602 }
00603
00615 function findInvalidRolefolders()
00616 {
00617
00618 if ($this->mode["scan"] !== true)
00619 {
00620 return false;
00621 }
00622
00623
00624 $this->invalid_rolefolders = array();
00625
00626 $this->writeScanLogLine("\nfindInvalidRolefolders:");
00627
00628
00629 $q = "SELECT object_data.*, ref_id FROM object_data ".
00630 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id ".
00631 "LEFT JOIN tree ON object_reference.ref_id = tree.child ".
00632 "WHERE (object_reference.obj_id IS NULL OR tree.child IS NULL) ".
00633 "AND object_data.type='rolf'";
00634 $r = $this->db->query($q);
00635
00636 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00637 {
00638 $this->invalid_rolefolders[] = array(
00639 "obj_id" => $row->obj_id,
00640 "type" => $row->type,
00641 "ref_id" => $row->ref_id,
00642 "child" => $row->child,
00643 "title" => $row->title,
00644 "desc" => $row->description,
00645 "owner" => $row->owner,
00646 "create_date" => $row->create_date,
00647 "last_update" => $row->last_update
00648 );
00649 }
00650
00651
00652 $q = "SELECT object_data.*, ref_id FROM object_data ".
00653 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id ".
00654 "LEFT JOIN tree ON object_reference.ref_id = tree.child ".
00655 "WHERE object_reference.ref_id ='".RECOVERY_FOLDER_ID."' ".
00656 "AND object_data.type='rolf'";
00657 $r = $this->db->query($q);
00658
00659 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00660 {
00661 $this->invalid_rolefolders[] = array(
00662 "obj_id" => $row->obj_id,
00663 "type" => $row->type,
00664 "ref_id" => $row->ref_id,
00665 "child" => $row->child,
00666 "title" => $row->title,
00667 "desc" => $row->description,
00668 "owner" => $row->owner,
00669 "create_date" => $row->create_date,
00670 "last_update" => $row->last_update
00671 );
00672 }
00673
00674 if (count($this->invalid_rolefolders) > 0)
00675 {
00676 $this->writeScanLogLine("obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
00677 $this->writeScanLogArray($this->invalid_rolefolders);
00678 return true;
00679 }
00680
00681 $this->writeScanLogLine("none");
00682 return false;
00683 }
00684
00694 function findInvalidRBACEntries()
00695 {
00696
00697 if ($this->mode["scan"] !== true)
00698 {
00699 return false;
00700 }
00701
00702
00703 $this->invalid_rbac_entries = array();
00704
00705 $this->writeScanLogLine("\nfindInvalidRBACEntries:");
00706
00707 $q = "SELECT object_data.*, ref_id FROM object_data ".
00708 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id ".
00709 "LEFT JOIN tree ON object_reference.ref_id = tree.child ".
00710 "WHERE (object_reference.obj_id IS NULL OR tree.child IS NULL) ".
00711 "AND object_data.type='rolf'";
00712 $r = $this->db->query($q);
00713
00714 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00715 {
00716 $this->invalid_rolefolders[] = array(
00717 "obj_id" => $row->obj_id,
00718 "type" => $row->type,
00719 "ref_id" => $row->ref_id,
00720 "child" => $row->child,
00721 "title" => $row->title,
00722 "desc" => $row->description,
00723 "owner" => $row->owner,
00724 "create_date" => $row->create_date,
00725 "last_update" => $row->last_update
00726 );
00727 }
00728
00729
00730 $q = "SELECT object_data.*, ref_id FROM object_data ".
00731 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id ".
00732 "LEFT JOIN tree ON object_reference.ref_id = tree.child ".
00733 "WHERE object_reference.ref_id ='".RECOVERY_FOLDER_ID."' ".
00734 "AND object_data.type='rolf'";
00735 $r = $this->db->query($q);
00736
00737 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00738 {
00739 $this->invalid_rolefolders[] = array(
00740 "obj_id" => $row->obj_id,
00741 "type" => $row->type,
00742 "ref_id" => $row->ref_id,
00743 "child" => $row->child,
00744 "title" => $row->title,
00745 "desc" => $row->description,
00746 "owner" => $row->owner,
00747 "create_date" => $row->create_date,
00748 "last_update" => $row->last_update
00749 );
00750 }
00751
00752 if (count($this->invalid_rolefolders) > 0)
00753 {
00754 $this->writeScanLogLine("obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
00755 $this->writeScanLogArray($this->invalid_rolefolders);
00756 return true;
00757 }
00758
00759 $this->writeScanLogLine("none");
00760 return false;
00761 }
00762
00776 function getMissingObjects()
00777 {
00778 return $this->missing_objects;
00779 }
00780
00790 function findInvalidReferences()
00791 {
00792
00793 if ($this->mode["scan"] !== true)
00794 {
00795 return false;
00796 }
00797
00798
00799 $this->invalid_references = array();
00800
00801 $this->writeScanLogLine("\nfindInvalidReferences:");
00802
00803 $q = "SELECT object_reference.* FROM object_reference ".
00804 "LEFT JOIN object_data ON object_data.obj_id = object_reference.obj_id ".
00805 "WHERE object_data.obj_id IS NULL ".
00806 "OR object_data.type NOT IN (".$this->rbac_object_types.")";
00807 $r = $this->db->query($q);
00808
00809 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00810 {
00811 $this->invalid_references[] = array(
00812 "ref_id" => $row->ref_id,
00813 "obj_id" => $row->obj_id,
00814 "msg" => "Object does not exist."
00815 );
00816 }
00817
00818 if (count($this->invalid_references) > 0)
00819 {
00820 $this->writeScanLogLine("ref_id\t\tobj_id");
00821 $this->writeScanLogArray($this->invalid_references);
00822 return true;
00823 }
00824
00825 $this->writeScanLogLine("none");
00826 return false;
00827 }
00828
00837 function getInvalidReferences()
00838 {
00839 return $this->invalid_references;
00840 }
00841
00851 function findInvalidChilds()
00852 {
00853
00854 if ($this->mode["scan"] !== true)
00855 {
00856 return false;
00857 }
00858
00859
00860 $this->invalid_childs = array();
00861
00862 $this->writeScanLogLine("\nfindInvalidChilds:");
00863
00864 $q = "SELECT tree.*,object_reference.ref_id FROM tree ".
00865 "LEFT JOIN object_reference ON tree.child = object_reference.ref_id ".
00866 "LEFT JOIN object_data ON object_reference.obj_id = object_data.obj_id ".
00867 "WHERE object_reference.ref_id IS NULL or object_data.obj_id IS NULL";
00868 $r = $this->db->query($q);
00869
00870 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00871 {
00872 $this->invalid_childs[] = array(
00873 "child" => $row->child,
00874 "ref_id" => $row->ref_id,
00875 "msg" => "No object found"
00876 );
00877 }
00878
00879 if (count($this->invalid_childs) > 0)
00880 {
00881 $this->writeScanLogLine("child\t\tref_id");
00882 $this->writeScanLogArray($this->invalid_childs);
00883 return true;
00884 }
00885
00886 $this->writeScanLogLine("none");
00887 return false;
00888 }
00889
00898 function getInvalidChilds()
00899 {
00900 return $this->invalid_childs;
00901 }
00902
00914 function findUnboundObjects()
00915 {
00916
00917 if ($this->mode["scan"] !== true)
00918 {
00919 return false;
00920 }
00921
00922
00923 $this->unbound_objects = array();
00924
00925 $this->writeScanLogLine("\nfindUnboundObjects:");
00926
00927 $q = "SELECT T2.tree AS deleted,T1.child,T1.parent,T2.parent AS grandparent FROM tree AS T1 ".
00928 "LEFT JOIN tree AS T2 ON T2.child=T1.parent ".
00929 "WHERE (T2.tree!=1 OR T2.tree IS NULL) AND T1.parent!=0";
00930 $r = $this->db->query($q);
00931
00932 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00933 {
00934
00935 if ($row->deleted === NULL)
00936 {
00937 $this->unbound_objects[] = array(
00938 "child" => $row->child,
00939 "parent" => $row->parent,
00940 "tree" => 1,
00941 "msg" => "No valid parent node found"
00942 );
00943 }
00944 }
00945
00946 if (count($this->unbound_objects) > 0)
00947 {
00948 $this->writeScanLogLine("child\t\tparent\ttree");
00949 $this->writeScanLogArray($this->unbound_objects);
00950 return true;
00951 }
00952
00953 $this->writeScanLogLine("none");
00954 return false;
00955 }
00956
00968 function findDeletedObjects()
00969 {
00970
00971 if ($this->mode["scan"] !== true)
00972 {
00973 return false;
00974 }
00975
00976
00977 $this->deleted_objects = array();
00978
00979 $this->writeScanLogLine("\nfindDeletedObjects:");
00980
00981 $q = "SELECT object_data.*,tree.tree,tree.child,tree.parent FROM object_data ".
00982 "LEFT JOIN object_reference ON object_data.obj_id=object_reference.obj_id ".
00983 "LEFT JOIN tree ON tree.child=object_reference.ref_id ".
00984 " WHERE tree !=1";
00985 $r = $this->db->query($q);
00986
00987 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
00988 {
00989 $this->deleted_objects[] = array(
00990 "child" => $row->child,
00991 "parent" => $row->parent,
00992 "tree" => $row->tree,
00993 "type" => $row->type,
00994 "title" => $row->title,
00995 "desc" => $row->description,
00996 "owner" => $row->owner,
00997 "create_date" => $row->create_date,
00998 "last_update" => $row->last_update
00999 );
01000 }
01001
01002 if (count($this->deleted_objects) > 0)
01003 {
01004 $this->writeScanLogLine("obj_id\tref_id\ttree\ttype\ttitle\tdesc\towner\tcreate_date\tlast_update");
01005 $this->writeScanLogArray($this->deleted_objects);
01006 return true;
01007 }
01008
01009 $this->writeScanLogLine("none");
01010 return false;
01011 }
01012
01013
01027 function getUnboundObjects()
01028 {
01029 return $this->unbound_objects;
01030 }
01031
01038 function getDeletedObjects()
01039 {
01040 return $this->deleted_objects;
01041 }
01042
01051 function getInvalidRolefolders()
01052 {
01053 return $this->invalid_rolefolders;
01054 }
01055
01065 function removeInvalidReferences($a_invalid_refs = NULL)
01066 {
01067 global $ilLog;
01068
01069
01070 if ($this->mode["clean"] !== true)
01071 {
01072 return false;
01073 }
01074
01075 $this->writeScanLogLine("\nremoveInvalidReferences:");
01076
01077 if ($a_invalid_refs === NULL and isset($this->invalid_references))
01078 {
01079 $a_invalid_refs =& $this->invalid_references;
01080 }
01081
01082
01083 if (!is_array($a_invalid_refs))
01084 {
01085 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01086 return false;
01087 }
01088
01089 if (count($a_invalid_refs) == 0)
01090 {
01091 $this->writeScanLogLine("none");
01092 return false;
01093 }
01094
01095
01096
01097
01098
01099 $message = sprintf('%s::removeInvalidReferences(): Started...',
01100 get_class($this));
01101 $ilLog->write($message,$ilLog->WARNING);
01102
01103 foreach ($a_invalid_refs as $entry)
01104 {
01105 $q = "DELETE FROM object_reference WHERE ref_id='".$entry["ref_id"]."' AND obj_id='".$entry["obj_id"]."'";
01106 $this->db->query($q);
01107
01108 $message = sprintf('%s::removeInvalidReferences(): Reference %s removed',
01109 get_class($this),
01110 $entry["ref_id"]);
01111 $ilLog->write($message,$ilLog->WARNING);
01112
01113 $this->writeScanLogLine("Entry ".$entry["ref_id"]." removed");
01114 }
01115
01116 return true;
01117 }
01118
01128 function removeInvalidChilds($a_invalid_childs = NULL)
01129 {
01130 global $ilLog;
01131
01132
01133 if ($this->mode["clean"] !== true)
01134 {
01135 return false;
01136 }
01137
01138 $this->writeScanLogLine("\nremoveInvalidChilds:");
01139
01140 if ($a_invalid_childs === NULL and isset($this->invalid_childs))
01141 {
01142 $a_invalid_childs =& $this->invalid_childs;
01143 }
01144
01145
01146 if (!is_array($a_invalid_childs))
01147 {
01148 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01149 return false;
01150 }
01151
01152
01153 if (count($a_invalid_childs) == 0)
01154 {
01155 $this->writeScanLogLine("none");
01156 return false;
01157 }
01158
01159
01160
01161
01162
01163 $message = sprintf('%s::removeInvalidChilds(): Started...',
01164 get_class($this));
01165 $ilLog->write($message,$ilLog->WARNING);
01166
01167 foreach ($a_invalid_childs as $entry)
01168 {
01169 $q = "DELETE FROM tree WHERE child='".$entry["child"]."'";
01170 $this->db->query($q);
01171
01172 $message = sprintf('%s::removeInvalidChilds(): Entry child=%s removed',
01173 get_class($this),
01174 $entry["child"]);
01175 $ilLog->write($message,$ilLog->WARNING);
01176
01177 $this->writeScanLogLine("Entry ".$entry["child"]." removed");
01178 }
01179
01180 return true;
01181 }
01182
01193 function removeInvalidRolefolders($a_invalid_rolefolders = NULL)
01194 {
01195 global $ilias,$ilLog;
01196
01197
01198 if ($this->mode["clean"] !== true)
01199 {
01200 return false;
01201 }
01202
01203 $this->writeScanLogLine("\nremoveInvalidRolefolders:");
01204
01205 if ($a_invalid_rolefolders === NULL and isset($this->invalid_rolefolders))
01206 {
01207 $a_invalid_rolefolders = $this->invalid_rolefolders;
01208 }
01209
01210
01211 if (!is_array($a_invalid_rolefolders))
01212 {
01213 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01214 return false;
01215 }
01216
01217
01218 if (count($a_invalid_rolefolders) == 0)
01219 {
01220 $this->writeScanLogLine("none");
01221 return false;
01222 }
01223
01224
01225
01226
01227
01228 $removed = false;
01229
01230 $message = sprintf('%s::removeInvalidRolefolders(): Started...',
01231 get_class($this));
01232 $ilLog->write($message,$ilLog->WARNING);
01233
01234 foreach ($a_invalid_rolefolders as $rolf)
01235 {
01236
01237 if ($rolf["ref_id"] === NULL)
01238 {
01239 $rolf["ref_id"] = $this->restoreReference($rolf["obj_id"]);
01240
01241 $this->writeScanLogLine("Created missing reference '".$rolf["ref_id"]."' for rolefolder object '".$rolf["obj_id"]."'");
01242 }
01243
01244
01245 $obj_data =& $ilias->obj_factory->getInstanceByRefId($rolf["ref_id"]);
01246 $obj_data->delete();
01247 unset($obj_data);
01248 $removed = true;
01249 $this->writeScanLogLine("Removed invalid rolefolder '".$rolf["title"]."' (id=".$rolf["obj_id"].",ref=".$rolf["ref_id"].") from system");
01250 }
01251
01252 return $removed;
01253 }
01254
01265 function restoreMissingObjects($a_missing_objects = NULL)
01266 {
01267 global $ilias,$rbacadmin,$ilLog;
01268
01269
01270 if ($this->mode["restore"] !== true)
01271 {
01272 return false;
01273 }
01274
01275 $this->writeScanLogLine("\nrestoreMissingObjects:");
01276
01277 if ($a_missing_objects === NULL and isset($this->missing_objects))
01278 {
01279 $a_missing_objects = $this->missing_objects;
01280 }
01281
01282
01283 if (!is_array($a_missing_objects))
01284 {
01285 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01286 return false;
01287 }
01288
01289
01290 if (count($a_missing_objects) == 0)
01291 {
01292 $this->writeScanLogLine("none");
01293 return false;
01294 }
01295
01296
01297
01298
01299
01300 $restored = false;
01301
01302 $message = sprintf('%s::restoreMissingObjects(): Started...',
01303 get_class($this));
01304 $ilLog->write($message,$ilLog->WARNING);
01305
01306 foreach ($a_missing_objects as $missing_obj)
01307 {
01308
01309 if ($missing_obj["ref_id"] === NULL)
01310 {
01311 $missing_obj["ref_id"] = $this->restoreReference($missing_obj["obj_id"]);
01312
01313 $this->writeScanLogLine("Created missing reference '".$missing_obj["ref_id"]."' for object '".$missing_obj["obj_id"]."'");
01314 }
01315
01316
01317 if (!in_array($missing_obj["type"],$this->object_types_exclude))
01318 {
01319 $rbacadmin->revokePermission($missing_obj["ref_id"]);
01320 $obj_data =& $ilias->obj_factory->getInstanceByRefId($missing_obj["ref_id"]);
01321 $obj_data->putInTree(RECOVERY_FOLDER_ID);
01322 $obj_data->setPermissions(RECOVERY_FOLDER_ID);
01323 $obj_data->initDefaultRoles();
01324 unset($obj_data);
01325
01326 $restored = true;
01327 $this->writeScanLogLine("Restored object '".$missing_obj["title"]."' (id=".$missing_obj["obj_id"].",ref=".$missing_obj["ref_id"].") in 'Restored objects folder'");
01328 }
01329
01330
01331 }
01332
01333 return $restored;
01334 }
01335
01345 function restoreReference($a_obj_id)
01346 {
01347 global $ilLog;
01348
01349 if (empty($a_obj_id))
01350 {
01351 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01352 return false;
01353 }
01354
01355 $q = "INSERT INTO object_reference (ref_id,obj_id) VALUES ('0','".$a_obj_id."')";
01356 $this->db->query($q);
01357
01358 $message = sprintf('%s::restoreReference(): new reference %s for obj_id %s created',
01359 get_class($this),
01360 $this->db->getLastInsertId(),
01361 $_obj_id);
01362 $ilLog->write($message,$ilLog->WARNING);
01363
01364 return $this->db->getLastInsertId();
01365 }
01366
01377 function restoreUnboundObjects($a_unbound_objects = NULL)
01378 {
01379 global $ilLog;
01380
01381
01382 if ($this->mode["restore"] !== true)
01383 {
01384 return false;
01385 }
01386
01387 $this->writeScanLogLine("\nrestoreUnboundObjects:");
01388
01389 if ($a_unbound_objects === NULL and isset($this->unbound_objects))
01390 {
01391 $a_unbound_objects = $this->unbound_objects;
01392 }
01393
01394
01395 if (!is_array($a_unbound_objects))
01396 {
01397 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01398 return false;
01399 }
01400
01401 $message = sprintf('%s::restoreUnboundObjects(): Started...',
01402 get_class($this));
01403 $ilLog->write($message,$ilLog->WARNING);
01404
01405
01406 return $this->restoreSubTrees($a_unbound_objects);
01407 }
01408
01418 function restoreTrash($a_deleted_objects = NULL)
01419 {
01420 global $ilLog;
01421
01422
01423 if ($this->mode["restore_trash"] !== true)
01424 {
01425 return false;
01426 }
01427
01428 $this->writeScanLogLine("\nrestoreTrash:");
01429
01430 if ($a_deleted_objects === NULL and isset($this->deleted_objects))
01431 {
01432 $a_deleted_objects = $this->deleted_objects;
01433 }
01434
01435
01436 if (!is_array($a_deleted_objects))
01437 {
01438 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01439 return false;
01440 }
01441
01442 $message = sprintf('%s::restoreTrash(): Started...',
01443 get_class($this));
01444 $ilLog->write($message,$ilLog->WARNING);
01445
01446
01447 $restored = $this->restoreDeletedObjects($a_deleted_objects);
01448
01449 if ($restored)
01450 {
01451 $q = "DELETE FROM tree WHERE tree!=1";
01452 $this->db->query($q);
01453
01454 $message = sprintf('%s::restoreTrash(): Removed all trees with tree id <> 1',
01455 get_class($this));
01456 $ilLog->write($message,$ilLog->WARNING);
01457
01458 $this->writeScanLogLine("Old tree entries removed");
01459 }
01460
01461 return $restored;
01462 }
01463
01472 function restoreDeletedObjects($a_nodes)
01473 {
01474 global $tree,$rbacadmin,$ilias,$ilLog;
01475
01476
01477 if (!is_array($a_nodes))
01478 {
01479 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01480 return false;
01481 }
01482
01483
01484 if (count($a_nodes) == 0)
01485 {
01486 $this->writeScanLogLine("none");
01487 return false;
01488 }
01489
01490 $message = sprintf('%s::restoreDeletedObjects()): Started...',
01491 get_class($this));
01492 $ilLog->write($message,$ilLog->WARNING);
01493
01494
01495
01496
01497 foreach ($a_nodes as $key => $node)
01498 {
01499 if ($node["type"] == "rolf")
01500 {
01501
01502 $tree->deleteTree($node);
01503
01504 $obj_data =& $ilias->obj_factory->getInstanceByRefId($node["child"]);
01505 $obj_data->delete();
01506 unset($a_nodes[$key]);
01507 }
01508 }
01509
01510
01511 foreach ($a_nodes as $node)
01512 {
01513
01514 $tree->deleteTree($node);
01515
01516 $rbacadmin->revokePermission($node["child"]);
01517 $obj_data =& $ilias->obj_factory->getInstanceByRefId($node["child"]);
01518 $obj_data->putInTree(RECOVERY_FOLDER_ID);
01519 $obj_data->setPermissions(RECOVERY_FOLDER_ID);
01520 $obj_data->initDefaultRoles();
01521 }
01522
01523 return true;
01524 }
01525
01534 function restoreSubTrees ($a_nodes)
01535 {
01536 global $tree,$rbacadmin,$ilias,$ilLog;
01537
01538
01539 if (!is_array($a_nodes))
01540 {
01541 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01542 return false;
01543 }
01544
01545
01546 if (count($a_nodes) == 0)
01547 {
01548 $this->writeScanLogLine("none");
01549 return false;
01550 }
01551
01552
01553
01554
01555
01556 $subnodes = array();
01557 $topnode = array();
01558
01559 $message = sprintf('%s::restoreSubTrees(): Started...',
01560 get_class($this));
01561 $ilLog->write($message,$ilLog->WARNING);
01562
01563
01564 foreach ($a_nodes as $node)
01565 {
01566
01567 $topnode = $tree->getNodeData($node["child"]);
01568
01569
01570
01571 if ($topnode["type"] == "rolf")
01572 {
01573 $rolfObj = $ilias->obj_factory->getInstanceByRefId($topnode["child"]);
01574 $rolfObj->delete();
01575 unset($top_node);
01576 unset($rolfObj);
01577 continue;
01578 }
01579
01580
01581 $subnodes[$node["child"]] = $tree->getSubtree($topnode);
01582
01583
01584 $tree->deleteTree($topnode);
01585 }
01586
01587
01588
01589 foreach ($subnodes as $key => $subnode)
01590 {
01591
01592
01593 $rbacadmin->revokePermission($key);
01594 $obj_data =& $ilias->obj_factory->getInstanceByRefId($key);
01595 $obj_data->putInTree(RECOVERY_FOLDER_ID);
01596 $obj_data->setPermissions(RECOVERY_FOLDER_ID);
01597 $obj_data->initDefaultRoles();
01598
01599 $this->writeScanLogLine("Object '".$obj_data->getId()."' restored.");
01600
01601
01602 array_shift($subnode);
01603
01604
01605 if (count($subnode) > 0)
01606 {
01607 foreach ($subnode as $node)
01608 {
01609 $rbacadmin->revokePermission($node["child"]);
01610 $obj_data =& $ilias->obj_factory->getInstanceByRefId($node["child"]);
01611 $obj_data->putInTree($node["parent"]);
01612 $obj_data->setPermissions($node["parent"]);
01613 $obj_data->initDefaultRoles();
01614
01615 $this->writeScanLogLine("Object '".$obj_data->getId()."' restored.");
01616 }
01617 }
01618 }
01619
01620
01621 $this->findInvalidChilds();
01622 $this->removeInvalidChilds();
01623
01624 return true;
01625 }
01626
01636 function purgeTrash($a_nodes = NULL)
01637 {
01638 global $ilLog;
01639
01640
01641 if ($this->mode["purge_trash"] !== true)
01642 {
01643 return false;
01644 }
01645
01646 $this->writeScanLogLine("\npurgeTrash:");
01647
01648 if ($a_nodes === NULL and isset($this->deleted_objects))
01649 {
01650 $a_nodes = $this->deleted_objects;
01651 }
01652
01653 $message = sprintf('%s::purgeTrash(): Started...',
01654 get_class($this));
01655 $ilLog->write($message,$ilLog->WARNING);
01656
01657
01658 return $this->purgeObjects($a_nodes);
01659 }
01660
01670 function purgeUnboundObjects($a_nodes = NULL)
01671 {
01672 global $ilLog;
01673
01674
01675 if ($this->mode["purge"] !== true)
01676 {
01677 return false;
01678 }
01679
01680 $this->writeScanLogLine("\npurgeUnboundObjects:");
01681
01682 if ($a_nodes === NULL and isset($this->unbound_objects))
01683 {
01684 $a_nodes = $this->unbound_objects;
01685 }
01686
01687 $message = sprintf('%s::purgeUnboundObjects(): Started...',
01688 get_class($this));
01689 $ilLog->write($message,$ilLog->WARNING);
01690
01691
01692 return $this->purgeObjects($a_nodes);
01693 }
01694
01704 function purgeMissingObjects($a_nodes = NULL)
01705 {
01706 global $ilLog;
01707
01708
01709 if ($this->mode["purge"] !== true)
01710 {
01711 return false;
01712 }
01713
01714 $this->writeScanLogLine("\npurgeMissingObjects:");
01715
01716 if ($a_nodes === NULL and isset($this->missing_objects))
01717 {
01718 $a_nodes = $this->missing_objects;
01719 }
01720
01721 $message = sprintf('%s::purgeMissingObjects(): Started...',
01722 get_class($this));
01723 $ilLog->write($message,$ilLog->WARNING);
01724
01725
01726 return $this->purgeObjects($a_nodes);
01727 }
01728
01736 function purgeObjects($a_nodes)
01737 {
01738 global $ilias,$ilLog;
01739
01740
01741 if (!is_array($a_nodes))
01742 {
01743 $this->throwError(INVALID_PARAM, WARNING, DEBUG);
01744 return false;
01745 }
01746
01747
01748 foreach ($a_nodes as $node)
01749 {
01750 $ref_id = ($node["child"]) ? $node["child"] : $node["ref_id"];
01751 $node_obj =& $ilias->obj_factory->getInstanceByRefId($ref_id,false);
01752
01753 if ($node_obj === false)
01754 {
01755 $this->invalid_objects[] = $node;
01756 continue;
01757 }
01758
01759 $message = sprintf('%s::purgeObjects(): Removing object (id:%s ref:%s)',
01760 get_class($this),
01761 $ref_id,
01762 $node_obj->getId);
01763 $ilLog->write($message,$ilLog->WARNING);
01764
01765 $node_obj->delete();
01766 ilTree::_removeEntry($node["tree"],$ref_id);
01767
01768 $this->writeScanLogLine("Object '".$node_obj->getId()."' deleted");
01769 }
01770
01771 $this->findInvalidChilds();
01772 $this->removeInvalidChilds();
01773
01774 return true;
01775 }
01776
01790 function initGapsInTree()
01791 {
01792 global $tree,$ilLog;
01793
01794 $message = sprintf('%s::initGapsInTree(): Started...',
01795 get_class($this));
01796 $ilLog->write($message,$ilLog->WARNING);
01797
01798
01799 if ($this->mode["clean"] !== true)
01800 {
01801 return false;
01802 }
01803 $this->writeScanLogLine("\nrenumberTree:");
01804
01805 $tree->renumber(ROOT_FOLDER_ID);
01806
01807 $this->writeScanLogLine("done");
01808
01809 return true;
01810 }
01811
01821 function handleErr($error)
01822 {
01823 $call_loc = $error->backtrace[count($error->backtrace)-1];
01824 $num_args = count($call_loc["args"]);
01825
01826 if ($num_args > 0)
01827 {
01828 foreach ($call_loc["args"] as $arg)
01829 {
01830 $type = gettype($arg);
01831
01832 switch ($type)
01833 {
01834 case "string":
01835 $value = strlen($arg);
01836 break;
01837
01838 case "array":
01839 $value = count($arg);
01840 break;
01841
01842 case "object":
01843 $value = get_class($arg);
01844 break;
01845
01846 case "boolean":
01847 $value = ($arg) ? "true" : "false";
01848 break;
01849
01850 default:
01851 $value = $arg;
01852 break;
01853 }
01854
01855 $arg_list[] = array(
01856 "type" => $type,
01857 "value" => "(".$value.")"
01858 );
01859 }
01860
01861 foreach ($arg_list as $arg)
01862 {
01863 $arg_str .= implode("",$arg)." ";
01864 }
01865 }
01866
01867 $err_msg = "<br/><b>".$error->getCode().":</b> ".$error->getMessage()." in ".$call_loc["class"].$call_loc["type"].$call_loc["function"]."()".
01868 "<br/>Called from: ".basename($call_loc["file"])." , line ".$call_loc["line"].
01869 "<br/>Passed parameters: [".$num_args."] ".$arg_str."<br/>";
01870 printf($err_msg);
01871
01872 if ($error->getUserInfo())
01873 {
01874 printf("<br/>Parameter details:");
01875 echo "<pre>";
01876 var_dump($call_loc["args"]);
01877 echo "</pre>";
01878 }
01879
01880 if ($error->getCode() == FATAL)
01881 {
01882 exit();
01883 }
01884 }
01885
01886 function writeScanLogArray($a_arr)
01887 {
01888 if (!$this->isLogEnabled())
01889 {
01890 return false;
01891 }
01892
01893 foreach ($a_arr as $entry)
01894 {
01895 $this->scan_log->write(implode("\t",$entry));
01896 }
01897 }
01898
01899 function writeScanLogLine($a_msg)
01900 {
01901 if (!$this->isLogEnabled())
01902 {
01903 return false;
01904 }
01905
01906 $this->scan_log->write($a_msg);
01907 }
01908
01912 function hasScanLog()
01913 {
01914
01915 return is_file(CLIENT_DATA_DIR."/".$this->scan_log_file);
01916 }
01917
01918 function readScanLog()
01919 {
01920
01921 if (! $this->hasScanLog())
01922 {
01923 return false;
01924 }
01925
01926 $scanfile =& file(CLIENT_DATA_DIR."/".$this->scan_log_file);
01927 if (!$scan_log =& $this->get_last_scan($scanfile))
01928 {
01929 return false;
01930 }
01931
01932 unset($scanfile);
01933
01934 return $scan_log;
01935 }
01936
01937 function get_last_scan($a_scan_log)
01938 {
01939 $logs = array_keys($a_scan_log,$this->scan_log_separator."\n");
01940
01941 if (count($logs) > 0)
01942 {
01943 return array_slice($a_scan_log,array_pop($logs)+2);
01944 }
01945
01946 return false;
01947 }
01948
01949 function checkTreeStructure($a_startnode = null)
01950 {
01951 global $tree;
01952
01953 $this->writeScanLogLine("\nchecking tree structure is disabled");
01954
01955 return false;
01956 }
01963 function dumpTree()
01964 {
01965 $this->writeScanLogLine("BEGIN dumpTree:");
01966
01967
01968
01969
01970 $q = 'SELECT child FROM tree GROUP BY child HAVING COUNT(*) > 1';
01971 $r = $this->db->query($q);
01972 $duplicateNodes = array();
01973 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
01974 {
01975 $duplicateNodes[] = $row->child;
01976 }
01977
01978
01979 $q = "SELECT tree.*,ref.ref_id,ref.obj_id AS refobj_id,dat.*,login "
01980 ."FROM tree "
01981 ."LEFT OUTER JOIN object_reference AS ref ON tree.child = ref.ref_id "
01982 ."LEFT OUTER JOIN object_data AS dat ON ref.obj_id = dat.obj_id "
01983 ."LEFT OUTER JOIN usr_data AS usr ON dat.owner = usr.usr_id "
01984 ."ORDER BY tree, lft";
01985 $r = $this->db->query($q);
01986
01987 $this->writeScanLogLine(
01988 '<table><tr>'
01989 .'<td>tree, child, parent, lft, rgt, depth</td>'
01990 .'<td>ref_id, ref.obj_id</td>'
01991 .'<td>obj_id, type, title</td>'
01992 .'</tr>'
01993 );
01994
01995
01996
01997
01998 $stack = array();
01999 $error_count = 0;
02000 $repository_tree_count = 0;
02001 $trash_trees_count = 0;
02002 $other_trees_count = 0;
02003 $not_in_tree_count = 0;
02004
02005
02006 $previousNumber = 0;
02007
02008 while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
02009 {
02010
02011 if (is_null($row->child))
02012 {
02013 $not_in_tree_count++;
02014 $error_count++;
02015 $isRowOkay = false;
02016 $isParentOkay = false;
02017 $isLftOkay = false;
02018 $isRgtOkay = false;
02019 $isDepthOkay = false;
02020
02021 $this->writeScanLogLine(
02022 '<tr>'
02023 .'<td>'
02024 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02025 .$row->tree.', '
02026 .$row->child.', '
02027 .(($isParentOkay) ? '' : 'parent:<b>')
02028 .$row->parent
02029 .(($isParentOkay) ? '' : '</b>')
02030 .', '
02031 .(($isLftOkay) ? '' : 'lft:<b>')
02032 .$row->lft
02033 .(($isLftOkay) ? '' : '</b>')
02034 .', '
02035 .(($isRgtOkay) ? '' : 'rgt:<b>')
02036 .$row->rgt
02037 .(($isRgtOkay) ? '' : '</b>')
02038 .', '
02039 .(($isDepthOkay) ? '' : 'depth:<b>')
02040 .$row->depth
02041 .(($isDepthOkay) ? '' : '</b>')
02042 .(($isRowOkay) ? '' : '</font>')
02043 .'</td><td>'
02044 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02045 .(($isRefRefOkay && $isChildOkay) ? '' : 'ref.ref_id:<b>')
02046 .$row->ref_id
02047 .(($isRefRefOkay && $isChildOkay) ? '' : '</b>')
02048 .', '
02049 .(($isRefObjOkay) ? '' : 'ref.obj_id:<b>')
02050 .$row->refobj_id
02051 .(($isRefObjOkay) ? '' : '</b>')
02052 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02053 .'</td><td>'
02054 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02055 .$indent
02056 .$row->obj_id.', '
02057 .$row->type.', '
02058 .$row->title.', '
02059 .$row->login
02060 .(($isRowOkay) ? '' : ' <b>*ERROR*</b><font color=#ff0000>')
02061 .'</td>'
02062 .'</tr>'
02063 );
02064 continue;
02065 }
02066
02067
02068
02069 $indent = "";
02070 for ($i = 1; $i < $row->depth; $i++)
02071 {
02072 $indent .= ". ";
02073 }
02074
02075
02076 if (count($stack) == 0 || $stack[0]->tree != $row->tree)
02077 {
02078 $stack = array();
02079 $previousNumber = $row->lft - 1;
02080 }
02081
02082 while (count($stack) > 0 && $stack[count($stack) - 1]->rgt < $row->lft)
02083 {
02084 $popped = array_pop($stack);
02085
02086
02087 $gap = $popped->rgt - $previousNumber - 1;
02088 if ($gap > 0)
02089 {
02090 $poppedIndent = "";
02091 for ($i = 1; $i < $popped->depth; $i++)
02092 {
02093 $poppedIndent .= ". ";
02094 }
02095 $this->writeScanLogLine(
02096 '<tr>'
02097 .'<td colspan=2><div align="right">'
02098 .'<font color=#00cc00>*gap* for '.($gap/2).' nodes at end of </font>'
02099 .'</div></td>'
02100 .'<td>'
02101 .'<font color=#00cc00>'
02102 .$poppedIndent
02103 .$popped->obj_id.', '
02104 .$popped->type.', '
02105 .$popped->title.', '
02106 .$popped->login
02107 .'</font>'
02108 .'</td>'
02109 .'</tr>'
02110 );
02111 }
02112 $previousNumber = $popped->rgt;
02113 unset($popped);
02114 }
02115
02116
02117
02118 $isRowOkay = true;
02119
02120
02121 $isChildOkay = true;
02122 $isParentOkay = true;
02123 $isLftOkay = true;
02124 $isRgtOkay = true;
02125 $isDepthOkay = true;
02126 $isGap = false;
02127
02128 if (count($stack) > 0)
02129 {
02130 $parent = $stack[count($stack) - 1];
02131 if ($parent->depth + 1 != $row->depth)
02132 {
02133 $isDepthOkay = false;
02134 $isRowOkay = false;
02135 }
02136 if ($parent->child != $row->parent)
02137 {
02138 $isParentOkay = false;
02139 $isRowOkay = false;
02140 }
02141 if ($parent->lft >= $row->lft)
02142 {
02143 $isLftOkay = false;
02144 $isRowOkay = false;
02145 }
02146 if ($parent->rgt <= $row->rgt)
02147 {
02148 $isRgtOkay = false;
02149 $isRowOkay = false;
02150 }
02151 }
02152
02153
02154 if ($row->lft >= $row->rgt)
02155 {
02156 $isLftOkay = false;
02157 $isRgtOkay = false;
02158 $isRowOkay = false;
02159 }
02160 if (in_array($row->child, $duplicateNodes))
02161 {
02162 $isChildOkay = false;
02163 $isRowOkay = false;
02164 }
02165
02166
02167 $isRefRefOkay = true;
02168 $isRefObjOkay = true;
02169 if ($row->ref_id == null)
02170 {
02171 $isRefRefOkay = false;
02172 $isRowOkay = false;
02173 }
02174 if ($row->obj_id == null)
02175 {
02176 $isRefObjOkay = false;
02177 $isRowOkay = false;
02178 }
02179
02180 if (! $isRowOkay)
02181 {
02182 $error_count++;
02183 }
02184
02185
02186
02187 $gap = $row->lft - $previousNumber - 1;
02188 $previousNumber = $row->lft;
02189 if ($gap > 0)
02190 {
02191 $this->writeScanLogLine(
02192 '<tr>'
02193 .'<td colspan=2><div align="right">'
02194 .'<font color=#00cc00>*gap* for '.($gap/2).' nodes between </font>'
02195 .'</div></td>'
02196 .'<td>'
02197 .'<font color=#00cc00>siblings</font>'
02198 .'</td>'
02199 .'</tr>'
02200 );
02201 }
02202
02203
02204
02205 $this->writeScanLogLine(
02206 '<tr>'
02207 .'<td>'
02208 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02209 .$row->tree.', '
02210 .$row->child.', '
02211 .(($isParentOkay) ? '' : 'parent:<b>')
02212 .$row->parent
02213 .(($isParentOkay) ? '' : '</b>')
02214 .', '
02215 .(($isLftOkay) ? '' : 'lft:<b>')
02216 .$row->lft
02217 .(($isLftOkay) ? '' : '</b>')
02218 .', '
02219 .(($isRgtOkay) ? '' : 'rgt:<b>')
02220 .$row->rgt
02221 .(($isRgtOkay) ? '' : '</b>')
02222 .', '
02223 .(($isDepthOkay) ? '' : 'depth:<b>')
02224 .$row->depth
02225 .(($isDepthOkay) ? '' : '</b>')
02226 .(($isRowOkay) ? '' : '</font>')
02227 .'</td><td>'
02228 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02229 .(($isRefRefOkay && $isChildOkay) ? '' : 'ref.ref_id:<b>')
02230 .$row->ref_id
02231 .(($isRefRefOkay && $isChildOkay) ? '' : '</b>')
02232 .', '
02233 .(($isRefObjOkay) ? '' : 'ref.obj_id:<b>')
02234 .$row->refobj_id
02235 .(($isRefObjOkay) ? '' : '</b>')
02236 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02237 .'</td><td>'
02238 .(($isRowOkay) ? '' : '<font color=#ff0000>')
02239 .$indent
02240 .$row->obj_id.', '
02241 .$row->type.', '
02242 .$row->title.', '
02243 .$row->login
02244 .(($isRowOkay) ? '' : ' <b>*ERROR*</b><font color=#ff0000>')
02245 .'</td>'
02246 .'</tr>'
02247 );
02248
02249
02250
02251
02252 $stack[] = $row;
02253
02254
02255
02256 if ($row->tree == 1)
02257 {
02258 $repository_tree_count++;
02259 }
02260 else if ($row->tree < 0)
02261 {
02262 $trash_trees_count++;
02263 }
02264 else
02265 {
02266 $other_trees_count++;
02267 }
02268
02269 }
02270
02271
02272 while (count($stack) > 0)
02273 {
02274 $popped = array_pop($stack);
02275
02276
02277 $gap = $popped->rgt - $previousNumber - 1;
02278 if ($gap > 0)
02279 {
02280 $poppedIndent = "";
02281 for ($i = 1; $i < $popped->depth; $i++)
02282 {
02283 $poppedIndent .= ". ";
02284 }
02285 $this->writeScanLogLine(
02286 '<tr>'
02287 .'<td colspan=2><div align="right">'
02288 .'<font color=#00cc00>*gap* for '.($gap/2).' nodes at end of </font>'
02289 .'</div></td>'
02290 .'<td>'
02291 .'<font color=#00cc00>'
02292 .$poppedIndent
02293 .$popped->obj_id.', '
02294 .$popped->type.', '
02295 .$popped->title
02296 .'</font>'
02297 .'</td>'
02298 .'</tr>'
02299 );
02300 }
02301 $previousNumber = $popped->rgt;
02302 unset($popped);
02303 }
02304
02305
02306 $this->writeScanLogLine("</table>");
02307
02308 if ($error_count > 0)
02309 {
02310 $this->writeScanLogLine('<font color=#ff0000>'.$error_count.' errors found while dumping tree.</font>');
02311 }
02312 else
02313 {
02314 $this->writeScanLogLine('No errors found while dumping tree.');
02315 }
02316 $this->writeScanLogLine("$repository_tree_count nodes in repository tree");
02317 $this->writeScanLogLine("$trash_trees_count nodes in trash trees");
02318 $this->writeScanLogLine("$other_trees_count nodes in other trees");
02319 $this->writeScanLogLine("$not_in_tree_count nodes are not in a tree");
02320 $this->writeScanLogLine("END dumpTree");
02321
02322 return $error_count;
02323 }
02324 }
02325 ?>