ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilSCTreeTasks.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
10{
11 private $db = null;
12 private $task = null;
13
14 public function __construct(ilSCTask $task)
15 {
16 $this->db = $GLOBALS['ilDB'];
17 $this->task = $task;
18 }
19
20
26 public static function findDeepestDuplicate()
27 {
28 global $ilDB;
29
30 $query = 'SELECT child FROM tree first '.
31 'WHERE EXISTS ( '.
32 'SELECT child FROM tree second WHERE first.child = second.child '.
33 'GROUP BY child HAVING COUNT(child) > 1 ) '.
34 'ORDER BY depth DESC';
35
36 $GLOBALS['ilLog']->write($query);
37
38 $res = $ilDB->query($query);
39 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
40 {
41 return $row->child;
42 }
43 return 0;
44 }
45
46 public static function repairPK()
47 {
48 #$GLOBALS['ilDB']->dropPrimaryKey('tree');
49 $GLOBALS['ilDB']->addPrimaryKey('tree', array('child'));
50 }
51
52 public static function getNodeInfo($a_tree_id, $a_child)
53 {
54 global $ilDB;
55
56 $query = 'SELECT * FROM tree WHERE child = '.$ilDB->quote($a_child,'integer').' AND tree = '. $ilDB->quote($a_tree_id,'integer');
57 $res = $ilDB->query($query);
58
59 $node = array();
60 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
61 {
62 $node['child'] = $row->child;
63 $node['tree'] = $row->tree;
64 $node['depth'] = $row->depth;
65
66 // read obj_id
67 $query = 'SELECT obj_id FROM object_reference WHERE ref_id = '.$ilDB->quote($a_child,'integer');
68 $ref_res = $ilDB->query($query);
69 while($ref_row = $ref_res->fetchRow(DB_FETCHMODE_OBJECT))
70 {
71 $node['obj_id'] = $ref_row->obj_id;
72
73 // read object info
74 $query = 'SELECT title, description, type FROM object_data '.
75 'WHERE obj_id = '.$ilDB->quote($ref_row->obj_id);
76 $obj_res = $ilDB->query($query);
77 while($obj_row = $obj_res->fetchRow(DB_FETCHMODE_OBJECT))
78 {
79 $node['title'] = $obj_row->title;
80 $node['description'] = $obj_row->description;
81 $node['type'] = $obj_row->type;
82 }
83 }
84 }
85 return $node;
86 }
87
88 public static function getChilds($a_tree_id, $a_childs)
89 {
90 global $ilDB;
91
92 $query = 'SELECT * FROM tree WHERE tree = '.$ilDB->quote($a_tree_id,'integer').' '.'AND child = '.$ilDB->quote($a_childs,'integer');
93 $res = $ilDB->query($query);
94
95 $childs = array();
96 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
97 {
98 $childs[] = $row->child;
99 }
100 return $childs;
101 }
102
108 public static function findDuplicates($a_duplicate_id)
109 {
110 global $ilDB;
111
112 $query = 'SELECT * FROM tree first '.
113 'WHERE EXISTS ( '.
114 'SELECT child FROM tree second WHERE first.child = second.child '.
115 'GROUP BY child HAVING COUNT(child) > 1 ) '.
116 'AND child = '.$ilDB->quote($a_duplicate_id,'integer').' '.
117 'ORDER BY depth DESC';
118 $res = $ilDB->query($query);
119
120 $GLOBALS['ilLog']->write($query);
121
122 $nodes = array();
123 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
124 {
125 $node = array();
126 $node['tree'] = $row->tree;
127 $node['child'] = $row->child;
128 $node['depth'] = $row->depth;
129
130 $nodes[] = $node;
131 }
132
133 return $nodes;
134 }
135
136 public static function hasDuplicate($a_child)
137 {
138 global $ilDB;
139
140 return count(self::findDuplicates($a_child));
141 }
142
143 public static function deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
144 {
145 $dups = self::findDuplicates($a_duplicate_id);
146 foreach($dups as $dup)
147 {
148 if($a_delete_trash and $dup['tree'] < 1)
149 {
150 self::deleteDuplicate($dup['tree'],$dup['child']);
151 }
152 if(!$a_delete_trash and $dup['tree'] == 1)
153 {
154 self::deleteDuplicate($dup['tree'],$dup['child']);
155 }
156 }
157 return TRUE;
158 }
159
160 protected static function deleteDuplicate($tree_id, $dup_id)
161 {
162 global $ilDB;
163
164 $query = 'SELECT child FROM tree '.
165 'WHERE parent = '.$ilDB->quote($dup_id,'integer').' '.
166 'AND tree = '.$ilDB->quote($tree_id,'integer');
167 $res = $ilDB->query($query);
168 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
169 {
170 // start recursion
171 self::deleteDuplicate($tree_id, $row->child);
172 }
173 // now delete node
174 if(self::hasDuplicate($dup_id))
175 {
176 $query = 'DELETE FROM tree '.
177 'WHERE child = '.$ilDB->quote($dup_id,'integer').' '.
178 'AND tree = '.$ilDB->quote($tree_id,'integer');
179 $ilDB->manipulate($query);
180 }
181 }
182
183
187 public function getDB()
188 {
189 return $this->db;
190 }
191
196 public function getTask()
197 {
198 return $this->task;
199 }
200
201
202
207 public function validateStructure()
208 {
209 $failures = $this->checkStructure();
210
211 if(count($failures))
212 {
213 $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
214 }
215 else
216 {
217 $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
218 }
219 $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
220 $this->getTask()->update();
221 return count($failures);
222 }
223
224
225 public function checkStructure()
226 {
227 return $GLOBALS['tree']->validateParentRelations();
228 global $ilDB;
229
230 $query = 'select child from tree child where not exists '.
231 '( '.
232 'select child from tree parent where child.parent = parent.child and (parent.lft < child.lft) and (parent.rgt > child.rgt) '.
233 ')'.
234 'and tree = 1 and child <> 1';
235 $res = $ilDB->query($query);
236
237 $failures = array();
238 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
239 {
240 $failures[] = $row->child;
241 }
242 return $failures;
243 }
244
245
246
250 public function validateDuplicates()
251 {
252 $failures = $this->checkDuplicates();
253
254 if(count($failures))
255 {
256 $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
257 }
258 else
259 {
260 $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
261 }
262 $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
263 $this->getTask()->update();
264 return count($failures);
265 }
266
270 public function checkDuplicates()
271 {
272 $query = 'SELECT child, count(child) num FROM tree '.
273 'GROUP BY child '.
274 'HAVING count(child) > 1';
275 $res = $this->getDB()->query($query);
276
277 $GLOBALS['ilLog']->write($query);
278
279 $failures = array();
280 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
281 {
282 $failures[] = $row->child;
283 }
284 return $failures;
285 }
286
287 public function findMissingTreeEntries()
288 {
289 global $ilDB;
290
291 $failures = $this->readMissingTreeEntries();
292
293 if(count($failures))
294 {
295 $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
296 }
297 else
298 {
299 $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
300 }
301
302 $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
303 $this->getTask()->update();
304 return count($failures);
305 }
306
307
311 public function findMissing()
312 {
313 global $ilDB;
314
315 $failures = $this->readMissing();
316
317 if(count($failures))
318 {
319 $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
320 }
321 else
322 {
323 $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
324 }
325
326 $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
327 $this->getTask()->update();
328 return count($failures);
329
330 }
331
335 public function repairMissing()
336 {
337 $failures = $this->readMissing();
338 $recf_ref_id = $this->createRecoveryContainer();
339 foreach($failures as $ref_id)
340 {
341 $this->repairMissingObject($recf_ref_id,$ref_id);
342 }
343
344 }
345
350 protected function repairMissingObject($a_parent_ref, $a_ref_id)
351 {
352 global $ilDB;
353
354 // check if object entry exist
355 $query = 'SELECT obj_id FROM object_reference '.
356 'WHERE ref_id = '.$ilDB->quote($a_ref_id,'integer');
357
358 $res = $ilDB->query($query);
359 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
360 {
361 $query = 'SELECT type, title FROM object_data '.
362 'WHERE obj_id = '.$ilDB->quote($row->obj_id,'integer');
363 $ores = $ilDB->query($query);
364
365 $done = FALSE;
366 while($orow = $ores->fetchRow(DB_FETCHMODE_OBJECT))
367 {
368 $GLOBALS['ilLog']->write(__METHOD__.': Moving to recovery folder: '.$orow->type.': '.$orow->title);
369 $done = TRUE;
370
371 include_once './Services/Object/classes/class.ilObjectFactory.php';
372 $factory = new ilObjectFactory();
373 $ref_obj = $factory->getInstanceByRefId($a_ref_id,FALSE);
374
375 if($ref_obj instanceof ilObjRoleFolder)
376 {
377 $ref_obj->delete();
378 }
379 elseif($ref_obj instanceof ilObject)
380 {
381 $ref_obj->putInTree($a_parent_ref);
382 $ref_obj->setPermissions($a_parent_ref);
383 $GLOBALS['ilLog']->write(__METHOD__.': Moving finished');
384 break;
385 }
386 }
387 if(!$done)
388 {
389 // delete reference value
390 $query = 'DELETE FROM object_reference WHERE ref_id = '.$ilDB->quote($a_ref_id,'integer');
391 $ilDB->manipulate($query);
392 $GLOBALS['ilLog']->write(__METHOD__.': Delete reference for "object" without tree and object_data entry: ref_id= '.$a_ref_id );
393 }
394 }
395
396 }
397
404 protected function readMissing()
405 {
406 global $ilDB;
407
408 $query = 'SELECT ref_id FROM object_reference '.
409 'LEFT JOIN tree ON ref_id = child '.
410 'WHERE child IS NULL';
411 $res = $ilDB->query($query);
412
413 $failures = array();
414 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
415 {
416 $failures[] = $row->ref_id;
417 }
418 return $failures;
419 }
420
425 public function repairMissingTreeEntries()
426 {
427 global $ilDB;
428
429 $missing = $this->readMissingTreeEntries();
430 $GLOBALS['ilLog']->write(__METHOD__.': '.print_r($missing,TRUE));
431
432 foreach($missing as $ref_id)
433 {
434 // check for duplicates
435 $query = 'SELECT tree, child FROM tree '.
436 'WHERE child = '.$ilDB->quote($ref_id);
437 $res = $ilDB->query($query);
438 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
439 {
440 $GLOBALS['ilLog']->write(__METHOD__.': '.$row->tree.': '.$ref_id);
441
442 $this->deleteMissingTreeEntry($row->tree,$ref_id);
443 }
444 }
445 }
446
450 protected function deleteMissingTreeEntry($a_tree_id,$a_ref_id)
451 {
452 global $ilDB;
453
454 $query = 'SELECT child FROM tree '.
455 'WHERE parent = '.$ilDB->quote($a_ref_id,'integer').' '.
456 'AND tree = '.$ilDB->quote($a_tree_id,'integer');
457
458 $res = $ilDB->query($query);
459 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
460 {
461 // check for duplicates
462 $query = 'SELECT tree, child FROM tree '.
463 'WHERE child = '.$ilDB->quote($row->child);
464 $resd = $ilDB->query($query);
465 while($rowd = $resd->fetchRow(DB_FETCHMODE_OBJECT))
466 {
467 $this->deleteMissingTreeEntry($rowd->tree,$rowd->child);
468 }
469 }
470
471 // finally delete
472 include_once './Services/Object/classes/class.ilObjectFactory.php';
473 $factory = new ilObjectFactory();
474 $ref_obj = $factory->getInstanceByRefId($a_ref_id,FALSE);
475
476 if(($ref_obj instanceof ilObject) and $ref_obj->getType())
477 {
478 $ref_obj->delete();
479 }
480
481 $query = 'DELETE from tree '.
482 'WHERE tree = '.$ilDB->quote($a_tree_id).' '.
483 'AND child = '.$ilDB->quote($a_ref_id);
484 $ilDB->manipulate($query);
485 }
486
487
494 protected function readMissingTreeEntries()
495 {
496 global $ilDB;
497
498 $query = 'SELECT child FROM tree '.
499 'LEFT JOIN object_reference ON child = ref_id '.
500 'WHERE ref_id IS NULL';
501
502 $res = $ilDB->query($query);
503
504 $failures = array();
505 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
506 {
507 $failures[] = $row->child;
508 }
509 return $failures;
510 }
511
512
516 protected function createRecoveryContainer()
517 {
518 $now = new ilDateTime(time(),IL_CAL_UNIX);
519
520 include_once './Modules/Folder/classes/class.ilObjFolder.php';
521 $folder = new ilObjFolder();
522 $folder->setTitle('__System check recovery: '.$now->get(IL_CAL_DATETIME));
523 $folder->create();
524 $folder->createReference();
525 $folder->putInTree(RECOVERY_FOLDER_ID);
526
527 return $folder->getRefId();
528 }
529
530
531
532
533}
534?>
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
const IL_CAL_UNIX
const IL_CAL_DATETIME
@classDescription Date and time handling
Class ilObjFolder.
Class ilObjRoleFolder.
Class ilObjectFactory.
Class ilObject Basic functions for all objects.
Defines a system check task.
const STATUS_COMPLETED
const STATUS_FAILED
Defines a system check task.
static findDeepestDuplicate()
find duplicates @global type $ilDB
static findDuplicates($a_duplicate_id)
find duplicates @global type $ilDB
validateStructure()
validate tree structure base on parent relation
deleteMissingTreeEntry($a_tree_id, $a_ref_id)
Delete missing tree entries from tree table.
static deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
findMissing()
Find missing objects.
__construct(ilSCTask $task)
repairMissingTreeEntries()
repair missing tree entries @global type $ilDB
checkDuplicates()
Check for duplicates.
static hasDuplicate($a_child)
static getNodeInfo($a_tree_id, $a_child)
readMissing()
Read missing objects in tree Entry in oject_reference but no entry in tree @global type $ilDB.
createRecoveryContainer()
Create a reccovery folder.
repairMissing()
Repair missing objects.
static getChilds($a_tree_id, $a_childs)
static deleteDuplicate($tree_id, $dup_id)
readMissingTreeEntries()
Read missing tree entries for referenced objects Entry in tree but no entry in object reference @glob...
repairMissingObject($a_parent_ref, $a_ref_id)
Repair missing object.
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
$ref_id
Definition: sahs_server.php:39
global $ilDB