ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Deletion.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
24{
25 public function __construct(
26 protected TreeInterface $tree,
27 protected PermissionInterface $permission,
28 protected EventInterface $event,
29 protected ObjectInterface $object,
30 protected bool $trash_enabled
31 ) {
32
33 }
34
40 public function deleteObjectsByRefIds(array $ids): void
41 {
42 // check if objects are already deleted
43 if (count($del_ids = $this->tree->getDeletedTreeNodeIds($ids)) > 0) {
44 throw new AlreadyDeletedException('Deletion: Some tree nodes are already deleted: ' . implode(', ', $del_ids));
45 }
46
47 // check delelete permissions
48 if (count($miss_ids = $this->permission->getRefIdsWithoutDeletePermission($ids)) > 0) {
49 throw new MissingPermissionException('Deletion: missing permission: ' . implode(', ', $miss_ids));
50 }
51
52 if ($this->trash_enabled) {
53 $this->moveToTrash($ids);
54 } else {
55 $this->removeObjectsFromSystemByRefIds($ids, true);
56 }
57 }
58
64 array $ref_ids,
65 bool $direct_from_tree = false
66 ): void {
67
68 $affected_ids = [];
69 $ref_ids = array_map('intval', $ref_ids);
70 foreach ($ref_ids as $id) {
71 $saved_tree = null;
72
73 // get subtree nodes
74 if (!$direct_from_tree) {
75 // from trash
76 $saved_tree = $this->tree->getTrashTree($id);
77 $node_data = $saved_tree->getNodeData($id);
78 // subtree nodes from trashed tree will include the $id node itself, too
79 $subtree_nodes = $saved_tree->getSubTree($node_data);
80 } else {
81 // from main tree
82 $node_data = $this->tree->getNodeData($id);
83 // subtree nodes will include the $id node itself, too
84 $subtree_nodes = $this->tree->getSubTree($node_data);
85 }
86
87 $this->event->beforeSubTreeRemoval(
88 $node_data['obj_id']
89 );
90
91 // remember already checked deleted node_ids
92 if (!$direct_from_tree) {
93 $checked[] = -$id;
94 } else {
95 $checked[] = $id;
96 }
97
98 // dive in recursive manner in each already deleted subtrees and remove these objects too
99
100 foreach ($subtree_nodes as $node) {
101 if (!$node_obj = $this->object->getInstanceByRefId($node["ref_id"])) {
102 continue;
103 }
104
105 // NOTE: This has been outside of the for loop before
106 $this->removeDeletedNodes($node["ref_id"], $checked, true, $affected_ids);
107
108 $this->event->beforeObjectRemoval(
109 $node_obj->getId(),
110 $node_obj->getRefId(),
111 $node_obj->getType(),
112 $node_obj->getTitle()
113 );
114 $affected_ids[$node["ref_id"]] = [
115 "ref_id" => $node["ref_id"],
116 "obj_id" => $node_obj->getId(),
117 "type" => $node_obj->getType(),
118 "old_parent_ref_id" => $node["parent"]
119 ];
120
121 // this is due to bug #1860 (even if this will not completely fix it)
122 // and the fact, that media pool folders may find their way into
123 // the recovery folder (what results in broken pools, if the are deleted)
124 // Alex, 2006-07-21
125 if (!$direct_from_tree || $node_obj->getType() !== "fold") {
126 try {
127 $node_obj->delete();
128 } catch (\Exception $e) {
129 $this->event->failedRemoval(
130 $node_obj->getId(),
131 $node_obj->getRefId(),
132 $node_obj->getType(),
133 $node_obj->getTitle(),
134 $e->getMessage()
135 );
136 }
137
138 }
139 }
140
141 // Use the saved tree object here (negative tree_id)
142 if (!$direct_from_tree) {
143 if ($saved_tree) {
144 $saved_tree->deleteTree($node_data);
145 }
146 } else {
147 $this->tree->deleteTree($node_data);
148 }
149
150 $this->event->afterTreeDeletion(
151 (int) $node_data['tree'],
152 (int) $node_data['child']
153 );
154 }
155
156 // send global events
157 foreach ($affected_ids as $aid) {
158 $this->event->afterObjectRemoval(
159 $aid["obj_id"],
160 $aid["ref_id"],
161 $aid["type"],
162 $aid["old_parent_ref_id"]
163 );
164 }
165 }
166
170 protected function removeDeletedNodes(
171 int $a_node_id,
172 array $a_checked,
173 bool $a_delete_objects, // seems to be always true
174 array &$a_affected_ids
175 ): void {
176
177 foreach ($this->tree->getTrashedSubtrees($a_node_id) as $tree_id) {
178 // $tree_id is negative here
179 // only continue recursion if fetched node wasn't touched already!
180 if (!in_array($tree_id, $a_checked)) {
181 $deleted_tree = $this->tree->getTree($tree_id);
182 $a_checked[] = $tree_id;
183
184 $tree_id *= (-1);
185 // $tree_id is positive here
186 $del_node_data = $deleted_tree->getNodeData($tree_id);
187 $del_subtree_nodes = $deleted_tree->getSubTree($del_node_data);
188 // delete trash in the trash of trash...
189 $this->removeDeletedNodes($tree_id, $a_checked, $a_delete_objects, $a_affected_ids);
190
191 if ($a_delete_objects) {
192 foreach ($del_subtree_nodes as $node) {
193 $object = $this->object->getInstanceByRefId($node["ref_id"]);
194 if (!is_null($object)) {
195 $a_affected_ids[$node["ref_id"]] = [
196 "ref_id" => $node["ref_id"],
197 "obj_id" => $object->getId(),
198 "type" => $object->getType(),
199 "old_parent_ref_id" => $node["parent"]
200 ];
201 $this->event->beforeObjectRemoval(
202 $object->getId(),
203 $object->getRefId(),
204 $object->getType(),
205 $object->getTitle()
206 );
207 try {
208 $object->delete();
209 } catch (\Exception $e) {
210 $this->event->failedRemoval(
211 $object->getId(),
212 $object->getRefId(),
213 $object->getType(),
214 $object->getTitle(),
215 $e->getMessage()
216 );
217 }
218 }
219 }
220 }
221 // tree instance with -child tree id
222 $trash_tree = $this->tree->getTree((int) $del_node_data['tree']);
223 $trash_tree->deleteTree($del_node_data);
224 $this->event->afterTreeDeletion(
225 (int) $del_node_data['tree'],
226 (int) $del_node_data['child']
227 );
228 }
229 }
230 }
231
232
233 protected function moveToTrash(array $ids): void
234 {
235 // save subtree / delete subtree from tree
236 $affected_ids = [];
237 $affected_parents = [];
238 foreach ($ids as $id) {
239 if ($this->tree->isDeleted($id)) {
240 throw new AlreadyDeletedException("Move To Trash: Object with ref_id: " . $id . " already deleted.");
241 }
242
243 $subnodes = $this->tree->getSubtree($this->tree->getNodeData($id));
244
245 foreach ($subnodes as $subnode) {
246 $this->permission->revokePermission((int) $subnode["child"]);
247
248 $affected_ids[$subnode["child"]] = $subnode["child"];
249 $affected_parents[$subnode["child"]] = $subnode["parent"];
250 }
251
252 $this->event->beforeMoveToTrash($id, $subnodes);
253
254 if (!$this->tree->moveToTrash($id)) {
255 throw new AlreadyDeletedException("Move To Trash: Object with ref_id: " . $id . " already deleted.");
256 }
257 $affected_ids[$id] = $id;
258 }
259
260 // send global events
261 foreach ($affected_ids as $aid) {
262 $this->event->afterMoveToTrash($aid, $affected_parents[$aid]);
263 }
264 }
265
266
267}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(protected TreeInterface $tree, protected PermissionInterface $permission, protected EventInterface $event, protected ObjectInterface $object, protected bool $trash_enabled)
Definition: Deletion.php:25
removeObjectsFromSystemByRefIds(array $ref_ids, bool $direct_from_tree=false)
Remove objects from system directly ($direct_from_tree === true) or from trash ($direct_from_tree ===...
Definition: Deletion.php:63
deleteObjectsByRefIds(array $ids)
Delete: If trash is enabled, objects are moved to the trash.
Definition: Deletion.php:40
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.
Definition: Deletion.php:170
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...