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 ?>
Class ilObjRoleFolder.
Defines a system check task.
findMissing()
Find missing objects.
Class ilObjFolder.
Class ilObjectFactory.
const IL_CAL_DATETIME
static findDuplicates($a_duplicate_id)
find duplicates type $ilDB
__construct(ilSCTask $task)
readMissingTreeEntries()
Read missing tree entries for referenced objects Entry in tree but no entry in object reference type...
static deleteDuplicate($tree_id, $dup_id)
const STATUS_FAILED
static findDeepestDuplicate()
find duplicates type $ilDB
Class ilObject Basic functions for all objects.
repairMissingTreeEntries()
repair missing tree entries type $ilDB
static getChilds($a_tree_id, $a_childs)
const IL_CAL_UNIX
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
repairMissingObject($a_parent_ref, $a_ref_id)
Repair missing object.
static hasDuplicate($a_child)
static deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
deleteMissingTreeEntry($a_tree_id, $a_ref_id)
Delete missing tree entries from tree table.
Date and time handling
repairMissing()
Repair missing objects.
const STATUS_COMPLETED
$ref_id
Definition: sahs_server.php:39
Defines a system check task.
createRecoveryContainer()
Create a reccovery folder.
readMissing()
Read missing objects in tree Entry in oject_reference but no entry in tree type $ilDB.
global $ilDB
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
checkDuplicates()
Check for duplicates.
validateStructure()
validate tree structure base on parent relation
static getNodeInfo($a_tree_id, $a_child)