ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilRepUtil.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once("./Services/Object/classes/class.ilObjectFactory.php");
5
14{
15
22 static public function deleteObjects($a_cur_ref_id, $a_ids)
23 {
24 global $ilAppEventHandler, $rbacsystem, $rbacadmin, $log, $ilUser, $tree, $lng,
26
27 include_once("./Services/Repository/exceptions/class.ilRepositoryException.php");
28
29 // Remove duplicate ids from array
30 $a_ids = array_unique((array) $a_ids);
31
32 // FOR ALL SELECTED OBJECTS
33 foreach ($a_ids as $id)
34 {
35 if ($tree->isDeleted($id))
36 {
37 $log->write(__METHOD__.': Object with ref_id: '.$id.' already deleted.');
38 throw new ilRepositoryException($lng->txt("msg_obj_already_deleted"));
39 }
40
41 // GET COMPLETE NODE_DATA OF ALL SUBTREE NODES
42 $node_data = $tree->getNodeData($id);
43 $subtree_nodes = $tree->getSubTree($node_data);
44
45 $all_node_data[] = $node_data;
46 $all_subtree_nodes[] = $subtree_nodes;
47
48 // CHECK DELETE PERMISSION OF ALL OBJECTS
49 foreach ($subtree_nodes as $node)
50 {
51 if($node['type'] == 'rolf')
52 {
53 continue;
54 }
55 if (!$rbacsystem->checkAccess('delete',$node["child"]))
56 {
57 $not_deletable[] = $node["child"];
58 $perform_delete = false;
59 }
60 }
61 }
62
63 // IF THERE IS ANY OBJECT WITH NO PERMISSION TO DELETE
64 if (count($not_deletable))
65 {
66 $not_deletable_titles = array();
67 foreach ($not_deletable as $key => $ref_id) {
69 $not_deletable_titles[] = ilObject::_lookupTitle($obj_id);
70 }
71
72 ilSession::clear("saved_post");
73 throw new ilRepositoryException(
74 $lng->txt("msg_no_perm_delete")." ".implode(', ',$not_deletable_titles)."<br/>".$lng->txt("msg_cancel"));
75 }
76
77 // DELETE THEM
78 if (!$all_node_data[0]["type"])
79 {
80// alex: this branch looks suspicious to me... I deactivate it for
81// now. Objects that aren't in the tree should overwrite this method.
82throw new ilRepositoryException($lng->txt("ilRepUtil::deleteObjects: Type information missing."));
83 // OBJECTS ARE NO 'TREE OBJECTS'
84 if ($rbacsystem->checkAccess('delete', $a_cur_ref_id))
85 {
86 foreach($a_ids as $id)
87 {
89 $obj->delete();
90
91 // write log entry
92 $log->write("ilObjectGUI::confirmedDeleteObject(), deleted obj_id ".$obj->getId().
93 ", type: ".$obj->getType().", title: ".$obj->getTitle());
94 }
95 }
96 else
97 {
98 throw new ilRepositoryException(
99 $lng->txt("no_perm_delete")."<br/>".$lng->txt("msg_cancel"));
100 }
101 }
102 else
103 {
104 // SAVE SUBTREE AND DELETE SUBTREE FROM TREE
105 $affected_ids = array();
106 $affected_parents = array();
107 foreach ($a_ids as $id)
108 {
109 if($tree->isDeleted($id))
110 {
111 $log->write(__METHOD__.': Object with ref_id: '.$id.' already deleted.');
112 throw new ilRepositoryException($lng->txt("msg_obj_already_deleted"));
113 }
114
115 // DELETE OLD PERMISSION ENTRIES
116 $subnodes = $tree->getSubtree($tree->getNodeData($id));
117
118 foreach ($subnodes as $subnode)
119 {
120 $rbacadmin->revokePermission($subnode["child"]);
121 // remove item from all user desktops
122 $affected_users = ilUtil::removeItemFromDesktops($subnode["child"]);
123
124 $affected_ids[$subnode["child"]] = $subnode["child"];
125 $affected_parents[$subnode["child"]] = $subnode["parent"];
126
127 // TODO: inform users by mail that object $id was deleted
128 //$mail->sendMail($id,$msg,$affected_users);
129 // should go to appevents at the end
130 }
131
132 // TODO: needs other handling
133 // This class shouldn't have to know anything about ECS
134 include_once('./Services/WebServices/ECS/classes/class.ilECSObjectSettings.php');
136
137 if(!$tree->saveSubTree($id, true))
138 {
139 $log->write(__METHOD__.': Object with ref_id: '.$id.' already deleted.');
140 throw new ilRepositoryException($lng->txt("msg_obj_already_deleted"));
141 }
142
143 // write log entry
144 $log->write("ilObjectGUI::confirmedDeleteObject(), moved ref_id ".$id.
145 " to trash");
146
147 // remove item from all user desktops
148 $affected_users = ilUtil::removeItemFromDesktops($id);
149
150 $affected_ids[$id] = $id;
151
152 // TODO: inform users by mail that object $id was deleted
153 //$mail->sendMail($id,$msg,$affected_users);
154 }
155
156 // send global events
157 foreach ($affected_ids as $aid)
158 {
159 $ilAppEventHandler->raise("Services/Object", "toTrash",
160 array( "obj_id" => ilObject::_lookupObjId($aid),
161 "ref_id" => $aid,
162 "old_parent_ref_id" => $affected_parents[$aid]
163 ));
164 }
165 }
166
167 if (!$ilSetting->get('enable_trash'))
168 {
170 }
171 }
172
178 public static function removeObjectsFromSystem($a_ref_ids, $a_from_recovery_folder = false)
179 {
180 global $rbacsystem, $log, $ilAppEventHandler, $tree;
181
182 $affected_ids = array();
183
184 // DELETE THEM
185 foreach ($a_ref_ids as $id)
186 {
187 // GET COMPLETE NODE_DATA OF ALL SUBTREE NODES
188 if (!$a_from_recovery_folder)
189 {
190 $saved_tree = new ilTree(-(int)$id);
191 $node_data = $saved_tree->getNodeData($id);
192 $subtree_nodes = $saved_tree->getSubTree($node_data);
193 }
194 else
195 {
196 $node_data = $tree->getNodeData($id);
197 $subtree_nodes = $tree->getSubTree($node_data);
198 }
199
200 // BEGIN ChangeEvent: Record remove from system.
201 require_once('Services/Tracking/classes/class.ilChangeEvent.php');
202 // Record write event
203 global $ilUser, $tree;
204 $parent_data = $tree->getParentNodeData($node_data['ref_id']);
205 ilChangeEvent::_recordWriteEvent($node_data['obj_id'], $ilUser->getId(), 'purge',
206 $parent_data['obj_id']);
207 // END ChangeEvent: Record remove from system.
208
209 // remember already checked deleted node_ids
210 if (!$a_from_recovery_folder)
211 {
212 $checked[] = -(int) $id;
213 }
214 else
215 {
216 $checked[] = $id;
217 }
218
219 // dive in recursive manner in each already deleted subtrees and remove these objects too
220 ilRepUtil::removeDeletedNodes($id, $checked, true, $affected_ids);
221
222 foreach ($subtree_nodes as $node)
223 {
224 if(!$node_obj = ilObjectFactory::getInstanceByRefId($node["ref_id"],false))
225 {
226 continue;
227 }
228
229 // write log entry
230 $log->write("ilObjectGUI::removeFromSystemObject(), delete obj_id: ".$node_obj->getId().
231 ", ref_id: ".$node_obj->getRefId().", type: ".$node_obj->getType().", ".
232 "title: ".$node_obj->getTitle());
233 $affected_ids[$node["ref_id"]] = array(
234 "ref_id" => $node["ref_id"],
235 "obj_id" => $node_obj->getId(),
236 "type" => $node_obj->getType(),
237 "old_parent_ref_id" => $node["parent"]);
238
239 // this is due to bug #1860 (even if this will not completely fix it)
240 // and the fact, that media pool folders may find their way into
241 // the recovery folder (what results in broken pools, if the are deleted)
242 // Alex, 2006-07-21
243 if (!$a_from_recovery_folder || $node_obj->getType() != "fold")
244 {
245 $node_obj->delete();
246 }
247 }
248
249 // Use the saved tree object here (negative tree_id)
250 if (!$a_from_recovery_folder)
251 {
252 $saved_tree->deleteTree($node_data);
253 }
254 else
255 {
256 $tree->deleteTree($node_data);
257 }
258
259 // write log entry
260 $log->write("ilObjectGUI::removeFromSystemObject(), deleted tree, tree_id: ".$node_data["tree"].
261 ", child: ".$node_data["child"]);
262
263 }
264
265 // send global events
266 foreach ($affected_ids as $aid)
267 {
268 $ilAppEventHandler->raise("Services/Object", "delete",
269 array("obj_id" => $aid["obj_id"],
270 "ref_id" => $aid["ref_id"],
271 "type" => $aid["type"],
272 "old_parent_ref_id" => $aid["old_parent_ref_id"]));
273 }
274 }
275
279 private static function removeDeletedNodes($a_node_id, $a_checked, $a_delete_objects,
280 &$a_affected_ids)
281 {
282 global $log, $ilDB, $tree;
283
284 $q = "SELECT tree FROM tree WHERE parent= ".
285 $ilDB->quote($a_node_id, "integer")." AND tree < 0";
286
287 $r = $ilDB->query($q);
288
289 while($row = $ilDB->fetchObject($r))
290 {
291 // only continue recursion if fetched node wasn't touched already!
292 if (!in_array($row->tree,$a_checked))
293 {
294 $deleted_tree = new ilTree($row->tree);
295 $a_checked[] = $row->tree;
296
297 $row->tree = $row->tree * (-1);
298 $del_node_data = $deleted_tree->getNodeData($row->tree);
299 $del_subtree_nodes = $deleted_tree->getSubTree($del_node_data);
300
301 ilRepUtil::removeDeletedNodes($row->tree,$a_checked, $a_delete_objects, $a_affected_ids);
302
303 if ($a_delete_objects)
304 {
305 foreach ($del_subtree_nodes as $node)
306 {
307 $node_obj = ilObjectFactory::getInstanceByRefId($node["ref_id"]);
308
309 // write log entry
310 $log->write("ilObjectGUI::removeDeletedNodes(), delete obj_id: ".$node_obj->getId().
311 ", ref_id: ".$node_obj->getRefId().", type: ".$node_obj->getType().", ".
312 "title: ".$node_obj->getTitle());
313 $a_affected_ids[$node["ref_id"]] = array(
314 "ref_id" => $node["ref_id"],
315 "obj_id" => $node_obj->getId(),
316 "type" => $node_obj->getType(),
317 "old_parent_ref_id" => $node["parent"]);
318
319 $node_obj->delete();
320
321 }
322 }
323
324 $tree->deleteTree($del_node_data);
325
326 // write log entry
327 $log->write("ilObjectGUI::removeDeletedNodes(), deleted tree, tree_id: ".$del_node_data["tree"].
328 ", child: ".$del_node_data["child"]);
329 }
330 }
331
332 return true;
333 }
334
338 static public function restoreObjects($a_cur_ref_id, $a_ref_ids)
339 {
340 global $rbacsystem, $log, $ilAppEventHandler, $lng, $tree;
341
342 $cur_obj_id = ilObject::_lookupObjId($a_cur_ref_id);
343
344 foreach ($a_ref_ids as $id)
345 {
347
348 if (!$rbacsystem->checkAccess('create', $a_cur_ref_id, $obj_data->getType()))
349 {
351 }
352 }
353
354 if (count($no_create))
355 {
356 include_once("./Services/Repository/exceptions/class.ilRepositoryException.php");
357 throw new ilRepositoryException($lng->txt("msg_no_perm_paste")." ".implode(',',$no_create));
358 }
359
360 $affected_ids = array();
361
362 foreach ($a_ref_ids as $id)
363 {
364 $affected_ids[$id] = $id;
365
366 // INSERT AND SET PERMISSIONS
367 try {
368 ilRepUtil::insertSavedNodes($id, $a_cur_ref_id, -(int) $id, $affected_ids);
369 }
370 catch (Exception $e) {
371 include_once("./Services/Repository/exceptions/class.ilRepositoryException.php");
372 throw new ilRepositoryException('Restore from trash failed with message: ' . $e->getMessage());
373 }
374
375
376 // BEGIN ChangeEvent: Record undelete.
377 require_once('Services/Tracking/classes/class.ilChangeEvent.php');
378 global $ilUser;
379
380
383 $ilUser->getId(),
384 'undelete',
385 ilObject::_lookupObjId($tree->getParentId($id))
386 );
388 $cur_obj_id,
389 $ilUser->getId());
390 // END PATCH ChangeEvent: Record undelete.
391
392 }
393
394 // send events
395 foreach ($affected_ids as $id)
396 {
397 // send global event
398 $ilAppEventHandler->raise("Services/Object", "undelete",
399 array("obj_id" => ilObject::_lookupObjId($id), "ref_id" => $id));
400 }
401 }
402
406 private static function insertSavedNodes($a_source_id, $a_dest_id, $a_tree_id, &$a_affected_ids)
407 {
408 global $rbacadmin, $rbacreview, $log, $tree;
409
410 ilLoggerFactory::getLogger('rep')->debug('Restoring from trash: source_id: '. $a_source_id.', dest_id: '. $a_dest_id.', tree_id:'. $a_tree_id);
411 ilLoggerFactory::getLogger('rep')->info('Restoring ref_id ' . $a_source_id . ' from trash.');
412
413 // read child of node
414 $saved_tree = new ilTree($a_tree_id);
415 $childs = $saved_tree->getChilds($a_source_id);
416
417 // then delete node and put in tree
418 try {
419 $tree->insertNodeFromTrash($a_source_id, $a_dest_id, $a_tree_id, IL_LAST_NODE, true);
420 }
421 catch (Exception $e) {
422 ilLoggerFactory::getLogger('rep')->error('Restore from trash failed with message: ' . $e->getMessage());
423 throw $e;
424 }
425
426 include_once './Services/Object/classes/class.ilObjectFactory.php';
427 $factory = new ilObjectFactory();
428 $ref_obj = $factory->getInstanceByRefId($a_source_id,FALSE);
429 if($ref_obj instanceof ilObject)
430 {
431 $lroles = $GLOBALS['rbacreview']->getRolesOfRoleFolder($a_source_id,true);
432 foreach($lroles as $role_id)
433 {
434 include_once './Services/AccessControl/classes/class.ilObjRole.php';
435 $role = new ilObjRole($role_id);
436 $role->setParent($a_source_id);
437 $role->delete();
438 }
439 if($a_dest_id)
440 {
441 $ref_obj->setPermissions($a_dest_id);
442 }
443 }
444 foreach ($childs as $child)
445 {
446 ilRepUtil::insertSavedNodes($child["child"],$a_source_id,$a_tree_id,$a_affected_ids);
447 }
448 }
449
450
451
452 //
453 // OBJECT TYPE HANDLING / REMOVAL
454 //
455
456 protected function findTypeInTrash($a_type)
457 {
458 global $ilDB;
459
460 $res = array();
461
462 $set = $ilDB->query("SELECT child".
463 " FROM tree".
464 " JOIN object_reference ref ON (tree.child = ref.ref_id)".
465 " JOIN object_data od ON (od.obj_id = ref.obj_id)".
466 " WHERE tree.tree < ".$ilDB->quote(0, "integer").
467 " AND od.type = ".$ilDB->quote($a_type, "text"));
468 while($row = $ilDB->fetchAssoc($set))
469 {
470 $res[] = $row["child"];
471 }
472
473 return $res;
474 }
475
476 protected function getObjectTypeId($a_type)
477 {
478 global $ilDB;
479
480 $set = $ilDB->query("SELECT obj_id".
481 " FROM object_data ".
482 " WHERE type = ".$ilDB->quote("typ", "text").
483 " AND title = ".$ilDB->quote($a_type, "text"));
484 $row = $ilDB->fetchAssoc($set);
485 return $row["obj_id"];
486 }
487
488 public function deleteObjectType($a_type)
489 {
490 global $ilDB, $tree, $ilSetting;
491
492 // delete object instances (repository/trash)
493
494 $ref_ids_in_tree = $tree->getSubTree($tree->getNodeData(ROOT_FOLDER_ID), false, $a_type);
495 if($ref_ids_in_tree)
496 {
497 $this->deleteObjects(null, $ref_ids_in_tree);
498 }
499
500 if($ilSetting->get('enable_trash'))
501 {
502 $ref_ids_in_trash = $this->findTypeInTrash($a_type);
503 if($ref_ids_in_trash)
504 {
505 self::removeObjectsFromSystem($ref_ids_in_trash);
506 }
507 }
508
509 // delete "component"
510 $type_id = $this->getObjectTypeId($a_type);
511 if($type_id)
512 {
513 // see ilRepositoryObjectPlugin::beforeActivation()
514
515 $ilDB->manipulate("DELETE FROM object_data".
516 " WHERE obj_id = ".$ilDB->quote($type_id, "integer"));
517
518 // RBAC
519
520 // basic operations
521 $ilDB->manipulate("DELETE FROM rbac_ta".
522 " WHERE typ_id = ".$ilDB->quote($type_id, "integer") /*.
523 " AND ".$ilDB->in("ops_id", array(1, 2, 3, 4, 6), "", "integer") */);
524
525 // creation operation
526 $set = $ilDB->query("SELECT ops_id".
527 " FROM rbac_operations ".
528 " WHERE class = ".$ilDB->quote("create", "text").
529 " AND operation = ".$ilDB->quote("create_".$a_type, "text"));
530 $row = $ilDB->fetchAssoc($set);
531 $create_ops_id = $row["ops_id"];
532 if($create_ops_id)
533 {
534 $ilDB->manipulate("DELETE FROM rbac_operations".
535 " WHERE ops_id = ".$ilDB->quote($create_ops_id, "integer"));
536
537 $ilDB->manipulate("DELETE FROM rbac_templates".
538 " WHERE ops_id = ".$ilDB->quote($create_ops_id, "integer"));
539
540 // container create
541 foreach(array("root", "cat", "crs", "grp", "fold") as $parent_type)
542 {
543 $parent_type_id = $this->getObjectTypeId($parent_type);
544 if($parent_type_id)
545 {
546 $ilDB->manipulate("DELETE FROM rbac_ta".
547 " WHERE typ_id = ".$ilDB->quote($parent_type_id, "integer").
548 " AND ops_id = ".$ilDB->quote($create_ops_id, "integer"));
549 }
550 }
551 }
552 }
553
554 // delete new item settings
555 include_once "Services/Repository/classes/class.ilObjRepositorySettings.php";
557 }
558
559
560}
An exception for terminatinating execution or to throw for unit testing.
const IL_LAST_NODE
Definition: class.ilTree.php:4
static _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id=null)
Records a write event.
static _handleDelete(array $a_subbtree_nodes)
static getLogger($a_component_id)
Get component logger.
Class ilObjRole.
Class ilObjectFactory.
static getInstanceByObjId($a_obj_id, $stop_on_error=true)
get an instance of an Ilias object by object id
static getInstanceByRefId($a_ref_id, $stop_on_error=true)
get an instance of an Ilias object by reference id
Class ilObject Basic functions for all objects.
static _lookupObjId($a_id)
static _lookupTitle($a_id)
lookup object title
Repository Utilities (application layer, put GUI related stuff into ilRepUtilGUI)
static deleteObjects($a_cur_ref_id, $a_ids)
Delete objects.
static removeDeletedNodes($a_node_id, $a_checked, $a_delete_objects, &$a_affected_ids)
Remove already deleted objects within the objects in trash.
findTypeInTrash($a_type)
getObjectTypeId($a_type)
static restoreObjects($a_cur_ref_id, $a_ref_ids)
Move objects from trash back to repository.
deleteObjectType($a_type)
static insertSavedNodes($a_source_id, $a_dest_id, $a_tree_id, &$a_affected_ids)
Recursive method to insert all saved nodes of the clipboard.
static removeObjectsFromSystem($a_ref_ids, $a_from_recovery_folder=false)
remove objects from trash bin and all entries therefore every object needs a specific deleteObject() ...
static clear($a_var)
Unset a value.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
static removeItemFromDesktops($a_id)
removes object from all user's desktops @access public
$r
Definition: example_031.php:79
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
global $lng
Definition: privfeed.php:17
global $ilSetting
Definition: privfeed.php:17
$ref_id
Definition: sahs_server.php:39
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:93