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;
1815 if ($this->workspace_object_ids &&
1816 in_array($row->objobj_id, $this->workspace_object_ids)) {
1821 if (is_null($row->child)) {
1822 switch ($row->type) {
1836 if (is_null($row->ref_id)) {
1847 $isParentOkay =
false;
1850 $isDepthOkay =
false;
1855 if ($row->type ===
"fold" && $this->isMediaFolder($row->obj_id)) {
1860 $isParentOkay =
false;
1863 $isDepthOkay =
false;
1868 $not_in_tree_count++;
1873 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1875 . $row->child .
', ' 1876 . (($isParentOkay) ?
'' :
'parent:<b>')
1878 . (($isParentOkay) ?
'' :
'</b>')
1880 . (($isLftOkay) ?
'' :
'lft:<b>')
1882 . (($isLftOkay) ?
'' :
'</b>')
1884 . (($isRgtOkay) ?
'' :
'rgt:<b>')
1886 . (($isRgtOkay) ?
'' :
'</b>')
1888 . (($isDepthOkay) ?
'' :
'depth:<b>')
1890 . (($isDepthOkay) ?
'' :
'</b>')
1891 . (($isRowOkay) ?
'' :
'</font>')
1893 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1894 . (($isRefRefOkay && $isChildOkay) ?
'' :
'ref.ref_id:<b>')
1896 . (($isRefRefOkay && $isChildOkay) ?
'' :
'</b>')
1898 . (($isRefObjOkay) ?
'' :
'ref.obj_id:<b>')
1900 . (($isRefObjOkay) ?
'' :
'</b>')
1901 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1902 . (($row->deleted !=
null) ?
', ' . $row->deleted :
'')
1904 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
1906 . $row->obj_id .
', ' 1908 . $row->login .
', ' 1910 . (($isRowOkay) ?
'' :
' <b>*ERROR*</b><font color=#ff0000>')
1920 for ($i = 1; $i < $row->depth; $i++) {
1925 if (count($stack) === 0 || $stack[0]->tree != $row->tree) {
1927 $previousNumber = $row->lft - 1;
1933 while (count($stack) > 0 && $stack[count($stack) - 1]->rgt < $row->lft) {
1934 $popped = array_pop($stack);
1937 $gap = $popped->rgt - $previousNumber - 1;
1940 for ($i = 1; $i < $popped->depth; $i++) {
1941 $poppedIndent .=
". ";
1945 .
'<td colspan=2><div align="right">' 1946 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes at end of </font>' 1949 .
'<font color=#00cc00>' 1951 . $popped->obj_id .
', ' 1952 . $popped->type .
', ' 1953 . $popped->login .
', ' 1960 $previousNumber = $popped->rgt;
1969 $isChildOkay =
true;
1970 $isParentOkay =
true;
1973 $isDepthOkay =
true;
1976 if (count($stack) > 0) {
1977 $parent = $stack[count($stack) - 1];
1978 if ($parent->depth + 1 != $row->depth) {
1979 $isDepthOkay =
false;
1982 if ($parent->child != $row->parent) {
1983 $isParentOkay =
false;
1986 if (
$GLOBALS[
'ilSetting']->
get(
'main_tree_impl',
'ns') ===
'ns') {
1987 if ($parent->lft >= $row->lft) {
1991 if ($parent->rgt <= $row->rgt) {
1999 if ($row->lft >= $row->rgt &&
$GLOBALS[
'ilSetting']->get(
'main_tree_impl',
'ns') ===
'ns') {
2004 if (in_array($row->child, $duplicateNodes)) {
2005 $isChildOkay =
false;
2010 $isRefRefOkay =
true;
2011 $isRefObjOkay =
true;
2012 if ($row->ref_id ==
null) {
2013 $isRefRefOkay =
false;
2016 if ($row->obj_id ==
null) {
2017 $isRefObjOkay =
false;
2027 if (
$GLOBALS[
'ilSetting']->
get(
'main_tree_impl',
'ns') ===
'ns') {
2028 $gap = $row->lft - $previousNumber - 1;
2029 $previousNumber = $row->lft;
2033 .
'<td colspan=2><div align="right">' 2034 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes between </font>' 2037 .
'<font color=#00cc00>siblings</font>' 2049 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2051 . $row->child .
', ' 2052 . (($isParentOkay) ?
'' :
'parent:<b>')
2054 . (($isParentOkay) ?
'' :
'</b>')
2056 . (($isLftOkay) ?
'' :
'lft:<b>')
2058 . (($isLftOkay) ?
'' :
'</b>')
2060 . (($isRgtOkay) ?
'' :
'rgt:<b>')
2062 . (($isRgtOkay) ?
'' :
'</b>')
2064 . (($isDepthOkay) ?
'' :
'depth:<b>')
2066 . (($isDepthOkay) ?
'' :
'</b>')
2067 . (($isRowOkay) ?
'' :
'</font>')
2069 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2070 . (($isRefRefOkay && $isChildOkay) ?
'' :
'ref.ref_id:<b>')
2072 . (($isRefRefOkay && $isChildOkay) ?
'' :
'</b>')
2074 . (($isRefObjOkay) ?
'' :
'ref.obj_id:<b>')
2076 . (($isRefObjOkay) ?
'' :
'</b>')
2077 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2078 . (($row->tree < 0) ?
', ' . $row->deleted :
'')
2080 . (($isRowOkay) ?
'' :
'<font color=#ff0000>')
2082 . $row->obj_id .
', ' 2084 . $row->login .
', ' 2086 . (($isRowOkay) ?
'' :
' <b>*ERROR*</b><font color=#ff0000>')
2098 if ($row->tree == 1) {
2099 $repository_tree_count++;
2100 } elseif ($row->tree < 0) {
2101 $trash_trees_count++;
2103 $other_trees_count++;
2109 while (count($stack) > 0) {
2110 $popped = array_pop($stack);
2113 $gap = $popped->rgt - $previousNumber - 1;
2116 for ($i = 1; $i < $popped->depth; $i++) {
2117 $poppedIndent .=
". ";
2121 .
'<td colspan=2><div align="right">' 2122 .
'<font color=#00cc00>*gap* for ' . ($gap / 2) .
' nodes at end of </font>' 2125 .
'<font color=#00cc00>' 2127 . $popped->obj_id .
', ' 2128 . $popped->type .
', ' 2129 . $popped->login .
', ' 2136 $previousNumber = $popped->rgt;
2143 if ($error_count > 0) {
2144 $this->
writeScanLogLine(
'<font color=#ff0000>' . $error_count .
' errors found while dumping tree.</font>');
2148 $this->
writeScanLogLine(
"$repository_tree_count nodes in repository tree");
2154 return $error_count;
2161 if (!is_array($this->media_pool_ids)) {
2162 $this->media_pool_ids = [];
2163 $query =
"SELECT child FROM mep_tree ";
2165 while ($row =
$ilDB->fetchObject(
$res)) {
2166 $this->media_pool_ids[] = $row->child;
2170 return in_array($a_obj_id, $this->media_pool_ids);
2184 return in_array($a_type, $this->object_types_exclude);
2191 if ($this->workspace_object_ids ===
null) {
2192 $this->workspace_object_ids = [];
2195 $set =
$ilDB->query(
"SELECT DISTINCT(obj_id) FROM object_reference_ws");
2196 while ($row =
$ilDB->fetchAssoc($set)) {
2197 $this->workspace_object_ids[] = $row[
"obj_id"];
2201 $set =
$ilDB->query(
"SELECT id FROM usr_portfolio");
2202 while ($row =
$ilDB->fetchAssoc($set)) {
2203 $this->workspace_object_ids[] = $row[
"id"];
2210 string $a_index =
"obj_id" 2212 if (count($a_data)) {
2216 if (is_array($this->workspace_object_ids)) {
2217 foreach ($a_data as $idx => $item) {
2218 if (in_array($item[$a_index], $this->workspace_object_ids)) {
2219 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.
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.
writeScanLogLine(string $a_msg)
array $invalid_rbac_entries
restoreTrash(?array $a_deleted_objects=null)
Restore all objects in trash to RecoveryFolder NOTE: All objects will be restored to top of RecoveryF...
purgeObjects(array $a_nodes)
removes objects from system
__construct(bool $a_log=false)
string $scan_log_separator
restoreMissingObjects(?array $a_missing_objects=null)
Restores missing reference and/or tree entry for all objects found by this::getMissingObjects() Resto...
ilObjectDefinition $obj_definition
removeInvalidChilds(?array $a_invalid_childs=null)
Removes all tree entries without any link to a valid object.
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...
removeInvalidReferences(?array $a_invalid_refs=null)
Removes all reference entries that are linked with invalid object IDs.
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...
hasScanLog()
Quickly determine if there is a scan log.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
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.
removeInvalidRolefolders(?array $a_invalid_rolefolders=null)
Removes invalid rolefolders.
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...
restoreUnboundObjects(?array $a_unbound_objects=null)
Restore objects (and their subobjects) to RecoveryFolder that are valid but not linked correctly in t...
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.
purgeUnboundObjects(?array $a_nodes=null)
Removes all invalid objects from system.
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...
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")
purgeTrash(?array $a_nodes=null)
Removes all objects in trash from system.
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...
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.
purgeMissingObjects(?array $a_nodes=null)
Removes all missing objects from system.
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...
exit
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.