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