ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilRepUtil.php
Go to the documentation of this file.
1<?php
2
25{
26 protected ilDBInterface $db;
27 protected ilTree $tree;
29
30 public function __construct()
31 {
32 global $DIC;
33
34 $this->db = $DIC->database();
35 $this->tree = $DIC->repositoryTree();
36 $this->settings = $DIC->settings();
37 }
38
46 public static function deleteObjects(
47 int $a_cur_ref_id,
48 array $a_ids
49 ): void {
50 global $DIC;
51
52 $DIC->repository()->internal()->domain()->deletion()->deleteObjectsByRefIds($a_ids);
53 }
54
64 public static function removeObjectsFromSystem(
65 array $a_ref_ids,
66 bool $a_from_recovery_folder = false
67 ): void {
68 global $DIC;
69
70 $ilLog = $DIC["ilLog"];
71 $ilAppEventHandler = $DIC["ilAppEventHandler"];
72 $tree = $DIC->repositoryTree();
73 $logger = $DIC->logger()->rep();
74
75 $log = $ilLog;
76
77 $affected_ids = [];
78
79 // DELETE THEM
80 $a_ref_ids = array_map('intval', $a_ref_ids);
81 foreach ($a_ref_ids as $id) {
82 $saved_tree = null;
83 // GET COMPLETE NODE_DATA OF ALL SUBTREE NODES
84 if (!$a_from_recovery_folder) {
86 $tree_id = end($trees);
87
88 if ($tree_id) {
89 $saved_tree = new ilTree($tree_id);
90 $node_data = $saved_tree->getNodeData($id);
91 $subtree_nodes = $saved_tree->getSubTree($node_data);
92 } else {
93 if (isset($affected_ids[$id])) { // see #43992
94 continue;
95 } else {
96 throw new ilRepositoryException('No valid tree id found for node id: ' . $id);
97 }
98 }
99 } else {
100 $node_data = $tree->getNodeData($id);
101 $subtree_nodes = $tree->getSubTree($node_data);
102 }
103
104 global $DIC;
105
106 $ilUser = $DIC->user();
107 $tree = $DIC->repositoryTree();
108
110 $node_data['obj_id'],
111 $ilUser->getId(),
112 'purge',
113 null
114 );
115 // END ChangeEvent: Record remove from system.
116
117 // remember already checked deleted node_ids
118 if (!$a_from_recovery_folder) {
119 $checked[] = -$id;
120 } else {
121 $checked[] = $id;
122 }
123
124 // dive in recursive manner in each already deleted subtrees and remove these objects too
125 self::removeDeletedNodes($id, $checked, true, $affected_ids);
126
127 foreach ($subtree_nodes as $node) {
128 if (!$node_obj = ilObjectFactory::getInstanceByRefId($node["ref_id"], false)) {
129 continue;
130 }
131
132 $logger->info(
133 'delete obj_id: ' . $node_obj->getId() .
134 ', ref_id: ' . $node_obj->getRefId() .
135 ', type: ' . $node_obj->getType() .
136 ', title: ' . $node_obj->getTitle()
137 );
138 $affected_ids[$node["ref_id"]] = [
139 "ref_id" => $node["ref_id"],
140 "obj_id" => $node_obj->getId(),
141 "type" => $node_obj->getType(),
142 "old_parent_ref_id" => $node["parent"]
143 ];
144
145 $node_obj->delete();
146 }
147
148 // Use the saved tree object here (negative tree_id)
149 if (!$a_from_recovery_folder) {
150 if ($saved_tree) {
151 $saved_tree->deleteTree($node_data);
152 }
153 } else {
154 $tree->deleteTree($node_data);
155 }
156
157 $logger->info(
158 'deleted tree, tree_id: ' . $node_data['tree'] .
159 ', child: ' . $node_data['child']
160 );
161 }
162
163 // send global events
164 foreach ($affected_ids as $aid) {
165 $ilAppEventHandler->raise(
166 "components/ILIAS/ILIASObject",
167 "delete",
168 [
169 "obj_id" => $aid["obj_id"],
170 "ref_id" => $aid["ref_id"],
171 "type" => $aid["type"],
172 "old_parent_ref_id" => $aid["old_parent_ref_id"]
173 ]
174 );
175 }
176 }
177
181 private static function removeDeletedNodes(
182 int $a_node_id,
183 array $a_checked,
184 bool $a_delete_objects,
185 array &$a_affected_ids
186 ): void {
187 global $DIC;
188
189 $ilLog = $DIC["ilLog"];
190 $ilDB = $DIC->database();
191 $tree = $DIC->repositoryTree();
192 $logger = $DIC->logger()->rep();
193
194 $log = $ilLog;
195
196 // this queries for trash items in the trash of deleted nodes
197 $q = 'SELECT tree FROM tree WHERE parent = ' . $ilDB->quote($a_node_id, ilDBConstants::T_INTEGER) .
198 ' AND tree < 0 ' .
199 ' AND tree = -1 * child' ;
200
201 $r = $ilDB->query($q);
202
203 while ($row = $ilDB->fetchObject($r)) {
204 // only continue recursion if fetched node wasn't touched already!
205 if (!in_array($row->tree, $a_checked)) {
206 $deleted_tree = new ilTree($row->tree);
207 $a_checked[] = $row->tree;
208
209 $row->tree *= (-1);
210 $del_node_data = $deleted_tree->getNodeData($row->tree);
211 $del_subtree_nodes = $deleted_tree->getSubTree($del_node_data);
212 // delete trash in the trash of trash...
213 self::removeDeletedNodes($row->tree, $a_checked, $a_delete_objects, $a_affected_ids);
214
215 if ($a_delete_objects) {
216 foreach ($del_subtree_nodes as $node) {
217 $node_obj = ilObjectFactory::getInstanceByRefId($node["ref_id"]);
218 $logger->info(
219 'removeDeletedNodes: delete obj_id: ' . $node_obj->getId() .
220 ', ref_id: ' . $node_obj->getRefId() .
221 ', type: ' . $node_obj->getType() .
222 ', title: ' . $node_obj->getTitle()
223 );
224 $a_affected_ids[$node["ref_id"]] = [
225 "ref_id" => $node["ref_id"],
226 "obj_id" => $node_obj->getId(),
227 "type" => $node_obj->getType(),
228 "old_parent_ref_id" => $node["parent"]
229 ];
230 $node_obj->delete();
231 }
232 }
233 // tree instance with -child tree id
234 $trash_tree = new ilTree($del_node_data['tree']);
235 $trash_tree->deleteTree($del_node_data);
236 $logger->info(
237 'removeDeltedNodes: deleted tree, tree_id: ' . $del_node_data['tree'] .
238 ', child: ' . $del_node_data['child']
239 );
240 }
241 }
242 }
243
252 public static function restoreObjects(
253 int $a_cur_ref_id,
254 array $a_ref_ids
255 ): void {
256 global $DIC;
257
258 $rbacsystem = $DIC->rbac()->system();
259 $ilAppEventHandler = $DIC["ilAppEventHandler"];
260 $lng = $DIC->language();
261 $tree = $DIC->repositoryTree();
262
263 $cur_obj_id = ilObject::_lookupObjId($a_cur_ref_id);
264
265 $no_create = [];
266
267 foreach ($a_ref_ids as $id) {
269
270 if (!$rbacsystem->checkAccess('create', $a_cur_ref_id, $obj_data->getType())) {
272 }
273 }
274
275 if (count($no_create)) {
276 throw new ilRepositoryException($lng->txt("msg_no_perm_paste") . " " . implode(',', $no_create));
277 }
278
279 $affected_ids = [];
280
281 foreach ($a_ref_ids as $id) {
282 $affected_ids[$id] = $id;
283
284 // INSERT AND SET PERMISSIONS
285 try {
286 $tree_ids = ilTree::lookupTreesForNode($id);
287 $tree_id = $tree_ids[0];
288 self::insertSavedNodes($id, $a_cur_ref_id, $tree_id, $affected_ids);
289 } catch (Exception $e) {
290 throw new ilRepositoryException('Restore from trash failed with message: ' . $e->getMessage());
291 }
292
293
294 // BEGIN ChangeEvent: Record undelete.
295 global $DIC;
296
297 $ilUser = $DIC->user();
298
299
302 $ilUser->getId(),
303 'undelete',
305 );
306 // END PATCH ChangeEvent: Record undelete.
307 }
308
309 // send events
310 foreach ($affected_ids as $id) {
311 // send global event
312 $ilAppEventHandler->raise(
313 "components/ILIAS/ILIASObject",
314 "undelete",
315 ["obj_id" => ilObject::_lookupObjId($id), "ref_id" => $id]
316 );
317 }
318 }
319
323 private static function insertSavedNodes(
324 int $a_source_id,
325 int $a_dest_id,
326 int $a_tree_id,
327 array &$a_affected_ids
328 ): void {
329 global $DIC;
330
331 $tree = $DIC->repositoryTree();
332
333 ilLoggerFactory::getLogger('rep')->debug('Restoring from trash: source_id: ' . $a_source_id . ', dest_id: ' . $a_dest_id . ', tree_id:' . $a_tree_id);
334 ilLoggerFactory::getLogger('rep')->info('Restoring ref_id ' . $a_source_id . ' from trash.');
335
336 // read child of node
337 $saved_tree = new ilTree($a_tree_id);
338 $childs = $saved_tree->getChilds($a_source_id);
339
340 // then delete node and put in tree
341 try {
342 $tree->insertNodeFromTrash($a_source_id, $a_dest_id, $a_tree_id, ilTree::POS_LAST_NODE, true);
343 } catch (Exception $e) {
344 ilLoggerFactory::getLogger('rep')->error('Restore from trash failed with message: ' . $e->getMessage());
345 throw $e;
346 }
347
348 $ref_obj = ilObjectFactory::getInstanceByRefId($a_source_id, false);
349 if ($ref_obj instanceof ilObject) {
350 $lroles = $GLOBALS['rbacreview']->getRolesOfRoleFolder($a_source_id, true);
351 foreach ($lroles as $role_id) {
352 $role = new ilObjRole($role_id);
353 $role->setParent($a_source_id);
354 $role->delete();
355 }
356 if ($a_dest_id) {
357 $ref_obj->setPermissions($a_dest_id);
358 }
359 }
360 foreach ($childs as $child) {
361 self::insertSavedNodes($child["child"], $a_source_id, $a_tree_id, $a_affected_ids);
362 }
363 }
364
365
366
367 //
368 // OBJECT TYPE HANDLING / REMOVAL
369 //
370
371 protected function findTypeInTrash(
372 string $a_type
373 ): array {
374 $ilDB = $this->db;
375
376 $res = [];
377
378 $set = $ilDB->query("SELECT child" .
379 " FROM tree" .
380 " JOIN object_reference ref ON (tree.child = ref.ref_id)" .
381 " JOIN object_data od ON (od.obj_id = ref.obj_id)" .
382 " WHERE tree.tree < " . $ilDB->quote(0, "integer") .
383 " AND od.type = " . $ilDB->quote($a_type, "text"));
384 while ($row = $ilDB->fetchAssoc($set)) {
385 $res[] = $row["child"];
386 }
387
388 return $res;
389 }
390
391 protected function getObjectTypeId(
392 string $a_type
393 ): int {
394 $ilDB = $this->db;
395
396 $set = $ilDB->query("SELECT obj_id" .
397 " FROM object_data " .
398 " WHERE type = " . $ilDB->quote("typ", "text") .
399 " AND title = " . $ilDB->quote($a_type, "text"));
400 $row = $ilDB->fetchAssoc($set);
401 return (int) $row["obj_id"];
402 }
403
404 public function deleteObjectType(
405 string $a_type
406 ): void {
407 $ilDB = $this->db;
408 $tree = $this->tree;
409 $ilSetting = $this->settings;
410
411 // delete object instances (repository/trash)
412
413 $ref_ids_in_tree = $tree->getSubTree($tree->getNodeData(ROOT_FOLDER_ID), false, [$a_type]);
414 if ($ref_ids_in_tree) {
415 self::deleteObjects(0, $ref_ids_in_tree);
416 }
417
418 if ($ilSetting->get('enable_trash')) {
419 $ref_ids_in_trash = $this->findTypeInTrash($a_type);
420 if ($ref_ids_in_trash) {
421 self::removeObjectsFromSystem($ref_ids_in_trash);
422 }
423 }
424
425 // delete "component"
426 $type_id = $this->getObjectTypeId($a_type);
427 if ($type_id) {
428 // see ilRepositoryObjectPlugin::beforeActivation()
429
430 $ilDB->manipulate("DELETE FROM object_data" .
431 " WHERE obj_id = " . $ilDB->quote($type_id, "integer"));
432
433 // RBAC
434
435 // basic operations
436 $ilDB->manipulate("DELETE FROM rbac_ta" .
437 " WHERE typ_id = " . $ilDB->quote($type_id, "integer") /*.
438 " AND ".$ilDB->in("ops_id", array(1, 2, 3, 4, 6), "", "integer") */);
439
440 // creation operation
441 $set = $ilDB->query("SELECT ops_id" .
442 " FROM rbac_operations " .
443 " WHERE class = " . $ilDB->quote("create", "text") .
444 " AND operation = " . $ilDB->quote("create_" . $a_type, "text"));
445 $row = $ilDB->fetchAssoc($set);
446 $create_ops_id = $row["ops_id"];
447 if ($create_ops_id) {
448 $ilDB->manipulate("DELETE FROM rbac_operations" .
449 " WHERE ops_id = " . $ilDB->quote($create_ops_id, "integer"));
450
451 $ilDB->manipulate("DELETE FROM rbac_templates" .
452 " WHERE ops_id = " . $ilDB->quote($create_ops_id, "integer"));
453
454 // container create
455 foreach (["root", "cat", "crs", "grp", "fold"] as $parent_type) {
456 $parent_type_id = $this->getObjectTypeId($parent_type);
457 if ($parent_type_id) {
458 $ilDB->manipulate("DELETE FROM rbac_ta" .
459 " WHERE typ_id = " . $ilDB->quote($parent_type_id, "integer") .
460 " AND ops_id = " . $ilDB->quote($create_ops_id, "integer"));
461 }
462 }
463 }
464 }
465
466 // delete new item settings
468 }
469}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static _recordWriteEvent(int $obj_id, int $usr_id, string $action, ?int $parent_obj_id=null)
Records a write event.
static getLogger(string $a_component_id)
Get component logger.
Class ilObjRole.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
Class ilObject Basic functions for all objects.
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static insertSavedNodes(int $a_source_id, int $a_dest_id, int $a_tree_id, array &$a_affected_ids)
Recursive method to insert all saved nodes of the clipboard.
ilSetting $settings
ilDBInterface $db
static removeDeletedNodes(int $a_node_id, array $a_checked, bool $a_delete_objects, array &$a_affected_ids)
Remove already deleted objects within the objects in trash.
static restoreObjects(int $a_cur_ref_id, array $a_ref_ids)
Move objects from trash back to repository.
static removeObjectsFromSystem(array $a_ref_ids, bool $a_from_recovery_folder=false)
remove objects from trash bin and all entries therefore every object needs a specific deleteObject() ...
findTypeInTrash(string $a_type)
getObjectTypeId(string $a_type)
static deleteObjects(int $a_cur_ref_id, array $a_ids)
Delete objects.
deleteObjectType(string $a_type)
ILIAS Setting Class.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
insertNodeFromTrash(int $a_source_id, int $a_target_id, int $a_tree_id, int $a_pos=self::POS_LAST_NODE, bool $a_reset_deleted_date=false)
Insert node from trash deletes trash entry.
getNodeData(int $a_node_id, ?int $a_tree_pk=null)
get all information of a node.
const POS_LAST_NODE
static lookupTreesForNode(int $node_id)
getSubTree(array $a_node, bool $a_with_data=true, array $a_type=[])
get all nodes in the subtree under specified node
deleteTree(array $a_node)
delete node and the whole subtree under this node
getParentId(int $a_node_id)
get parent id of given node
const ROOT_FOLDER_ID
Definition: constants.php:32
Interface ilDBInterface.
$log
Definition: ltiresult.php:34
$res
Definition: ltiservices.php:69
global $lng
Definition: privfeed.php:31
global $ilSetting
Definition: privfeed.php:31
global $DIC
Definition: shib_login.php:26
$q
Definition: shib_logout.php:25
$GLOBALS["DIC"]
Definition: wac.php:54