52 "adm",
"root",
"mail",
"usrf",
"objf",
"lngf",
53 "trac",
"taxf",
"auth",
"rolf",
"assf",
"svyf",
"extt",
"adve",
"fold" 62 "restore_trash" =>
false,
63 "purge_trash" =>
false 93 $this->obj_definition = $DIC[
"objDefinition"];
94 $this->db = $DIC->database();
95 $this->
lng = $DIC->language();
96 $this->log = $DIC[
"ilLog"];
97 $this->rbacadmin = $DIC->rbac()->admin();
98 $this->tree = $DIC->repositoryTree();
99 $this->
user = $DIC->user();
100 $objDefinition = $DIC[
"objDefinition"];
101 $ilDB = $DIC->database();
104 $this->rbac_object_types = $objDefinition->getAllRBACObjects();
106 if ($a_log ===
true) {
107 $this->logging =
true;
116 $this->scan_log->setLogFormat(
"");
127 return array_keys($this->mode);
139 public function setMode(
string $a_mode,
bool $a_value): bool
141 if ((!array_key_exists($a_mode, $this->mode) && $a_mode !==
"all") || !is_bool($a_value)) {
142 $this->throwError(INVALID_PARAM, FATAL,
DEBUG);
146 if ($a_mode ===
"all") {
147 foreach ($this->mode as $mode => $value) {
148 $this->mode[
$mode] = $a_value;
151 $this->mode[$a_mode] = $a_value;
163 if (!array_key_exists($a_mode, $this->mode)) {
164 $this->throwError(VALIDATER_UNKNOWN_MODE, WARNING,
DEBUG);
168 return $this->mode[$a_mode];
185 if ($this->mode[
"restore"] ===
true) {
186 $this->mode[
"scan"] =
true;
187 $this->mode[
"purge"] =
false;
190 if ($this->mode[
"purge"] ===
true) {
191 $this->mode[
"scan"] =
true;
192 $this->mode[
"restore"] =
false;
195 if ($this->mode[
"restore_trash"] ===
true) {
196 $this->mode[
"scan"] =
true;
197 $this->mode[
"purge_trash"] =
false;
200 if ($this->mode[
"purge_trash"] ===
true) {
201 $this->mode[
"scan"] =
true;
202 $this->mode[
"restore_trash"] =
false;
205 if ($this->mode[
"clean"] ===
true) {
206 $this->mode[
"scan"] =
true;
224 $summary .= $lng->
txt(
"scanning_system");
226 $summary .= $lng->
txt(
"disabled");
228 $summary .=
"<br/>" . $lng->
txt(
"searching_invalid_refs");
232 $summary .= $lng->
txt(
"found_none");
235 $summary .=
"<br/>" . $lng->
txt(
"searching_invalid_childs");
239 $summary .= $lng->
txt(
"found_none");
242 $summary .=
"<br/>" . $lng->
txt(
"searching_missing_objs");
246 $summary .= $lng->
txt(
"found_none");
249 $summary .=
"<br/>" . $lng->
txt(
"searching_unbound_objs");
253 $summary .= $lng->
txt(
"found_none");
256 $summary .=
"<br/>" . $lng->
txt(
"searching_deleted_objs");
260 $summary .= $lng->
txt(
"found_none");
263 $summary .=
"<br/>" . $lng->
txt(
"searching_invalid_rolfs");
267 $summary .= $lng->
txt(
"found_none");
270 $summary .=
"<br/><br/>" . $lng->
txt(
"analyzing_tree_structure");
272 $summary .= $lng->
txt(
"tree_corrupt");
274 $summary .= $lng->
txt(
"done");
280 $summary .=
"<br /><br />" . $lng->
txt(
"dumping_tree");
282 $summary .= $lng->
txt(
"disabled");
285 if ($error_count > 0) {
286 $summary .= $lng->
txt(
"tree_corrupt");
288 $summary .= $lng->
txt(
"done");
294 $summary .=
"<br /><br />" . $lng->
txt(
"cleaning");
296 $summary .= $lng->
txt(
"disabled");
298 $summary .=
"<br />" . $lng->
txt(
"removing_invalid_refs");
300 $summary .= strtolower($lng->
txt(
"done"));
302 $summary .= $lng->
txt(
"nothing_to_remove") . $lng->
txt(
"skipped");
305 $summary .=
"<br />" . $lng->
txt(
"removing_invalid_childs");
307 $summary .= strtolower($lng->
txt(
"done"));
309 $summary .= $lng->
txt(
"nothing_to_remove") . $lng->
txt(
"skipped");
312 $summary .=
"<br />" . $lng->
txt(
"removing_invalid_rolfs");
314 $summary .= strtolower($lng->
txt(
"done"));
316 $summary .= $lng->
txt(
"nothing_to_remove") . $lng->
txt(
"skipped");
326 $summary .=
"<br /><br />" . $lng->
txt(
"restoring");
329 $summary .= $lng->
txt(
"disabled");
331 $summary .=
"<br />" . $lng->
txt(
"restoring_missing_objs");
333 $summary .= strtolower($lng->
txt(
"done"));
335 $summary .= $lng->
txt(
"nothing_to_restore") . $lng->
txt(
"skipped");
338 $summary .=
"<br />" . $lng->
txt(
"restoring_unbound_objs");
340 $summary .= strtolower($lng->
txt(
"done"));
342 $summary .= $lng->
txt(
"nothing_to_restore") . $lng->
txt(
"skipped");
347 $summary .=
"<br /><br />" . $lng->
txt(
"restoring_trash");
350 $summary .= $lng->
txt(
"disabled");
352 $summary .= strtolower($lng->
txt(
"done"));
354 $summary .= $lng->
txt(
"nothing_to_restore") . $lng->
txt(
"skipped");
358 $summary .=
"<br /><br />" . $lng->
txt(
"purging");
361 $summary .= $lng->
txt(
"disabled");
363 $summary .=
"<br />" . $lng->
txt(
"purging_missing_objs");
365 $summary .= strtolower($lng->
txt(
"done"));
367 $summary .= $lng->
txt(
"nothing_to_purge") . $lng->
txt(
"skipped");
370 $summary .=
"<br />" . $lng->
txt(
"purging_unbound_objs");
372 $summary .= strtolower($lng->
txt(
"done"));
374 $summary .= $lng->
txt(
"nothing_to_purge") . $lng->
txt(
"skipped");
379 $summary .=
"<br /><br />" . $lng->
txt(
"purging_trash");
382 $summary .= $lng->
txt(
"disabled");
384 $summary .= strtolower($lng->
txt(
"done"));
386 $summary .= $lng->
txt(
"nothing_to_purge") . $lng->
txt(
"skipped");
391 $summary .=
"<br /><br />" . $lng->
txt(
"cleaning_final");
393 $summary .=
"<br />" . $lng->
txt(
"initializing_gaps") .
" " . strtolower($lng->
txt(
"done"));
401 foreach ($this->mode as $mode => $value) {
402 $arr[] = $mode .
"[" . (
int) $value .
"]";
418 if ($this->mode[
"scan"] !==
true) {
423 $this->missing_objects = [];
432 $q =
"SELECT object_data.*, ref_id FROM object_data " .
433 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id " .
434 "LEFT JOIN tree ON object_reference.ref_id = tree.child " .
435 "WHERE tree.child IS NULL " .
436 "AND (object_reference.obj_id IS NOT NULL " .
437 " OR object_data.type <> 'file' AND " .
438 $ilDB->in(
'object_data.type', $this->rbac_object_types,
false,
'text') .
440 $r = $this->db->query(
$q);
443 #if (!in_array($row->type,$this->object_types_exclude)) 445 $this->missing_objects[] = [
446 "obj_id" => $row->obj_id,
447 "type" => $row->type,
448 "ref_id" => $row->ref_id,
449 "child" => $row->child,
450 "title" => $row->title,
451 "desc" => $row->description,
452 "owner" => $row->owner,
453 "create_date" => $row->create_date,
454 "last_update" => $row->last_update
460 if (count($this->missing_objects) > 0) {
461 $this->
writeScanLogLine(
"obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
482 if ($this->mode[
"scan"] !==
true) {
487 $this->invalid_rolefolders = [];
492 $q =
"SELECT object_data.*, ref_id FROM object_data " .
493 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id " .
494 "LEFT JOIN tree ON object_reference.ref_id = tree.child " .
495 "WHERE (object_reference.obj_id IS NULL OR tree.child IS NULL) " .
496 "AND object_data.type='rolf'";
497 $r = $this->db->query(
$q);
500 $this->invalid_rolefolders[] = [
501 "obj_id" => $row->obj_id,
502 "type" => $row->type,
503 "ref_id" => $row->ref_id,
504 "child" => $row->child,
505 "title" => $row->title,
506 "desc" => $row->description,
507 "owner" => $row->owner,
508 "create_date" => $row->create_date,
509 "last_update" => $row->last_update
514 $q =
"SELECT object_data.*, ref_id FROM object_data " .
515 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id " .
516 "LEFT JOIN tree ON object_reference.ref_id = tree.child " .
518 "AND object_data.type='rolf'";
519 $r = $this->db->query(
$q);
522 $this->invalid_rolefolders[] = [
523 "obj_id" => $row->obj_id,
524 "type" => $row->type,
525 "ref_id" => $row->ref_id,
526 "child" => $row->child,
527 "title" => $row->title,
528 "desc" => $row->description,
529 "owner" => $row->owner,
530 "create_date" => $row->create_date,
531 "last_update" => $row->last_update
536 if (count($this->invalid_rolefolders) > 0) {
537 $this->
writeScanLogLine(
"obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
556 if ($this->mode[
"scan"] !==
true) {
561 $this->invalid_rbac_entries = [];
565 $q =
"SELECT object_data.*, ref_id FROM object_data " .
566 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id " .
567 "LEFT JOIN tree ON object_reference.ref_id = tree.child " .
568 "WHERE (object_reference.obj_id IS NULL OR tree.child IS NULL) " .
569 "AND object_data.type='rolf'";
570 $r = $this->db->query(
$q);
573 $this->invalid_rolefolders[] = [
574 "obj_id" => $row->obj_id,
575 "type" => $row->type,
576 "ref_id" => $row->ref_id,
577 "child" => $row->child,
578 "title" => $row->title,
579 "desc" => $row->description,
580 "owner" => $row->owner,
581 "create_date" => $row->create_date,
582 "last_update" => $row->last_update
587 $q =
"SELECT object_data.*, ref_id FROM object_data " .
588 "LEFT JOIN object_reference ON object_data.obj_id = object_reference.obj_id " .
589 "LEFT JOIN tree ON object_reference.ref_id = tree.child " .
591 "AND object_data.type='rolf'";
592 $r = $this->db->query(
$q);
595 $this->invalid_rolefolders[] = [
596 "obj_id" => $row->obj_id,
597 "type" => $row->type,
598 "ref_id" => $row->ref_id,
599 "child" => $row->child,
600 "title" => $row->title,
601 "desc" => $row->description,
602 "owner" => $row->owner,
603 "create_date" => $row->create_date,
604 "last_update" => $row->last_update
609 if (count($this->invalid_rolefolders) > 0) {
610 $this->
writeScanLogLine(
"obj_id\ttype\tref_id\tchild\ttitle\tdesc\towner\tcreate_date\tlast_update");
642 if ($this->mode[
"scan"] !==
true) {
647 $this->invalid_references = [];
650 $q =
"SELECT object_reference.* FROM object_reference " .
651 "LEFT JOIN object_data ON object_data.obj_id = object_reference.obj_id " .
652 "WHERE object_data.obj_id IS NULL " .
653 "OR " .
$ilDB->in(
'object_data.type', $this->rbac_object_types,
true,
'text');
654 $r = $this->db->query(
$q);
657 $this->invalid_references[] = [
658 "ref_id" => $row->ref_id,
659 "obj_id" => $row->obj_id,
660 "msg" =>
"Object does not exist." 665 if (count($this->invalid_references) > 0) {
691 if ($this->mode[
"scan"] !==
true) {
696 $this->invalid_childs = [];
700 $q =
"SELECT tree.*,object_reference.ref_id FROM tree " .
701 "LEFT JOIN object_reference ON tree.child = object_reference.ref_id " .
702 "LEFT JOIN object_data ON object_reference.obj_id = object_data.obj_id " .
703 "WHERE object_reference.ref_id IS NULL or object_data.obj_id IS NULL";
704 $r = $this->db->query(
$q);
706 $this->invalid_childs[] = [
707 "child" => $row->child,
708 "ref_id" => $row->ref_id,
709 "msg" =>
"No object found" 713 if (count($this->invalid_childs) > 0) {
741 if ($this->mode[
"scan"] !==
true) {
746 $this->unbound_objects = [];
750 $q =
"SELECT T1.tree,T1.child,T1.parent," .
751 "T2.tree deleted,T2.parent grandparent " .
753 "LEFT JOIN tree T2 ON T2.child=T1.parent " .
754 "WHERE (T2.tree!=1 OR T2.tree IS NULL) AND T1.parent!=0";
755 $r = $this->db->query(
$q);
759 if ($row->deleted === null) {
760 $this->unbound_objects[] = [
761 "child" => $row->child,
762 "parent" => $row->parent,
763 "tree" => $row->tree,
764 "msg" =>
"No valid parent node found" 769 if (count($this->unbound_objects) > 0) {
789 if ($this->mode[
"scan"] !==
true) {
794 $this->deleted_objects = [];
799 $query =
"SELECT object_data.*,tree.tree,tree.child,tree.parent,deleted " .
800 "FROM object_data " .
801 "LEFT JOIN object_reference ON object_data.obj_id=object_reference.obj_id " .
802 "LEFT JOIN tree ON tree.child=object_reference.ref_id " .
803 " WHERE tree != 1 " .
805 $r = $this->db->query($query);
810 $this->deleted_objects[] = [
811 "child" => $row->child,
812 "parent" => $row->parent,
813 "tree" => $row->tree,
814 "type" => $row->type,
815 "title" => $row->title,
816 "desc" => $row->description,
817 "owner" => $row->owner,
818 "deleted" => $row->deleted,
819 "deleted_timestamp" => $tmp_date->get(
IL_CAL_UNIX),
820 "create_date" => $row->create_date,
821 "last_update" => $row->last_update
825 if (count($this->deleted_objects) > 0) {
870 array $a_invalid_refs = null
876 if ($this->mode[
"clean"] !==
true) {
882 if ($a_invalid_refs === null && isset($this->invalid_references)) {
887 if (!is_array($a_invalid_refs)) {
888 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
892 if (count($a_invalid_refs) === 0) {
902 '%s::removeInvalidReferences(): Started...',
905 $ilLog->write(
$message, $ilLog->WARNING);
910 foreach ($a_invalid_refs as $entry) {
911 $query =
"DELETE FROM object_reference WHERE ref_id= " . $this->db->quote($entry[
"ref_id"],
'integer') .
912 " AND obj_id = " . $this->db->quote($entry[
"obj_id"],
'integer') .
" ";
916 '%s::removeInvalidReferences(): Reference %s removed',
920 $ilLog->write(
$message, $ilLog->WARNING);
934 array $a_invalid_childs = null
939 if ($this->mode[
"clean"] !==
true) {
945 if ($a_invalid_childs === null && isset($this->invalid_childs)) {
950 if (!is_array($a_invalid_childs)) {
951 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
956 if (count($a_invalid_childs) === 0) {
966 '%s::removeInvalidChilds(): Started...',
969 $ilLog->write(
$message, $ilLog->WARNING);
971 foreach ($a_invalid_childs as $entry) {
972 $q =
"DELETE FROM tree WHERE child='" . $entry[
"child"] .
"'";
973 $this->db->query(
$q);
976 '%s::removeInvalidChilds(): Entry child=%s removed',
980 $ilLog->write(
$message, $ilLog->WARNING);
995 array $a_invalid_rolefolders = null
1000 if ($this->mode[
"clean"] !==
true) {
1006 if ($a_invalid_rolefolders === null && isset($this->invalid_rolefolders)) {
1011 if (!is_array($a_invalid_rolefolders)) {
1012 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1017 if (count($a_invalid_rolefolders) === 0) {
1029 '%s::removeInvalidRolefolders(): Started...',
1032 $ilLog->write(
$message, $ilLog->WARNING);
1037 foreach ($a_invalid_rolefolders as $rolf) {
1039 if ($rolf[
"ref_id"] === null) {
1042 $this->
writeScanLogLine(
"Created missing reference '" . $rolf[
"ref_id"] .
"' for rolefolder object '" . $rolf[
"obj_id"] .
"'");
1047 $obj_data->delete();
1050 $this->
writeScanLogLine(
"Removed invalid rolefolder '" . $rolf[
"title"] .
"' (id=" . $rolf[
"obj_id"] .
",ref=" . $rolf[
"ref_id"] .
") from system");
1065 array $a_missing_objects = null
1071 if ($this->mode[
"restore"] !==
true) {
1077 if ($a_missing_objects === null && isset($this->missing_objects)) {
1082 if (!is_array($a_missing_objects)) {
1083 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1088 if (count($a_missing_objects) === 0) {
1100 '%s::restoreMissingObjects(): Started...',
1103 $ilLog->write(
$message, $ilLog->WARNING);
1108 foreach ($a_missing_objects as $missing_obj) {
1110 if ($missing_obj[
"ref_id"] === null) {
1113 $this->
writeScanLogLine(
"Created missing reference '" . $missing_obj[
"ref_id"] .
"' for object '" . $missing_obj[
"obj_id"] .
"'");
1117 #if (!in_array($missing_obj["type"],$this->object_types_exclude)) 1126 $this->
writeScanLogLine(
"Restored object '" . $missing_obj[
"title"] .
"' (id=" . $missing_obj[
"obj_id"] .
",ref=" . $missing_obj[
"ref_id"] .
") in 'Restored objects folder'");
1145 if (empty($a_obj_id)) {
1146 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1150 $next_id =
$ilDB->nextId(
'object_reference');
1151 $query =
"INSERT INTO object_reference (ref_id, obj_id) " .
1152 "VALUES (" . $this->db->quote($next_id,
'integer') .
", " . $this->db->quote($a_obj_id,
'integer') .
")";
1156 '%s::restoreReference(): new reference %s for obj_id %s created',
1161 $ilLog->write(
$message, $ilLog->WARNING);
1172 array $a_unbound_objects = null
1177 if ($this->mode[
"restore"] !==
true) {
1183 if ($a_unbound_objects === null && isset($this->unbound_objects)) {
1188 if (!is_array($a_unbound_objects)) {
1189 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1194 '%s::restoreUnboundObjects(): Started...',
1197 $ilLog->write(
$message, $ilLog->WARNING);
1210 array $a_deleted_objects = null
1215 if ($this->mode[
"restore_trash"] !==
true) {
1221 if ($a_deleted_objects === null && isset($this->deleted_objects)) {
1226 if (!is_array($a_deleted_objects)) {
1227 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1232 '%s::restoreTrash(): Started...',
1235 $ilLog->write(
$message, $ilLog->WARNING);
1241 $q =
"DELETE FROM tree WHERE tree!=1";
1242 $this->db->query(
$q);
1245 '%s::restoreTrash(): Removed all trees with tree id <> 1',
1248 $ilLog->write(
$message, $ilLog->WARNING);
1271 if (!is_array($a_nodes)) {
1272 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1277 if (count($a_nodes) === 0) {
1283 '%s::restoreDeletedObjects()): Started...',
1286 $ilLog->write(
$message, $ilLog->WARNING);
1291 foreach ($a_nodes as
$key => $node) {
1292 if ($node[
"type"] ===
"rolf") {
1297 $obj_data->delete();
1298 unset($a_nodes[
$key]);
1303 foreach ($a_nodes as $node) {
1329 if (!is_array($a_nodes)) {
1330 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1335 if (count($a_nodes) === 0) {
1348 '%s::restoreSubTrees(): Started...',
1351 $ilLog->write(
$message, $ilLog->WARNING);
1354 foreach ($a_nodes as $node) {
1356 $topnode = $tree->
getNodeData($node[
"child"], $node[
'tree']);
1360 if ($topnode[
"type"] ===
"rolf") {
1363 unset($top_node, $rolfObj);
1368 $subnodes[$node[
"child"]] = $tree->
getSubTree($topnode);
1376 foreach ($subnodes as
$key => $subnode) {
1386 array_shift($subnode);
1389 if (count($subnode) > 0) {
1390 foreach ($subnode as $node) {
1393 $obj_data->putInTree($node[
"parent"]);
1394 $obj_data->setPermissions($node[
"parent"]);
1414 array $a_nodes = null
1419 if ($this->mode[
"purge_trash"] !==
true) {
1425 if ($a_nodes === null && isset($this->deleted_objects)) {
1429 '%s::purgeTrash(): Started...',
1432 $ilLog->write(
$message, $ilLog->WARNING);
1444 array $a_nodes = null
1449 if ($this->mode[
"purge"] !==
true) {
1455 if ($a_nodes === null && isset($this->unbound_objects)) {
1460 '%s::purgeUnboundObjects(): Started...',
1463 $ilLog->write(
$message, $ilLog->WARNING);
1475 array $a_nodes = null
1480 if ($this->mode[
"purge"] !==
true) {
1486 if ($a_nodes === null && isset($this->missing_objects)) {
1491 '%s::purgeMissingObjects(): Started...',
1494 $ilLog->write(
$message, $ilLog->WARNING);
1512 $count_limit = $ilUser->
getPref(
"systemcheck_count_limit");
1513 if (!is_numeric($count_limit) || $count_limit < 0) {
1514 $count_limit = count($a_nodes);
1516 $timestamp_limit = time();
1517 $age_limit = $ilUser->getPref(
"systemcheck_age_limit");
1518 if (is_numeric($age_limit) && $age_limit > 0) {
1519 $timestamp_limit -= $age_limit * 60 * 60 * 24;
1521 $type_limit = $ilUser->getPref(
"systemcheck_type_limit");
1523 $type_limit = trim($type_limit);
1524 if ($type_limit ===
'') {
1530 if (!is_array($a_nodes)) {
1531 $this->throwError(INVALID_PARAM, WARNING,
DEBUG);
1538 foreach ($a_nodes as $node) {
1539 if ($type_limit && $node[
'type'] != $type_limit) {
1542 $node[
'child'] .
"\t\t" . $node[
'type'] .
"\t\t" . $node[
'title']
1549 if ($count > $count_limit) {
1550 $this->
writeScanLogLine(
"Stopped purging after " . ($count - 1) .
" objects, because count limit was reached: " . $count_limit);
1553 if ($node[
"deleted_timestamp"] > $timestamp_limit) {
1554 $this->
writeScanLogLine(
"Stopped purging after " . ($count - 1) .
" objects, because timestamp limit was reached: " . date(
"c", $timestamp_limit));
1558 $ref_id = ($node[
"child"]) ?: $node[
"ref_id"];
1561 if ($node_obj ===
false) {
1562 $this->invalid_objects[] = $node;
1567 '%s::purgeObjects(): Removing object (id:%s ref:%s)',
1572 $ilLog->write(
$message, $ilLog->WARNING);
1574 $startTime = microtime(
true);
1575 $node_obj->delete();
1577 $endTime = microtime(
true);
1580 "\t" . $node[
'type'] .
"\t" . round($endTime - $startTime, 1) .
"\t" . $node[
'title']);
1605 '%s::initGapsInTree(): Started...',
1608 $ilLog->write(
$message, $ilLog->WARNING);
1611 if ($this->mode[
"clean"] !==
true) {
1632 $call_loc = $error->backtrace[count($error->backtrace) - 1];
1633 $num_args = count($call_loc[
"args"]);
1636 if ($num_args > 0) {
1637 foreach ($call_loc[
"args"] as $arg) {
1638 $type = gettype($arg);
1642 $value = strlen($arg);
1646 $value = count($arg);
1650 $value = get_class($arg);
1654 $value = ($arg) ?
"true" :
"false";
1664 "value" =>
"(" . $value .
")" 1668 foreach ($arg_list as $arg) {
1669 $arg_str .= implode(
"", $arg) .
" ";
1673 $err_msg =
"<br/><b>" . $error->getCode() .
":</b> " . $error->getMessage() .
" in " . $call_loc[
"class"] . $call_loc[
"type"] . $call_loc[
"function"] .
"()" .
1674 "<br/>Called from: " . basename($call_loc[
"file"]) .
" , line " . $call_loc[
"line"] .
1675 "<br/>Passed parameters: [" . $num_args .
"] " . $arg_str .
"<br/>";
1686 if ($error->getCode() == FATAL) {
1697 foreach ($a_arr as $entry) {
1698 $this->scan_log->write(implode(
"\t", $entry));
1708 $this->scan_log->write($a_msg);
1747 $logs = array_keys($a_scan_log, $this->scan_log_separator .
"\n");
1749 if (count($logs) > 0) {
1750 return array_slice($a_scan_log, array_pop($logs) + 2);
1774 $q =
'SELECT child FROM tree GROUP BY child HAVING COUNT(*) > 1';
1775 $r = $this->db->query(
$q);
1776 $duplicateNodes = [];
1778 $duplicateNodes[] = $row->child;
1782 $q =
"SELECT tree.*,ref.ref_id,dat.obj_id objobj_id,ref.obj_id refobj_id,ref.deleted,dat.* " 1784 .
"RIGHT JOIN object_reference ref ON tree.child = ref.ref_id " 1785 .
"RIGHT JOIN object_data dat ON ref.obj_id = dat.obj_id " 1787 .
"ORDER BY tree, lft, type, dat.title";
1788 $r = $this->db->query(
$q);
1792 .
'<td>tree, child, parent, lft, rgt, depth</td>' 1793 .
'<td>ref_id, ref.obj_id, deleted</td>' 1794 .
'<td>obj_id, type, owner, title</td>' 1803 $repository_tree_count = 0;
1804 $trash_trees_count = 0;
1805 $other_trees_count = 0;
1806 $not_in_tree_count = 0;
1809 $previousNumber = 0;
1812 $isRefRefOkay =
true;
1813 $isRefObjOkay =
true;
1814 $isChildOkay =
true;
1818 if ($this->workspace_object_ids &&
1819 in_array($row->objobj_id, $this->workspace_object_ids)) {
1824 if (is_null($row->child)) {
1825 switch ($row->type) {
1839 if (is_null($row->ref_id)) {
1850 $isParentOkay =
false;
1853 $isDepthOkay =
false;
1858 if ($row->type ===
"fold" && $this->isMediaFolder($row->obj_id)) {
1863 $isParentOkay =
false;
1866 $isDepthOkay =
false;
1871 $not_in_tree_count++;
1876 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1878 . $row->child .
', ' 1879 . (($isParentOkay) ?
'' :
'parent:<b>')
1881 . (($isParentOkay) ?
'' :
'</b>')
1883 . (($isLftOkay) ?
'' :
'lft:<b>')
1885 . (($isLftOkay) ?
'' :
'</b>')
1887 . (($isRgtOkay) ?
'' :
'rgt:<b>')
1889 . (($isRgtOkay) ?
'' :
'</b>')
1891 . (($isDepthOkay) ?
'' :
'depth:<b>')
1893 . (($isDepthOkay) ?
'' :
'</b>')
1894 . (($isRowOkay) ?
'' :
'</font>')
1896 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1897 . (($isRefRefOkay && $isChildOkay) ?
'' :
'ref.ref_id:<b>')
1899 . (($isRefRefOkay && $isChildOkay) ?
'' :
'</b>')
1901 . (($isRefObjOkay) ?
'' :
'ref.obj_id:<b>')
1903 . (($isRefObjOkay) ?
'' :
'</b>')
1904 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1905 . (($row->deleted != null) ?
', ' . $row->deleted :
'')
1907 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1909 . $row->obj_id .
', ' 1911 . ($row->login ??
'') .
', ' 1913 . (($isRowOkay) ?
'' :
' <b>*ERROR*</b><font color=#ff0000>')
1923 for ($i = 1; $i < $row->depth; $i++) {
1928 if (count($stack) === 0 || $stack[0]->tree != $row->tree) {
1930 $previousNumber = $row->lft - 1;
1936 while (count($stack) > 0 && $stack[count($stack) - 1]->rgt < $row->lft) {
1937 $popped = array_pop($stack);
1940 $gap = $popped->rgt - $previousNumber - 1;
1943 for ($i = 1; $i < $popped->depth; $i++) {
1944 $poppedIndent .=
". ";
1948 .
'<td colspan=2><div align="right">' 1949 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes at end of </font>' 1952 .
'<font color=#00cc00>' 1954 . $popped->obj_id .
', ' 1955 . $popped->type .
', ' 1956 . ($popped->login ??
'') .
', ' 1963 $previousNumber = $popped->rgt;
1972 $isChildOkay =
true;
1973 $isParentOkay =
true;
1976 $isDepthOkay =
true;
1979 if (count($stack) > 0) {
1980 $parent = $stack[count($stack) - 1];
1981 if ($parent->depth + 1 != $row->depth) {
1982 $isDepthOkay =
false;
1985 if ($parent->child != $row->parent) {
1986 $isParentOkay =
false;
1989 if (
$GLOBALS[
'ilSetting']->
get(
'main_tree_impl',
'ns') ===
'ns') {
1990 if ($parent->lft >= $row->lft) {
1994 if ($parent->rgt <= $row->rgt) {
2002 if ($row->lft >= $row->rgt &&
$GLOBALS[
'ilSetting']->get(
'main_tree_impl',
'ns') ===
'ns') {
2007 if (in_array($row->child, $duplicateNodes)) {
2008 $isChildOkay =
false;
2013 $isRefRefOkay =
true;
2014 $isRefObjOkay =
true;
2015 if ($row->ref_id == null) {
2016 $isRefRefOkay =
false;
2019 if ($row->obj_id == null) {
2020 $isRefObjOkay =
false;
2030 if (
$GLOBALS[
'ilSetting']->
get(
'main_tree_impl',
'ns') ===
'ns') {
2031 $gap = $row->lft - $previousNumber - 1;
2032 $previousNumber = $row->lft;
2036 .
'<td colspan=2><div align="right">' 2037 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes between </font>' 2040 .
'<font color=#00cc00>siblings</font>' 2052 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2054 . $row->child .
', ' 2055 . (($isParentOkay) ?
'' :
'parent:<b>')
2057 . (($isParentOkay) ?
'' :
'</b>')
2059 . (($isLftOkay) ?
'' :
'lft:<b>')
2061 . (($isLftOkay) ?
'' :
'</b>')
2063 . (($isRgtOkay) ?
'' :
'rgt:<b>')
2065 . (($isRgtOkay) ?
'' :
'</b>')
2067 . (($isDepthOkay) ?
'' :
'depth:<b>')
2069 . (($isDepthOkay) ?
'' :
'</b>')
2070 . (($isRowOkay) ?
'' :
'</font>')
2072 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2073 . (($isRefRefOkay && $isChildOkay) ?
'' :
'ref.ref_id:<b>')
2075 . (($isRefRefOkay && $isChildOkay) ?
'' :
'</b>')
2077 . (($isRefObjOkay) ?
'' :
'ref.obj_id:<b>')
2079 . (($isRefObjOkay) ?
'' :
'</b>')
2080 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2081 . (($row->tree < 0) ?
', ' . $row->deleted :
'')
2083 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2085 . $row->obj_id .
', ' 2087 . ($row->login ??
'') .
', ' .
', ' 2089 . (($isRowOkay) ?
'' :
' <b>*ERROR*</b><font color=#ff0000>')
2101 if ($row->tree == 1) {
2102 $repository_tree_count++;
2103 } elseif ($row->tree < 0) {
2104 $trash_trees_count++;
2106 $other_trees_count++;
2112 while (count($stack) > 0) {
2113 $popped = array_pop($stack);
2116 $gap = $popped->rgt - $previousNumber - 1;
2119 for ($i = 1; $i < $popped->depth; $i++) {
2120 $poppedIndent .=
". ";
2124 .
'<td colspan=2><div align="right">' 2125 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes at end of </font>' 2128 .
'<font color=#00cc00>' 2130 . $popped->obj_id .
', ' 2131 . $popped->type .
', ' 2132 . ($popped->login ??
'') .
', ' 2139 $previousNumber = $popped->rgt;
2146 if ($error_count > 0) {
2147 $this->
writeScanLogLine(
'<font color=#ff0000>' . $error_count .
' errors found while dumping tree.</font>');
2151 $this->
writeScanLogLine(
"$repository_tree_count nodes in repository tree");
2157 return $error_count;
2164 if (!is_array($this->media_pool_ids)) {
2165 $this->media_pool_ids = [];
2166 $query =
"SELECT child FROM mep_tree ";
2168 while ($row =
$ilDB->fetchObject(
$res)) {
2169 $this->media_pool_ids[] = $row->child;
2173 return in_array($a_obj_id, $this->media_pool_ids);
2187 return in_array($a_type, $this->object_types_exclude);
2194 if ($this->workspace_object_ids === null) {
2195 $this->workspace_object_ids = [];
2198 $set =
$ilDB->query(
"SELECT DISTINCT(obj_id) FROM object_reference_ws");
2199 while ($row =
$ilDB->fetchAssoc($set)) {
2200 $this->workspace_object_ids[] = $row[
"obj_id"];
2204 $set =
$ilDB->query(
"SELECT id FROM usr_portfolio");
2205 while ($row =
$ilDB->fetchAssoc($set)) {
2206 $this->workspace_object_ids[] = $row[
"id"];
2213 string $a_index =
"obj_id" 2215 if (count($a_data)) {
2219 if (is_array($this->workspace_object_ids)) {
2220 foreach ($a_data as $idx => $item) {
2221 if (in_array($item[$a_index], $this->workspace_object_ids)) {
2222 unset($a_data[$idx]);
findDeletedObjects()
Search database for all tree entries having no valid parent (=> no valid path to root node) and store...
array $invalid_objects
contains correct registrated objects but data are corrupted (experimental)
getDeletedObjects()
Gets all object in trash.
getNodeData(int $a_node_id, ?int $a_tree_pk=null)
get all information of a node.
removeInvalidChilds(array $a_invalid_childs=null)
Removes all tree entries without any link to a valid object.
findMissingObjects()
Search database for all object entries with missing reference and/or tree entry and stores result in ...
array $object_types_exclude
list of object types to exclude from recovering
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
isModeEnabled(string $a_mode)
getInvalidChilds()
Gets all tree entries without any link to a valid object.
purgeUnboundObjects(array $a_nodes=null)
Removes all invalid objects from system.
writeScanLogLine(string $a_msg)
array $invalid_rbac_entries
purgeObjects(array $a_nodes)
removes objects from system
__construct(bool $a_log=false)
string $scan_log_separator
ilObjectDefinition $obj_definition
deleteScanLog()
Delete scan log.
deleteTree(array $a_node)
delete node and the whole subtree under this node
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
revokePermission(int $a_ref_id, int $a_rol_id=0, bool $a_keep_protected=true)
Revokes permissions of an object of one role.
dumpTree()
Dumps the Tree structure into the scan log.
isExcludedFromRecovery(string $a_type, int $a_obj_id)
handleErr(object $error)
Callback function handles PEAR_error and outputs detailed infos about error TODO: implement that in g...
writeScanLogArray(array $a_arr)
findInvalidChilds()
Search database for all tree entries without any link to a valid object and stores result in $this->i...
getUnboundObjects()
Gets all tree entries having no valid parent (=> no valid path to root node) Returns an array with ch...
purgeMissingObjects(array $a_nodes=null)
Removes all missing objects from system.
restoreMissingObjects(array $a_missing_objects=null)
Restores missing reference and/or tree entry for all objects found by this::getMissingObjects() Resto...
hasScanLog()
Quickly determine if there is a scan log.
parses the objects.xml it handles the xml-description of all ilias objects
restoreUnboundObjects(array $a_unbound_objects=null)
Restore objects (and their subobjects) to RecoveryFolder that are valid but not linked correctly in t...
get_last_scan(array $a_scan_log)
getInvalidReferences()
Gets all reference entries that are not linked with a valid object id.
validate()
Performs the validation for each enabled mode.
getMissingObjects()
Gets all object entries with missing reference and/or tree entry.
restoreSubTrees(array $a_nodes)
Restore objects (and their subobjects) to RecoveryFolder.
getPref(string $a_keyword)
restoreReference(int $a_obj_id)
restore a reference for an object Creates a new reference entry in DB table object_reference for $a_o...
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
renumber(int $node_id=1, int $i=1)
Wrapper for renumber.
restoreDeletedObjects(array $a_nodes)
Restore deleted objects (and their subobjects) to RecoveryFolder.
array $invalid_rolefolders
contains missing objects that are rolefolders.
findInvalidReferences()
Search database for all reference entries that are not linked with a valid object id and stores resul...
removeInvalidReferences(array $a_invalid_refs=null)
Removes all reference entries that are linked with invalid object IDs.
findInvalidRolefolders()
Search database for all rolefolder object entries with missing reference entry.
getInvalidRolefolders()
Gets invalid rolefolders (same as missing objects)
array $workspace_object_ids
getPossibleModes()
get possible ilValidator modes
filterWorkspaceObjects(array &$a_data, string $a_index="obj_id")
findUnboundObjects()
Search database for all tree entries having no valid parent (=> no valid path to root node) and store...
setModeDependencies()
Sets modes by considering mode dependencies; some modes require other modes to be activated...
restoreTrash(array $a_deleted_objects=null)
Restore all objects in trash to RecoveryFolder NOTE: All objects will be restored to top of RecoveryF...
array $invalid_references
findInvalidRBACEntries()
Search database for all role entries that are linked to invalid ref_ids, stores results in $this->inv...
setMode(string $a_mode, bool $a_value)
set mode of ilValidator Usage: setMode("restore",true) => enable object restorey setMode("all",true) => enable all features For all possible modes see variables declaration
isMediaFolder(int $a_obj_id)
Class ilRbacAdmin Core functions for role based access control.
removeInvalidRolefolders(array $a_invalid_rolefolders=null)
Removes invalid rolefolders.
getSubTree(array $a_node, bool $a_with_data=true, array $a_type=[])
get all nodes in the subtree under specified node
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _removeEntry(int $a_tree, int $a_child, string $a_db_table="tree")
STATIC METHOD Removes a single entry from a tree.
initGapsInTree()
Initializes gaps in lft/rgt values of a tree.
purgeTrash(array $a_nodes=null)
Removes all objects in trash from system.